Scippy

SCIP

Solving Constraint Integer Programs

var.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2017 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file var.c
17  * @brief methods for problem variables
18  * @author Tobias Achterberg
19  * @author Timo Berthold
20  * @author Gerald Gamrath
21  * @author Stefan Heinz
22  * @author Marc Pfetsch
23  * @author Michael Winkler
24  * @author Kati Wolter
25  * @author Stefan Vigerske
26  *
27  * @todo Possibly implement the access of bounds of multi-aggregated variables by accessing the
28  * corresponding linear constraint if it exists. This seems to require some work, since the linear
29  * constraint has to be stored. Moreover, it has even to be created in case the original constraint
30  * was deleted after multi-aggregation, but the bounds of the multi-aggregated variable should be
31  * changed. This has to be done with care in order to not loose the performance gains of
32  * multi-aggregation.
33  */
34 
35 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
36 
37 #include <stdlib.h>
38 #include <assert.h>
39 #include <string.h>
40 
41 #include "scip/def.h"
42 #include "scip/prop.h"
43 #include "scip/relax.h"
44 #include "scip/var.h"
45 #include "scip/cons.h"
46 #include "scip/event.h"
47 #include "scip/history.h"
48 #include "scip/implics.h"
49 #include "scip/lp.h"
50 #include "scip/primal.h"
51 #include "scip/prob.h"
52 #include "scip/set.h"
53 #include "scip/sol.h"
54 #include "scip/stat.h"
55 #include "scip/tree.h"
56 #include "scip/reopt.h"
57 
58 #include "scip/debug.h"
59 
60 #include "scip/pub_message.h"
61 #include "scip/pub_history.h"
62 
63 #define MAXIMPLSCLOSURE 100 /**< maximal number of descendants of implied variable for building closure
64  * in implication graph */
65 #define MAXABSVBCOEF 1e+5 /**< maximal absolute coefficient in variable bounds added due to implications */
66 
67 /*
68  * hole, holelist, and domain methods
69  */
70 
71 /** creates a new holelist element */
72 static
74  SCIP_HOLELIST** holelist, /**< pointer to holelist to create */
75  BMS_BLKMEM* blkmem, /**< block memory for target holelist */
76  SCIP_SET* set, /**< global SCIP settings */
77  SCIP_Real left, /**< left bound of open interval in new hole */
78  SCIP_Real right /**< right bound of open interval in new hole */
79  )
80 {
81  assert(holelist != NULL);
82  assert(blkmem != NULL);
83  assert(SCIPsetIsLT(set, left, right));
84 
85  SCIPsetDebugMsg(set, "create hole list element (%.15g,%.15g) in blkmem %p\n", left, right, (void*)blkmem);
86 
87  SCIP_ALLOC( BMSallocBlockMemory(blkmem, holelist) );
88  (*holelist)->hole.left = left;
89  (*holelist)->hole.right = right;
90  (*holelist)->next = NULL;
91 
92  return SCIP_OKAY;
93 }
94 
95 /** frees all elements in the holelist */
96 static
97 void holelistFree(
98  SCIP_HOLELIST** holelist, /**< pointer to holelist to free */
99  BMS_BLKMEM* blkmem /**< block memory for target holelist */
100  )
101 {
102  assert(holelist != NULL);
103  assert(blkmem != NULL);
104 
105  while( *holelist != NULL )
106  {
107  SCIP_HOLELIST* next;
108 
109  SCIPdebugMessage("free hole list element (%.15g,%.15g) in blkmem %p\n",
110  (*holelist)->hole.left, (*holelist)->hole.right, (void*)blkmem);
111 
112  next = (*holelist)->next;
113  BMSfreeBlockMemory(blkmem, holelist);
114  assert(*holelist == NULL);
115 
116  *holelist = next;
117  }
118  assert(*holelist == NULL);
119 }
120 
121 /** duplicates a list of holes */
122 static
124  SCIP_HOLELIST** target, /**< pointer to target holelist */
125  BMS_BLKMEM* blkmem, /**< block memory for target holelist */
126  SCIP_SET* set, /**< global SCIP settings */
127  SCIP_HOLELIST* source /**< holelist to duplicate */
128  )
129 {
130  assert(target != NULL);
131 
132  while( source != NULL )
133  {
134  assert(source->next == NULL || SCIPsetIsGE(set, source->next->hole.left, source->hole.right));
135  SCIP_CALL( holelistCreate(target, blkmem, set, source->hole.left, source->hole.right) );
136  source = source->next;
137  target = &(*target)->next;
138  }
139 
140  return SCIP_OKAY;
141 }
142 
143 /** adds a hole to the domain */
144 static
146  SCIP_DOM* dom, /**< domain to add hole to */
147  BMS_BLKMEM* blkmem, /**< block memory */
148  SCIP_SET* set, /**< global SCIP settings */
149  SCIP_Real left, /**< left bound of open interval in new hole */
150  SCIP_Real right, /**< right bound of open interval in new hole */
151  SCIP_Bool* added /**< pointer to store whether the hole was added (variable didn't had that hole before), or NULL */
152  )
153 {
154  SCIP_HOLELIST** insertpos;
155  SCIP_HOLELIST* next;
156 
157  assert(dom != NULL);
158  assert(added != NULL);
159 
160  /* search for the position of the new hole */
161  insertpos = &dom->holelist;
162  while( *insertpos != NULL && (*insertpos)->hole.left < left )
163  insertpos = &(*insertpos)->next;
164 
165  /* check if new hole already exists in the hole list or is a sub hole of an existing one */
166  if( *insertpos != NULL && (*insertpos)->hole.left == left && (*insertpos)->hole.right >= right ) /*lint !e777 */
167  {
168  SCIPsetDebugMsg(set, "new hole (%.15g,%.15g) is redundant through known hole (%.15g,%.15g)\n",
169  left, right, (*insertpos)->hole.left, (*insertpos)->hole.right);
170  *added = FALSE;
171  return SCIP_OKAY;
172  }
173 
174  /* add hole */
175  *added = TRUE;
176 
177  next = *insertpos;
178  SCIP_CALL( holelistCreate(insertpos, blkmem, set, left, right) );
179  (*insertpos)->next = next;
180 
181  return SCIP_OKAY;
182 }
183 
184 /** merges overlapping holes into single holes, computes and moves lower and upper bound, respectively */
185 /**@todo the domMerge() method is currently called if a lower or an upper bound locally or globally changed; this could
186  * be more efficient if performed with the knowledge if it was a lower or an upper bound which triggered this
187  * merge */
188 static
189 void domMerge(
190  SCIP_DOM* dom, /**< domain to merge */
191  BMS_BLKMEM* blkmem, /**< block memory */
192  SCIP_SET* set, /**< global SCIP settings */
193  SCIP_Real* newlb, /**< pointer to store new lower bound */
194  SCIP_Real* newub /**< pointer to store new upper bound */
195  )
196 {
197  SCIP_HOLELIST** holelistptr;
198  SCIP_HOLELIST** lastnextptr;
199  SCIP_Real* lastrightptr;
200 
201  assert(dom != NULL);
202  assert(SCIPsetIsLE(set, dom->lb, dom->ub));
203 
204 #ifndef NDEBUG
205  {
206  /* check if the holelist is sorted w.r.t. to the left interval bounds */
207  SCIP_Real lastleft;
208 
209  holelistptr = &dom->holelist;
210 
211  lastleft = -SCIPsetInfinity(set);
212 
213  while( *holelistptr != NULL )
214  {
215  if( (*holelistptr)->next != NULL )
216  {
217  assert( SCIPsetIsLE(set, lastleft, (*holelistptr)->hole.left) );
218  lastleft = (*holelistptr)->hole.left;
219  }
220 
221  holelistptr = &(*holelistptr)->next;
222  }
223  }
224 #endif
225 
226  SCIPsetDebugMsg(set, "merge hole list\n");
227 
228  holelistptr = &dom->holelist;
229  lastrightptr = &dom->lb; /* lower bound is the right bound of the hole (-infinity,lb) */
230  lastnextptr = holelistptr;
231 
232  while( *holelistptr != NULL )
233  {
234  SCIPsetDebugMsg(set, "check hole (%.15g,%.15g) last right interval was <%.15g>\n", (*holelistptr)->hole.left, (*holelistptr)->hole.right, *lastrightptr);
235 
236  /* check that the hole is not empty */
237  assert(SCIPsetIsLT(set, (*holelistptr)->hole.left, (*holelistptr)->hole.right));
238 
239  if( SCIPsetIsGE(set, (*holelistptr)->hole.left, dom->ub) )
240  {
241  /* the remaining holes start behind the upper bound: remove them */
242  SCIPsetDebugMsg(set, "remove remaining hole since upper bound <%.15g> is less then the left hand side of the current hole\n", dom->ub);
243  holelistFree(holelistptr, blkmem);
244  assert(*holelistptr == NULL);
245 
246  /* unlink this hole from the previous hole */
247  *lastnextptr = NULL;
248  }
249  else if( SCIPsetIsGT(set, (*holelistptr)->hole.right, dom->ub) )
250  {
251  /* the hole overlaps the upper bound: decrease upper bound, remove this hole and all remaining holes */
252  SCIPsetDebugMsg(set, "upper bound <%.15g> lays in current hole; store new upper bound and remove this and all remaining holes\n", dom->ub);
253 
254  assert(SCIPsetIsLT(set, (*holelistptr)->hole.left, dom->ub));
255 
256  /* adjust upper bound */
257  dom->ub = (*holelistptr)->hole.left;
258 
259  if(newub != NULL )
260  *newub = (*holelistptr)->hole.left;
261 
262  /* remove remaining hole list */
263  holelistFree(holelistptr, blkmem);
264  assert(*holelistptr == NULL);
265 
266  /* unlink this hole from the previous hole */
267  *lastnextptr = NULL;
268  }
269  else if( SCIPsetIsGT(set, *lastrightptr, (*holelistptr)->hole.left) )
270  {
271  /* the right bound of the last hole is greater than the left bound of this hole: increase the right bound of
272  * the last hole, delete this hole */
273  SCIP_HOLELIST* nextholelist;
274 
275  if( SCIPsetIsEQ(set, *lastrightptr, dom->lb ) )
276  {
277  /* the reason for the overlap results from the lower bound hole (-infinity,lb); therefore, we can increase
278  * the lower bound */
279  SCIPsetDebugMsg(set, "lower bound <%.15g> lays in current hole; store new lower bound and remove hole\n", dom->lb);
280  *lastrightptr = MAX(*lastrightptr, (*holelistptr)->hole.right);
281 
282  /* adjust lower bound */
283  dom->lb = *lastrightptr;
284 
285  if(newlb != NULL )
286  *newlb = *lastrightptr;
287  }
288  else
289  {
290  SCIPsetDebugMsg(set, "current hole overlaps with the previous one (...,%.15g); merge to (...,%.15g)\n",
291  *lastrightptr, MAX(*lastrightptr, (*holelistptr)->hole.right) );
292  *lastrightptr = MAX(*lastrightptr, (*holelistptr)->hole.right);
293  }
294  nextholelist = (*holelistptr)->next;
295  (*holelistptr)->next = NULL;
296  holelistFree(holelistptr, blkmem);
297 
298  /* connect the linked list after removing the hole */
299  *lastnextptr = nextholelist;
300 
301  /* get next hole */
302  *holelistptr = nextholelist;
303  }
304  else
305  {
306  /* the holes do not overlap: update lastholelist and lastrightptr */
307  lastrightptr = &(*holelistptr)->hole.right;
308  lastnextptr = &(*holelistptr)->next;
309 
310  /* get next hole */
311  holelistptr = &(*holelistptr)->next;
312  }
313  }
314 
315 #ifndef NDEBUG
316  {
317  /* check that holes are merged */
318  SCIP_Real lastright;
319 
320  lastright = dom->lb; /* lower bound is the right bound of the hole (-infinity,lb) */
321  holelistptr = &dom->holelist;
322 
323  while( *holelistptr != NULL )
324  {
325  /* check the the last right interval is smaller or equal to the current left interval (none overlapping) */
326  assert( SCIPsetIsLE(set, lastright, (*holelistptr)->hole.left) );
327 
328  /* check the hole property (check that the hole is not empty) */
329  assert( SCIPsetIsLT(set, (*holelistptr)->hole.left, (*holelistptr)->hole.right) );
330  lastright = (*holelistptr)->hole.right;
331 
332  /* get next hole */
333  holelistptr = &(*holelistptr)->next;
334  }
335 
336  /* check the the last right interval is smaller or equal to the upper bound (none overlapping) */
337  assert( SCIPsetIsLE(set, lastright, dom->ub) );
338  }
339 #endif
340 }
341 
342 /*
343  * domain change methods
344  */
345 
346 /** ensures, that bound change info array for lower bound changes can store at least num entries */
347 static
349  SCIP_VAR* var, /**< problem variable */
350  BMS_BLKMEM* blkmem, /**< block memory */
351  SCIP_SET* set, /**< global SCIP settings */
352  int num /**< minimum number of entries to store */
353  )
354 {
355  assert(var != NULL);
356  assert(var->nlbchginfos <= var->lbchginfossize);
357  assert(SCIPvarIsTransformed(var));
358 
359  if( num > var->lbchginfossize )
360  {
361  int newsize;
362 
363  newsize = SCIPsetCalcMemGrowSize(set, num);
364  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->lbchginfos, var->lbchginfossize, newsize) );
365  var->lbchginfossize = newsize;
366  }
367  assert(num <= var->lbchginfossize);
368 
369  return SCIP_OKAY;
370 }
371 
372 /** ensures, that bound change info array for upper bound changes can store at least num entries */
373 static
375  SCIP_VAR* var, /**< problem variable */
376  BMS_BLKMEM* blkmem, /**< block memory */
377  SCIP_SET* set, /**< global SCIP settings */
378  int num /**< minimum number of entries to store */
379  )
380 {
381  assert(var != NULL);
382  assert(var->nubchginfos <= var->ubchginfossize);
383  assert(SCIPvarIsTransformed(var));
384 
385  if( num > var->ubchginfossize )
386  {
387  int newsize;
388 
389  newsize = SCIPsetCalcMemGrowSize(set, num);
390  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->ubchginfos, var->ubchginfossize, newsize) );
391  var->ubchginfossize = newsize;
392  }
393  assert(num <= var->ubchginfossize);
394 
395  return SCIP_OKAY;
396 }
397 
398 /** adds domain change info to the variable's lower bound change info array */
399 static
401  SCIP_VAR* var, /**< problem variable */
402  BMS_BLKMEM* blkmem, /**< block memory */
403  SCIP_SET* set, /**< global SCIP settings */
404  SCIP_Real oldbound, /**< old value for bound */
405  SCIP_Real newbound, /**< new value for bound */
406  int depth, /**< depth in the tree, where the bound change takes place */
407  int pos, /**< position of the bound change in its bound change array */
408  SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself) */
409  SCIP_CONS* infercons, /**< constraint that infered this bound change, or NULL */
410  SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
411  int inferinfo, /**< user information for inference to help resolving the conflict */
412  SCIP_BOUNDTYPE inferboundtype, /**< type of bound for inference var: lower or upper bound */
413  SCIP_BOUNDCHGTYPE boundchgtype /**< bound change type: branching decision or infered bound change */
414  )
415 {
416  assert(var != NULL);
417  assert(SCIPsetIsLT(set, oldbound, newbound));
418  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, oldbound));
419  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
420  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, oldbound, 0.0));
421  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, 1.0));
422  assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
423  assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
424  assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
425 
426  SCIPsetDebugMsg(set, "adding lower bound change info to var <%s>[%g,%g]: depth=%d, pos=%d, infer%s=<%s>, inferinfo=%d, %g -> %g\n",
427  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, depth, pos, infercons != NULL ? "cons" : "prop",
428  infercons != NULL ? SCIPconsGetName(infercons) : (inferprop != NULL ? SCIPpropGetName(inferprop) : "-"), inferinfo,
429  oldbound, newbound);
430 
431  SCIP_CALL( varEnsureLbchginfosSize(var, blkmem, set, var->nlbchginfos+1) );
432  var->lbchginfos[var->nlbchginfos].oldbound = oldbound;
433  var->lbchginfos[var->nlbchginfos].newbound = newbound;
434  var->lbchginfos[var->nlbchginfos].var = var;
435  var->lbchginfos[var->nlbchginfos].bdchgidx.depth = depth;
436  var->lbchginfos[var->nlbchginfos].bdchgidx.pos = pos;
437  var->lbchginfos[var->nlbchginfos].pos = var->nlbchginfos; /*lint !e732*/
438  var->lbchginfos[var->nlbchginfos].boundchgtype = boundchgtype; /*lint !e641*/
439  var->lbchginfos[var->nlbchginfos].boundtype = SCIP_BOUNDTYPE_LOWER; /*lint !e641*/
440  var->lbchginfos[var->nlbchginfos].redundant = FALSE;
441  var->lbchginfos[var->nlbchginfos].inferboundtype = inferboundtype; /*lint !e641*/
442  var->lbchginfos[var->nlbchginfos].inferencedata.var = infervar;
443  var->lbchginfos[var->nlbchginfos].inferencedata.info = inferinfo;
444 
445  /**@note The "pos" data member of the bound change info has a size of 27 bits */
446  assert(var->nlbchginfos < 1 << 27);
447 
448  switch( boundchgtype )
449  {
451  break;
453  assert(infercons != NULL);
454  var->lbchginfos[var->nlbchginfos].inferencedata.reason.cons = infercons;
455  break;
457  var->lbchginfos[var->nlbchginfos].inferencedata.reason.prop = inferprop;
458  break;
459  default:
460  SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
461  return SCIP_INVALIDDATA;
462  }
463 
464  var->nlbchginfos++;
465 
466  assert(var->nlbchginfos < 2
468  &var->lbchginfos[var->nlbchginfos-1].bdchgidx));
469 
470  return SCIP_OKAY;
471 }
472 
473 /** adds domain change info to the variable's upper bound change info array */
474 static
476  SCIP_VAR* var, /**< problem variable */
477  BMS_BLKMEM* blkmem, /**< block memory */
478  SCIP_SET* set, /**< global SCIP settings */
479  SCIP_Real oldbound, /**< old value for bound */
480  SCIP_Real newbound, /**< new value for bound */
481  int depth, /**< depth in the tree, where the bound change takes place */
482  int pos, /**< position of the bound change in its bound change array */
483  SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself) */
484  SCIP_CONS* infercons, /**< constraint that infered this bound change, or NULL */
485  SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
486  int inferinfo, /**< user information for inference to help resolving the conflict */
487  SCIP_BOUNDTYPE inferboundtype, /**< type of bound for inference var: lower or upper bound */
488  SCIP_BOUNDCHGTYPE boundchgtype /**< bound change type: branching decision or infered bound change */
489  )
490 {
491  assert(var != NULL);
492  assert(SCIPsetIsGT(set, oldbound, newbound));
493  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, oldbound));
494  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
495  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, oldbound, 1.0));
496  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, 0.0));
497  assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
498  assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
499  assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
500 
501  SCIPsetDebugMsg(set, "adding upper bound change info to var <%s>[%g,%g]: depth=%d, pos=%d, infer%s=<%s>, inferinfo=%d, %g -> %g\n",
502  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, depth, pos, infercons != NULL ? "cons" : "prop",
503  infercons != NULL ? SCIPconsGetName(infercons) : (inferprop != NULL ? SCIPpropGetName(inferprop) : "-"), inferinfo,
504  oldbound, newbound);
505 
506  SCIP_CALL( varEnsureUbchginfosSize(var, blkmem, set, var->nubchginfos+1) );
507  var->ubchginfos[var->nubchginfos].oldbound = oldbound;
508  var->ubchginfos[var->nubchginfos].newbound = newbound;
509  var->ubchginfos[var->nubchginfos].var = var;
510  var->ubchginfos[var->nubchginfos].bdchgidx.depth = depth;
511  var->ubchginfos[var->nubchginfos].bdchgidx.pos = pos;
512  var->ubchginfos[var->nubchginfos].pos = var->nubchginfos; /*lint !e732*/
513  var->ubchginfos[var->nubchginfos].boundchgtype = boundchgtype; /*lint !e641*/
514  var->ubchginfos[var->nubchginfos].boundtype = SCIP_BOUNDTYPE_UPPER; /*lint !e641*/
515  var->ubchginfos[var->nubchginfos].redundant = FALSE;
516  var->ubchginfos[var->nubchginfos].inferboundtype = inferboundtype; /*lint !e641*/
517  var->ubchginfos[var->nubchginfos].inferencedata.var = infervar;
518  var->ubchginfos[var->nubchginfos].inferencedata.info = inferinfo;
519 
520  /**@note The "pos" data member of the bound change info has a size of 27 bits */
521  assert(var->nubchginfos < 1 << 27);
522 
523  switch( boundchgtype )
524  {
526  break;
528  assert(infercons != NULL);
529  var->ubchginfos[var->nubchginfos].inferencedata.reason.cons = infercons;
530  break;
532  var->ubchginfos[var->nubchginfos].inferencedata.reason.prop = inferprop;
533  break;
534  default:
535  SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
536  return SCIP_INVALIDDATA;
537  }
538 
539  var->nubchginfos++;
540 
541  assert(var->nubchginfos < 2
543  &var->ubchginfos[var->nubchginfos-1].bdchgidx));
544 
545  return SCIP_OKAY;
546 }
547 
548 /** applies single bound change */
550  SCIP_BOUNDCHG* boundchg, /**< bound change to apply */
551  BMS_BLKMEM* blkmem, /**< block memory */
552  SCIP_SET* set, /**< global SCIP settings */
553  SCIP_STAT* stat, /**< problem statistics */
554  SCIP_LP* lp, /**< current LP data */
555  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
556  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
557  int depth, /**< depth in the tree, where the bound change takes place */
558  int pos, /**< position of the bound change in its bound change array */
559  SCIP_Bool* cutoff /**< pointer to store whether an infeasible bound change was detected */
560  )
561 {
562  SCIP_VAR* var;
563 
564  assert(boundchg != NULL);
565  assert(stat != NULL);
566  assert(depth > 0);
567  assert(pos >= 0);
568  assert(cutoff != NULL);
569 
570  *cutoff = FALSE;
571 
572  /* ignore redundant bound changes */
573  if( boundchg->redundant )
574  return SCIP_OKAY;
575 
576  var = boundchg->var;
577  assert(var != NULL);
579  assert(!SCIPvarIsIntegral(var) || SCIPsetIsIntegral(set, boundchg->newbound));
580 
581  /* apply bound change */
582  switch( boundchg->boundtype )
583  {
585  /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
586  if( SCIPsetIsGT(set, boundchg->newbound, var->locdom.lb) )
587  {
588  if( SCIPsetIsLE(set, boundchg->newbound, var->locdom.ub) )
589  {
590  /* add the bound change info to the variable's bound change info array */
591  switch( boundchg->boundchgtype )
592  {
594  SCIPsetDebugMsg(set, " -> branching: new lower bound of <%s>[%g,%g]: %g\n",
595  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
596  SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
598  stat->lastbranchvar = var;
600  stat->lastbranchvalue = boundchg->newbound;
601  break;
602 
604  assert(boundchg->data.inferencedata.reason.cons != NULL);
605  SCIPsetDebugMsg(set, " -> constraint <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
606  SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
607  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
608  SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
609  boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
610  boundchg->data.inferencedata.info,
612  break;
613 
615  SCIPsetDebugMsg(set, " -> propagator <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
616  boundchg->data.inferencedata.reason.prop != NULL
617  ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
618  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
619  SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
620  boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
621  boundchg->data.inferencedata.info,
623  break;
624 
625  default:
626  SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
627  return SCIP_INVALIDDATA;
628  }
629 
630  /* change local bound of variable */
631  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, boundchg->newbound) );
632  }
633  else
634  {
635  SCIPsetDebugMsg(set, " -> cutoff: new lower bound of <%s>[%g,%g]: %g\n",
636  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
637  *cutoff = TRUE;
638  boundchg->redundant = TRUE; /* bound change has not entered the lbchginfos array of the variable! */
639  }
640  }
641  else
642  {
643  /* mark bound change to be inactive */
644  SCIPsetDebugMsg(set, " -> inactive %s: new lower bound of <%s>[%g,%g]: %g\n",
645  (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
646  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
647  boundchg->redundant = TRUE;
648  }
649  break;
650 
652  /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
653  if( SCIPsetIsLT(set, boundchg->newbound, var->locdom.ub) )
654  {
655  if( SCIPsetIsGE(set, boundchg->newbound, var->locdom.lb) )
656  {
657  /* add the bound change info to the variable's bound change info array */
658  switch( boundchg->boundchgtype )
659  {
661  SCIPsetDebugMsg(set, " -> branching: new upper bound of <%s>[%g,%g]: %g\n",
662  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
663  SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
665  stat->lastbranchvar = var;
667  stat->lastbranchvalue = boundchg->newbound;
668  break;
669 
671  assert(boundchg->data.inferencedata.reason.cons != NULL);
672  SCIPsetDebugMsg(set, " -> constraint <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
673  SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
674  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
675  SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
676  boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
677  boundchg->data.inferencedata.info,
679  break;
680 
682  SCIPsetDebugMsg(set, " -> propagator <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
683  boundchg->data.inferencedata.reason.prop != NULL
684  ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
685  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
686  SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
687  boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
688  boundchg->data.inferencedata.info,
690  break;
691 
692  default:
693  SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
694  return SCIP_INVALIDDATA;
695  }
696 
697  /* change local bound of variable */
698  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, boundchg->newbound) );
699  }
700  else
701  {
702  SCIPsetDebugMsg(set, " -> cutoff: new upper bound of <%s>[%g,%g]: %g\n",
703  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
704  *cutoff = TRUE;
705  boundchg->redundant = TRUE; /* bound change has not entered the ubchginfos array of the variable! */
706  }
707  }
708  else
709  {
710  /* mark bound change to be inactive */
711  SCIPsetDebugMsg(set, " -> inactive %s: new upper bound of <%s>[%g,%g]: %g\n",
712  (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
713  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
714  boundchg->redundant = TRUE;
715  }
716  break;
717 
718  default:
719  SCIPerrorMessage("unknown bound type\n");
720  return SCIP_INVALIDDATA;
721  }
722 
723  /* update the branching and inference history */
724  if( !boundchg->applied && !boundchg->redundant )
725  {
726  assert(var == boundchg->var);
727 
729  {
730  SCIP_CALL( SCIPvarIncNBranchings(var, blkmem, set, stat,
733  }
734  else if( stat->lastbranchvar != NULL )
735  {
736  /**@todo if last branching variable is unknown, retrieve it from the nodes' boundchg arrays */
737  SCIP_CALL( SCIPvarIncInferenceSum(stat->lastbranchvar, blkmem, set, stat, stat->lastbranchdir, stat->lastbranchvalue, 1.0) );
738  }
739  boundchg->applied = TRUE;
740  }
741 
742  return SCIP_OKAY;
743 }
744 
745 /** undoes single bound change */
747  SCIP_BOUNDCHG* boundchg, /**< bound change to remove */
748  BMS_BLKMEM* blkmem, /**< block memory */
749  SCIP_SET* set, /**< global SCIP settings */
750  SCIP_STAT* stat, /**< problem statistics */
751  SCIP_LP* lp, /**< current LP data */
752  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
753  SCIP_EVENTQUEUE* eventqueue /**< event queue */
754  )
755 {
756  SCIP_VAR* var;
757 
758  assert(boundchg != NULL);
759  assert(stat != NULL);
760 
761  /* ignore redundant bound changes */
762  if( boundchg->redundant )
763  return SCIP_OKAY;
764 
765  var = boundchg->var;
766  assert(var != NULL);
768 
769  /* undo bound change: apply the previous bound change of variable */
770  switch( boundchg->boundtype )
771  {
773  var->nlbchginfos--;
774  assert(var->nlbchginfos >= 0);
775  assert(var->lbchginfos != NULL);
776  assert( SCIPsetIsFeasEQ(set, var->lbchginfos[var->nlbchginfos].newbound, var->locdom.lb) ); /*lint !e777*/
777  assert( SCIPsetIsFeasLE(set, boundchg->newbound, var->locdom.lb) ); /* current lb might be larger to intermediate global bound change */
778 
779  SCIPsetDebugMsg(set, "removed lower bound change info of var <%s>[%g,%g]: depth=%d, pos=%d, %g -> %g\n",
780  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub,
783 
784  /* reinstall the previous local bound */
785  SCIP_CALL( SCIPvarChgLbLocal(boundchg->var, blkmem, set, stat, lp, branchcand, eventqueue,
786  var->lbchginfos[var->nlbchginfos].oldbound) );
787 
788  /* in case all bound changes are removed the local bound should match the global bound */
789  assert(var->nlbchginfos > 0 || SCIPsetIsFeasEQ(set, var->locdom.lb, var->glbdom.lb));
790 
791  break;
792 
794  var->nubchginfos--;
795  assert(var->nubchginfos >= 0);
796  assert(var->ubchginfos != NULL);
797  assert( SCIPsetIsFeasEQ(set, var->ubchginfos[var->nubchginfos].newbound, var->locdom.ub) ); /*lint !e777*/
798  assert( SCIPsetIsFeasGE(set, boundchg->newbound, var->locdom.ub) ); /* current ub might be smaller to intermediate global bound change */
799 
800  SCIPsetDebugMsg(set, "removed upper bound change info of var <%s>[%g,%g]: depth=%d, pos=%d, %g -> %g\n",
801  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub,
804 
805  /* reinstall the previous local bound */
806  SCIP_CALL( SCIPvarChgUbLocal(boundchg->var, blkmem, set, stat, lp, branchcand, eventqueue,
807  var->ubchginfos[var->nubchginfos].oldbound) );
808 
809  /* in case all bound changes are removed the local bound should match the global bound */
810  assert(var->nubchginfos > 0 || SCIPsetIsFeasEQ(set, var->locdom.ub, var->glbdom.ub));
811 
812  break;
813 
814  default:
815  SCIPerrorMessage("unknown bound type\n");
816  return SCIP_INVALIDDATA;
817  }
818 
819  /* update last branching variable */
821  {
822  stat->lastbranchvar = NULL;
824  }
825 
826  return SCIP_OKAY;
827 }
828 
829 /** applies single bound change to the global problem by changing the global bound of the corresponding variable */
830 static
832  SCIP_BOUNDCHG* boundchg, /**< bound change to apply */
833  BMS_BLKMEM* blkmem, /**< block memory */
834  SCIP_SET* set, /**< global SCIP settings */
835  SCIP_STAT* stat, /**< problem statistics */
836  SCIP_LP* lp, /**< current LP data */
837  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
838  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
839  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
840  SCIP_Bool* cutoff /**< pointer to store whether an infeasible bound change was detected */
841  )
842 {
843  SCIP_VAR* var;
844  SCIP_Real newbound;
845  SCIP_BOUNDTYPE boundtype;
846 
847  assert(boundchg != NULL);
848  assert(cutoff != NULL);
849 
850  *cutoff = FALSE;
851 
852  /* ignore redundant bound changes */
853  if( boundchg->redundant )
854  return SCIP_OKAY;
855 
856  var = SCIPboundchgGetVar(boundchg);
857  newbound = SCIPboundchgGetNewbound(boundchg);
858  boundtype = SCIPboundchgGetBoundtype(boundchg);
859 
860  /* check if the bound change is redundant which can happen due to a (better) global bound change which was performed
861  * after that bound change was applied
862  *
863  * @note a global bound change is not captured by the redundant member of the bound change data structure
864  */
865  if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasLE(set, newbound, SCIPvarGetLbGlobal(var)))
866  || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasGE(set, newbound, SCIPvarGetUbGlobal(var))) )
867  {
868  return SCIP_OKAY;
869  }
870 
871  SCIPsetDebugMsg(set, "applying global bound change: <%s>[%g,%g] %s %g\n",
873  boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", newbound);
874 
875  /* check for cutoff */
876  if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGT(set, newbound, SCIPvarGetUbGlobal(var)))
877  || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLT(set, newbound, SCIPvarGetLbGlobal(var))) )
878  {
879  *cutoff = TRUE;
880  return SCIP_OKAY;
881  }
882 
883  /* apply bound change */
884  SCIP_CALL( SCIPvarChgBdGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound, boundtype) );
885 
886  return SCIP_OKAY;
887 }
888 
889 /** captures branching and inference data of bound change */
890 static
892  SCIP_BOUNDCHG* boundchg /**< bound change to remove */
893  )
894 {
895  assert(boundchg != NULL);
896 
897  /* capture variable associated with the bound change */
898  assert(boundchg->var != NULL);
899  SCIPvarCapture(boundchg->var);
900 
901  switch( boundchg->boundchgtype )
902  {
905  break;
906 
908  assert(boundchg->data.inferencedata.var != NULL);
909  assert(boundchg->data.inferencedata.reason.cons != NULL);
910  SCIPconsCapture(boundchg->data.inferencedata.reason.cons);
911  break;
912 
913  default:
914  SCIPerrorMessage("invalid bound change type\n");
915  return SCIP_INVALIDDATA;
916  }
917 
918  return SCIP_OKAY;
919 }
920 
921 /** releases branching and inference data of bound change */
922 static
924  SCIP_BOUNDCHG* boundchg, /**< bound change to remove */
925  BMS_BLKMEM* blkmem, /**< block memory */
926  SCIP_SET* set, /**< global SCIP settings */
927  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
928  SCIP_LP* lp /**< current LP data */
929 
930  )
931 {
932  assert(boundchg != NULL);
933 
934  switch( boundchg->boundchgtype )
935  {
938  break;
939 
941  assert(boundchg->data.inferencedata.var != NULL);
942  assert(boundchg->data.inferencedata.reason.cons != NULL);
943  SCIP_CALL( SCIPconsRelease(&boundchg->data.inferencedata.reason.cons, blkmem, set) );
944  break;
945 
946  default:
947  SCIPerrorMessage("invalid bound change type\n");
948  return SCIP_INVALIDDATA;
949  }
950 
951  /* release variable */
952  assert(boundchg->var != NULL);
953  SCIP_CALL( SCIPvarRelease(&boundchg->var, blkmem, set, eventqueue, lp) );
954 
955 
956  return SCIP_OKAY;
957 }
958 
959 /** creates empty domain change data with dynamic arrays */
960 static
962  SCIP_DOMCHG** domchg, /**< pointer to domain change data */
963  BMS_BLKMEM* blkmem /**< block memory */
964  )
965 {
966  assert(domchg != NULL);
967  assert(blkmem != NULL);
968 
969  SCIP_ALLOC( BMSallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN)) );
970  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
971  (*domchg)->domchgdyn.nboundchgs = 0;
972  (*domchg)->domchgdyn.boundchgs = NULL;
973  (*domchg)->domchgdyn.nholechgs = 0;
974  (*domchg)->domchgdyn.holechgs = NULL;
975  (*domchg)->domchgdyn.boundchgssize = 0;
976  (*domchg)->domchgdyn.holechgssize = 0;
977 
978  return SCIP_OKAY;
979 }
980 
981 /** frees domain change data */
983  SCIP_DOMCHG** domchg, /**< pointer to domain change */
984  BMS_BLKMEM* blkmem, /**< block memory */
985  SCIP_SET* set, /**< global SCIP settings */
986  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
987  SCIP_LP* lp /**< current LP data */
988  )
989 {
990  assert(domchg != NULL);
991  assert(blkmem != NULL);
992 
993  if( *domchg != NULL )
994  {
995  int i;
996 
997  /* release variables, branching and inference data associated with the bound changes */
998  for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
999  {
1000  SCIP_CALL( boundchgReleaseData(&(*domchg)->domchgbound.boundchgs[i], blkmem, set, eventqueue, lp) );
1001  }
1002 
1003  /* free memory for bound and hole changes */
1004  switch( (*domchg)->domchgdyn.domchgtype )
1005  {
1006  case SCIP_DOMCHGTYPE_BOUND:
1007  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgbound.boundchgs, (*domchg)->domchgbound.nboundchgs);
1008  BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOUND));
1009  break;
1010  case SCIP_DOMCHGTYPE_BOTH:
1011  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgboth.boundchgs, (*domchg)->domchgboth.nboundchgs);
1012  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgboth.holechgs, (*domchg)->domchgboth.nholechgs);
1013  BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH));
1014  break;
1016  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.boundchgs, (*domchg)->domchgdyn.boundchgssize);
1017  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.holechgs, (*domchg)->domchgdyn.holechgssize);
1018  BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN));
1019  break;
1020  default:
1021  SCIPerrorMessage("invalid domain change type\n");
1022  return SCIP_INVALIDDATA;
1023  }
1024  }
1025 
1026  return SCIP_OKAY;
1027 }
1028 
1029 /** converts a static domain change data into a dynamic one */
1030 static
1032  SCIP_DOMCHG** domchg, /**< pointer to domain change data */
1033  BMS_BLKMEM* blkmem /**< block memory */
1034  )
1035 {
1036  assert(domchg != NULL);
1037  assert(blkmem != NULL);
1038 
1039  SCIPdebugMessage("making domain change data %p pointing to %p dynamic\n", (void*)domchg, (void*)*domchg);
1040 
1041  if( *domchg == NULL )
1042  {
1043  SCIP_CALL( domchgCreate(domchg, blkmem) );
1044  }
1045  else
1046  {
1047  switch( (*domchg)->domchgdyn.domchgtype )
1048  {
1049  case SCIP_DOMCHGTYPE_BOUND:
1050  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOUND), sizeof(SCIP_DOMCHGDYN)) );
1051  (*domchg)->domchgdyn.nholechgs = 0;
1052  (*domchg)->domchgdyn.holechgs = NULL;
1053  (*domchg)->domchgdyn.boundchgssize = (*domchg)->domchgdyn.nboundchgs;
1054  (*domchg)->domchgdyn.holechgssize = 0;
1055  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1056  break;
1057  case SCIP_DOMCHGTYPE_BOTH:
1058  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH), sizeof(SCIP_DOMCHGDYN)) );
1059  (*domchg)->domchgdyn.boundchgssize = (*domchg)->domchgdyn.nboundchgs;
1060  (*domchg)->domchgdyn.holechgssize = (*domchg)->domchgdyn.nholechgs;
1061  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1062  break;
1064  break;
1065  default:
1066  SCIPerrorMessage("invalid domain change type\n");
1067  return SCIP_INVALIDDATA;
1068  }
1069  }
1070 #ifndef NDEBUG
1071  {
1072  int i;
1073  for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1074  assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1075  || EPSISINT((*domchg)->domchgbound.boundchgs[i].newbound, 1e-06));
1076  }
1077 #endif
1078 
1079  return SCIP_OKAY;
1080 }
1081 
1082 /** converts a dynamic domain change data into a static one, using less memory than for a dynamic one */
1084  SCIP_DOMCHG** domchg, /**< pointer to domain change data */
1085  BMS_BLKMEM* blkmem, /**< block memory */
1086  SCIP_SET* set, /**< global SCIP settings */
1087  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1088  SCIP_LP* lp /**< current LP data */
1089  )
1090 {
1091  assert(domchg != NULL);
1092  assert(blkmem != NULL);
1093 
1094  SCIPsetDebugMsg(set, "making domain change data %p pointing to %p static\n", (void*)domchg, (void*)*domchg);
1095 
1096  if( *domchg != NULL )
1097  {
1098  switch( (*domchg)->domchgdyn.domchgtype )
1099  {
1100  case SCIP_DOMCHGTYPE_BOUND:
1101  if( (*domchg)->domchgbound.nboundchgs == 0 )
1102  {
1103  SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1104  }
1105  break;
1106  case SCIP_DOMCHGTYPE_BOTH:
1107  if( (*domchg)->domchgboth.nholechgs == 0 )
1108  {
1109  if( (*domchg)->domchgbound.nboundchgs == 0 )
1110  {
1111  SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1112  }
1113  else
1114  {
1115  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH), sizeof(SCIP_DOMCHGBOUND)) );
1116  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOUND; /*lint !e641*/
1117  }
1118  }
1119  break;
1121  if( (*domchg)->domchgboth.nholechgs == 0 )
1122  {
1123  if( (*domchg)->domchgbound.nboundchgs == 0 )
1124  {
1125  SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1126  }
1127  else
1128  {
1129  /* shrink dynamic size arrays to their minimal sizes */
1130  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.boundchgs, \
1131  (*domchg)->domchgdyn.boundchgssize, (*domchg)->domchgdyn.nboundchgs) ); /*lint !e571*/
1132  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.holechgs, (*domchg)->domchgdyn.holechgssize);
1133 
1134  /* convert into static domain change */
1135  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN), sizeof(SCIP_DOMCHGBOUND)) );
1136  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOUND; /*lint !e641*/
1137  }
1138  }
1139  else
1140  {
1141  /* shrink dynamic size arrays to their minimal sizes */
1142  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.boundchgs, \
1143  (*domchg)->domchgdyn.boundchgssize, (*domchg)->domchgdyn.nboundchgs) ); /*lint !e571*/
1144  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.holechgs, \
1145  (*domchg)->domchgdyn.holechgssize, (*domchg)->domchgdyn.nholechgs) );
1146 
1147  /* convert into static domain change */
1148  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN), sizeof(SCIP_DOMCHGBOTH)) );
1149  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOTH; /*lint !e641*/
1150  }
1151  break;
1152  default:
1153  SCIPerrorMessage("invalid domain change type\n");
1154  return SCIP_INVALIDDATA;
1155  }
1156 #ifndef NDEBUG
1157  if( *domchg != NULL )
1158  {
1159  int i;
1160  for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1161  assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1162  || SCIPsetIsFeasIntegral(set, (*domchg)->domchgbound.boundchgs[i].newbound));
1163  }
1164 #endif
1165  }
1166 
1167  return SCIP_OKAY;
1168 }
1169 
1170 /** ensures, that boundchgs array can store at least num entries */
1171 static
1173  SCIP_DOMCHG* domchg, /**< domain change data structure */
1174  BMS_BLKMEM* blkmem, /**< block memory */
1175  SCIP_SET* set, /**< global SCIP settings */
1176  int num /**< minimum number of entries to store */
1177  )
1178 {
1179  assert(domchg != NULL);
1180  assert(domchg->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1181 
1182  if( num > domchg->domchgdyn.boundchgssize )
1183  {
1184  int newsize;
1185 
1186  newsize = SCIPsetCalcMemGrowSize(set, num);
1187  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &domchg->domchgdyn.boundchgs, domchg->domchgdyn.boundchgssize, newsize) );
1188  domchg->domchgdyn.boundchgssize = newsize;
1189  }
1190  assert(num <= domchg->domchgdyn.boundchgssize);
1191 
1192  return SCIP_OKAY;
1193 }
1194 
1195 /** ensures, that holechgs array can store at least num additional entries */
1196 static
1198  SCIP_DOMCHG* domchg, /**< domain change data structure */
1199  BMS_BLKMEM* blkmem, /**< block memory */
1200  SCIP_SET* set, /**< global SCIP settings */
1201  int num /**< minimum number of additional entries to store */
1202  )
1203 {
1204  assert(domchg != NULL);
1205  assert(domchg->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1206 
1207  if( num > domchg->domchgdyn.holechgssize )
1208  {
1209  int newsize;
1210 
1211  newsize = SCIPsetCalcMemGrowSize(set, num);
1212  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &domchg->domchgdyn.holechgs, domchg->domchgdyn.holechgssize, newsize) );
1213  domchg->domchgdyn.holechgssize = newsize;
1214  }
1215  assert(num <= domchg->domchgdyn.holechgssize);
1216 
1217  return SCIP_OKAY;
1218 }
1219 
1220 /** applies domain change */
1222  SCIP_DOMCHG* domchg, /**< domain change to apply */
1223  BMS_BLKMEM* blkmem, /**< block memory */
1224  SCIP_SET* set, /**< global SCIP settings */
1225  SCIP_STAT* stat, /**< problem statistics */
1226  SCIP_LP* lp, /**< current LP data */
1227  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1228  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1229  int depth, /**< depth in the tree, where the domain change takes place */
1230  SCIP_Bool* cutoff /**< pointer to store whether an infeasible domain change was detected */
1231  )
1232 {
1233  int i;
1234 
1235  assert(cutoff != NULL);
1236 
1237  *cutoff = FALSE;
1238 
1239  SCIPsetDebugMsg(set, "applying domain changes at %p in depth %d\n", (void*)domchg, depth);
1240 
1241  if( domchg == NULL )
1242  return SCIP_OKAY;
1243 
1244  /* apply bound changes */
1245  for( i = 0; i < (int)domchg->domchgbound.nboundchgs; ++i )
1246  {
1247  SCIP_CALL( SCIPboundchgApply(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp,
1248  branchcand, eventqueue, depth, i, cutoff) );
1249  if( *cutoff )
1250  break;
1251  }
1252  SCIPsetDebugMsg(set, " -> %u bound changes (cutoff %u)\n", domchg->domchgbound.nboundchgs, *cutoff);
1253 
1254  /* mark all bound changes after a cutoff redundant */
1255  for( ; i < (int)domchg->domchgbound.nboundchgs; ++i )
1256  domchg->domchgbound.boundchgs[i].redundant = TRUE;
1257 
1258  /* apply holelist changes */
1259  if( domchg->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_BOUND ) /*lint !e641*/
1260  {
1261  for( i = 0; i < domchg->domchgboth.nholechgs; ++i )
1262  *(domchg->domchgboth.holechgs[i].ptr) = domchg->domchgboth.holechgs[i].newlist;
1263  SCIPsetDebugMsg(set, " -> %d hole changes\n", domchg->domchgboth.nholechgs);
1264  }
1265 
1266  return SCIP_OKAY;
1267 }
1268 
1269 /** undoes domain change */
1271  SCIP_DOMCHG* domchg, /**< domain change to remove */
1272  BMS_BLKMEM* blkmem, /**< block memory */
1273  SCIP_SET* set, /**< global SCIP settings */
1274  SCIP_STAT* stat, /**< problem statistics */
1275  SCIP_LP* lp, /**< current LP data */
1276  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1277  SCIP_EVENTQUEUE* eventqueue /**< event queue */
1278  )
1279 {
1280  int i;
1281 
1282  SCIPsetDebugMsg(set, "undoing domain changes at %p\n", (void*)domchg);
1283  if( domchg == NULL )
1284  return SCIP_OKAY;
1285 
1286  /* undo holelist changes */
1287  if( domchg->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_BOUND ) /*lint !e641*/
1288  {
1289  for( i = domchg->domchgboth.nholechgs-1; i >= 0; --i )
1290  *(domchg->domchgboth.holechgs[i].ptr) = domchg->domchgboth.holechgs[i].oldlist;
1291  SCIPsetDebugMsg(set, " -> %d hole changes\n", domchg->domchgboth.nholechgs);
1292  }
1293 
1294  /* undo bound changes */
1295  for( i = domchg->domchgbound.nboundchgs-1; i >= 0; --i )
1296  {
1297  SCIP_CALL( SCIPboundchgUndo(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp, branchcand, eventqueue) );
1298  }
1299  SCIPsetDebugMsg(set, " -> %u bound changes\n", domchg->domchgbound.nboundchgs);
1300 
1301  return SCIP_OKAY;
1302 }
1303 
1304 /** applies domain change to the global problem */
1306  SCIP_DOMCHG* domchg, /**< domain change to apply */
1307  BMS_BLKMEM* blkmem, /**< block memory */
1308  SCIP_SET* set, /**< global SCIP settings */
1309  SCIP_STAT* stat, /**< problem statistics */
1310  SCIP_LP* lp, /**< current LP data */
1311  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1312  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1313  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1314  SCIP_Bool* cutoff /**< pointer to store whether an infeasible domain change was detected */
1315  )
1316 {
1317  int i;
1318 
1319  assert(cutoff != NULL);
1320 
1321  *cutoff = FALSE;
1322 
1323  if( domchg == NULL )
1324  return SCIP_OKAY;
1325 
1326  SCIPsetDebugMsg(set, "applying domain changes at %p to the global problem\n", (void*)domchg);
1327 
1328  /* apply bound changes */
1329  for( i = 0; i < (int)domchg->domchgbound.nboundchgs; ++i )
1330  {
1331  SCIP_CALL( boundchgApplyGlobal(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp,
1332  branchcand, eventqueue, cliquetable, cutoff) );
1333  if( *cutoff )
1334  break;
1335  }
1336  SCIPsetDebugMsg(set, " -> %u global bound changes\n", domchg->domchgbound.nboundchgs);
1337 
1338  /**@todo globally apply holelist changes - how can this be done without confusing pointer updates? */
1339 
1340  return SCIP_OKAY;
1341 }
1342 
1343 /** adds bound change to domain changes */
1345  SCIP_DOMCHG** domchg, /**< pointer to domain change data structure */
1346  BMS_BLKMEM* blkmem, /**< block memory */
1347  SCIP_SET* set, /**< global SCIP settings */
1348  SCIP_VAR* var, /**< variable to change the bounds for */
1349  SCIP_Real newbound, /**< new value for bound */
1350  SCIP_BOUNDTYPE boundtype, /**< type of bound for var: lower or upper bound */
1351  SCIP_BOUNDCHGTYPE boundchgtype, /**< type of bound change: branching decision or inference */
1352  SCIP_Real lpsolval, /**< solval of variable in last LP on path to node, or SCIP_INVALID if unknown */
1353  SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself), or NULL */
1354  SCIP_CONS* infercons, /**< constraint that deduced the bound change, or NULL */
1355  SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
1356  int inferinfo, /**< user information for inference to help resolving the conflict */
1357  SCIP_BOUNDTYPE inferboundtype /**< type of bound for inference var: lower or upper bound */
1358  )
1359 {
1360  SCIP_BOUNDCHG* boundchg;
1361 
1362  assert(domchg != NULL);
1363  assert(var != NULL);
1365  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
1366  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, boundtype == SCIP_BOUNDTYPE_LOWER ? 1.0 : 0.0));
1367  assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
1368  assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
1369  assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
1370 
1371  SCIPsetDebugMsg(set, "adding %s bound change <%s: %g> of variable <%s> to domain change at %p pointing to %p\n",
1372  boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
1373  newbound, var->name, (void*)domchg, (void*)*domchg);
1374 
1375  /* if domain change data doesn't exist, create it;
1376  * if domain change is static, convert it into dynamic change
1377  */
1378  if( *domchg == NULL )
1379  {
1380  SCIP_CALL( domchgCreate(domchg, blkmem) );
1381  }
1382  else if( (*domchg)->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_DYNAMIC ) /*lint !e641*/
1383  {
1384  SCIP_CALL( domchgMakeDynamic(domchg, blkmem) );
1385  }
1386  assert(*domchg != NULL && (*domchg)->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1387 
1388  /* get memory for additional bound change */
1389  SCIP_CALL( domchgEnsureBoundchgsSize(*domchg, blkmem, set, (*domchg)->domchgdyn.nboundchgs+1) );
1390 
1391  /* fill in the bound change data */
1392  boundchg = &(*domchg)->domchgdyn.boundchgs[(*domchg)->domchgdyn.nboundchgs];
1393  boundchg->var = var;
1394  switch( boundchgtype )
1395  {
1397  boundchg->data.branchingdata.lpsolval = lpsolval;
1398  break;
1400  assert(infercons != NULL);
1401  boundchg->data.inferencedata.var = infervar;
1402  boundchg->data.inferencedata.reason.cons = infercons;
1403  boundchg->data.inferencedata.info = inferinfo;
1404  break;
1406  boundchg->data.inferencedata.var = infervar;
1407  boundchg->data.inferencedata.reason.prop = inferprop;
1408  boundchg->data.inferencedata.info = inferinfo;
1409  break;
1410  default:
1411  SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
1412  return SCIP_INVALIDDATA;
1413  }
1414 
1415  boundchg->newbound = newbound;
1416  boundchg->boundchgtype = boundchgtype; /*lint !e641*/
1417  boundchg->boundtype = boundtype; /*lint !e641*/
1418  boundchg->inferboundtype = inferboundtype; /*lint !e641*/
1419  boundchg->applied = FALSE;
1420  boundchg->redundant = FALSE;
1421  (*domchg)->domchgdyn.nboundchgs++;
1422 
1423  /* capture branching and inference data associated with the bound changes */
1424  SCIP_CALL( boundchgCaptureData(boundchg) );
1425 
1426 #ifdef SCIP_DISABLED_CODE /* expensive debug check */
1427 #ifdef SCIP_MORE_DEBUG
1428  {
1429  int i;
1430  for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1431  assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1432  || SCIPsetIsFeasIntegral(set, (*domchg)->domchgbound.boundchgs[i].newbound));
1433  }
1434 #endif
1435 #endif
1436 
1437  return SCIP_OKAY;
1438 }
1439 
1440 /** adds hole change to domain changes */
1442  SCIP_DOMCHG** domchg, /**< pointer to domain change data structure */
1443  BMS_BLKMEM* blkmem, /**< block memory */
1444  SCIP_SET* set, /**< global SCIP settings */
1445  SCIP_HOLELIST** ptr, /**< changed list pointer */
1446  SCIP_HOLELIST* newlist, /**< new value of list pointer */
1447  SCIP_HOLELIST* oldlist /**< old value of list pointer */
1448  )
1449 {
1450  SCIP_HOLECHG* holechg;
1451 
1452  assert(domchg != NULL);
1453  assert(ptr != NULL);
1454 
1455  /* if domain change data doesn't exist, create it;
1456  * if domain change is static, convert it into dynamic change
1457  */
1458  if( *domchg == NULL )
1459  {
1460  SCIP_CALL( domchgCreate(domchg, blkmem) );
1461  }
1462  else if( (*domchg)->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_DYNAMIC ) /*lint !e641*/
1463  {
1464  SCIP_CALL( domchgMakeDynamic(domchg, blkmem) );
1465  }
1466  assert(*domchg != NULL && (*domchg)->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1467 
1468  /* get memory for additional hole change */
1469  SCIP_CALL( domchgEnsureHolechgsSize(*domchg, blkmem, set, (*domchg)->domchgdyn.nholechgs+1) );
1470 
1471  /* fill in the hole change data */
1472  holechg = &(*domchg)->domchgdyn.holechgs[(*domchg)->domchgdyn.nholechgs];
1473  holechg->ptr = ptr;
1474  holechg->newlist = newlist;
1475  holechg->oldlist = oldlist;
1476  (*domchg)->domchgdyn.nholechgs++;
1477 
1478  return SCIP_OKAY;
1479 }
1480 
1481 
1482 
1483 
1484 /*
1485  * methods for variables
1486  */
1487 
1488 /** returns adjusted lower bound value, which is rounded for integral variable types */
1489 static
1491  SCIP_SET* set, /**< global SCIP settings */
1492  SCIP_VARTYPE vartype, /**< type of variable */
1493  SCIP_Real lb /**< lower bound to adjust */
1494  )
1495 {
1496  if( lb < 0 && SCIPsetIsInfinity(set, -lb) )
1497  return -SCIPsetInfinity(set);
1498  else if( lb > 0 && SCIPsetIsInfinity(set, lb) )
1499  return SCIPsetInfinity(set);
1500  else if( vartype != SCIP_VARTYPE_CONTINUOUS )
1501  return SCIPsetFeasCeil(set, lb);
1502  else if( SCIPsetIsZero(set, lb) )
1503  return 0.0;
1504  else
1505  return lb;
1506 }
1507 
1508 /** returns adjusted upper bound value, which is rounded for integral variable types */
1509 static
1511  SCIP_SET* set, /**< global SCIP settings */
1512  SCIP_VARTYPE vartype, /**< type of variable */
1513  SCIP_Real ub /**< upper bound to adjust */
1514  )
1515 {
1516  if( ub > 0 && SCIPsetIsInfinity(set, ub) )
1517  return SCIPsetInfinity(set);
1518  else if( ub < 0 && SCIPsetIsInfinity(set, -ub) )
1519  return -SCIPsetInfinity(set);
1520  else if( vartype != SCIP_VARTYPE_CONTINUOUS )
1521  return SCIPsetFeasFloor(set, ub);
1522  else if( SCIPsetIsZero(set, ub) )
1523  return 0.0;
1524  else
1525  return ub;
1526 }
1527 
1528 /** removes (redundant) cliques, implications and variable bounds of variable from all other variables' implications and variable
1529  * bounds arrays, and optionally removes them also from the variable itself
1530  */
1532  SCIP_VAR* var, /**< problem variable */
1533  BMS_BLKMEM* blkmem, /**< block memory */
1534  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1535  SCIP_SET* set, /**< global SCIP settings */
1536  SCIP_Bool irrelevantvar, /**< has the variable become irrelevant? */
1537  SCIP_Bool onlyredundant, /**< should only the redundant implications and variable bounds be removed? */
1538  SCIP_Bool removefromvar /**< should the implications and variable bounds be removed from the var itself? */
1539  )
1540 {
1541  SCIP_Real lb;
1542  SCIP_Real ub;
1543 
1544  assert(var != NULL);
1546  assert(SCIPvarIsActive(var) || SCIPvarGetType(var) != SCIP_VARTYPE_BINARY);
1547 
1548  lb = SCIPvarGetLbGlobal(var);
1549  ub = SCIPvarGetUbGlobal(var);
1550 
1551  SCIPsetDebugMsg(set, "removing %s implications and vbounds of %s<%s>[%g,%g]\n",
1552  onlyredundant ? "redundant" : "all", irrelevantvar ? "irrelevant " : "", SCIPvarGetName(var), lb, ub);
1553 
1554  /* remove implications of (fixed) binary variable */
1555  if( var->implics != NULL && (!onlyredundant || lb > 0.5 || ub < 0.5) )
1556  {
1557  SCIP_Bool varfixing;
1558 
1559  assert(SCIPvarIsBinary(var));
1560 
1561  varfixing = FALSE;
1562  do
1563  {
1564  SCIP_VAR** implvars;
1565  SCIP_BOUNDTYPE* impltypes;
1566  int nimpls;
1567  int i;
1568 
1569  nimpls = SCIPimplicsGetNImpls(var->implics, varfixing);
1570  implvars = SCIPimplicsGetVars(var->implics, varfixing);
1571  impltypes = SCIPimplicsGetTypes(var->implics, varfixing);
1572 
1573  for( i = 0; i < nimpls; i++ )
1574  {
1575  SCIP_VAR* implvar;
1576  SCIP_BOUNDTYPE impltype;
1577 
1578  implvar = implvars[i];
1579  impltype = impltypes[i];
1580  assert(implvar != var);
1581 
1582  /* remove for all implications z == 0 / 1 ==> x <= p / x >= p (x not binary)
1583  * the following variable bound from x's variable bounds
1584  * x <= b*z+d (z in vubs of x) , for z == 0 / 1 ==> x <= p
1585  * x >= b*z+d (z in vlbs of x) , for z == 0 / 1 ==> x >= p
1586  */
1587  if( impltype == SCIP_BOUNDTYPE_UPPER )
1588  {
1589  if( implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1590  {
1591  SCIPsetDebugMsg(set, "deleting variable bound: <%s> == %u ==> <%s> <= %g\n",
1592  SCIPvarGetName(var), varfixing, SCIPvarGetName(implvar),
1593  SCIPimplicsGetBounds(var->implics, varfixing)[i]);
1594  SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, varfixing) );
1595  implvar->closestvblpcount = -1;
1596  var->closestvblpcount = -1;
1597  }
1598  }
1599  else
1600  {
1601  if( implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1602  {
1603  SCIPsetDebugMsg(set, "deleting variable bound: <%s> == %u ==> <%s> >= %g\n",
1604  SCIPvarGetName(var), varfixing, SCIPvarGetName(implvar),
1605  SCIPimplicsGetBounds(var->implics, varfixing)[i]);
1606  SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, !varfixing) );
1607  implvar->closestvblpcount = -1;
1608  var->closestvblpcount = -1;
1609  }
1610  }
1611  }
1612  varfixing = !varfixing;
1613  }
1614  while( varfixing == TRUE );
1615 
1616  if( removefromvar )
1617  {
1618  /* free the implications data structures */
1619  SCIPimplicsFree(&var->implics, blkmem);
1620  }
1621  }
1622 
1623  /* remove the (redundant) variable lower bounds */
1624  if( var->vlbs != NULL )
1625  {
1626  SCIP_VAR** vars;
1627  SCIP_Real* coefs;
1628  SCIP_Real* constants;
1629  int nvbds;
1630  int newnvbds;
1631  int i;
1632 
1633  nvbds = SCIPvboundsGetNVbds(var->vlbs);
1634  vars = SCIPvboundsGetVars(var->vlbs);
1635  coefs = SCIPvboundsGetCoefs(var->vlbs);
1636  constants = SCIPvboundsGetConstants(var->vlbs);
1637 
1638  /* remove for all variable bounds x >= b*z+d the following implication from z's implications
1639  * z == ub ==> x >= b*ub + d , if b > 0
1640  * z == lb ==> x >= b*lb + d , if b < 0
1641  */
1642  newnvbds = 0;
1643  for( i = 0; i < nvbds; i++ )
1644  {
1645  SCIP_VAR* implvar;
1646  SCIP_Real coef;
1647 
1648  assert(newnvbds <= i);
1649 
1650  implvar = vars[i];
1651  assert(implvar != NULL);
1652 
1653  coef = coefs[i];
1654  assert(!SCIPsetIsZero(set, coef));
1655 
1656  /* check, if we want to remove the variable bound */
1657  if( onlyredundant )
1658  {
1659  SCIP_Real vbound;
1660 
1661  vbound = MAX(coef * SCIPvarGetUbGlobal(implvar), coef * SCIPvarGetLbGlobal(implvar)) + constants[i]; /*lint !e666*/
1662  if( SCIPsetIsFeasGT(set, vbound, lb) )
1663  {
1664  /* the variable bound is not redundant: keep it */
1665  if( removefromvar )
1666  {
1667  if( newnvbds < i )
1668  {
1669  vars[newnvbds] = implvar;
1670  coefs[newnvbds] = coef;
1671  constants[newnvbds] = constants[i];
1672  }
1673  newnvbds++;
1674  }
1675  continue;
1676  }
1677  }
1678 
1679  /* remove the corresponding implication */
1680  if( implvar->implics != NULL ) /* variable may have been aggregated in the mean time */
1681  {
1682  SCIPsetDebugMsg(set, "deleting implication: <%s> == %d ==> <%s> >= %g\n",
1683  SCIPvarGetName(implvar), (coef > 0.0), SCIPvarGetName(var), MAX(coef, 0.0) + constants[i]);
1684  SCIP_CALL( SCIPimplicsDel(&implvar->implics, blkmem, set, (coef > 0.0), var, SCIP_BOUNDTYPE_LOWER) );
1685  }
1686  if( coef > 0.0 && implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1687  {
1688  SCIPsetDebugMsg(set, "deleting variable upper bound from <%s> involving variable %s\n",
1689  SCIPvarGetName(implvar), SCIPvarGetName(var));
1690  SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, FALSE) );
1691  implvar->closestvblpcount = -1;
1692  var->closestvblpcount = -1;
1693  }
1694  else if( coef < 0.0 && implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1695  {
1696  SCIPsetDebugMsg(set, "deleting variable lower bound from <%s> involving variable %s\n",
1697  SCIPvarGetName(implvar), SCIPvarGetName(var));
1698  SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, TRUE) );
1699  implvar->closestvblpcount = -1;
1700  var->closestvblpcount = -1;
1701  }
1702  }
1703 
1704  if( removefromvar )
1705  {
1706  /* update the number of variable bounds */
1707  SCIPvboundsShrink(&var->vlbs, blkmem, newnvbds);
1708  var->closestvblpcount = -1;
1709  }
1710  }
1711 
1712  /**@todo in general, variable bounds like x >= b*z + d corresponding to an implication like z = ub ==> x >= b*ub + d
1713  * might be missing because we only add variable bounds with reasonably small value of b. thus, we currently
1714  * cannot remove such variables x from z's implications.
1715  */
1716 
1717  /* remove the (redundant) variable upper bounds */
1718  if( var->vubs != NULL )
1719  {
1720  SCIP_VAR** vars;
1721  SCIP_Real* coefs;
1722  SCIP_Real* constants;
1723  int nvbds;
1724  int newnvbds;
1725  int i;
1726 
1727  nvbds = SCIPvboundsGetNVbds(var->vubs);
1728  vars = SCIPvboundsGetVars(var->vubs);
1729  coefs = SCIPvboundsGetCoefs(var->vubs);
1730  constants = SCIPvboundsGetConstants(var->vubs);
1731 
1732  /* remove for all variable bounds x <= b*z+d the following implication from z's implications
1733  * z == lb ==> x <= b*lb + d , if b > 0
1734  * z == ub ==> x <= b*ub + d , if b < 0
1735  */
1736  newnvbds = 0;
1737  for( i = 0; i < nvbds; i++ )
1738  {
1739  SCIP_VAR* implvar;
1740  SCIP_Real coef;
1741 
1742  assert(newnvbds <= i);
1743 
1744  implvar = vars[i];
1745  assert(implvar != NULL);
1746 
1747  coef = coefs[i];
1748  assert(!SCIPsetIsZero(set, coef));
1749 
1750  /* check, if we want to remove the variable bound */
1751  if( onlyredundant )
1752  {
1753  SCIP_Real vbound;
1754 
1755  vbound = MIN(coef * SCIPvarGetUbGlobal(implvar), coef * SCIPvarGetLbGlobal(implvar)) + constants[i]; /*lint !e666*/
1756  if( SCIPsetIsFeasLT(set, vbound, ub) )
1757  {
1758  /* the variable bound is not redundant: keep it */
1759  if( removefromvar )
1760  {
1761  if( newnvbds < i )
1762  {
1763  vars[newnvbds] = implvar;
1764  coefs[newnvbds] = coefs[i];
1765  constants[newnvbds] = constants[i];
1766  }
1767  newnvbds++;
1768  }
1769  continue;
1770  }
1771  }
1772 
1773  /* remove the corresponding implication */
1774  if( implvar->implics != NULL ) /* variable may have been aggregated in the mean time */
1775  {
1776  SCIPsetDebugMsg(set, "deleting implication: <%s> == %d ==> <%s> <= %g\n",
1777  SCIPvarGetName(implvar), (coef < 0.0), SCIPvarGetName(var), MIN(coef, 0.0) + constants[i]);
1778  SCIP_CALL( SCIPimplicsDel(&implvar->implics, blkmem, set, (coef < 0.0), var, SCIP_BOUNDTYPE_UPPER) );
1779  }
1780  if( coef < 0.0 && implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1781  {
1782  SCIPsetDebugMsg(set, "deleting variable upper bound from <%s> involving variable %s\n",
1783  SCIPvarGetName(implvar), SCIPvarGetName(var));
1784  SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, TRUE) );
1785  implvar->closestvblpcount = -1;
1786  var->closestvblpcount = -1;
1787  }
1788  else if( coef > 0.0 && implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1789  {
1790  SCIPsetDebugMsg(set, "deleting variable lower bound from <%s> involving variable %s\n",
1791  SCIPvarGetName(implvar), SCIPvarGetName(var));
1792  SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, FALSE) );
1793  implvar->closestvblpcount = -1;
1794  var->closestvblpcount = -1;
1795  }
1796  }
1797 
1798  if( removefromvar )
1799  {
1800  /* update the number of variable bounds */
1801  SCIPvboundsShrink(&var->vubs, blkmem, newnvbds);
1802  var->closestvblpcount = -1;
1803  }
1804  }
1805 
1806  /* remove the variable from all cliques */
1807  if( SCIPvarIsBinary(var) )
1808  {
1809  SCIPcliquelistRemoveFromCliques(var->cliquelist, cliquetable, var, irrelevantvar);
1810  SCIPcliquelistFree(&var->cliquelist, blkmem);
1811  }
1812 
1813  /**@todo variable bounds like x <= b*z + d with z general integer are not removed from x's vbd arrays, because
1814  * z has no link (like in the binary case) to x
1815  */
1816 
1817  return SCIP_OKAY;
1818 }
1819 
1820 /** sets the variable name */
1821 static
1823  SCIP_VAR* var, /**< problem variable */
1824  BMS_BLKMEM* blkmem, /**< block memory */
1825  SCIP_STAT* stat, /**< problem statistics, or NULL */
1826  const char* name /**< name of variable, or NULL for automatic name creation */
1827  )
1828 {
1829  assert(blkmem != NULL);
1830  assert(var != NULL);
1831 
1832  if( name == NULL )
1833  {
1834  char s[SCIP_MAXSTRLEN];
1835 
1836  assert(stat != NULL);
1837 
1838  (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "_var%d_", stat->nvaridx);
1839  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->name, s, strlen(s)+1) );
1840  }
1841  else
1842  {
1843  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->name, name, strlen(name)+1) );
1844  }
1845 
1846  return SCIP_OKAY;
1847 }
1848 
1849 
1850 /** creates variable; if variable is of integral type, fractional bounds are automatically rounded; an integer variable
1851  * with bounds zero and one is automatically converted into a binary variable
1852  */
1853 static
1855  SCIP_VAR** var, /**< pointer to variable data */
1856  BMS_BLKMEM* blkmem, /**< block memory */
1857  SCIP_SET* set, /**< global SCIP settings */
1858  SCIP_STAT* stat, /**< problem statistics */
1859  const char* name, /**< name of variable, or NULL for automatic name creation */
1860  SCIP_Real lb, /**< lower bound of variable */
1861  SCIP_Real ub, /**< upper bound of variable */
1862  SCIP_Real obj, /**< objective function value */
1863  SCIP_VARTYPE vartype, /**< type of variable */
1864  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
1865  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
1866  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
1867  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
1868  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
1869  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
1870  SCIP_VARDATA* vardata /**< user data for this specific variable */
1871  )
1872 {
1873  assert(var != NULL);
1874  assert(blkmem != NULL);
1875  assert(stat != NULL);
1876 
1877  /* adjust bounds of variable */
1878  lb = adjustedLb(set, vartype, lb);
1879  ub = adjustedUb(set, vartype, ub);
1880 
1881  /* convert [0,1]-integers into binary variables and check that binary variables have correct bounds */
1882  if( (SCIPsetIsEQ(set, lb, 0.0) || SCIPsetIsEQ(set, lb, 1.0))
1883  && (SCIPsetIsEQ(set, ub, 0.0) || SCIPsetIsEQ(set, ub, 1.0)) )
1884  {
1885  if( vartype == SCIP_VARTYPE_INTEGER )
1886  vartype = SCIP_VARTYPE_BINARY;
1887  }
1888  else
1889  {
1890  if( vartype == SCIP_VARTYPE_BINARY )
1891  {
1892  SCIPerrorMessage("invalid bounds [%.2g,%.2g] for binary variable <%s>\n", lb, ub, name);
1893  return SCIP_INVALIDDATA;
1894  }
1895  }
1896 
1897  assert(vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, lb, 0.0) || SCIPsetIsEQ(set, lb, 1.0));
1898  assert(vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, ub, 0.0) || SCIPsetIsEQ(set, ub, 1.0));
1899 
1900  SCIP_ALLOC( BMSallocBlockMemory(blkmem, var) );
1901 
1902  /* set variable's name */
1903  SCIP_CALL( varSetName(*var, blkmem, stat, name) );
1904 
1905 #ifndef NDEBUG
1906  (*var)->scip = set->scip;
1907 #endif
1908  (*var)->obj = obj;
1909  (*var)->unchangedobj = obj;
1910  (*var)->branchfactor = 1.0;
1911  (*var)->rootsol = 0.0;
1912  (*var)->bestrootsol = 0.0;
1913  (*var)->bestrootredcost = 0.0;
1914  (*var)->bestrootlpobjval = SCIP_INVALID;
1915  (*var)->relaxsol = 0.0;
1916  (*var)->nlpsol = 0.0;
1917  (*var)->primsolavg = 0.5 * (lb + ub);
1918  (*var)->conflictlb = SCIP_REAL_MIN;
1919  (*var)->conflictub = SCIP_REAL_MAX;
1920  (*var)->conflictrelaxedlb = (*var)->conflictlb;
1921  (*var)->conflictrelaxedub = (*var)->conflictub;
1922  (*var)->lazylb = -SCIPsetInfinity(set);
1923  (*var)->lazyub = SCIPsetInfinity(set);
1924  (*var)->glbdom.holelist = NULL;
1925  (*var)->glbdom.lb = lb;
1926  (*var)->glbdom.ub = ub;
1927  (*var)->locdom.holelist = NULL;
1928  (*var)->locdom.lb = lb;
1929  (*var)->locdom.ub = ub;
1930  (*var)->varcopy = varcopy;
1931  (*var)->vardelorig = vardelorig;
1932  (*var)->vartrans = vartrans;
1933  (*var)->vardeltrans = vardeltrans;
1934  (*var)->vardata = vardata;
1935  (*var)->parentvars = NULL;
1936  (*var)->negatedvar = NULL;
1937  (*var)->vlbs = NULL;
1938  (*var)->vubs = NULL;
1939  (*var)->implics = NULL;
1940  (*var)->cliquelist = NULL;
1941  (*var)->eventfilter = NULL;
1942  (*var)->lbchginfos = NULL;
1943  (*var)->ubchginfos = NULL;
1944  (*var)->index = stat->nvaridx;
1945  (*var)->probindex = -1;
1946  (*var)->pseudocandindex = -1;
1947  (*var)->eventqueueindexobj = -1;
1948  (*var)->eventqueueindexlb = -1;
1949  (*var)->eventqueueindexub = -1;
1950  (*var)->parentvarssize = 0;
1951  (*var)->nparentvars = 0;
1952  (*var)->nuses = 0;
1953  (*var)->nlocksdown = 0;
1954  (*var)->nlocksup = 0;
1955  (*var)->branchpriority = 0;
1956  (*var)->branchdirection = SCIP_BRANCHDIR_AUTO; /*lint !e641*/
1957  (*var)->lbchginfossize = 0;
1958  (*var)->nlbchginfos = 0;
1959  (*var)->ubchginfossize = 0;
1960  (*var)->nubchginfos = 0;
1961  (*var)->conflictlbcount = 0;
1962  (*var)->conflictubcount = 0;
1963  (*var)->closestvlbidx = -1;
1964  (*var)->closestvubidx = -1;
1965  (*var)->closestvblpcount = -1;
1966  (*var)->initial = initial;
1967  (*var)->removable = removable;
1968  (*var)->deleted = FALSE;
1969  (*var)->donotmultaggr = FALSE;
1970  (*var)->vartype = vartype; /*lint !e641*/
1971  (*var)->pseudocostflag = FALSE;
1972  (*var)->eventqueueimpl = FALSE;
1973  (*var)->deletable = FALSE;
1974  (*var)->delglobalstructs = FALSE;
1975  (*var)->clqcomponentidx = -1;
1976 
1977  stat->nvaridx++;
1978 
1979  /* create branching and inference history entries */
1980  SCIP_CALL( SCIPhistoryCreate(&(*var)->history, blkmem) );
1981  SCIP_CALL( SCIPhistoryCreate(&(*var)->historycrun, blkmem) );
1982 
1983  /* the value based history is only created on demand */
1984  (*var)->valuehistory = NULL;
1985 
1986  return SCIP_OKAY;
1987 }
1988 
1989 /** creates and captures an original problem variable; an integer variable with bounds
1990  * zero and one is automatically converted into a binary variable
1991  */
1993  SCIP_VAR** var, /**< pointer to variable data */
1994  BMS_BLKMEM* blkmem, /**< block memory */
1995  SCIP_SET* set, /**< global SCIP settings */
1996  SCIP_STAT* stat, /**< problem statistics */
1997  const char* name, /**< name of variable, or NULL for automatic name creation */
1998  SCIP_Real lb, /**< lower bound of variable */
1999  SCIP_Real ub, /**< upper bound of variable */
2000  SCIP_Real obj, /**< objective function value */
2001  SCIP_VARTYPE vartype, /**< type of variable */
2002  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2003  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2004  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2005  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2006  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2007  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2008  SCIP_VARDATA* vardata /**< user data for this specific variable */
2009  )
2010 {
2011  assert(var != NULL);
2012  assert(blkmem != NULL);
2013  assert(stat != NULL);
2014 
2015  /* create variable */
2016  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2017  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2018 
2019  /* set variable status and data */
2020  (*var)->varstatus = SCIP_VARSTATUS_ORIGINAL; /*lint !e641*/
2021  (*var)->data.original.origdom.holelist = NULL;
2022  (*var)->data.original.origdom.lb = lb;
2023  (*var)->data.original.origdom.ub = ub;
2024  (*var)->data.original.transvar = NULL;
2025 
2026  /* capture variable */
2027  SCIPvarCapture(*var);
2028 
2029  return SCIP_OKAY;
2030 }
2031 
2032 /** creates and captures a loose variable belonging to the transformed problem; an integer variable with bounds
2033  * zero and one is automatically converted into a binary variable
2034  */
2036  SCIP_VAR** var, /**< pointer to variable data */
2037  BMS_BLKMEM* blkmem, /**< block memory */
2038  SCIP_SET* set, /**< global SCIP settings */
2039  SCIP_STAT* stat, /**< problem statistics */
2040  const char* name, /**< name of variable, or NULL for automatic name creation */
2041  SCIP_Real lb, /**< lower bound of variable */
2042  SCIP_Real ub, /**< upper bound of variable */
2043  SCIP_Real obj, /**< objective function value */
2044  SCIP_VARTYPE vartype, /**< type of variable */
2045  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2046  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2047  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2048  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2049  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2050  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2051  SCIP_VARDATA* vardata /**< user data for this specific variable */
2052  )
2053 {
2054  assert(var != NULL);
2055  assert(blkmem != NULL);
2056 
2057  /* create variable */
2058  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2059  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2060 
2061  /* create event filter for transformed variable */
2062  SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
2063 
2064  /* set variable status and data */
2065  (*var)->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
2066 
2067  /* capture variable */
2068  SCIPvarCapture(*var);
2069 
2070  return SCIP_OKAY;
2071 }
2072 
2073 /** copies and captures a variable from source to target SCIP; an integer variable with bounds zero and one is
2074  * automatically converted into a binary variable; in case the variable data cannot be copied the variable is not
2075  * copied at all
2076  */
2078  SCIP_VAR** var, /**< pointer to store the target variable */
2079  BMS_BLKMEM* blkmem, /**< block memory */
2080  SCIP_SET* set, /**< global SCIP settings */
2081  SCIP_STAT* stat, /**< problem statistics */
2082  SCIP* sourcescip, /**< source SCIP data structure */
2083  SCIP_VAR* sourcevar, /**< source variable */
2084  SCIP_HASHMAP* varmap, /**< a hashmap to store the mapping of source variables corresponding
2085  * target variables */
2086  SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
2087  * target constraints */
2088  SCIP_Bool global /**< should global or local bounds be used? */
2089  )
2090 {
2091  SCIP_VARDATA* targetdata;
2092  SCIP_RESULT result;
2093  SCIP_Real lb;
2094  SCIP_Real ub;
2095 
2096  assert(set != NULL);
2097  assert(blkmem != NULL);
2098  assert(stat != NULL);
2099  assert(sourcescip != NULL);
2100  assert(sourcevar != NULL);
2101  assert(var != NULL);
2102  assert(set->stage == SCIP_STAGE_PROBLEM);
2103  assert(varmap != NULL);
2104  assert(consmap != NULL);
2105 
2106  /** @todo copy hole lists */
2107  assert(global || SCIPvarGetHolelistLocal(sourcevar) == NULL);
2108  assert(!global || SCIPvarGetHolelistGlobal(sourcevar) == NULL);
2109 
2110  result = SCIP_DIDNOTRUN;
2111  targetdata = NULL;
2112 
2113  if( SCIPvarGetStatus(sourcevar) == SCIP_VARSTATUS_ORIGINAL )
2114  {
2115  lb = SCIPvarGetLbOriginal(sourcevar);
2116  ub = SCIPvarGetUbOriginal(sourcevar);
2117  }
2118  else
2119  {
2120  lb = global ? SCIPvarGetLbGlobal(sourcevar) : SCIPvarGetLbLocal(sourcevar);
2121  ub = global ? SCIPvarGetUbGlobal(sourcevar) : SCIPvarGetUbLocal(sourcevar);
2122  }
2123 
2124  /* creates and captures the variable in the target SCIP and initialize callback methods and variable data to NULL */
2125  SCIP_CALL( SCIPvarCreateOriginal(var, blkmem, set, stat, SCIPvarGetName(sourcevar),
2126  lb, ub, SCIPvarGetObj(sourcevar), SCIPvarGetType(sourcevar),
2127  SCIPvarIsInitial(sourcevar), SCIPvarIsRemovable(sourcevar),
2128  NULL, NULL, NULL, NULL, NULL) );
2129  assert(*var != NULL);
2130 
2131  /* directly copy donotmultaggr flag */
2132  (*var)->donotmultaggr = sourcevar->donotmultaggr;
2133 
2134  /* insert variable into mapping between source SCIP and the target SCIP */
2135  assert(!SCIPhashmapExists(varmap, sourcevar));
2136  SCIP_CALL( SCIPhashmapInsert(varmap, sourcevar, *var) );
2137 
2138  /* in case there exists variable data and the variable data copy callback, try to copy variable data */
2139  if( sourcevar->vardata != NULL && sourcevar->varcopy != NULL )
2140  {
2141  SCIP_CALL( sourcevar->varcopy(set->scip, sourcescip, sourcevar, sourcevar->vardata,
2142  varmap, consmap, (*var), &targetdata, &result) );
2143 
2144  /* evaluate result */
2145  if( result != SCIP_DIDNOTRUN && result != SCIP_SUCCESS )
2146  {
2147  SCIPerrorMessage("variable data copying method returned invalid result <%d>\n", result);
2148  return SCIP_INVALIDRESULT;
2149  }
2150 
2151  assert(targetdata == NULL || result == SCIP_SUCCESS);
2152 
2153  /* if copying was successful, add the created variable data to the variable as well as all callback methods */
2154  if( result == SCIP_SUCCESS )
2155  {
2156  (*var)->varcopy = sourcevar->varcopy;
2157  (*var)->vardelorig = sourcevar->vardelorig;
2158  (*var)->vartrans = sourcevar->vartrans;
2159  (*var)->vardeltrans = sourcevar->vardeltrans;
2160  (*var)->vardata = targetdata;
2161  }
2162  }
2163 
2164  /* we initialize histories of the variables by copying the source variable-information */
2165  if( set->history_allowtransfer )
2166  {
2167  SCIPvarMergeHistories((*var), sourcevar, stat);
2168  }
2169 
2170  /* in case the copying was successfully, add the created variable data to the variable as well as all callback
2171  * methods
2172  */
2173  if( result == SCIP_SUCCESS )
2174  {
2175  (*var)->varcopy = sourcevar->varcopy;
2176  (*var)->vardelorig = sourcevar->vardelorig;
2177  (*var)->vartrans = sourcevar->vartrans;
2178  (*var)->vardeltrans = sourcevar->vardeltrans;
2179  (*var)->vardata = targetdata;
2180  }
2181 
2182  SCIPsetDebugMsg(set, "created copy <%s> of variable <%s>\n", SCIPvarGetName(*var), SCIPvarGetName(sourcevar));
2183 
2184  return SCIP_OKAY;
2185 }
2186 
2187 /** parse given string for a SCIP_Real bound */
2188 static
2190  SCIP_SET* set, /**< global SCIP settings */
2191  const char* str, /**< string to parse */
2192  SCIP_Real* value, /**< pointer to store the parsed value */
2193  char** endptr /**< pointer to store the final string position if successfully parsed */
2194  )
2195 {
2196  /* first check for infinity value */
2197  if( strncmp(str, "+inf", 4) == 0 )
2198  {
2199  *value = SCIPsetInfinity(set);
2200  (*endptr) = (char*)str + 4;
2201  }
2202  else if( strncmp(str, "-inf", 4) == 0 )
2203  {
2204  *value = -SCIPsetInfinity(set);
2205  (*endptr) = (char*)str + 4;
2206  }
2207  else
2208  {
2209  if( !SCIPstrToRealValue(str, value, endptr) )
2210  return SCIP_READERROR;
2211  }
2212 
2213  return SCIP_OKAY;
2214 }
2215 
2216 /** parse the characters as bounds */
2217 static
2219  SCIP_SET* set, /**< global SCIP settings */
2220  const char* str, /**< string to parse */
2221  char* type, /**< bound type (global, local, or lazy) */
2222  SCIP_Real* lb, /**< pointer to store the lower bound */
2223  SCIP_Real* ub, /**< pointer to store the upper bound */
2224  char** endptr /**< pointer to store the final string position if successfully parsed (or NULL if an error occured) */
2225  )
2226 {
2227  char token[SCIP_MAXSTRLEN];
2228 
2229  SCIPsetDebugMsg(set, "parsing bounds: '%s'\n", str);
2230 
2231  /* get bound type */
2232  SCIPstrCopySection(str, ' ', ' ', type, SCIP_MAXSTRLEN, endptr);
2233  if ( strncmp(type, "original", 8) != 0 && strncmp(type, "global", 6) != 0 && strncmp(type, "local", 5) != 0 && strncmp(type, "lazy", 4) != 0 )
2234  {
2235  SCIPsetDebugMsg(set, "unkown bound type <%s>\n", type);
2236  *endptr = NULL;
2237  return SCIP_OKAY;
2238  }
2239 
2240  SCIPsetDebugMsg(set, "parsed bound type <%s>\n", type);
2241 
2242  /* get lower bound */
2243  SCIPstrCopySection(str, '[', ',', token, SCIP_MAXSTRLEN, endptr);
2244  str = *endptr;
2245  SCIP_CALL( parseValue(set, token, lb, endptr) );
2246 
2247  /* get upper bound */
2248  SCIP_CALL( parseValue(set, str, ub, endptr) );
2249 
2250  SCIPsetDebugMsg(set, "parsed bounds: [%g,%g]\n", *lb, *ub);
2251 
2252  /* skip end of bounds */
2253  while ( **endptr != '\0' && (**endptr == ']' || **endptr == ',') )
2254  ++(*endptr);
2255 
2256  return SCIP_OKAY;
2257 }
2258 
2259 /** parses a given string for a variable informations */
2260 static
2262  SCIP_SET* set, /**< global SCIP settings */
2263  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2264  const char* str, /**< string to parse */
2265  char* name, /**< pointer to store the variable name */
2266  SCIP_Real* lb, /**< pointer to store the lower bound */
2267  SCIP_Real* ub, /**< pointer to store the upper bound */
2268  SCIP_Real* obj, /**< pointer to store the objective coefficient */
2269  SCIP_VARTYPE* vartype, /**< pointer to store the variable type */
2270  SCIP_Real* lazylb, /**< pointer to store if the lower bound is lazy */
2271  SCIP_Real* lazyub, /**< pointer to store if the upper bound is lazy */
2272  SCIP_Bool local, /**< should the local bound be applied */
2273  char** endptr, /**< pointer to store the final string position if successfully */
2274  SCIP_Bool* success /**< pointer store if the paring process was successful */
2275  )
2276 {
2277  SCIP_Real parsedlb;
2278  SCIP_Real parsedub;
2279  char token[SCIP_MAXSTRLEN];
2280  char* strptr;
2281  int i;
2282 
2283  assert(lb != NULL);
2284  assert(ub != NULL);
2285  assert(obj != NULL);
2286  assert(vartype != NULL);
2287  assert(lazylb != NULL);
2288  assert(lazyub != NULL);
2289  assert(success != NULL);
2290 
2291  (*success) = TRUE;
2292 
2293  /* copy variable type */
2294  SCIPstrCopySection(str, '[', ']', token, SCIP_MAXSTRLEN, endptr);
2295  assert(str != *endptr);
2296  SCIPsetDebugMsg(set, "parsed variable type <%s>\n", token);
2297 
2298  /* get variable type */
2299  if( strncmp(token, "binary", 3) == 0 )
2300  (*vartype) = SCIP_VARTYPE_BINARY;
2301  else if( strncmp(token, "integer", 3) == 0 )
2302  (*vartype) = SCIP_VARTYPE_INTEGER;
2303  else if( strncmp(token, "implicit", 3) == 0 )
2304  (*vartype) = SCIP_VARTYPE_IMPLINT;
2305  else if( strncmp(token, "continuous", 3) == 0 )
2306  (*vartype) = SCIP_VARTYPE_CONTINUOUS;
2307  else
2308  {
2309  SCIPmessagePrintWarning(messagehdlr, "unknown variable type\n");
2310  (*success) = FALSE;
2311  return SCIP_OKAY;
2312  }
2313 
2314  /* move string pointer behind variable type */
2315  str = *endptr;
2316 
2317  /* get variable name */
2318  SCIPstrCopySection(str, '<', '>', name, SCIP_MAXSTRLEN, endptr);
2319  assert(endptr != NULL);
2320  SCIPsetDebugMsg(set, "parsed variable name <%s>\n", name);
2321 
2322  /* move string pointer behind variable name */
2323  str = *endptr;
2324 
2325  /* cut out objective coefficient */
2326  SCIPstrCopySection(str, '=', ',', token, SCIP_MAXSTRLEN, endptr);
2327 
2328  /* move string pointer behind objective coefficient */
2329  str = *endptr;
2330 
2331  /* get objective coefficient */
2332  if( !SCIPstrToRealValue(token, obj, endptr) )
2333  {
2334  *endptr = NULL;
2335  return SCIP_READERROR;
2336  }
2337 
2338  SCIPsetDebugMsg(set, "parsed objective coefficient <%g>\n", *obj);
2339 
2340  /* parse global/original bounds */
2341  SCIP_CALL( parseBounds(set, str, token, lb, ub, endptr) );
2342  assert(strncmp(token, "global", 6) == 0 || strncmp(token, "original", 8) == 0);
2343 
2344  /* initialize the lazy bound */
2345  *lazylb = -SCIPsetInfinity(set);
2346  *lazyub = SCIPsetInfinity(set);
2347 
2348  /* store pointer */
2349  strptr = *endptr;
2350 
2351  /* possibly parse optional local and lazy bounds */
2352  for( i = 0; i < 2 && *endptr != NULL && **endptr != '\0'; ++i )
2353  {
2354  /* start after previous bounds */
2355  strptr = *endptr;
2356 
2357  /* parse global bounds */
2358  SCIP_CALL( parseBounds(set, strptr, token, &parsedlb, &parsedub, endptr) );
2359 
2360  /* stop if parsing of bounds failed */
2361  if( *endptr == NULL )
2362  break;
2363 
2364  if( strncmp(token, "local", 5) == 0 && local )
2365  {
2366  *lb = parsedlb;
2367  *ub = parsedub;
2368  }
2369  else if( strncmp(token, "lazy", 4) == 0 )
2370  {
2371  *lazylb = parsedlb;
2372  *lazyub = parsedub;
2373  }
2374  }
2375 
2376  /* restore pointer */
2377  if ( *endptr == NULL )
2378  *endptr = strptr;
2379 
2380  /* check bounds for binary variables */
2381  if ( (*vartype) == SCIP_VARTYPE_BINARY )
2382  {
2383  if ( SCIPsetIsLT(set, *lb, 0.0) || SCIPsetIsGT(set, *ub, 1.0) )
2384  {
2385  SCIPerrorMessage("Parsed invalid bounds for binary variable <%s>: [%f, %f].\n", name, *lb, *ub);
2386  return SCIP_READERROR;
2387  }
2388  if ( !SCIPsetIsInfinity(set, -(*lazylb)) && !SCIPsetIsInfinity(set, *lazyub) &&
2389  ( SCIPsetIsLT(set, *lazylb, 0.0) || SCIPsetIsGT(set, *lazyub, 1.0) ) )
2390  {
2391  SCIPerrorMessage("Parsed invalid lazy bounds for binary variable <%s>: [%f, %f].\n", name, *lazylb, *lazyub);
2392  return SCIP_READERROR;
2393  }
2394  }
2395 
2396  return SCIP_OKAY;
2397 }
2398 
2399 /** parses variable information (in cip format) out of a string; if the parsing process was successful an original
2400  * variable is created and captured; if variable is of integral type, fractional bounds are automatically rounded; an
2401  * integer variable with bounds zero and one is automatically converted into a binary variable
2402  */
2404  SCIP_VAR** var, /**< pointer to variable data */
2405  BMS_BLKMEM* blkmem, /**< block memory */
2406  SCIP_SET* set, /**< global SCIP settings */
2407  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2408  SCIP_STAT* stat, /**< problem statistics */
2409  const char* str, /**< string to parse */
2410  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2411  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2412  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2413  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable */
2414  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data */
2415  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable */
2416  SCIP_VARDATA* vardata, /**< user data for this specific variable */
2417  char** endptr, /**< pointer to store the final string position if successfully */
2418  SCIP_Bool* success /**< pointer store if the paring process was successful */
2419  )
2420 {
2421  char name[SCIP_MAXSTRLEN];
2422  SCIP_Real lb;
2423  SCIP_Real ub;
2424  SCIP_Real obj;
2425  SCIP_VARTYPE vartype;
2426  SCIP_Real lazylb;
2427  SCIP_Real lazyub;
2428 
2429  assert(var != NULL);
2430  assert(blkmem != NULL);
2431  assert(stat != NULL);
2432  assert(endptr != NULL);
2433  assert(success != NULL);
2434 
2435  /* parse string in cip format for variable information */
2436  SCIP_CALL( varParse(set, messagehdlr, str, name, &lb, &ub, &obj, &vartype, &lazylb, &lazyub, FALSE, endptr, success) );
2437 
2438  if( *success )
2439  {
2440  /* create variable */
2441  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2442  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2443 
2444  /* set variable status and data */
2445  (*var)->varstatus = SCIP_VARSTATUS_ORIGINAL; /*lint !e641*/
2446  (*var)->data.original.origdom.holelist = NULL;
2447  (*var)->data.original.origdom.lb = lb;
2448  (*var)->data.original.origdom.ub = ub;
2449  (*var)->data.original.transvar = NULL;
2450 
2451  /* set lazy status of variable bounds */
2452  (*var)->lazylb = lazylb;
2453  (*var)->lazyub = lazyub;
2454 
2455  /* capture variable */
2456  SCIPvarCapture(*var);
2457  }
2458 
2459  return SCIP_OKAY;
2460 }
2461 
2462 /** parses variable information (in cip format) out of a string; if the parsing process was successful a loose variable
2463  * belonging to the transformed problem is created and captured; if variable is of integral type, fractional bounds are
2464  * automatically rounded; an integer variable with bounds zero and one is automatically converted into a binary
2465  * variable
2466  */
2468  SCIP_VAR** var, /**< pointer to variable data */
2469  BMS_BLKMEM* blkmem, /**< block memory */
2470  SCIP_SET* set, /**< global SCIP settings */
2471  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2472  SCIP_STAT* stat, /**< problem statistics */
2473  const char* str, /**< string to parse */
2474  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2475  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2476  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2477  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable */
2478  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data */
2479  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable */
2480  SCIP_VARDATA* vardata, /**< user data for this specific variable */
2481  char** endptr, /**< pointer to store the final string position if successfully */
2482  SCIP_Bool* success /**< pointer store if the paring process was successful */
2483  )
2484 {
2485  char name[SCIP_MAXSTRLEN];
2486  SCIP_Real lb;
2487  SCIP_Real ub;
2488  SCIP_Real obj;
2489  SCIP_VARTYPE vartype;
2490  SCIP_Real lazylb;
2491  SCIP_Real lazyub;
2492 
2493  assert(var != NULL);
2494  assert(blkmem != NULL);
2495  assert(endptr != NULL);
2496  assert(success != NULL);
2497 
2498  /* parse string in cip format for variable information */
2499  SCIP_CALL( varParse(set, messagehdlr, str, name, &lb, &ub, &obj, &vartype, &lazylb, &lazyub, TRUE, endptr, success) );
2500 
2501  if( *success )
2502  {
2503  /* create variable */
2504  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2505  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2506 
2507  /* create event filter for transformed variable */
2508  SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
2509 
2510  /* set variable status and data */
2511  (*var)->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
2512 
2513  /* set lazy status of variable bounds */
2514  (*var)->lazylb = lazylb;
2515  (*var)->lazyub = lazyub;
2516 
2517  /* capture variable */
2518  SCIPvarCapture(*var);
2519  }
2520 
2521  return SCIP_OKAY;
2522 }
2523 
2524 /** ensures, that parentvars array of var can store at least num entries */
2525 static
2527  SCIP_VAR* var, /**< problem variable */
2528  BMS_BLKMEM* blkmem, /**< block memory */
2529  SCIP_SET* set, /**< global SCIP settings */
2530  int num /**< minimum number of entries to store */
2531  )
2532 {
2533  assert(var->nparentvars <= var->parentvarssize);
2534 
2535  if( num > var->parentvarssize )
2536  {
2537  int newsize;
2538 
2539  newsize = SCIPsetCalcMemGrowSize(set, num);
2540  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->parentvars, var->parentvarssize, newsize) );
2541  var->parentvarssize = newsize;
2542  }
2543  assert(num <= var->parentvarssize);
2544 
2545  return SCIP_OKAY;
2546 }
2547 
2548 /** adds variable to parent list of a variable and captures parent variable */
2549 static
2551  SCIP_VAR* var, /**< variable to add parent to */
2552  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
2553  SCIP_SET* set, /**< global SCIP settings */
2554  SCIP_VAR* parentvar /**< parent variable to add */
2555  )
2556 {
2557  assert(var != NULL);
2558  assert(parentvar != NULL);
2559 
2560  /* the direct original counterpart must be stored as first parent */
2561  assert(var->nparentvars == 0 || SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL);
2562 
2563  SCIPsetDebugMsg(set, "adding parent <%s>[%p] to variable <%s>[%p] in slot %d\n",
2564  parentvar->name, (void*)parentvar, var->name, (void*)var, var->nparentvars);
2565 
2566  SCIP_CALL( varEnsureParentvarsSize(var, blkmem, set, var->nparentvars+1) );
2567 
2568  var->parentvars[var->nparentvars] = parentvar;
2569  var->nparentvars++;
2570 
2571  SCIPvarCapture(parentvar);
2572 
2573  return SCIP_OKAY;
2574 }
2575 
2576 /** deletes and releases all variables from the parent list of a variable, frees the memory of parents array */
2577 static
2579  SCIP_VAR** var, /**< pointer to variable */
2580  BMS_BLKMEM* blkmem, /**< block memory */
2581  SCIP_SET* set, /**< global SCIP settings */
2582  SCIP_EVENTQUEUE* eventqueue, /**< event queue (or NULL, if it's an original variable) */
2583  SCIP_LP* lp /**< current LP data (or NULL, if it's an original variable) */
2584  )
2585 {
2586  SCIP_VAR* parentvar;
2587  int i;
2588 
2589  SCIPsetDebugMsg(set, "free parents of <%s>\n", (*var)->name);
2590 
2591  /* release the parent variables and remove the link from the parent variable to the child */
2592  for( i = 0; i < (*var)->nparentvars; ++i )
2593  {
2594  assert((*var)->parentvars != NULL);
2595  parentvar = (*var)->parentvars[i];
2596  assert(parentvar != NULL);
2597 
2598  switch( SCIPvarGetStatus(parentvar) )
2599  {
2601  assert(parentvar->data.original.transvar == *var);
2602  assert(&parentvar->data.original.transvar != var);
2603  parentvar->data.original.transvar = NULL;
2604  break;
2605 
2607  assert(parentvar->data.aggregate.var == *var);
2608  assert(&parentvar->data.aggregate.var != var);
2609  parentvar->data.aggregate.var = NULL;
2610  break;
2611 
2612 #if 0
2613  /* The following code is unclear: should the current variable be removed from its parents? */
2615  assert(parentvar->data.multaggr.vars != NULL);
2616  for( v = 0; v < parentvar->data.multaggr.nvars && parentvar->data.multaggr.vars[v] != *var; ++v )
2617  {}
2618  assert(v < parentvar->data.multaggr.nvars && parentvar->data.multaggr.vars[v] == *var);
2619  if( v < parentvar->data.multaggr.nvars-1 )
2620  {
2621  parentvar->data.multaggr.vars[v] = parentvar->data.multaggr.vars[parentvar->data.multaggr.nvars-1];
2622  parentvar->data.multaggr.scalars[v] = parentvar->data.multaggr.scalars[parentvar->data.multaggr.nvars-1];
2623  }
2624  parentvar->data.multaggr.nvars--;
2625  break;
2626 #endif
2627 
2629  assert(parentvar->negatedvar == *var);
2630  assert((*var)->negatedvar == parentvar);
2631  parentvar->negatedvar = NULL;
2632  (*var)->negatedvar = NULL;
2633  break;
2634 
2635  default:
2636  SCIPerrorMessage("parent variable is neither ORIGINAL, AGGREGATED nor NEGATED\n");
2637  return SCIP_INVALIDDATA;
2638  } /*lint !e788*/
2639 
2640  SCIP_CALL( SCIPvarRelease(&(*var)->parentvars[i], blkmem, set, eventqueue, lp) );
2641  }
2642 
2643  /* free parentvars array */
2644  BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->parentvars, (*var)->parentvarssize);
2645 
2646  return SCIP_OKAY;
2647 }
2648 
2649 /** frees a variable */
2650 static
2652  SCIP_VAR** var, /**< pointer to variable */
2653  BMS_BLKMEM* blkmem, /**< block memory */
2654  SCIP_SET* set, /**< global SCIP settings */
2655  SCIP_EVENTQUEUE* eventqueue, /**< event queue (may be NULL, if it's not a column variable) */
2656  SCIP_LP* lp /**< current LP data (may be NULL, if it's not a column variable) */
2657  )
2658 {
2659  assert(var != NULL);
2660  assert(*var != NULL);
2661  assert(SCIPvarGetStatus(*var) != SCIP_VARSTATUS_COLUMN || &(*var)->data.col->var != var);
2662  assert((*var)->nuses == 0);
2663  assert((*var)->probindex == -1);
2664 
2665  SCIPsetDebugMsg(set, "free variable <%s> with status=%d\n", (*var)->name, SCIPvarGetStatus(*var));
2666 
2667  switch( SCIPvarGetStatus(*var) )
2668  {
2670  assert((*var)->data.original.transvar == NULL); /* cannot free variable, if transformed variable is still existing */
2671  holelistFree(&(*var)->data.original.origdom.holelist, blkmem);
2672  assert((*var)->data.original.origdom.holelist == NULL);
2673  break;
2674  case SCIP_VARSTATUS_LOOSE:
2675  break;
2676  case SCIP_VARSTATUS_COLUMN:
2677  SCIP_CALL( SCIPcolFree(&(*var)->data.col, blkmem, set, eventqueue, lp) ); /* free corresponding LP column */
2678  break;
2679  case SCIP_VARSTATUS_FIXED:
2681  break;
2683  BMSfreeBlockMemoryArray(blkmem, &(*var)->data.multaggr.vars, (*var)->data.multaggr.varssize);
2684  BMSfreeBlockMemoryArray(blkmem, &(*var)->data.multaggr.scalars, (*var)->data.multaggr.varssize);
2685  break;
2687  break;
2688  default:
2689  SCIPerrorMessage("unknown variable status\n");
2690  return SCIP_INVALIDDATA;
2691  }
2692 
2693  /* release all parent variables and free the parentvars array */
2694  SCIP_CALL( varFreeParents(var, blkmem, set, eventqueue, lp) );
2695 
2696  /* free user data */
2698  {
2699  if( (*var)->vardelorig != NULL )
2700  {
2701  SCIP_CALL( (*var)->vardelorig(set->scip, *var, &(*var)->vardata) );
2702  }
2703  }
2704  else
2705  {
2706  if( (*var)->vardeltrans != NULL )
2707  {
2708  SCIP_CALL( (*var)->vardeltrans(set->scip, *var, &(*var)->vardata) );
2709  }
2710  }
2711 
2712  /* free event filter */
2713  if( (*var)->eventfilter != NULL )
2714  {
2715  SCIP_CALL( SCIPeventfilterFree(&(*var)->eventfilter, blkmem, set) );
2716  }
2717  assert((*var)->eventfilter == NULL);
2718 
2719  /* free hole lists */
2720  holelistFree(&(*var)->glbdom.holelist, blkmem);
2721  holelistFree(&(*var)->locdom.holelist, blkmem);
2722  assert((*var)->glbdom.holelist == NULL);
2723  assert((*var)->locdom.holelist == NULL);
2724 
2725  /* free variable bounds data structures */
2726  SCIPvboundsFree(&(*var)->vlbs, blkmem);
2727  SCIPvboundsFree(&(*var)->vubs, blkmem);
2728 
2729  /* free implications data structures */
2730  SCIPimplicsFree(&(*var)->implics, blkmem);
2731 
2732  /* free clique list data structures */
2733  SCIPcliquelistFree(&(*var)->cliquelist, blkmem);
2734 
2735  /* free bound change information arrays */
2736  BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->lbchginfos, (*var)->lbchginfossize);
2737  BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->ubchginfos, (*var)->ubchginfossize);
2738 
2739  /* free branching and inference history entries */
2740  SCIPhistoryFree(&(*var)->history, blkmem);
2741  SCIPhistoryFree(&(*var)->historycrun, blkmem);
2742  SCIPvaluehistoryFree(&(*var)->valuehistory, blkmem);
2743 
2744  /* free variable data structure */
2745  BMSfreeBlockMemoryArray(blkmem, &(*var)->name, strlen((*var)->name)+1);
2746  BMSfreeBlockMemory(blkmem, var);
2747 
2748  return SCIP_OKAY;
2749 }
2750 
2751 /** increases usage counter of variable */
2752 void SCIPvarCapture(
2753  SCIP_VAR* var /**< variable */
2754  )
2755 {
2756  assert(var != NULL);
2757  assert(var->nuses >= 0);
2758 
2759  SCIPdebugMessage("capture variable <%s> with nuses=%d\n", var->name, var->nuses);
2760  var->nuses++;
2761 }
2762 
2763 /** decreases usage counter of variable, and frees memory if necessary */
2765  SCIP_VAR** var, /**< pointer to variable */
2766  BMS_BLKMEM* blkmem, /**< block memory */
2767  SCIP_SET* set, /**< global SCIP settings */
2768  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2769  SCIP_LP* lp /**< current LP data (or NULL, if it's an original variable) */
2770  )
2771 {
2772  assert(var != NULL);
2773  assert(*var != NULL);
2774  assert((*var)->nuses >= 1);
2775  assert(blkmem != NULL);
2776  assert((*var)->scip == set->scip);
2777 
2778  SCIPsetDebugMsg(set, "release variable <%s> with nuses=%d\n", (*var)->name, (*var)->nuses);
2779  (*var)->nuses--;
2780  if( (*var)->nuses == 0 )
2781  {
2782  SCIP_CALL( varFree(var, blkmem, set, eventqueue, lp) );
2783  }
2784 
2785  *var = NULL;
2786 
2787  return SCIP_OKAY;
2788 }
2789 
2790 /** change variable name */
2792  SCIP_VAR* var, /**< problem variable */
2793  BMS_BLKMEM* blkmem, /**< block memory */
2794  const char* name /**< name of variable */
2795  )
2796 {
2797  assert(name != NULL);
2798 
2799  /* remove old variable name */
2800  BMSfreeBlockMemoryArray(blkmem, &var->name, strlen(var->name)+1);
2801 
2802  /* set new variable name */
2803  SCIP_CALL( varSetName(var, blkmem, NULL, name) );
2804 
2805  return SCIP_OKAY;
2806 }
2807 
2808 /** initializes variable data structure for solving */
2809 void SCIPvarInitSolve(
2810  SCIP_VAR* var /**< problem variable */
2811  )
2812 {
2813  assert(var != NULL);
2814 
2816  var->conflictlbcount = 0;
2817  var->conflictubcount = 0;
2818 }
2819 
2820 /** outputs the given bounds into the file stream */
2821 static
2822 void printBounds(
2823  SCIP_SET* set, /**< global SCIP settings */
2824  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2825  FILE* file, /**< output file (or NULL for standard output) */
2826  SCIP_Real lb, /**< lower bound */
2827  SCIP_Real ub, /**< upper bound */
2828  const char* name /**< bound type name */
2829  )
2830 {
2831  assert(set != NULL);
2832 
2833  SCIPmessageFPrintInfo(messagehdlr, file, ", %s=", name);
2834  if( SCIPsetIsInfinity(set, lb) )
2835  SCIPmessageFPrintInfo(messagehdlr, file, "[+inf,");
2836  else if( SCIPsetIsInfinity(set, -lb) )
2837  SCIPmessageFPrintInfo(messagehdlr, file, "[-inf,");
2838  else
2839  SCIPmessageFPrintInfo(messagehdlr, file, "[%.15g,", lb);
2840  if( SCIPsetIsInfinity(set, ub) )
2841  SCIPmessageFPrintInfo(messagehdlr, file, "+inf]");
2842  else if( SCIPsetIsInfinity(set, -ub) )
2843  SCIPmessageFPrintInfo(messagehdlr, file, "-inf]");
2844  else
2845  SCIPmessageFPrintInfo(messagehdlr, file, "%.15g]", ub);
2846 }
2847 
2848 /** prints hole list to file stream */
2849 static
2850 void printHolelist(
2851  SCIP_SET* set, /**< global SCIP settings */
2852  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2853  FILE* file, /**< output file (or NULL for standard output) */
2854  SCIP_HOLELIST* holelist, /**< hole list pointer to hole of interest */
2855  const char* name /**< hole type name */
2856  )
2857 { /*lint --e{715}*/
2858  SCIP_Real left;
2859  SCIP_Real right;
2860 
2861  if( holelist == NULL )
2862  return;
2863 
2864  left = SCIPholelistGetLeft(holelist);
2865  right = SCIPholelistGetRight(holelist);
2866 
2867  /* display first hole */
2868  SCIPmessageFPrintInfo(messagehdlr, file, ", %s=(%g,%g)", name, left, right);
2869  holelist = SCIPholelistGetNext(holelist);
2870 
2871  while(holelist != NULL )
2872  {
2873  left = SCIPholelistGetLeft(holelist);
2874  right = SCIPholelistGetRight(holelist);
2875 
2876  /* display hole */
2877  SCIPmessageFPrintInfo(messagehdlr, file, "(%g,%g)", left, right);
2878 
2879  /* get next hole */
2880  holelist = SCIPholelistGetNext(holelist);
2881  }
2882 }
2883 
2884 /** outputs variable information into file stream */
2886  SCIP_VAR* var, /**< problem variable */
2887  SCIP_SET* set, /**< global SCIP settings */
2888  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2889  FILE* file /**< output file (or NULL for standard output) */
2890  )
2891 {
2892  SCIP_HOLELIST* holelist;
2893  SCIP_Real lb;
2894  SCIP_Real ub;
2895  int i;
2896 
2897  assert(var != NULL);
2898  assert(var->scip == set->scip);
2899 
2900  /* type of variable */
2901  switch( SCIPvarGetType(var) )
2902  {
2903  case SCIP_VARTYPE_BINARY:
2904  SCIPmessageFPrintInfo(messagehdlr, file, " [binary]");
2905  break;
2906  case SCIP_VARTYPE_INTEGER:
2907  SCIPmessageFPrintInfo(messagehdlr, file, " [integer]");
2908  break;
2909  case SCIP_VARTYPE_IMPLINT:
2910  SCIPmessageFPrintInfo(messagehdlr, file, " [implicit]");
2911  break;
2913  SCIPmessageFPrintInfo(messagehdlr, file, " [continuous]");
2914  break;
2915  default:
2916  SCIPerrorMessage("unknown variable type\n");
2917  SCIPABORT();
2918  return SCIP_ERROR; /*lint !e527*/
2919  }
2920 
2921  /* name */
2922  SCIPmessageFPrintInfo(messagehdlr, file, " <%s>:", var->name);
2923 
2924  /* objective value */
2925  SCIPmessageFPrintInfo(messagehdlr, file, " obj=%.15g", var->obj);
2926 
2927  /* bounds (global bounds for transformed variables, original bounds for original variables) */
2928  if( !SCIPvarIsTransformed(var) )
2929  {
2930  /* output original bound */
2931  lb = SCIPvarGetLbOriginal(var);
2932  ub = SCIPvarGetUbOriginal(var);
2933  printBounds(set, messagehdlr, file, lb, ub, "original bounds");
2934 
2935  /* output lazy bound */
2936  lb = SCIPvarGetLbLazy(var);
2937  ub = SCIPvarGetUbLazy(var);
2938 
2939  /* only display the lazy bounds if they are different from [-infinity,infinity] */
2940  if( !SCIPsetIsInfinity(set, -lb) || !SCIPsetIsInfinity(set, ub) )
2941  printBounds(set, messagehdlr, file, lb, ub, "lazy bounds");
2942 
2943  holelist = SCIPvarGetHolelistOriginal(var);
2944  printHolelist(set, messagehdlr, file, holelist, "original holes");
2945  }
2946  else
2947  {
2948  /* output global bound */
2949  lb = SCIPvarGetLbGlobal(var);
2950  ub = SCIPvarGetUbGlobal(var);
2951  printBounds(set, messagehdlr, file, lb, ub, "global bounds");
2952 
2953  /* output local bound */
2954  lb = SCIPvarGetLbLocal(var);
2955  ub = SCIPvarGetUbLocal(var);
2956  printBounds(set, messagehdlr, file, lb, ub, "local bounds");
2957 
2958  /* output lazy bound */
2959  lb = SCIPvarGetLbLazy(var);
2960  ub = SCIPvarGetUbLazy(var);
2961 
2962  /* only display the lazy bounds if they are different from [-infinity,infinity] */
2963  if( !SCIPsetIsInfinity(set, -lb) || !SCIPsetIsInfinity(set, ub) )
2964  printBounds(set, messagehdlr, file, lb, ub, "lazy bounds");
2965 
2966  /* global hole list */
2967  holelist = SCIPvarGetHolelistGlobal(var);
2968  printHolelist(set, messagehdlr, file, holelist, "global holes");
2969 
2970  /* local hole list */
2971  holelist = SCIPvarGetHolelistLocal(var);
2972  printHolelist(set, messagehdlr, file, holelist, "local holes");
2973  }
2974 
2975  /* fixings and aggregations */
2976  switch( SCIPvarGetStatus(var) )
2977  {
2979  case SCIP_VARSTATUS_LOOSE:
2980  case SCIP_VARSTATUS_COLUMN:
2981  break;
2982 
2983  case SCIP_VARSTATUS_FIXED:
2984  SCIPmessageFPrintInfo(messagehdlr, file, ", fixed:");
2985  if( SCIPsetIsInfinity(set, var->glbdom.lb) )
2986  SCIPmessageFPrintInfo(messagehdlr, file, "+inf");
2987  else if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
2988  SCIPmessageFPrintInfo(messagehdlr, file, "-inf");
2989  else
2990  SCIPmessageFPrintInfo(messagehdlr, file, "%.15g", var->glbdom.lb);
2991  break;
2992 
2994  SCIPmessageFPrintInfo(messagehdlr, file, ", aggregated:");
2995  if( !SCIPsetIsZero(set, var->data.aggregate.constant) )
2996  SCIPmessageFPrintInfo(messagehdlr, file, " %.15g", var->data.aggregate.constant);
2997  SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g<%s>", var->data.aggregate.scalar, SCIPvarGetName(var->data.aggregate.var));
2998  break;
2999 
3001  SCIPmessageFPrintInfo(messagehdlr, file, ", aggregated:");
3002  if( var->data.multaggr.nvars == 0 || !SCIPsetIsZero(set, var->data.multaggr.constant) )
3003  SCIPmessageFPrintInfo(messagehdlr, file, " %.15g", var->data.multaggr.constant);
3004  for( i = 0; i < var->data.multaggr.nvars; ++i )
3005  SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g<%s>", var->data.multaggr.scalars[i], SCIPvarGetName(var->data.multaggr.vars[i]));
3006  break;
3007 
3009  SCIPmessageFPrintInfo(messagehdlr, file, ", negated: %.15g - <%s>", var->data.negate.constant, SCIPvarGetName(var->negatedvar));
3010  break;
3011 
3012  default:
3013  SCIPerrorMessage("unknown variable status\n");
3014  SCIPABORT();
3015  return SCIP_ERROR; /*lint !e527*/
3016  }
3017 
3018  SCIPmessageFPrintInfo(messagehdlr, file, "\n");
3019 
3020  return SCIP_OKAY;
3021 }
3022 
3023 /** issues a VARUNLOCKED event on the given variable */
3024 static
3026  SCIP_VAR* var, /**< problem variable to change */
3027  BMS_BLKMEM* blkmem, /**< block memory */
3028  SCIP_SET* set, /**< global SCIP settings */
3029  SCIP_EVENTQUEUE* eventqueue /**< event queue */
3030  )
3031 {
3032  SCIP_EVENT* event;
3033 
3034  assert(var != NULL);
3035  assert(var->nlocksdown <= 1 && var->nlocksup <= 1);
3036  assert(var->scip == set->scip);
3037 
3038  /* issue VARUNLOCKED event on variable */
3039  SCIP_CALL( SCIPeventCreateVarUnlocked(&event, blkmem, var) );
3040  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
3041 
3042  return SCIP_OKAY;
3043 }
3044 
3045 /** modifies lock numbers for rounding */
3047  SCIP_VAR* var, /**< problem variable */
3048  BMS_BLKMEM* blkmem, /**< block memory */
3049  SCIP_SET* set, /**< global SCIP settings */
3050  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3051  int addnlocksdown, /**< increase in number of rounding down locks */
3052  int addnlocksup /**< increase in number of rounding up locks */
3053  )
3054 {
3055  SCIP_VAR* lockvar;
3056 
3057  assert(var != NULL);
3058  assert(var->nlocksup >= 0);
3059  assert(var->nlocksdown >= 0);
3060  assert(var->scip == set->scip);
3061 
3062  if( addnlocksdown == 0 && addnlocksup == 0 )
3063  return SCIP_OKAY;
3064 
3065  SCIPsetDebugMsg(set, "add rounding locks %d/%d to variable <%s> (locks=%d/%d)\n",
3066  addnlocksdown, addnlocksup, var->name, var->nlocksdown, var->nlocksup);
3067 
3068  lockvar = var;
3069 
3070  while( TRUE ) /*lint !e716 */
3071  {
3072  assert(lockvar != NULL);
3073 
3074  switch( SCIPvarGetStatus(lockvar) )
3075  {
3077  if( lockvar->data.original.transvar != NULL )
3078  {
3079  lockvar = lockvar->data.original.transvar;
3080  break;
3081  }
3082  else
3083  {
3084  lockvar->nlocksdown += addnlocksdown;
3085  lockvar->nlocksup += addnlocksup;
3086 
3087  assert(lockvar->nlocksdown >= 0);
3088  assert(lockvar->nlocksup >= 0);
3089 
3090  return SCIP_OKAY;
3091  }
3092  case SCIP_VARSTATUS_LOOSE:
3093  case SCIP_VARSTATUS_COLUMN:
3094  case SCIP_VARSTATUS_FIXED:
3095  lockvar->nlocksdown += addnlocksdown;
3096  lockvar->nlocksup += addnlocksup;
3097 
3098  assert(lockvar->nlocksdown >= 0);
3099  assert(lockvar->nlocksup >= 0);
3100 
3101  if( lockvar->nlocksdown <= 1 && lockvar->nlocksup <= 1 )
3102  {
3103  SCIP_CALL( varEventVarUnlocked(lockvar, blkmem, set, eventqueue) );
3104  }
3105 
3106  return SCIP_OKAY;
3108  if( lockvar->data.aggregate.scalar < 0.0 )
3109  {
3110  int tmp = addnlocksup;
3111 
3112  addnlocksup = addnlocksdown;
3113  addnlocksdown = tmp;
3114  }
3115 
3116  lockvar = lockvar->data.aggregate.var;
3117  break;
3119  {
3120  int v;
3121 
3122  assert(!lockvar->donotmultaggr);
3123 
3124  for( v = lockvar->data.multaggr.nvars - 1; v >= 0; --v )
3125  {
3126  if( lockvar->data.multaggr.scalars[v] > 0.0 )
3127  {
3128  SCIP_CALL( SCIPvarAddLocks(lockvar->data.multaggr.vars[v], blkmem, set, eventqueue, addnlocksdown,
3129  addnlocksup) );
3130  }
3131  else
3132  {
3133  SCIP_CALL( SCIPvarAddLocks(lockvar->data.multaggr.vars[v], blkmem, set, eventqueue, addnlocksup,
3134  addnlocksdown) );
3135  }
3136  }
3137  return SCIP_OKAY;
3138  }
3140  {
3141  int tmp = addnlocksup;
3142 
3143  assert(lockvar->negatedvar != NULL);
3144  assert(SCIPvarGetStatus(lockvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
3145  assert(lockvar->negatedvar->negatedvar == lockvar);
3146 
3147  addnlocksup = addnlocksdown;
3148  addnlocksdown = tmp;
3149 
3150  lockvar = lockvar->negatedvar;
3151  break;
3152  }
3153  default:
3154  SCIPerrorMessage("unknown variable status\n");
3155  return SCIP_INVALIDDATA;
3156  }
3157  }
3158 }
3159 
3160 /** gets number of locks for rounding down */
3162  SCIP_VAR* var /**< problem variable */
3163  )
3164 {
3165  int nlocks;
3166  int i;
3167 
3168  assert(var != NULL);
3169  assert(var->nlocksdown >= 0);
3170 
3171  switch( SCIPvarGetStatus(var) )
3172  {
3174  if( var->data.original.transvar != NULL )
3176  else
3177  return var->nlocksdown;
3178 
3179  case SCIP_VARSTATUS_LOOSE:
3180  case SCIP_VARSTATUS_COLUMN:
3181  case SCIP_VARSTATUS_FIXED:
3182  return var->nlocksdown;
3183 
3185  if( var->data.aggregate.scalar > 0.0 )
3186  return SCIPvarGetNLocksDown(var->data.aggregate.var);
3187  else
3188  return SCIPvarGetNLocksUp(var->data.aggregate.var);
3189 
3191  assert(!var->donotmultaggr);
3192  nlocks = 0;
3193  for( i = 0; i < var->data.multaggr.nvars; ++i )
3194  {
3195  if( var->data.multaggr.scalars[i] > 0.0 )
3196  nlocks += SCIPvarGetNLocksDown(var->data.multaggr.vars[i]);
3197  else
3198  nlocks += SCIPvarGetNLocksUp(var->data.multaggr.vars[i]);
3199  }
3200  return nlocks;
3201 
3203  assert(var->negatedvar != NULL);
3205  assert(var->negatedvar->negatedvar == var);
3206  return SCIPvarGetNLocksUp(var->negatedvar);
3207 
3208  default:
3209  SCIPerrorMessage("unknown variable status\n");
3210  SCIPABORT();
3211  return INT_MAX; /*lint !e527*/
3212  }
3213 }
3214 
3215 /** gets number of locks for rounding up */
3216 int SCIPvarGetNLocksUp(
3217  SCIP_VAR* var /**< problem variable */
3218  )
3219 {
3220  int nlocks;
3221  int i;
3222 
3223  assert(var != NULL);
3224  assert(var->nlocksup >= 0);
3225 
3226  switch( SCIPvarGetStatus(var) )
3227  {
3229  if( var->data.original.transvar != NULL )
3231  else
3232  return var->nlocksup;
3233 
3234  case SCIP_VARSTATUS_LOOSE:
3235  case SCIP_VARSTATUS_COLUMN:
3236  case SCIP_VARSTATUS_FIXED:
3237  return var->nlocksup;
3238 
3240  if( var->data.aggregate.scalar > 0.0 )
3241  return SCIPvarGetNLocksUp(var->data.aggregate.var);
3242  else
3243  return SCIPvarGetNLocksDown(var->data.aggregate.var);
3244 
3246  assert(!var->donotmultaggr);
3247  nlocks = 0;
3248  for( i = 0; i < var->data.multaggr.nvars; ++i )
3249  {
3250  if( var->data.multaggr.scalars[i] > 0.0 )
3251  nlocks += SCIPvarGetNLocksUp(var->data.multaggr.vars[i]);
3252  else
3253  nlocks += SCIPvarGetNLocksDown(var->data.multaggr.vars[i]);
3254  }
3255  return nlocks;
3256 
3258  assert(var->negatedvar != NULL);
3260  assert(var->negatedvar->negatedvar == var);
3261  return SCIPvarGetNLocksDown(var->negatedvar);
3262 
3263  default:
3264  SCIPerrorMessage("unknown variable status\n");
3265  SCIPABORT();
3266  return INT_MAX; /*lint !e527*/
3267  }
3268 }
3269 
3270 /** is it possible, to round variable down and stay feasible? */
3272  SCIP_VAR* var /**< problem variable */
3273  )
3274 {
3275  return (SCIPvarGetNLocksDown(var) == 0);
3276 }
3277 
3278 /** is it possible, to round variable up and stay feasible? */
3280  SCIP_VAR* var /**< problem variable */
3281  )
3282 {
3283  return (SCIPvarGetNLocksUp(var) == 0);
3284 }
3285 
3286 /** gets and captures transformed variable of a given variable; if the variable is not yet transformed,
3287  * a new transformed variable for this variable is created
3288  */
3290  SCIP_VAR* origvar, /**< original problem variable */
3291  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3292  SCIP_SET* set, /**< global SCIP settings */
3293  SCIP_STAT* stat, /**< problem statistics */
3294  SCIP_OBJSENSE objsense, /**< objective sense of original problem; transformed is always MINIMIZE */
3295  SCIP_VAR** transvar /**< pointer to store the transformed variable */
3296  )
3297 {
3298  char name[SCIP_MAXSTRLEN];
3299 
3300  assert(origvar != NULL);
3301  assert(origvar->scip == set->scip);
3302  assert(SCIPvarGetStatus(origvar) == SCIP_VARSTATUS_ORIGINAL);
3303  assert(SCIPsetIsEQ(set, origvar->glbdom.lb, origvar->locdom.lb));
3304  assert(SCIPsetIsEQ(set, origvar->glbdom.ub, origvar->locdom.ub));
3305  assert(origvar->vlbs == NULL);
3306  assert(origvar->vubs == NULL);
3307  assert(transvar != NULL);
3308 
3309  /* check if variable is already transformed */
3310  if( origvar->data.original.transvar != NULL )
3311  {
3312  *transvar = origvar->data.original.transvar;
3313  SCIPvarCapture(*transvar);
3314  }
3315  else
3316  {
3317  /* create transformed variable */
3318  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "t_%s", origvar->name);
3319  SCIP_CALL( SCIPvarCreateTransformed(transvar, blkmem, set, stat, name,
3320  origvar->glbdom.lb, origvar->glbdom.ub, (SCIP_Real)objsense * origvar->obj,
3321  SCIPvarGetType(origvar), origvar->initial, origvar->removable,
3322  origvar->vardelorig, origvar->vartrans, origvar->vardeltrans, origvar->varcopy, NULL) );
3323 
3324  /* copy the branch factor and priority */
3325  (*transvar)->branchfactor = origvar->branchfactor;
3326  (*transvar)->branchpriority = origvar->branchpriority;
3327  (*transvar)->branchdirection = origvar->branchdirection; /*lint !e732*/
3328 
3329  /* duplicate hole lists */
3330  SCIP_CALL( holelistDuplicate(&(*transvar)->glbdom.holelist, blkmem, set, origvar->glbdom.holelist) );
3331  SCIP_CALL( holelistDuplicate(&(*transvar)->locdom.holelist, blkmem, set, origvar->locdom.holelist) );
3332 
3333  /* link original and transformed variable */
3334  origvar->data.original.transvar = *transvar;
3335  SCIP_CALL( varAddParent(*transvar, blkmem, set, origvar) );
3336 
3337  /* copy rounding locks */
3338  (*transvar)->nlocksdown = origvar->nlocksdown;
3339  (*transvar)->nlocksup = origvar->nlocksup;
3340  assert((*transvar)->nlocksdown >= 0);
3341  assert((*transvar)->nlocksup >= 0);
3342 
3343  /* copy doNotMultiaggr status */
3344  (*transvar)->donotmultaggr = origvar->donotmultaggr;
3345 
3346  /* copy lazy bounds */
3347  (*transvar)->lazylb = origvar->lazylb;
3348  (*transvar)->lazyub = origvar->lazyub;
3349 
3350  /* transfer eventual variable statistics; do not update global statistics, because this has been done
3351  * when original variable was created
3352  */
3353  SCIPhistoryUnite((*transvar)->history, origvar->history, FALSE);
3354 
3355  /* transform user data */
3356  if( origvar->vartrans != NULL )
3357  {
3358  SCIP_CALL( origvar->vartrans(set->scip, origvar, origvar->vardata, *transvar, &(*transvar)->vardata) );
3359  }
3360  else
3361  (*transvar)->vardata = origvar->vardata;
3362  }
3363 
3364  SCIPsetDebugMsg(set, "transformed variable: <%s>[%p] -> <%s>[%p]\n", origvar->name, (void*)origvar, (*transvar)->name, (void*)*transvar);
3365 
3366  return SCIP_OKAY;
3367 }
3368 
3369 /** gets corresponding transformed variable of an original or negated original variable */
3371  SCIP_VAR* origvar, /**< original problem variable */
3372  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3373  SCIP_SET* set, /**< global SCIP settings */
3374  SCIP_STAT* stat, /**< problem statistics */
3375  SCIP_VAR** transvar /**< pointer to store the transformed variable, or NULL if not existing yet */
3376  )
3377 {
3378  assert(origvar != NULL);
3380  assert(origvar->scip == set->scip);
3381 
3382  if( SCIPvarGetStatus(origvar) == SCIP_VARSTATUS_NEGATED )
3383  {
3384  assert(origvar->negatedvar != NULL);
3386 
3387  if( origvar->negatedvar->data.original.transvar == NULL )
3388  *transvar = NULL;
3389  else
3390  {
3391  SCIP_CALL( SCIPvarNegate(origvar->negatedvar->data.original.transvar, blkmem, set, stat, transvar) );
3392  }
3393  }
3394  else
3395  *transvar = origvar->data.original.transvar;
3396 
3397  return SCIP_OKAY;
3398 }
3399 
3400 /** converts loose transformed variable into column variable, creates LP column */
3402  SCIP_VAR* var, /**< problem variable */
3403  BMS_BLKMEM* blkmem, /**< block memory */
3404  SCIP_SET* set, /**< global SCIP settings */
3405  SCIP_STAT* stat, /**< problem statistics */
3406  SCIP_PROB* prob, /**< problem data */
3407  SCIP_LP* lp /**< current LP data */
3408  )
3409 {
3410  assert(var != NULL);
3411  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
3412  assert(var->scip == set->scip);
3413 
3414  SCIPsetDebugMsg(set, "creating column for variable <%s>\n", var->name);
3415 
3416  /* switch variable status */
3417  var->varstatus = SCIP_VARSTATUS_COLUMN; /*lint !e641*/
3418 
3419  /* create column of variable */
3420  SCIP_CALL( SCIPcolCreate(&var->data.col, blkmem, set, stat, var, 0, NULL, NULL, var->removable) );
3421 
3422  if( var->probindex != -1 )
3423  {
3424  /* inform problem about the variable's status change */
3425  SCIP_CALL( SCIPprobVarChangedStatus(prob, blkmem, set, NULL, NULL, var) );
3426 
3427  /* inform LP, that problem variable is now a column variable and no longer loose */
3428  SCIP_CALL( SCIPlpUpdateVarColumn(lp, set, var) );
3429  }
3430 
3431  return SCIP_OKAY;
3432 }
3433 
3434 /** converts column transformed variable back into loose variable, frees LP column */
3436  SCIP_VAR* var, /**< problem variable */
3437  BMS_BLKMEM* blkmem, /**< block memory */
3438  SCIP_SET* set, /**< global SCIP settings */
3439  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3440  SCIP_PROB* prob, /**< problem data */
3441  SCIP_LP* lp /**< current LP data */
3442  )
3443 {
3444  assert(var != NULL);
3445  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
3446  assert(var->scip == set->scip);
3447  assert(var->data.col != NULL);
3448  assert(var->data.col->lppos == -1);
3449  assert(var->data.col->lpipos == -1);
3450 
3451  SCIPsetDebugMsg(set, "deleting column for variable <%s>\n", var->name);
3452 
3453  /* free column of variable */
3454  SCIP_CALL( SCIPcolFree(&var->data.col, blkmem, set, eventqueue, lp) );
3455 
3456  /* switch variable status */
3457  var->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
3458 
3459  if( var->probindex != -1 )
3460  {
3461  /* inform problem about the variable's status change */
3462  SCIP_CALL( SCIPprobVarChangedStatus(prob, blkmem, set, NULL, NULL, var) );
3463 
3464  /* inform LP, that problem variable is now a loose variable and no longer a column */
3465  SCIP_CALL( SCIPlpUpdateVarLoose(lp, set, var) );
3466  }
3467 
3468  return SCIP_OKAY;
3469 }
3470 
3471 /** issues a VARFIXED event on the given variable and all its parents (except ORIGINAL parents);
3472  * the event issuing on the parents is necessary, because unlike with bound changes, the parent variables
3473  * are not informed about a fixing of an active variable they are pointing to
3474  */
3475 static
3477  SCIP_VAR* var, /**< problem variable to change */
3478  BMS_BLKMEM* blkmem, /**< block memory */
3479  SCIP_SET* set, /**< global SCIP settings */
3480  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3481  int fixeventtype /**< is this event a fixation(0), an aggregation(1), or a
3482  * multi-aggregation(2)
3483  */
3484  )
3485 {
3486  SCIP_EVENT* event;
3487  SCIP_VARSTATUS varstatus;
3488  int i;
3489 
3490  assert(var != NULL);
3491  assert(var->scip == set->scip);
3492  assert(0 <= fixeventtype && fixeventtype <= 2);
3493 
3494  /* issue VARFIXED event on variable */
3495  SCIP_CALL( SCIPeventCreateVarFixed(&event, blkmem, var) );
3496  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
3497 
3498 #ifndef NDEBUG
3499  for( i = var->nparentvars -1; i >= 0; --i )
3500  {
3502  }
3503 #endif
3504 
3505  switch( fixeventtype )
3506  {
3507  case 0:
3508  /* process all parents of a fixed variable */
3509  for( i = var->nparentvars - 1; i >= 0; --i )
3510  {
3511  varstatus = SCIPvarGetStatus(var->parentvars[i]);
3512 
3513  assert(varstatus != SCIP_VARSTATUS_FIXED);
3514 
3515  /* issue event on all not yet fixed parent variables, (that should already issued this event) except the original
3516  * one
3517  */
3518  if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3519  {
3520  SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3521  }
3522  }
3523  break;
3524  case 1:
3525  /* process all parents of a aggregated variable */
3526  for( i = var->nparentvars - 1; i >= 0; --i )
3527  {
3528  varstatus = SCIPvarGetStatus(var->parentvars[i]);
3529 
3530  assert(varstatus != SCIP_VARSTATUS_FIXED);
3531 
3532  /* issue event for not aggregated parent variable, because for these and its parents the var event was already
3533  * issued(, except the original one)
3534  *
3535  * @note that even before an aggregated parent variable, there might be variables, for which the vent was not
3536  * yet issued
3537  */
3538  if( varstatus == SCIP_VARSTATUS_AGGREGATED )
3539  continue;
3540 
3541  if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3542  {
3543  SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3544  }
3545  }
3546  break;
3547  case 2:
3548  /* process all parents of a aggregated variable */
3549  for( i = var->nparentvars - 1; i >= 0; --i )
3550  {
3551  varstatus = SCIPvarGetStatus(var->parentvars[i]);
3552 
3553  assert(varstatus != SCIP_VARSTATUS_FIXED);
3554 
3555  /* issue event on all parent variables except the original one */
3556  if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3557  {
3558  SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3559  }
3560  }
3561  break;
3562  default:
3563  SCIPerrorMessage("unknown variable fixation event origin\n");
3564  return SCIP_INVALIDDATA;
3565  }
3566 
3567  return SCIP_OKAY;
3568 }
3569 
3570 /** converts variable into fixed variable */
3572  SCIP_VAR* var, /**< problem variable */
3573  BMS_BLKMEM* blkmem, /**< block memory */
3574  SCIP_SET* set, /**< global SCIP settings */
3575  SCIP_STAT* stat, /**< problem statistics */
3576  SCIP_PROB* transprob, /**< tranformed problem data */
3577  SCIP_PROB* origprob, /**< original problem data */
3578  SCIP_PRIMAL* primal, /**< primal data */
3579  SCIP_TREE* tree, /**< branch and bound tree */
3580  SCIP_REOPT* reopt, /**< reoptimization data structure */
3581  SCIP_LP* lp, /**< current LP data */
3582  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3583  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3584  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
3585  SCIP_Real fixedval, /**< value to fix variable at */
3586  SCIP_Bool* infeasible, /**< pointer to store whether the fixing is infeasible */
3587  SCIP_Bool* fixed /**< pointer to store whether the fixing was performed (variable was unfixed) */
3588  )
3589 {
3590  SCIP_Real obj;
3591  SCIP_Real childfixedval;
3592 
3593  assert(var != NULL);
3594  assert(var->scip == set->scip);
3595  assert(SCIPsetIsEQ(set, var->glbdom.lb, var->locdom.lb));
3596  assert(SCIPsetIsEQ(set, var->glbdom.ub, var->locdom.ub));
3597  assert(infeasible != NULL);
3598  assert(fixed != NULL);
3599 
3600  SCIPsetDebugMsg(set, "fix variable <%s>[%g,%g] to %g\n", var->name, var->glbdom.lb, var->glbdom.ub, fixedval);
3601 
3602  *infeasible = FALSE;
3603  *fixed = FALSE;
3604 
3606  {
3607  *infeasible = !SCIPsetIsFeasEQ(set, fixedval, var->locdom.lb);
3608  SCIPsetDebugMsg(set, " -> variable already fixed to %g (fixedval=%g): infeasible=%u\n", var->locdom.lb, fixedval, *infeasible);
3609  return SCIP_OKAY;
3610  }
3611  else if( (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPsetIsFeasIntegral(set, fixedval))
3612  || SCIPsetIsFeasLT(set, fixedval, var->locdom.lb)
3613  || SCIPsetIsFeasGT(set, fixedval, var->locdom.ub) )
3614  {
3615  SCIPsetDebugMsg(set, " -> fixing infeasible: locdom=[%g,%g], fixedval=%g\n", var->locdom.lb, var->locdom.ub, fixedval);
3616  *infeasible = TRUE;
3617  return SCIP_OKAY;
3618  }
3619 
3620  switch( SCIPvarGetStatus(var) )
3621  {
3623  if( var->data.original.transvar == NULL )
3624  {
3625  SCIPerrorMessage("cannot fix an untransformed original variable\n");
3626  return SCIP_INVALIDDATA;
3627  }
3628  SCIP_CALL( SCIPvarFix(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
3629  lp, branchcand, eventqueue, cliquetable, fixedval, infeasible, fixed) );
3630  break;
3631 
3632  case SCIP_VARSTATUS_LOOSE:
3633  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
3634 
3635  /* set the fixed variable's objective value to 0.0 */
3636  obj = var->obj;
3637  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
3638 
3639  /* since we change the variable type form loose to fixed, we have to adjust the number of loose
3640  * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
3641  * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
3642  * objective of this variable is set to zero
3643  */
3644  SCIPlpDecNLoosevars(lp);
3645 
3646  /* change variable's bounds to fixed value (thereby removing redundant implications and variable bounds) */
3647  holelistFree(&var->glbdom.holelist, blkmem);
3648  holelistFree(&var->locdom.holelist, blkmem);
3649  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, fixedval) );
3650  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, fixedval) );
3651 
3652  /* explicitly set variable's bounds, even if the fixed value is in epsilon range of the old bound */
3653  var->glbdom.lb = fixedval;
3654  var->glbdom.ub = fixedval;
3655  var->locdom.lb = fixedval;
3656  var->locdom.ub = fixedval;
3657 
3658  /* delete implications and variable bounds information */
3659  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
3660  assert(var->vlbs == NULL);
3661  assert(var->vubs == NULL);
3662  assert(var->implics == NULL);
3663  assert(var->cliquelist == NULL);
3664 
3665  /* clear the history of the variable */
3666  SCIPhistoryReset(var->history);
3668 
3669  /* convert variable into fixed variable */
3670  var->varstatus = SCIP_VARSTATUS_FIXED; /*lint !e641*/
3671 
3672  /* inform problem about the variable's status change */
3673  if( var->probindex != -1 )
3674  {
3675  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
3676  }
3677 
3678  /* reset the objective value of the fixed variable, thus adjusting the problem's objective offset */
3679  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventqueue, obj) );
3680 
3681  /* issue VARFIXED event */
3682  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 0) );
3683 
3684  *fixed = TRUE;
3685  break;
3686 
3687  case SCIP_VARSTATUS_COLUMN:
3688  SCIPerrorMessage("cannot fix a column variable\n");
3689  return SCIP_INVALIDDATA;
3690 
3691  case SCIP_VARSTATUS_FIXED:
3692  SCIPerrorMessage("cannot fix a fixed variable again\n"); /*lint !e527*/
3693  SCIPABORT(); /* case is already handled in earlier if condition */
3694  return SCIP_INVALIDDATA; /*lint !e527*/
3695 
3697  /* fix aggregation variable y in x = a*y + c, instead of fixing x directly */
3698  assert(SCIPsetIsZero(set, var->obj));
3699  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
3700  if( SCIPsetIsInfinity(set, fixedval) || SCIPsetIsInfinity(set, -fixedval) )
3701  childfixedval = (var->data.aggregate.scalar < 0.0 ? -fixedval : fixedval);
3702  else
3703  childfixedval = (fixedval - var->data.aggregate.constant)/var->data.aggregate.scalar;
3704  SCIP_CALL( SCIPvarFix(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
3705  branchcand, eventqueue, cliquetable, childfixedval, infeasible, fixed) );
3706  break;
3707 
3709  SCIPerrorMessage("cannot fix a multiple aggregated variable\n");
3710  SCIPABORT();
3711  return SCIP_INVALIDDATA; /*lint !e527*/
3712 
3714  /* fix negation variable x in x' = offset - x, instead of fixing x' directly */
3715  assert(SCIPsetIsZero(set, var->obj));
3716  assert(var->negatedvar != NULL);
3718  assert(var->negatedvar->negatedvar == var);
3719  SCIP_CALL( SCIPvarFix(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
3720  branchcand, eventqueue, cliquetable, var->data.negate.constant - fixedval, infeasible, fixed) );
3721  break;
3722 
3723  default:
3724  SCIPerrorMessage("unknown variable status\n");
3725  return SCIP_INVALIDDATA;
3726  }
3727 
3728  return SCIP_OKAY;
3729 }
3730 
3731 /** transforms given variables, scalars and constant to the corresponding active variables, scalars and constant
3732  *
3733  * If the number of needed active variables is greater than the available slots in the variable array, nothing happens except
3734  * that the required size is stored in the corresponding variable; hence, if afterwards the required size is greater than the
3735  * available slots (varssize), nothing happens; otherwise, the active variable representation is stored in the arrays.
3736  *
3737  * The reason for this approach is that we cannot reallocate memory, since we do not know how the
3738  * memory has been allocated (e.g., by a C++ 'new' or SCIP functions).
3739  */
3741  SCIP_SET* set, /**< global SCIP settings */
3742  SCIP_VAR** vars, /**< variable array to get active variables */
3743  SCIP_Real* scalars, /**< scalars a_1, ..., a_n in linear sum a_1*x_1 + ... + a_n*x_n + c */
3744  int* nvars, /**< pointer to number of variables and values in vars and scalars array */
3745  int varssize, /**< available slots in vars and scalars array */
3746  SCIP_Real* constant, /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c */
3747  int* requiredsize, /**< pointer to store the required array size for the active variables */
3748  SCIP_Bool mergemultiples /**< should multiple occurrences of a var be replaced by a single coeff? */
3749  )
3750 {
3751  SCIP_VAR** activevars;
3752  SCIP_Real* activescalars;
3753  int nactivevars;
3754  SCIP_Real activeconstant;
3755  SCIP_Bool activeconstantinf;
3756  int activevarssize;
3757 
3758  SCIP_VAR* var;
3759  SCIP_Real scalar;
3760  int v;
3761 
3762  SCIP_VAR** tmpvars;
3763  SCIP_VAR** multvars;
3764  SCIP_Real* tmpscalars;
3765  SCIP_Real* multscalars;
3766  int tmpvarssize;
3767  int ntmpvars;
3768  int nmultvars;
3769 
3770  SCIP_VAR* multvar;
3771  SCIP_Real multscalar;
3772  SCIP_Real multconstant;
3773  int pos;
3774 
3775  int noldtmpvars;
3776 
3777  SCIP_VAR** tmpvars2;
3778  SCIP_Real* tmpscalars2;
3779  int tmpvarssize2;
3780  int ntmpvars2;
3781 
3782  assert(set != NULL);
3783  assert(nvars != NULL);
3784  assert(scalars != NULL || *nvars == 0);
3785  assert(constant != NULL);
3786  assert(requiredsize != NULL);
3787  assert(*nvars <= varssize);
3788 
3789  *requiredsize = 0;
3790 
3791  if( *nvars == 0 )
3792  return SCIP_OKAY;
3793 
3794  assert(vars != NULL);
3795 
3796  /* handle the "easy" case of just one variable and avoid memory allocation if the variable is already active */
3797  if( *nvars == 1 && (vars[0]->varstatus == ((int) SCIP_VARSTATUS_COLUMN) || vars[0]->varstatus == ((int) SCIP_VARSTATUS_LOOSE)) )
3798  {
3799  *requiredsize = 1;
3800 
3801  return SCIP_OKAY;
3802  }
3803 
3804  nactivevars = 0;
3805  activeconstant = 0.0;
3806  activeconstantinf = FALSE;
3807  activevarssize = (*nvars) * 2;
3808  ntmpvars = *nvars;
3809  tmpvarssize = *nvars;
3810 
3811  tmpvarssize2 = 1;
3812 
3813  /* allocate temporary memory */
3814  SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpvars2, tmpvarssize2) );
3815  SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpscalars2, tmpvarssize2) );
3816  SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
3817  SCIP_CALL( SCIPsetAllocBufferArray(set, &activescalars, activevarssize) );
3818  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
3819  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpscalars, scalars, ntmpvars) );
3820 
3821  /* to avoid unnecessary expanding of variable arrays while disaggregating several variables multiple times combine same variables
3822  * first, first get all corresponding variables with status loose, column, multaggr or fixed
3823  */
3824  for( v = ntmpvars - 1; v >= 0; --v )
3825  {
3826  var = tmpvars[v];
3827  scalar = tmpscalars[v];
3828 
3829  assert(var != NULL);
3830  /* transforms given variable, scalar and constant to the corresponding active, fixed, or
3831  * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed
3832  * variable, "scalar" will be 0.0 and the value of the sum will be stored in "constant".
3833  */
3834  SCIP_CALL( SCIPvarGetProbvarSum(&var, set, &scalar, &activeconstant) );
3835  assert(var != NULL);
3836 
3837  assert(SCIPsetIsInfinity(set, activeconstant) == (activeconstant == SCIPsetInfinity(set))); /*lint !e777*/
3838  assert(SCIPsetIsInfinity(set, -activeconstant) == (activeconstant == -SCIPsetInfinity(set))); /*lint !e777*/
3839 
3840  activeconstantinf = SCIPsetIsInfinity(set, activeconstant) || SCIPsetIsInfinity(set, -activeconstant);
3841 
3842  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
3843  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
3846 
3847  tmpvars[v] = var;
3848  tmpscalars[v] = scalar;
3849  }
3850  noldtmpvars = ntmpvars;
3851 
3852  /* sort all variables to combine equal variables easily */
3853  SCIPsortPtrReal((void**)tmpvars, tmpscalars, SCIPvarComp, ntmpvars);
3854  for( v = ntmpvars - 1; v > 0; --v )
3855  {
3856  /* combine same variables */
3857  if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
3858  {
3859  tmpscalars[v - 1] += tmpscalars[v];
3860  --ntmpvars;
3861  tmpvars[v] = tmpvars[ntmpvars];
3862  tmpscalars[v] = tmpscalars[ntmpvars];
3863  }
3864  }
3865  /* sort all variables again to combine equal variables later on */
3866  if( noldtmpvars > ntmpvars )
3867  SCIPsortPtrReal((void**)tmpvars, tmpscalars, SCIPvarComp, ntmpvars);
3868 
3869  /* collect for each variable the representation in active variables */
3870  while( ntmpvars >= 1 )
3871  {
3872  --ntmpvars;
3873  ntmpvars2 = 0;
3874  var = tmpvars[ntmpvars];
3875  scalar = tmpscalars[ntmpvars];
3876 
3877  assert(var != NULL);
3878 
3879  /* TODO: maybe we should test here on SCIPsetIsZero() instead of 0.0 */
3880  if( scalar == 0.0 )
3881  continue;
3882 
3883  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
3884  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
3887 
3888  switch( SCIPvarGetStatus(var) )
3889  {
3890  case SCIP_VARSTATUS_LOOSE:
3891  case SCIP_VARSTATUS_COLUMN:
3892  /* x = a*y + c */
3893  if( nactivevars >= activevarssize )
3894  {
3895  activevarssize *= 2;
3896  SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
3897  SCIP_CALL( SCIPsetReallocBufferArray(set, &activescalars, activevarssize) );
3898  assert(nactivevars < activevarssize);
3899  }
3900  activevars[nactivevars] = var;
3901  activescalars[nactivevars] = scalar;
3902  nactivevars++;
3903  break;
3904 
3906  /* x = a_1*y_1 + ... + a_n*y_n + c */
3907  nmultvars = var->data.multaggr.nvars;
3908  multvars = var->data.multaggr.vars;
3909  multscalars = var->data.multaggr.scalars;
3910 
3911  if( nmultvars + ntmpvars > tmpvarssize )
3912  {
3913  while( nmultvars + ntmpvars > tmpvarssize )
3914  tmpvarssize *= 2;
3915  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
3916  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpscalars, tmpvarssize) );
3917  assert(nmultvars + ntmpvars <= tmpvarssize);
3918  }
3919 
3920  if( nmultvars > tmpvarssize2 )
3921  {
3922  while( nmultvars > tmpvarssize2 )
3923  tmpvarssize2 *= 2;
3924  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars2, tmpvarssize2) );
3925  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpscalars2, tmpvarssize2) );
3926  assert(nmultvars <= tmpvarssize2);
3927  }
3928 
3929  --nmultvars;
3930 
3931  for( ; nmultvars >= 0; --nmultvars )
3932  {
3933  multvar = multvars[nmultvars];
3934  multscalar = multscalars[nmultvars];
3935  multconstant = 0;
3936 
3937  assert(multvar != NULL);
3938  SCIP_CALL( SCIPvarGetProbvarSum(&multvar, set, &multscalar, &multconstant) );
3939  assert(multvar != NULL);
3940 
3941  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
3942  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
3945 
3946  if( !activeconstantinf )
3947  {
3948  assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
3949 
3950  if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) )
3951  {
3952  assert(scalar != 0.0);
3953  if( scalar * multconstant > 0.0 )
3954  {
3955  activeconstant = SCIPsetInfinity(set);
3956  activeconstantinf = TRUE;
3957  }
3958  else
3959  {
3960  activeconstant = -SCIPsetInfinity(set);
3961  activeconstantinf = TRUE;
3962  }
3963  }
3964  else
3965  activeconstant += scalar * multconstant;
3966  }
3967 #ifndef NDEBUG
3968  else
3969  {
3970  assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
3971  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
3972  assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
3973  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
3974  }
3975 #endif
3976 
3977  if( SCIPsortedvecFindPtr((void**)tmpvars, SCIPvarComp, multvar, ntmpvars, &pos) )
3978  {
3979  assert(SCIPvarCompare(tmpvars[pos], multvar) == 0);
3980  tmpscalars[pos] += scalar * multscalar;
3981  }
3982  else
3983  {
3984  tmpvars2[ntmpvars2] = multvar;
3985  tmpscalars2[ntmpvars2] = scalar * multscalar;
3986  ++(ntmpvars2);
3987  assert(ntmpvars2 <= tmpvarssize2);
3988  }
3989  }
3990 
3991  /* sort all variables to combine equal variables easily */
3992  SCIPsortPtrReal((void**)tmpvars2, tmpscalars2, SCIPvarComp, ntmpvars2);
3993  for( v = ntmpvars2 - 1; v > 0; --v )
3994  {
3995  /* combine same variables */
3996  if( SCIPvarCompare(tmpvars2[v], tmpvars2[v - 1]) == 0 )
3997  {
3998  tmpscalars2[v - 1] += tmpscalars2[v];
3999  --ntmpvars2;
4000  tmpvars2[v] = tmpvars2[ntmpvars2];
4001  tmpscalars2[v] = tmpscalars2[ntmpvars2];
4002  }
4003  }
4004 
4005  for( v = 0; v < ntmpvars2; ++v )
4006  {
4007  tmpvars[ntmpvars] = tmpvars2[v];
4008  tmpscalars[ntmpvars] = tmpscalars2[v];
4009  ++(ntmpvars);
4010  assert(ntmpvars <= tmpvarssize);
4011  }
4012  SCIPsortPtrReal((void**)tmpvars, tmpscalars, SCIPvarComp, ntmpvars);
4013 
4014  if( !activeconstantinf )
4015  {
4016  assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
4017 
4018  multconstant = SCIPvarGetMultaggrConstant(var);
4019 
4020  if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) )
4021  {
4022  assert(scalar != 0.0);
4023  if( scalar * multconstant > 0.0 )
4024  {
4025  activeconstant = SCIPsetInfinity(set);
4026  activeconstantinf = TRUE;
4027  }
4028  else
4029  {
4030  activeconstant = -SCIPsetInfinity(set);
4031  activeconstantinf = TRUE;
4032  }
4033  }
4034  else
4035  activeconstant += scalar * multconstant;
4036  }
4037 #ifndef NDEBUG
4038  else
4039  {
4040  multconstant = SCIPvarGetMultaggrConstant(var);
4041  assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
4042  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4043  assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
4044  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4045  }
4046 #endif
4047  break;
4048 
4049  case SCIP_VARSTATUS_FIXED:
4053  default:
4054  /* case x = c, but actually we should not be here, since SCIPvarGetProbvarSum() returns a scalar of 0.0 for
4055  * fixed variables and is handled already
4056  */
4057  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED);
4058  assert(SCIPsetIsZero(set, var->glbdom.lb) && SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub));
4059  }
4060  }
4061 
4062  if( mergemultiples )
4063  {
4064  /* sort variable and scalar array by variable index */
4065  SCIPsortPtrReal((void**)activevars, activescalars, SCIPvarComp, nactivevars);
4066 
4067  /* eliminate duplicates and count required size */
4068  v = nactivevars - 1;
4069  while( v > 0 )
4070  {
4071  /* combine both variable since they are the same */
4072  if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
4073  {
4074  if( activescalars[v - 1] + activescalars[v] != 0.0 )
4075  {
4076  activescalars[v - 1] += activescalars[v];
4077  --nactivevars;
4078  activevars[v] = activevars[nactivevars];
4079  activescalars[v] = activescalars[nactivevars];
4080  }
4081  else
4082  {
4083  --nactivevars;
4084  activevars[v] = activevars[nactivevars];
4085  activescalars[v] = activescalars[nactivevars];
4086  --nactivevars;
4087  --v;
4088  activevars[v] = activevars[nactivevars];
4089  activescalars[v] = activescalars[nactivevars];
4090  }
4091  }
4092  --v;
4093  }
4094  }
4095  *requiredsize = nactivevars;
4096 
4097  if( varssize >= *requiredsize )
4098  {
4099  assert(vars != NULL);
4100 
4101  *nvars = *requiredsize;
4102 
4103  if( !SCIPsetIsInfinity(set, *constant) && !SCIPsetIsInfinity(set, -(*constant)) )
4104  {
4105  /* if the activeconstant is infinite, the constant pointer gets the same value, otherwise add the value */
4106  if( activeconstantinf )
4107  (*constant) = activeconstant;
4108  else
4109  (*constant) += activeconstant;
4110  }
4111 #ifndef NDEBUG
4112  else
4113  {
4114  assert(!SCIPsetIsInfinity(set, (*constant)) || !SCIPsetIsInfinity(set, -activeconstant));
4115  assert(!SCIPsetIsInfinity(set, -(*constant)) || !SCIPsetIsInfinity(set, activeconstant));
4116  }
4117 #endif
4118 
4119  /* copy active variable and scalar array to the given arrays */
4120  for( v = 0; v < *nvars; ++v )
4121  {
4122  vars[v] = activevars[v];
4123  scalars[v] = activescalars[v]; /*lint !e613*/
4124  }
4125  }
4126 
4127  assert(SCIPsetIsInfinity(set, *constant) == ((*constant) == SCIPsetInfinity(set))); /*lint !e777*/
4128  assert(SCIPsetIsInfinity(set, -(*constant)) == ((*constant) == -SCIPsetInfinity(set))); /*lint !e777*/
4129 
4130  SCIPsetFreeBufferArray(set, &tmpscalars);
4131  SCIPsetFreeBufferArray(set, &tmpvars);
4132  SCIPsetFreeBufferArray(set, &activescalars);
4133  SCIPsetFreeBufferArray(set, &activevars);
4134  SCIPsetFreeBufferArray(set, &tmpscalars2);
4135  SCIPsetFreeBufferArray(set, &tmpvars2);
4136 
4137  return SCIP_OKAY;
4138 }
4139 
4140 
4141 /** flattens aggregation graph of multi-aggregated variable in order to avoid exponential recursion later on */
4143  SCIP_VAR* var, /**< problem variable */
4144  BMS_BLKMEM* blkmem, /**< block memory */
4145  SCIP_SET* set /**< global SCIP settings */
4146  )
4147 {
4148  SCIP_Real multconstant;
4149  int multvarssize;
4150  int nmultvars;
4151  int multrequiredsize;
4152 
4153  assert( var != NULL );
4154  assert( SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR );
4155  assert(var->scip == set->scip);
4156 
4157  multconstant = var->data.multaggr.constant;
4158  nmultvars = var->data.multaggr.nvars;
4159  multvarssize = var->data.multaggr.varssize;
4160 
4161  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize, TRUE) );
4162 
4163  if( multrequiredsize > multvarssize )
4164  {
4165  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.vars), multvarssize, multrequiredsize) );
4166  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.scalars), multvarssize, multrequiredsize) );
4167  multvarssize = multrequiredsize;
4168  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize, TRUE) );
4169  assert( multrequiredsize <= multvarssize );
4170  }
4171  /**@note After the flattening the multi aggregation might resolve to be in fact an aggregation (or even a fixing?).
4172  * This issue is not resolved right now, since var->data.multaggr.nvars < 2 should not cause troubles. However, one
4173  * may loose performance hereby, since aggregated variables are easier to handle.
4174  *
4175  * Note, that there are two cases where SCIPvarFlattenAggregationGraph() is called: The easier one is that it is
4176  * called while installing the multi-aggregation. in principle, the described issue could be handled straightforward
4177  * in this case by aggregating or fixing the variable instead. The more complicated case is the one, when the
4178  * multi-aggregation is used, e.g., in linear presolving (and the variable is already declared to be multi-aggregated).
4179  *
4180  * By now, it is not allowed to fix or aggregate multi-aggregated variables which would be necessary in this case.
4181  *
4182  * The same issue appears in the SCIPvarGetProbvar...() methods.
4183  */
4184 
4185  var->data.multaggr.constant = multconstant;
4186  var->data.multaggr.nvars = nmultvars;
4187  var->data.multaggr.varssize = multvarssize;
4188 
4189  return SCIP_OKAY;
4190 }
4191 
4192 /** merge two variable histories together; a typical use case is that \p othervar is an image of the target variable
4193  * in a SCIP copy. Method should be applied with care, especially because no internal checks are performed whether
4194  * the history merge is reasonable
4195  *
4196  * @note Do not use this method if the two variables originate from two SCIP's with different objective functions, since
4197  * this corrupts the variable pseudo costs
4198  * @note Apply with care; no internal checks are performed if the two variables should be merged
4199  */
4201  SCIP_VAR* targetvar, /**< the variable that should contain both histories afterwards */
4202  SCIP_VAR* othervar, /**< the variable whose history is to be merged with that of the target variable */
4203  SCIP_STAT* stat /**< problem statistics */
4204  )
4205 {
4206  /* merge only the history of the current run into the target history */
4207  SCIPhistoryUnite(targetvar->history, othervar->historycrun, FALSE);
4208 
4209  /* apply the changes also to the global history */
4210  SCIPhistoryUnite(stat->glbhistory, othervar->historycrun, FALSE);
4211 }
4212 
4213 /** sets the history of a variable; this method is typically used within reoptimization to keep and update the variable
4214  * history over several iterations
4215  */
4216 void SCIPvarSetHistory(
4217  SCIP_VAR* var, /**< variable */
4218  SCIP_HISTORY* history, /**< the history which is to set */
4219  SCIP_STAT* stat /**< problem statistics */
4220  )
4221 {
4222  /* merge only the history of the current run into the target history */
4223  SCIPhistoryUnite(var->history, history, FALSE);
4224 
4225  /* apply the changes also to the global history */
4226  SCIPhistoryUnite(stat->glbhistory, history, FALSE);
4227 }
4228 
4229 /** tightens the bounds of both variables in aggregation x = a*y + c */
4230 static
4232  SCIP_VAR* var, /**< problem variable */
4233  BMS_BLKMEM* blkmem, /**< block memory */
4234  SCIP_SET* set, /**< global SCIP settings */
4235  SCIP_STAT* stat, /**< problem statistics */
4236  SCIP_PROB* transprob, /**< tranformed problem data */
4237  SCIP_PROB* origprob, /**< original problem data */
4238  SCIP_PRIMAL* primal, /**< primal data */
4239  SCIP_TREE* tree, /**< branch and bound tree */
4240  SCIP_REOPT* reopt, /**< reoptimization data structure */
4241  SCIP_LP* lp, /**< current LP data */
4242  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4243  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4244  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4245  SCIP_VAR* aggvar, /**< variable y in aggregation x = a*y + c */
4246  SCIP_Real scalar, /**< multiplier a in aggregation x = a*y + c */
4247  SCIP_Real constant, /**< constant shift c in aggregation x = a*y + c */
4248  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4249  SCIP_Bool* fixed /**< pointer to store whether the variables were fixed */
4250  )
4251 {
4252  SCIP_Real varlb;
4253  SCIP_Real varub;
4254  SCIP_Real aggvarlb;
4255  SCIP_Real aggvarub;
4256  SCIP_Bool aggvarbdschanged;
4257 
4258  assert(var != NULL);
4259  assert(var->scip == set->scip);
4260  assert(aggvar != NULL);
4261  assert(!SCIPsetIsZero(set, scalar));
4262  assert(infeasible != NULL);
4263  assert(fixed != NULL);
4264 
4265  *infeasible = FALSE;
4266  *fixed = FALSE;
4267 
4268  SCIPsetDebugMsg(set, "updating bounds of variables in aggregation <%s> == %g*<%s> %+g\n", var->name, scalar, aggvar->name, constant);
4269  SCIPsetDebugMsg(set, " old bounds: <%s> [%g,%g] <%s> [%g,%g]\n",
4270  var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
4271 
4272  /* loop as long additional changes may be found */
4273  do
4274  {
4275  aggvarbdschanged = FALSE;
4276 
4277  /* update the bounds of the aggregated variable x in x = a*y + c */
4278  if( scalar > 0.0 )
4279  {
4280  if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
4281  varlb = -SCIPsetInfinity(set);
4282  else
4283  varlb = aggvar->glbdom.lb * scalar + constant;
4284  if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
4285  varub = SCIPsetInfinity(set);
4286  else
4287  varub = aggvar->glbdom.ub * scalar + constant;
4288  }
4289  else
4290  {
4291  if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
4292  varub = SCIPsetInfinity(set);
4293  else
4294  varub = aggvar->glbdom.lb * scalar + constant;
4295  if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
4296  varlb = -SCIPsetInfinity(set);
4297  else
4298  varlb = aggvar->glbdom.ub * scalar + constant;
4299  }
4300  varlb = MAX(varlb, var->glbdom.lb);
4301  varub = MIN(varub, var->glbdom.ub);
4302  SCIPvarAdjustLb(var, set, &varlb);
4303  SCIPvarAdjustUb(var, set, &varub);
4304 
4305  /* check the new bounds */
4306  if( SCIPsetIsGT(set, varlb, varub) )
4307  {
4308  /* the aggregation is infeasible */
4309  *infeasible = TRUE;
4310  return SCIP_OKAY;
4311  }
4312  else if( SCIPsetIsEQ(set, varlb, varub) )
4313  {
4314  /* the aggregated variable is fixed -> fix both variables */
4315  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4316  eventqueue, cliquetable, varlb, infeasible, fixed) );
4317  if( !(*infeasible) )
4318  {
4319  SCIP_Bool aggfixed;
4320 
4321  SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4322  eventqueue, cliquetable, (varlb-constant)/scalar, infeasible, &aggfixed) );
4323  assert(*fixed == aggfixed);
4324  }
4325  return SCIP_OKAY;
4326  }
4327  else
4328  {
4329  if( SCIPsetIsGT(set, varlb, var->glbdom.lb) )
4330  {
4331  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, varlb) );
4332  }
4333  if( SCIPsetIsLT(set, varub, var->glbdom.ub) )
4334  {
4335  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, varub) );
4336  }
4337 
4338  /* update the hole list of the aggregation variable */
4339  /**@todo update hole list of aggregation variable */
4340  }
4341 
4342  /* update the bounds of the aggregation variable y in x = a*y + c -> y = (x-c)/a */
4343  if( scalar > 0.0 )
4344  {
4345  if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
4346  aggvarlb = -SCIPsetInfinity(set);
4347  else
4348  aggvarlb = (var->glbdom.lb - constant) / scalar;
4349  if( SCIPsetIsInfinity(set, var->glbdom.ub) )
4350  aggvarub = SCIPsetInfinity(set);
4351  else
4352  aggvarub = (var->glbdom.ub - constant) / scalar;
4353  }
4354  else
4355  {
4356  if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
4357  aggvarub = SCIPsetInfinity(set);
4358  else
4359  aggvarub = (var->glbdom.lb - constant) / scalar;
4360  if( SCIPsetIsInfinity(set, var->glbdom.ub) )
4361  aggvarlb = -SCIPsetInfinity(set);
4362  else
4363  aggvarlb = (var->glbdom.ub - constant) / scalar;
4364  }
4365  aggvarlb = MAX(aggvarlb, aggvar->glbdom.lb);
4366  aggvarub = MIN(aggvarub, aggvar->glbdom.ub);
4367  SCIPvarAdjustLb(aggvar, set, &aggvarlb);
4368  SCIPvarAdjustUb(aggvar, set, &aggvarub);
4369 
4370  /* check the new bounds */
4371  if( SCIPsetIsGT(set, aggvarlb, aggvarub) )
4372  {
4373  /* the aggregation is infeasible */
4374  *infeasible = TRUE;
4375  return SCIP_OKAY;
4376  }
4377  else if( SCIPsetIsEQ(set, aggvarlb, aggvarub) )
4378  {
4379  /* the aggregation variable is fixed -> fix both variables */
4380  SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4381  eventqueue, cliquetable, aggvarlb, infeasible, fixed) );
4382  if( !(*infeasible) )
4383  {
4384  SCIP_Bool varfixed;
4385 
4386  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4387  eventqueue, cliquetable, aggvarlb * scalar + constant, infeasible, &varfixed) );
4388  assert(*fixed == varfixed);
4389  }
4390  return SCIP_OKAY;
4391  }
4392  else
4393  {
4394  SCIP_Real oldbd;
4395  if( SCIPsetIsGT(set, aggvarlb, aggvar->glbdom.lb) )
4396  {
4397  oldbd = aggvar->glbdom.lb;
4398  SCIP_CALL( SCIPvarChgLbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, aggvarlb) );
4399  aggvarbdschanged = !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.lb);
4400  }
4401  if( SCIPsetIsLT(set, aggvarub, aggvar->glbdom.ub) )
4402  {
4403  oldbd = aggvar->glbdom.ub;
4404  SCIP_CALL( SCIPvarChgUbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, aggvarub) );
4405  aggvarbdschanged = aggvarbdschanged || !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.ub);
4406  }
4407 
4408  /* update the hole list of the aggregation variable */
4409  /**@todo update hole list of aggregation variable */
4410  }
4411  }
4412  while( aggvarbdschanged );
4413 
4414  SCIPsetDebugMsg(set, " new bounds: <%s> [%g,%g] <%s> [%g,%g]\n",
4415  var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
4416 
4417  return SCIP_OKAY;
4418 }
4419 
4420 /** converts loose variable into aggregated variable */
4422  SCIP_VAR* var, /**< loose problem variable */
4423  BMS_BLKMEM* blkmem, /**< block memory */
4424  SCIP_SET* set, /**< global SCIP settings */
4425  SCIP_STAT* stat, /**< problem statistics */
4426  SCIP_PROB* transprob, /**< tranformed problem data */
4427  SCIP_PROB* origprob, /**< original problem data */
4428  SCIP_PRIMAL* primal, /**< primal data */
4429  SCIP_TREE* tree, /**< branch and bound tree */
4430  SCIP_REOPT* reopt, /**< reoptimization data structure */
4431  SCIP_LP* lp, /**< current LP data */
4432  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4433  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4434  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4435  SCIP_VAR* aggvar, /**< loose variable y in aggregation x = a*y + c */
4436  SCIP_Real scalar, /**< multiplier a in aggregation x = a*y + c */
4437  SCIP_Real constant, /**< constant shift c in aggregation x = a*y + c */
4438  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4439  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
4440  )
4441 {
4442  SCIP_VAR** vars;
4443  SCIP_Real* coefs;
4444  SCIP_Real* constants;
4445  SCIP_Real obj;
4446  SCIP_Real branchfactor;
4447  SCIP_Bool fixed;
4448  int branchpriority;
4449  int nlocksdown;
4450  int nlocksup;
4451  int nvbds;
4452  int i;
4453  int j;
4454 
4455  assert(var != NULL);
4456  assert(aggvar != NULL);
4457  assert(var->scip == set->scip);
4458  assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
4459  assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
4460  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
4461  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
4462  assert(infeasible != NULL);
4463  assert(aggregated != NULL);
4464 
4465  *infeasible = FALSE;
4466  *aggregated = FALSE;
4467 
4468  /* get active problem variable of aggregation variable */
4469  SCIP_CALL( SCIPvarGetProbvarSum(&aggvar, set, &scalar, &constant) );
4470 
4471  /* aggregation is a fixing, if the scalar is zero */
4472  if( SCIPsetIsZero(set, scalar) )
4473  {
4474  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue,
4475  cliquetable, constant, infeasible, aggregated) );
4476  return SCIP_OKAY;
4477  }
4478 
4479  /* don't perform the aggregation if the aggregation variable is multi-aggregated itself */
4480  if( SCIPvarGetStatus(aggvar) == SCIP_VARSTATUS_MULTAGGR )
4481  return SCIP_OKAY;
4482 
4483  /**@todo currently we don't perform the aggregation if the aggregation variable has a non-empty hole list; this
4484  * should be changed in the future
4485  */
4486  if( SCIPvarGetHolelistGlobal(var) != NULL )
4487  return SCIP_OKAY;
4488 
4489  assert(aggvar->glbdom.lb == aggvar->locdom.lb); /*lint !e777*/
4490  assert(aggvar->glbdom.ub == aggvar->locdom.ub); /*lint !e777*/
4491  assert(SCIPvarGetStatus(aggvar) == SCIP_VARSTATUS_LOOSE);
4492 
4493  SCIPsetDebugMsg(set, "aggregate variable <%s>[%g,%g] == %g*<%s>[%g,%g] %+g\n", var->name, var->glbdom.lb, var->glbdom.ub,
4494  scalar, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub, constant);
4495 
4496  /* if variable and aggregation variable are equal, the variable can be fixed: x == a*x + c => x == c/(1-a) */
4497  if( var == aggvar )
4498  {
4499  if( SCIPsetIsEQ(set, scalar, 1.0) )
4500  *infeasible = !SCIPsetIsZero(set, constant);
4501  else
4502  {
4503  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4504  eventqueue, cliquetable, constant/(1.0-scalar), infeasible, aggregated) );
4505  }
4506  return SCIP_OKAY;
4507  }
4508 
4509  /* tighten the bounds of aggregated and aggregation variable */
4510  SCIP_CALL( varUpdateAggregationBounds(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
4511  branchcand, eventqueue, cliquetable, aggvar, scalar, constant, infeasible, &fixed) );
4512  if( *infeasible || fixed )
4513  {
4514  *aggregated = fixed;
4515  return SCIP_OKAY;
4516  }
4517 
4518  /* delete implications and variable bounds of the aggregated variable from other variables, but keep them in the
4519  * aggregated variable
4520  */
4521  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, FALSE) );
4522  assert(var->cliquelist == NULL);
4523 
4524  /* set the aggregated variable's objective value to 0.0 */
4525  obj = var->obj;
4526  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
4527 
4528  /* unlock all rounding locks */
4529  nlocksdown = var->nlocksdown;
4530  nlocksup = var->nlocksup;
4531  var->nlocksdown = 0;
4532  var->nlocksup = 0;
4533 
4534  /* check, if variable should be used as NEGATED variable of the aggregation variable */
4535  if( SCIPvarIsBinary(var) && SCIPvarIsBinary(aggvar)
4536  && var->negatedvar == NULL && aggvar->negatedvar == NULL
4537  && SCIPsetIsEQ(set, scalar, -1.0) && SCIPsetIsEQ(set, constant, 1.0) )
4538  {
4539  /* link both variables as negation pair */
4540  var->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
4541  var->data.negate.constant = 1.0;
4542  var->negatedvar = aggvar;
4543  aggvar->negatedvar = var;
4544 
4545  /* copy doNotMultiaggr status */
4546  aggvar->donotmultaggr |= var->donotmultaggr;
4547 
4548  /* mark both variables to be non-deletable */
4550  SCIPvarMarkNotDeletable(aggvar);
4551  }
4552  else
4553  {
4554  /* convert variable into aggregated variable */
4555  var->varstatus = SCIP_VARSTATUS_AGGREGATED; /*lint !e641*/
4556  var->data.aggregate.var = aggvar;
4557  var->data.aggregate.scalar = scalar;
4558  var->data.aggregate.constant = constant;
4559 
4560  /* copy doNotMultiaggr status */
4561  aggvar->donotmultaggr |= var->donotmultaggr;
4562 
4563  /* mark both variables to be non-deletable */
4565  SCIPvarMarkNotDeletable(aggvar);
4566  }
4567 
4568  /* make aggregated variable a parent of the aggregation variable */
4569  SCIP_CALL( varAddParent(aggvar, blkmem, set, var) );
4570 
4571  /* relock the rounding locks of the variable, thus increasing the locks of the aggregation variable */
4572  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, nlocksdown, nlocksup) );
4573 
4574  /* move the variable bounds to the aggregation variable:
4575  * - add all variable bounds again to the variable, thus adding it to the aggregation variable
4576  * - free the variable bounds data structures
4577  */
4578  if( var->vlbs != NULL )
4579  {
4580  nvbds = SCIPvboundsGetNVbds(var->vlbs);
4581  vars = SCIPvboundsGetVars(var->vlbs);
4582  coefs = SCIPvboundsGetCoefs(var->vlbs);
4583  constants = SCIPvboundsGetConstants(var->vlbs);
4584  for( i = 0; i < nvbds && !(*infeasible); ++i )
4585  {
4586  SCIP_CALL( SCIPvarAddVlb(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
4587  eventqueue, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
4588  }
4589  }
4590  if( var->vubs != NULL )
4591  {
4592  nvbds = SCIPvboundsGetNVbds(var->vubs);
4593  vars = SCIPvboundsGetVars(var->vubs);
4594  coefs = SCIPvboundsGetCoefs(var->vubs);
4595  constants = SCIPvboundsGetConstants(var->vubs);
4596  for( i = 0; i < nvbds && !(*infeasible); ++i )
4597  {
4598  SCIP_CALL( SCIPvarAddVub(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
4599  eventqueue, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
4600  }
4601  }
4602  SCIPvboundsFree(&var->vlbs, blkmem);
4603  SCIPvboundsFree(&var->vubs, blkmem);
4604 
4605  /* move the implications to the aggregation variable:
4606  * - add all implications again to the variable, thus adding it to the aggregation variable
4607  * - free the implications data structures
4608  */
4609  if( var->implics != NULL && SCIPvarGetType(aggvar) == SCIP_VARTYPE_BINARY )
4610  {
4611  assert(SCIPvarIsBinary(var));
4612  for( i = 0; i < 2; ++i )
4613  {
4614  SCIP_VAR** implvars;
4615  SCIP_BOUNDTYPE* impltypes;
4616  SCIP_Real* implbounds;
4617  int nimpls;
4618 
4619  nimpls = SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i);
4620  implvars = SCIPimplicsGetVars(var->implics, (SCIP_Bool)i);
4621  impltypes = SCIPimplicsGetTypes(var->implics, (SCIP_Bool)i);
4622  implbounds = SCIPimplicsGetBounds(var->implics, (SCIP_Bool)i);
4623 
4624  for( j = 0; j < nimpls && !(*infeasible); ++j )
4625  {
4626  /* @todo can't we omit transitive closure, because it should already have been done when adding the
4627  * implication to the aggregated variable?
4628  */
4629  SCIP_CALL( SCIPvarAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
4630  branchcand, eventqueue, (SCIP_Bool)i, implvars[j], impltypes[j], implbounds[j], FALSE, infeasible,
4631  NULL) );
4632  assert(nimpls == SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i));
4633  }
4634  }
4635  }
4636  SCIPimplicsFree(&var->implics, blkmem);
4637 
4638  /* add the history entries to the aggregation variable and clear the history of the aggregated variable */
4639  SCIPhistoryUnite(aggvar->history, var->history, scalar < 0.0);
4640  SCIPhistoryUnite(aggvar->historycrun, var->historycrun, scalar < 0.0);
4641  SCIPhistoryReset(var->history);
4643 
4644  /* update flags of aggregation variable */
4645  aggvar->removable &= var->removable;
4646 
4647  /* update branching factors and priorities of both variables to be the maximum of both variables */
4648  branchfactor = MAX(aggvar->branchfactor, var->branchfactor);
4649  branchpriority = MAX(aggvar->branchpriority, var->branchpriority);
4650  SCIP_CALL( SCIPvarChgBranchFactor(aggvar, set, branchfactor) );
4651  SCIP_CALL( SCIPvarChgBranchPriority(aggvar, branchpriority) );
4652  SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
4653  SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
4654 
4655  /* update branching direction of both variables to agree to a single direction */
4656  if( scalar >= 0.0 )
4657  {
4659  {
4661  }
4662  else if( (SCIP_BRANCHDIR)aggvar->branchdirection == SCIP_BRANCHDIR_AUTO )
4663  {
4665  }
4666  else if( var->branchdirection != aggvar->branchdirection )
4667  {
4669  }
4670  }
4671  else
4672  {
4674  {
4676  }
4677  else if( (SCIP_BRANCHDIR)aggvar->branchdirection == SCIP_BRANCHDIR_AUTO )
4678  {
4680  }
4681  else if( var->branchdirection != aggvar->branchdirection )
4682  {
4684  }
4685  }
4686 
4687  if( var->probindex != -1 )
4688  {
4689  /* inform problem about the variable's status change */
4690  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
4691  }
4692 
4693  /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
4694  * variable and the problem's objective offset
4695  */
4696  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventqueue, obj) );
4697 
4698  /* issue VARFIXED event */
4699  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 1) );
4700 
4701  *aggregated = TRUE;
4702 
4703  return SCIP_OKAY;
4704 }
4705 
4706 /** Tries to aggregate an equality a*x + b*y == c consisting of two (implicit) integral active problem variables x and
4707  * y. An integer aggregation (i.e. integral coefficients a' and b', such that a'*x + b'*y == c') is searched.
4708  *
4709  * This can lead to the detection of infeasibility (e.g. if c' is fractional), or to a rejection of the aggregation
4710  * (denoted by aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
4711  */
4712 static
4714  SCIP_SET* set, /**< global SCIP settings */
4715  BMS_BLKMEM* blkmem, /**< block memory */
4716  SCIP_STAT* stat, /**< problem statistics */
4717  SCIP_PROB* transprob, /**< tranformed problem data */
4718  SCIP_PROB* origprob, /**< original problem data */
4719  SCIP_PRIMAL* primal, /**< primal data */
4720  SCIP_TREE* tree, /**< branch and bound tree */
4721  SCIP_REOPT* reopt, /**< reoptimization data structure */
4722  SCIP_LP* lp, /**< current LP data */
4723  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4724  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4725  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4726  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4727  SCIP_VAR* varx, /**< integral variable x in equality a*x + b*y == c */
4728  SCIP_VAR* vary, /**< integral variable y in equality a*x + b*y == c */
4729  SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
4730  SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
4731  SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
4732  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4733  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
4734  )
4735 {
4736  SCIP_VAR* aggvar;
4737  char aggvarname[SCIP_MAXSTRLEN];
4738  SCIP_Longint scalarxn = 0;
4739  SCIP_Longint scalarxd = 0;
4740  SCIP_Longint scalaryn = 0;
4741  SCIP_Longint scalaryd = 0;
4742  SCIP_Longint a;
4743  SCIP_Longint b;
4744  SCIP_Longint c;
4745  SCIP_Longint scm;
4746  SCIP_Longint gcd;
4747  SCIP_Longint currentclass;
4748  SCIP_Longint classstep;
4749  SCIP_Longint xsol;
4750  SCIP_Longint ysol;
4751  SCIP_Bool success;
4752  SCIP_VARTYPE vartype;
4753 
4754 #define MAXDNOM 1000000LL
4755 
4756  assert(set != NULL);
4757  assert(blkmem != NULL);
4758  assert(stat != NULL);
4759  assert(transprob != NULL);
4760  assert(origprob != NULL);
4761  assert(tree != NULL);
4762  assert(lp != NULL);
4763  assert(cliquetable != NULL);
4764  assert(branchcand != NULL);
4765  assert(eventqueue != NULL);
4766  assert(varx != NULL);
4767  assert(vary != NULL);
4768  assert(varx != vary);
4769  assert(infeasible != NULL);
4770  assert(aggregated != NULL);
4771  assert(SCIPsetGetStage(set) == SCIP_STAGE_PRESOLVING);
4772  assert(SCIPvarGetStatus(varx) == SCIP_VARSTATUS_LOOSE);
4774  assert(SCIPvarGetStatus(vary) == SCIP_VARSTATUS_LOOSE);
4776  assert(!SCIPsetIsZero(set, scalarx));
4777  assert(!SCIPsetIsZero(set, scalary));
4778 
4779  *infeasible = FALSE;
4780  *aggregated = FALSE;
4781 
4782  /* get rational representation of coefficients */
4783  success = SCIPrealToRational(scalarx, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalarxn, &scalarxd);
4784  if( success )
4785  success = SCIPrealToRational(scalary, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalaryn, &scalaryd);
4786  if( !success )
4787  return SCIP_OKAY;
4788  assert(scalarxd >= 1);
4789  assert(scalaryd >= 1);
4790 
4791  /* multiply equality with smallest common denominator */
4792  scm = SCIPcalcSmaComMul(scalarxd, scalaryd);
4793  a = (scm/scalarxd)*scalarxn;
4794  b = (scm/scalaryd)*scalaryn;
4795  rhs *= scm;
4796 
4797  /* divide equality by the greatest common divisor of a and b */
4798  gcd = SCIPcalcGreComDiv(ABS(a), ABS(b));
4799  a /= gcd;
4800  b /= gcd;
4801  rhs /= gcd;
4802  assert(a != 0);
4803  assert(b != 0);
4804 
4805  /* check, if right hand side is integral */
4806  if( !SCIPsetIsFeasIntegral(set, rhs) )
4807  {
4808  *infeasible = TRUE;
4809  return SCIP_OKAY;
4810  }
4811  c = (SCIP_Longint)(SCIPsetFeasFloor(set, rhs));
4812 
4813  /* check, if we are in an easy case with either |a| = 1 or |b| = 1 */
4814  if( (a == 1 || a == -1) && SCIPvarGetType(vary) == SCIP_VARTYPE_INTEGER )
4815  {
4816  /* aggregate x = - b/a*y + c/a */
4817  /*lint --e{653}*/
4818  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
4819  branchcand, eventqueue, vary, (SCIP_Real)(-b/a), (SCIP_Real)(c/a), infeasible, aggregated) );
4820  assert(*aggregated);
4821  return SCIP_OKAY;
4822  }
4823  if( (b == 1 || b == -1) && SCIPvarGetType(varx) == SCIP_VARTYPE_INTEGER )
4824  {
4825  /* aggregate y = - a/b*x + c/b */
4826  /*lint --e{653}*/
4827  SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
4828  branchcand, eventqueue, varx, (SCIP_Real)(-a/b), (SCIP_Real)(c/b), infeasible, aggregated) );
4829  assert(*aggregated);
4830  return SCIP_OKAY;
4831  }
4832 
4833  /* Both variables are integers, their coefficients are not multiples of each other, and they don't have any
4834  * common divisor. Let (x',y') be a solution of the equality
4835  * a*x + b*y == c -> a*x == c - b*y
4836  * Then x = -b*z + x', y = a*z + y' with z integral gives all solutions to the equality.
4837  */
4838 
4839  /* find initial solution (x',y'):
4840  * - find y' such that c - b*y' is a multiple of a
4841  * - start in equivalence class c%a
4842  * - step through classes, where each step increases class number by (-b)%a, until class 0 is visited
4843  * - if equivalence class 0 is visited, we are done: y' equals the number of steps taken
4844  * - because a and b don't have a common divisor, each class is visited at most once, and at most a-1 steps are needed
4845  * - calculate x' with x' = (c - b*y')/a (which must be integral)
4846  *
4847  * Algorithm works for a > 0 only.
4848  */
4849  if( a < 0 )
4850  {
4851  a = -a;
4852  b = -b;
4853  c = -c;
4854  }
4855  assert(0 <= a);
4856 
4857  /* search upwards from ysol = 0 */
4858  ysol = 0;
4859  currentclass = c%a;
4860  if( currentclass < 0 )
4861  currentclass += a;
4862  assert(0 <= currentclass && currentclass < a);
4863 
4864  classstep = (-b)%a;
4865 
4866  if( classstep < 0 )
4867  classstep += a;
4868  assert(0 <= classstep && classstep < a);
4869 
4870  while( currentclass != 0 )
4871  {
4872  assert(0 <= currentclass && currentclass < a);
4873  currentclass += classstep;
4874  if( currentclass >= a )
4875  currentclass -= a;
4876  ysol++;
4877  }
4878  assert(ysol < a);
4879  assert(((c - b*ysol)%a) == 0);
4880 
4881  xsol = (c - b*ysol)/a;
4882 
4883  /* determine variable type for new artificial variable:
4884  *
4885  * if both variables are implicit integer the new variable can be implicit too, because the integer implication on
4886  * these both variables should be enforced by some other variables, otherwise the new variable needs to be of
4887  * integral type
4888  */
4891 
4892  /* feasible solutions are (x,y) = (x',y') + z*(-b,a)
4893  * - create new integer variable z with infinite bounds
4894  * - aggregate variable x = -b*z + x'
4895  * - aggregate variable y = a*z + y'
4896  * - the bounds of z are calculated automatically during aggregation
4897  */
4898  (void) SCIPsnprintf(aggvarname, SCIP_MAXSTRLEN, "agg%d", stat->nvaridx);
4899  SCIP_CALL( SCIPvarCreateTransformed(&aggvar, blkmem, set, stat,
4900  aggvarname, -SCIPsetInfinity(set), SCIPsetInfinity(set), 0.0, vartype,
4902  NULL, NULL, NULL, NULL, NULL) );
4903 
4904  SCIP_CALL( SCIPprobAddVar(transprob, blkmem, set, lp, branchcand, eventfilter, eventqueue, aggvar) );
4905 
4906  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
4907  branchcand, eventqueue, aggvar, (SCIP_Real)(-b), (SCIP_Real)xsol, infeasible, aggregated) );
4908  assert(*aggregated || *infeasible);
4909 
4910  if( !(*infeasible) )
4911  {
4912  SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
4913  branchcand, eventqueue, aggvar, (SCIP_Real)a, (SCIP_Real)ysol, infeasible, aggregated) );
4914  assert(*aggregated || *infeasible);
4915  }
4916 
4917  /* release z */
4918  SCIP_CALL( SCIPvarRelease(&aggvar, blkmem, set, eventqueue, lp) );
4919 
4920  return SCIP_OKAY;
4921 }
4922 
4923 /** performs second step of SCIPaggregateVars():
4924  * the variable to be aggregated is chosen among active problem variables x' and y', preferring a less strict variable
4925  * type as aggregation variable (i.e. continuous variables are preferred over implicit integers, implicit integers
4926  * or integers over binaries). If none of the variables is continuous, it is tried to find an integer
4927  * aggregation (i.e. integral coefficients a'' and b'', such that a''*x' + b''*y' == c''). This can lead to
4928  * the detection of infeasibility (e.g. if c'' is fractional), or to a rejection of the aggregation (denoted by
4929  * aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
4930  *
4931  * @todo check for fixings, infeasibility, bound changes, or domain holes:
4932  * a) if there is no easy aggregation and we have one binary variable and another integer/implicit/binary variable
4933  * b) for implicit integer variables with fractional aggregation scalar (we cannot (for technical reasons) and do
4934  * not want to aggregate implicit integer variables, since we loose the corresponding divisibility property)
4935  */
4937  SCIP_SET* set, /**< global SCIP settings */
4938  BMS_BLKMEM* blkmem, /**< block memory */
4939  SCIP_STAT* stat, /**< problem statistics */
4940  SCIP_PROB* transprob, /**< tranformed problem data */
4941  SCIP_PROB* origprob, /**< original problem data */
4942  SCIP_PRIMAL* primal, /**< primal data */
4943  SCIP_TREE* tree, /**< branch and bound tree */
4944  SCIP_REOPT* reopt, /**< reoptimization data structure */
4945  SCIP_LP* lp, /**< current LP data */
4946  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4947  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4948  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4949  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4950  SCIP_VAR* varx, /**< variable x in equality a*x + b*y == c */
4951  SCIP_VAR* vary, /**< variable y in equality a*x + b*y == c */
4952  SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
4953  SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
4954  SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
4955  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4956  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
4957  )
4958 {
4959  SCIP_Bool easyaggr;
4960  SCIP_Real maxscalar;
4961  SCIP_Real absquot;
4962 
4963  assert(set != NULL);
4964  assert(blkmem != NULL);
4965  assert(stat != NULL);
4966  assert(transprob != NULL);
4967  assert(origprob != NULL);
4968  assert(tree != NULL);
4969  assert(lp != NULL);
4970  assert(cliquetable != NULL);
4971  assert(branchcand != NULL);
4972  assert(eventqueue != NULL);
4973  assert(varx != NULL);
4974  assert(vary != NULL);
4975  assert(varx != vary);
4976  assert(infeasible != NULL);
4977  assert(aggregated != NULL);
4978  assert(SCIPsetGetStage(set) == SCIP_STAGE_PRESOLVING);
4979  assert(SCIPvarGetStatus(varx) == SCIP_VARSTATUS_LOOSE);
4980  assert(SCIPvarGetStatus(vary) == SCIP_VARSTATUS_LOOSE);
4981  assert(!SCIPsetIsZero(set, scalarx));
4982  assert(!SCIPsetIsZero(set, scalary));
4983 
4984  *infeasible = FALSE;
4985  *aggregated = FALSE;
4986 
4987  absquot = REALABS(scalarx / scalary);
4988  maxscalar = SCIPsetFeastol(set) / SCIPsetEpsilon(set);
4989  maxscalar = MAX(maxscalar, 1.0);
4990 
4991  if( absquot > maxscalar || absquot < 1 / maxscalar )
4992  return SCIP_OKAY;
4993 
4994  /* prefer aggregating the variable of more general type (preferred aggregation variable is varx) */
4995  if( SCIPvarGetType(vary) > SCIPvarGetType(varx) ||
4996  (SCIPvarGetType(vary) == SCIPvarGetType(varx) && !SCIPvarIsBinary(vary) && SCIPvarIsBinary(varx)) )
4997  {
4998  SCIP_VAR* var;
4999  SCIP_Real scalar;
5000 
5001  /* switch the variables, such that varx is the variable of more general type (cont > implint > int > bin) */
5002  var = vary;
5003  vary = varx;
5004  varx = var;
5005  scalar = scalary;
5006  scalary = scalarx;
5007  scalarx = scalar;
5008  }
5009 
5010  /* don't aggregate if the aggregation would lead to a binary variable aggregated to a non-binary variable */
5011  if( SCIPvarIsBinary(varx) && !SCIPvarIsBinary(vary) )
5012  return SCIP_OKAY;
5013 
5014  assert(SCIPvarGetType(varx) >= SCIPvarGetType(vary));
5015 
5016  /* figure out, which variable should be aggregated */
5017  easyaggr = FALSE;
5018 
5019  /* check if it is an easy aggregation that means:
5020  *
5021  * a*x + b*y == c -> x == -b/a * y + c/a iff |b/a| > feastol and |a/b| > feastol
5022  */
5023  if( !SCIPsetIsFeasZero(set, scalary/scalarx) && !SCIPsetIsFeasZero(set, scalarx/scalary) )
5024  {
5026  {
5027  easyaggr = TRUE;
5028  }
5029  else if( SCIPsetIsFeasIntegral(set, scalary/scalarx) )
5030  {
5031  easyaggr = TRUE;
5032  }
5033  else if( SCIPsetIsFeasIntegral(set, scalarx/scalary) && SCIPvarGetType(vary) == SCIPvarGetType(varx) )
5034  {
5035  /* we have an easy aggregation if we flip the variables x and y */
5036  SCIP_VAR* var;
5037  SCIP_Real scalar;
5038 
5039  /* switch the variables, such that varx is the aggregated variable */
5040  var = vary;
5041  vary = varx;
5042  varx = var;
5043  scalar = scalary;
5044  scalary = scalarx;
5045  scalarx = scalar;
5046  easyaggr = TRUE;
5047  }
5048  else if( SCIPvarGetType(varx) == SCIP_VARTYPE_CONTINUOUS )
5049  {
5050  /* the aggregation is still easy if both variables are continuous */
5051  assert(SCIPvarGetType(vary) == SCIP_VARTYPE_CONTINUOUS); /* otherwise we are in the first case */
5052  easyaggr = TRUE;
5053  }
5054  }
5055 
5056  /* did we find an "easy" aggregation? */
5057  if( easyaggr )
5058  {
5059  SCIP_Real scalar;
5060  SCIP_Real constant;
5061 
5062  assert(SCIPvarGetType(varx) >= SCIPvarGetType(vary));
5063 
5064  /* calculate aggregation scalar and constant: a*x + b*y == c => x == -b/a * y + c/a */
5065  scalar = -scalary/scalarx;
5066  constant = rhs/scalarx;
5067 
5068  /* check aggregation for integer feasibility */
5071  && SCIPsetIsFeasIntegral(set, scalar) && !SCIPsetIsFeasIntegral(set, constant) )
5072  {
5073  *infeasible = TRUE;
5074  return SCIP_OKAY;
5075  }
5076 
5077  /* if the aggregation scalar is fractional, we cannot (for technical reasons) and do not want to aggregate implicit integer variables,
5078  * since then we would loose the corresponding divisibility property
5079  */
5080  assert(SCIPvarGetType(varx) != SCIP_VARTYPE_IMPLINT || SCIPsetIsFeasIntegral(set, scalar));
5081 
5082  /* aggregate the variable */
5083  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5084  branchcand, eventqueue, vary, scalar, constant, infeasible, aggregated) );
5085  assert(*aggregated || *infeasible);
5086  }
5089  {
5090  /* the variables are both integral: we have to try to find an integer aggregation */
5091  SCIP_CALL( tryAggregateIntVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5092  branchcand, eventfilter, eventqueue, varx, vary, scalarx, scalary, rhs, infeasible, aggregated) );
5093  }
5094 
5095  return SCIP_OKAY;
5096 }
5097 
5098 /** converts variable into multi-aggregated variable */
5100  SCIP_VAR* var, /**< problem variable */
5101  BMS_BLKMEM* blkmem, /**< block memory */
5102  SCIP_SET* set, /**< global SCIP settings */
5103  SCIP_STAT* stat, /**< problem statistics */
5104  SCIP_PROB* transprob, /**< tranformed problem data */
5105  SCIP_PROB* origprob, /**< original problem data */
5106  SCIP_PRIMAL* primal, /**< primal data */
5107  SCIP_TREE* tree, /**< branch and bound tree */
5108  SCIP_REOPT* reopt, /**< reoptimization data structure */
5109  SCIP_LP* lp, /**< current LP data */
5110  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5111  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5112  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
5113  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5114  int naggvars, /**< number n of variables in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5115  SCIP_VAR** aggvars, /**< variables y_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5116  SCIP_Real* scalars, /**< multipliers a_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5117  SCIP_Real constant, /**< constant shift c in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5118  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
5119  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
5120  )
5121 {
5122  SCIP_VAR** tmpvars;
5123  SCIP_Real* tmpscalars;
5124  SCIP_Real obj;
5125  SCIP_Real branchfactor;
5126  int branchpriority;
5127  SCIP_BRANCHDIR branchdirection;
5128  int nlocksdown;
5129  int nlocksup;
5130  int v;
5131  SCIP_Real tmpconstant;
5132  SCIP_Real tmpscalar;
5133  int ntmpvars;
5134  int tmpvarssize;
5135  int tmprequiredsize;
5136 
5137  assert(var != NULL);
5138  assert(var->scip == set->scip);
5139  assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
5140  assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
5141  assert(naggvars == 0 || aggvars != NULL);
5142  assert(naggvars == 0 || scalars != NULL);
5143  assert(infeasible != NULL);
5144  assert(aggregated != NULL);
5145 
5146  SCIPsetDebugMsg(set, "trying multi-aggregating variable <%s> == ...%d vars... %+g\n", var->name, naggvars, constant);
5147 
5148  *infeasible = FALSE;
5149  *aggregated = FALSE;
5150 
5151  switch( SCIPvarGetStatus(var) )
5152  {
5154  if( var->data.original.transvar == NULL )
5155  {
5156  SCIPerrorMessage("cannot multi-aggregate an untransformed original variable\n");
5157  return SCIP_INVALIDDATA;
5158  }
5159  SCIP_CALL( SCIPvarMultiaggregate(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
5160  reopt, lp, cliquetable, branchcand, eventfilter, eventqueue, naggvars, aggvars, scalars, constant, infeasible, aggregated) );
5161  break;
5162 
5163  case SCIP_VARSTATUS_LOOSE:
5164  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
5165 
5166  /* check if we would create a self-reference */
5167  ntmpvars = naggvars;
5168  tmpvarssize = naggvars;
5169  tmpconstant = constant;
5170  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpvars, aggvars, ntmpvars) );
5171  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpscalars, scalars, ntmpvars) );
5172 
5173  /* get all active variables for multi-aggregation */
5174  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize, FALSE) );
5175  if( tmprequiredsize > tmpvarssize )
5176  {
5177  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpvars, tmpvarssize, tmprequiredsize) );
5178  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize, tmprequiredsize) );
5179  tmpvarssize = tmprequiredsize;
5180  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize, FALSE) );
5181  assert( tmprequiredsize <= tmpvarssize );
5182  }
5183 
5184  tmpscalar = 0.0;
5185 
5186  /* iterate over all active variables of the multi-aggregation and filter all variables which are equal to the
5187  * possible multi-aggregated variable
5188  */
5189  for( v = ntmpvars - 1; v >= 0; --v )
5190  {
5191  assert(tmpvars[v] != NULL);
5192  assert(SCIPvarGetStatus(tmpvars[v]) == SCIP_VARSTATUS_LOOSE);
5193 
5194  if( tmpvars[v]->index == var->index )
5195  {
5196  tmpscalar += tmpscalars[v];
5197  tmpvars[v] = tmpvars[ntmpvars - 1];
5198  tmpscalars[v] = tmpscalars[ntmpvars - 1];
5199  --ntmpvars;
5200  }
5201  }
5202 
5203  /* this means that x = x + a_1*y_1 + ... + a_n*y_n + c */
5204  if( SCIPsetIsEQ(set, tmpscalar, 1.0) )
5205  {
5206  if( ntmpvars == 0 )
5207  {
5208  if( SCIPsetIsZero(set, tmpconstant) ) /* x = x */
5209  {
5210  SCIPsetDebugMsg(set, "Possible multi-aggregation was completely resolved and detected to be redundant.\n");
5211  goto TERMINATE;
5212  }
5213  else /* 0 = c and c != 0 */
5214  {
5215  SCIPsetDebugMsg(set, "Multi-aggregation was completely resolved and led to infeasibility.\n");
5216  *infeasible = TRUE;
5217  goto TERMINATE;
5218  }
5219  }
5220  else if( ntmpvars == 1 ) /* 0 = a*y + c => y = -c/a */
5221  {
5222  assert(tmpscalars[0] != 0.0);
5223  assert(tmpvars[0] != NULL);
5224 
5225  SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(tmpvars[0]), -constant/tmpscalars[0]);
5226  SCIP_CALL( SCIPvarFix(tmpvars[0], blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5227  branchcand, eventqueue, cliquetable, -constant/tmpscalars[0], infeasible, aggregated) );
5228  goto TERMINATE;
5229  }
5230  else if( ntmpvars == 2 ) /* 0 = a_1*y_1 + a_2*y_2 + c => y_1 = -a_2/a_1 * y_2 - c/a_1 */
5231  {
5232  /* both variables are different active problem variables, and both scalars are non-zero: try to aggregate them */
5233 
5234  SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
5235  SCIPvarGetName(tmpvars[0]), SCIPvarGetName(tmpvars[1]), tmpscalars[0], tmpscalars[1], -tmpconstant);
5236 
5237  SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
5238  cliquetable, branchcand, eventfilter, eventqueue, tmpvars[0], tmpvars[1], tmpscalars[0],
5239  tmpscalars[1], -tmpconstant, infeasible, aggregated) );
5240 
5241  goto TERMINATE;
5242  }
5243  else
5244  /* @todo: it is possible to multi-aggregate another variable, does it make sense?,
5245  * rest looks like 0 = a_1*y_1 + ... + a_n*y_n + c and has at least three variables
5246  */
5247  goto TERMINATE;
5248  }
5249  /* this means that x = b*x + a_1*y_1 + ... + a_n*y_n + c */
5250  else if( !SCIPsetIsZero(set, tmpscalar) )
5251  {
5252  tmpscalar = 1 - tmpscalar;
5253  tmpconstant /= tmpscalar;
5254  for( v = ntmpvars - 1; v >= 0; --v )
5255  tmpscalars[v] /= tmpscalar;
5256  }
5257 
5258  /* check, if we are in one of the simple cases */
5259  if( ntmpvars == 0 )
5260  {
5261  SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(var), tmpconstant);
5262  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
5263  eventqueue, cliquetable, tmpconstant, infeasible, aggregated) );
5264  goto TERMINATE;
5265  }
5266 
5267  /* if only one aggregation variable is left, we perform a normal aggregation instead of a multi-aggregation */
5268  if( ntmpvars == 1 )
5269  {
5270  SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
5271  SCIPvarGetName(var), SCIPvarGetName(tmpvars[0]), 1.0, -tmpscalars[0], tmpconstant);
5272 
5273  SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
5274  cliquetable, branchcand, eventfilter, eventqueue, var, tmpvars[0], 1.0, -tmpscalars[0], tmpconstant,
5275  infeasible, aggregated) );
5276 
5277  goto TERMINATE;
5278  }
5279 
5280  /**@todo currently we don't perform the multi aggregation if the multi aggregation variable has a non
5281  * empty hole list; this should be changed in the future */
5282  if( SCIPvarGetHolelistGlobal(var) != NULL )
5283  goto TERMINATE;
5284 
5285  /* if the variable is not allowed to be multi-aggregated */
5286  if( SCIPvarDoNotMultaggr(var) )
5287  {
5288  SCIPsetDebugMsg(set, "variable is not allowed to be multi-aggregated.\n");
5289  goto TERMINATE;
5290  }
5291 
5292  /* if the variable to be multi-aggregated has implications or variable bounds (i.e. is the implied variable or
5293  * variable bound variable of another variable), we have to remove it from the other variables implications or
5294  * variable bounds
5295  */
5296  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
5297  assert(var->vlbs == NULL);
5298  assert(var->vubs == NULL);
5299  assert(var->implics == NULL);
5300  assert(var->cliquelist == NULL);
5301 
5302  /* set the aggregated variable's objective value to 0.0 */
5303  obj = var->obj;
5304  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
5305 
5306  /* since we change the variable type form loose to multi aggregated, we have to adjust the number of loose
5307  * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
5308  * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
5309  * objective of this variable is set to zero
5310  */
5311  SCIPlpDecNLoosevars(lp);
5312 
5313  /* unlock all rounding locks */
5314  nlocksdown = var->nlocksdown;
5315  nlocksup = var->nlocksup;
5316  var->nlocksdown = 0;
5317  var->nlocksup = 0;
5318 
5319  /* convert variable into multi-aggregated variable */
5320  var->varstatus = SCIP_VARSTATUS_MULTAGGR; /*lint !e641*/
5321  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.vars, tmpvars, ntmpvars) );
5322  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.scalars, tmpscalars, ntmpvars) );
5323  var->data.multaggr.constant = tmpconstant;
5324  var->data.multaggr.nvars = ntmpvars;
5325  var->data.multaggr.varssize = ntmpvars;
5326 
5327  /* mark variable to be non-deletable */
5329 
5330  /* relock the rounding locks of the variable, thus increasing the locks of the aggregation variables */
5331  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, nlocksdown, nlocksup) );
5332 
5333  /* update flags and branching factors and priorities of aggregation variables;
5334  * update preferred branching direction of all aggregation variables that don't have a preferred direction yet
5335  */
5336  branchfactor = var->branchfactor;
5337  branchpriority = var->branchpriority;
5338  branchdirection = (SCIP_BRANCHDIR)var->branchdirection;
5339 
5340  for( v = 0; v < ntmpvars; ++v )
5341  {
5342  assert(tmpvars[v] != NULL);
5343  tmpvars[v]->removable &= var->removable;
5344  branchfactor = MAX(tmpvars[v]->branchfactor, branchfactor);
5345  branchpriority = MAX(tmpvars[v]->branchpriority, branchpriority);
5346 
5347  /* mark variable to be non-deletable */
5348  SCIPvarMarkNotDeletable(tmpvars[v]);
5349  }
5350  for( v = 0; v < ntmpvars; ++v )
5351  {
5352  SCIP_CALL( SCIPvarChgBranchFactor(tmpvars[v], set, branchfactor) );
5353  SCIP_CALL( SCIPvarChgBranchPriority(tmpvars[v], branchpriority) );
5354  if( (SCIP_BRANCHDIR)tmpvars[v]->branchdirection == SCIP_BRANCHDIR_AUTO )
5355  {
5356  if( tmpscalars[v] >= 0.0 )
5357  {
5358  SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], branchdirection) );
5359  }
5360  else
5361  {
5362  SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], SCIPbranchdirOpposite(branchdirection)) );
5363  }
5364  }
5365  }
5366  SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
5367  SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
5368 
5369  if( var->probindex != -1 )
5370  {
5371  /* inform problem about the variable's status change */
5372  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
5373  }
5374 
5375  /* issue VARFIXED event */
5376  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 2) );
5377 
5378  /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
5379  * variables and the problem's objective offset
5380  */
5381  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventqueue, obj) );
5382 
5383  *aggregated = TRUE;
5384 
5385  TERMINATE:
5386  BMSfreeBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize);
5387  BMSfreeBlockMemoryArray(blkmem, &tmpvars, tmpvarssize);
5388 
5389  break;
5390 
5391  case SCIP_VARSTATUS_COLUMN:
5392  SCIPerrorMessage("cannot multi-aggregate a column variable\n");
5393  return SCIP_INVALIDDATA;
5394 
5395  case SCIP_VARSTATUS_FIXED:
5396  SCIPerrorMessage("cannot multi-aggregate a fixed variable\n");
5397  return SCIP_INVALIDDATA;
5398 
5400  SCIPerrorMessage("cannot multi-aggregate an aggregated variable\n");
5401  return SCIP_INVALIDDATA;
5402 
5404  SCIPerrorMessage("cannot multi-aggregate a multiple aggregated variable again\n");
5405  return SCIP_INVALIDDATA;
5406 
5408  /* aggregate negation variable x in x' = offset - x, instead of aggregating x' directly:
5409  * x' = a_1*y_1 + ... + a_n*y_n + c -> x = offset - x' = offset - a_1*y_1 - ... - a_n*y_n - c
5410  */
5411  assert(SCIPsetIsZero(set, var->obj));
5412  assert(var->negatedvar != NULL);
5414  assert(var->negatedvar->negatedvar == var);
5415 
5416  /* switch the signs of the aggregation scalars */
5417  for( v = 0; v < naggvars; ++v )
5418  scalars[v] *= -1.0;
5419 
5420  /* perform the multi aggregation on the negation variable */
5421  SCIP_CALL( SCIPvarMultiaggregate(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5422  cliquetable, branchcand, eventfilter, eventqueue, naggvars, aggvars, scalars,
5423  var->data.negate.constant - constant, infeasible, aggregated) );
5424 
5425  /* switch the signs of the aggregation scalars again, to reset them to their original values */
5426  for( v = 0; v < naggvars; ++v )
5427  scalars[v] *= -1.0;
5428  break;
5429 
5430  default:
5431  SCIPerrorMessage("unknown variable status\n");
5432  return SCIP_INVALIDDATA;
5433  }
5434 
5435  return SCIP_OKAY;
5436 }
5437 
5438 /** transformed variables are resolved to their active, fixed, or multi-aggregated problem variable of a variable,
5439  * or for original variables the same variable is returned
5440  */
5441 static
5443  SCIP_VAR* var /**< problem variable */
5444  )
5445 {
5446  SCIP_VAR* retvar;
5447 
5448  assert(var != NULL);
5449 
5450  retvar = var;
5451 
5452  SCIPdebugMessage("get active variable of <%s>\n", var->name);
5453 
5454  while( TRUE ) /*lint !e716 */
5455  {
5456  assert(retvar != NULL);
5457 
5458  switch( SCIPvarGetStatus(retvar) )
5459  {
5461  case SCIP_VARSTATUS_LOOSE:
5462  case SCIP_VARSTATUS_COLUMN:
5463  case SCIP_VARSTATUS_FIXED:
5464  return retvar;
5465 
5467  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
5468  if ( retvar->data.multaggr.nvars == 1 )
5469  retvar = retvar->data.multaggr.vars[0];
5470  else
5471  return retvar;
5472  break;
5473 
5475  retvar = retvar->data.aggregate.var;
5476  break;
5477 
5479  retvar = retvar->negatedvar;
5480  break;
5481 
5482  default:
5483  SCIPerrorMessage("unknown variable status\n");
5484  SCIPABORT();
5485  return NULL; /*lint !e527*/
5486  }
5487  }
5488 }
5489 
5490 /** returns whether variable is not allowed to be multi-aggregated */
5492  SCIP_VAR* var /**< problem variable */
5493  )
5494 {
5495  SCIP_VAR* retvar;
5496 
5497  assert(var != NULL);
5498 
5499  retvar = varGetActiveVar(var);
5500  assert(retvar != NULL);
5501 
5502  switch( SCIPvarGetStatus(retvar) )
5503  {
5505  case SCIP_VARSTATUS_LOOSE:
5506  case SCIP_VARSTATUS_COLUMN:
5507  case SCIP_VARSTATUS_FIXED:
5508  return retvar->donotmultaggr;
5509 
5511  return FALSE;
5512 
5515  default:
5516  SCIPerrorMessage("wrong variable status\n");
5517  SCIPABORT();
5518  return FALSE; /*lint !e527 */
5519  }
5520 }
5521 
5522 /** gets negated variable x' = offset - x of problem variable x; the negated variable is created if not yet existing;
5523  * the negation offset of binary variables is always 1, the offset of other variables is fixed to lb + ub when the
5524  * negated variable is created
5525  */
5527  SCIP_VAR* var, /**< problem variable to negate */
5528  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
5529  SCIP_SET* set, /**< global SCIP settings */
5530  SCIP_STAT* stat, /**< problem statistics */
5531  SCIP_VAR** negvar /**< pointer to store the negated variable */
5532  )
5533 {
5534  assert(var != NULL);
5535  assert(var->scip == set->scip);
5536  assert(negvar != NULL);
5537 
5538  /* check, if we already created the negated variable */
5539  if( var->negatedvar == NULL )
5540  {
5541  char negvarname[SCIP_MAXSTRLEN];
5542 
5543  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED);
5544 
5545  SCIPsetDebugMsg(set, "creating negated variable of <%s>\n", var->name);
5546 
5547  /* negation is only possible for bounded variables */
5548  if( SCIPsetIsInfinity(set, -var->glbdom.lb) || SCIPsetIsInfinity(set, var->glbdom.ub) )
5549  {
5550  SCIPerrorMessage("cannot negate unbounded variable\n");
5551  return SCIP_INVALIDDATA;
5552  }
5553 
5554  (void) SCIPsnprintf(negvarname, SCIP_MAXSTRLEN, "%s_neg", var->name);
5555 
5556  /* create negated variable */
5557  SCIP_CALL( varCreate(negvar, blkmem, set, stat, negvarname, var->glbdom.lb, var->glbdom.ub, 0.0,
5558  SCIPvarGetType(var), var->initial, var->removable, NULL, NULL, NULL, NULL, NULL) );
5559  (*negvar)->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
5560  if( SCIPvarIsBinary(var) )
5561  (*negvar)->data.negate.constant = 1.0;
5562  else
5563  (*negvar)->data.negate.constant = var->glbdom.lb + var->glbdom.ub;
5564 
5565  /* create event filter for transformed variable */
5566  if( SCIPvarIsTransformed(var) )
5567  {
5568  SCIP_CALL( SCIPeventfilterCreate(&(*negvar)->eventfilter, blkmem) );
5569  }
5570 
5571  /* set the bounds corresponding to the negation variable */
5572  (*negvar)->glbdom.lb = (*negvar)->data.negate.constant - var->glbdom.ub;
5573  (*negvar)->glbdom.ub = (*negvar)->data.negate.constant - var->glbdom.lb;
5574  (*negvar)->locdom.lb = (*negvar)->data.negate.constant - var->locdom.ub;
5575  (*negvar)->locdom.ub = (*negvar)->data.negate.constant - var->locdom.lb;
5576  /**@todo create holes in the negated variable corresponding to the holes of the negation variable */
5577 
5578  /* link the variables together */
5579  var->negatedvar = *negvar;
5580  (*negvar)->negatedvar = var;
5581 
5582  /* mark both variables to be non-deletable */
5584  SCIPvarMarkNotDeletable(*negvar);
5585 
5586  /* copy the branch factor and priority, and use the negative preferred branching direction */
5587  (*negvar)->branchfactor = var->branchfactor;
5588  (*negvar)->branchpriority = var->branchpriority;
5589  (*negvar)->branchdirection = SCIPbranchdirOpposite((SCIP_BRANCHDIR)var->branchdirection); /*lint !e641*/
5590 
5591  /* copy doNotMultiaggr status */
5592  (*negvar)->donotmultaggr = var->donotmultaggr;
5593 
5594  /* copy lazy bounds (they have to be flipped) */
5595  (*negvar)->lazylb = (*negvar)->data.negate.constant - var->lazyub;
5596  (*negvar)->lazyub = (*negvar)->data.negate.constant - var->lazylb;
5597 
5598  /* make negated variable a parent of the negation variable (negated variable is captured as a parent) */
5599  SCIP_CALL( varAddParent(var, blkmem, set, *negvar) );
5600  assert((*negvar)->nuses == 1);
5601  }
5602  assert(var->negatedvar != NULL);
5603 
5604  /* return the negated variable */
5605  *negvar = var->negatedvar;
5606 
5607  /* exactly one variable of the negation pair has to be marked as negated variable */
5609 
5610  return SCIP_OKAY;
5611 }
5612 
5613 /** informs variable that its position in problem's vars array changed */
5614 static
5615 void varSetProbindex(
5616  SCIP_VAR* var, /**< problem variable */
5617  int probindex /**< new problem index of variable (-1 for removal) */
5618  )
5619 {
5620  assert(var != NULL);
5621  assert(probindex >= 0 || var->vlbs == NULL);
5622  assert(probindex >= 0 || var->vubs == NULL);
5623  assert(probindex >= 0 || var->implics == NULL);
5624 
5625  var->probindex = probindex;
5627  {
5628  assert(var->data.col != NULL);
5629  var->data.col->var_probindex = probindex;
5630  }
5631 }
5632 
5633 /** informs variable that its position in problem's vars array changed */
5634 void SCIPvarSetProbindex(
5635  SCIP_VAR* var, /**< problem variable */
5636  int probindex /**< new problem index of variable */
5637  )
5638 {
5639  assert(var != NULL);
5640  assert(probindex >= 0);
5641 
5642  varSetProbindex(var, probindex);
5643 }
5644 
5645 /** gives the variable a new name
5646  *
5647  * @note the old pointer is overwritten, which might result in a memory leakage
5648  */
5650  SCIP_VAR* var, /**< problem variable */
5651  const char* name /**< new name of variable */
5652  )
5653 {
5654  assert(var != NULL);
5655  assert(name != NULL);
5656 
5657  var->name = (char*)name;
5658 }
5659 
5660 /** informs variable that it will be removed from the problem; adjusts probindex and removes variable from the
5661  * implication graph;
5662  * If 'final' is TRUE, the thorough implication graph removal is not performed. Instead, only the
5663  * variable bounds and implication data structures of the variable are freed. Since in the final removal
5664  * of all variables from the transformed problem, this deletes the implication graph completely and is faster
5665  * than removing the variables one by one, each time updating all lists of the other variables.
5666  */
5668  SCIP_VAR* var, /**< problem variable */
5669  BMS_BLKMEM* blkmem, /**< block memory buffer */
5670  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5671  SCIP_SET* set, /**< global SCIP settings */
5672  SCIP_Bool final /**< is this the final removal of all problem variables? */
5673  )
5674 {
5675  assert(SCIPvarGetProbindex(var) >= 0);
5676  assert(var->scip == set->scip);
5677 
5678  /* if the variable is active in the transformed problem, remove it from the implication graph */
5679  if( SCIPvarIsTransformed(var)
5681  {
5682  if( final )
5683  {
5684  /* just destroy the data structures */
5685  SCIPvboundsFree(&var->vlbs, blkmem);
5686  SCIPvboundsFree(&var->vubs, blkmem);
5687  SCIPimplicsFree(&var->implics, blkmem);
5688  }
5689  else
5690  {
5691  /* unlink the variable from all other variables' lists and free the data structures */
5692  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
5693  }
5694  }
5695 
5696  /* mark the variable to be no longer a member of the problem */
5697  varSetProbindex(var, -1);
5698 
5699  return SCIP_OKAY;
5700 }
5701 
5702 /** marks the variable to be deleted from the problem */
5703 void SCIPvarMarkDeleted(
5704  SCIP_VAR* var /**< problem variable */
5705  )
5706 {
5707  assert(var != NULL);
5708  assert(var->probindex != -1);
5709 
5710  var->deleted = TRUE;
5711 }
5712 
5713 /** marks the variable to not to be multi-aggregated */
5715  SCIP_VAR* var /**< problem variable */
5716  )
5717 {
5718  SCIP_VAR* retvar;
5719 
5720  assert(var != NULL);
5721 
5722  retvar = varGetActiveVar(var);
5723  assert(retvar != NULL);
5724 
5725  switch( SCIPvarGetStatus(retvar) )
5726  {
5728  case SCIP_VARSTATUS_LOOSE:
5729  case SCIP_VARSTATUS_COLUMN:
5730  case SCIP_VARSTATUS_FIXED:
5731  retvar->donotmultaggr = TRUE;
5732  break;
5733 
5735  SCIPerrorMessage("cannot mark a multi-aggregated variable to not be multi-aggregated.\n");
5736  return SCIP_INVALIDDATA;
5737 
5740  default:
5741  SCIPerrorMessage("wrong variable status\n");
5742  return SCIP_INVALIDDATA;
5743  }
5744 
5745  return SCIP_OKAY;
5746 }
5747 
5748 /** changes type of variable; cannot be called, if var belongs to a problem */
5750  SCIP_VAR* var, /**< problem variable to change */
5751  SCIP_VARTYPE vartype /**< new type of variable */
5752  )
5753 {
5754  assert(var != NULL);
5755 
5756  SCIPdebugMessage("change type of <%s> from %d to %d\n", var->name, SCIPvarGetType(var), vartype);
5757 
5758  if( var->probindex >= 0 )
5759  {
5760  SCIPerrorMessage("cannot change type of variable already in the problem\n");
5761  return SCIP_INVALIDDATA;
5762  }
5763 
5764  var->vartype = vartype; /*lint !e641*/
5765  if( var->negatedvar != NULL )
5766  var->negatedvar->vartype = vartype; /*lint !e641*/
5767 
5768  return SCIP_OKAY;
5769 }
5770 
5771 /** appends OBJCHANGED event to the event queue */
5772 static
5774  SCIP_VAR* var, /**< problem variable to change */
5775  BMS_BLKMEM* blkmem, /**< block memory */
5776  SCIP_SET* set, /**< global SCIP settings */
5777  SCIP_PRIMAL* primal, /**< primal data */
5778  SCIP_LP* lp, /**< current LP data */
5779  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5780  SCIP_Real oldobj, /**< old objective value for variable */
5781  SCIP_Real newobj /**< new objective value for variable */
5782  )
5783 {
5784  SCIP_EVENT* event;
5785 
5786  assert(var != NULL);
5787  assert(var->scip == set->scip);
5788  assert(var->eventfilter != NULL);
5790  assert(SCIPvarIsTransformed(var));
5791  assert(!SCIPsetIsEQ(set, oldobj, newobj));
5792 
5793  SCIP_CALL( SCIPeventCreateObjChanged(&event, blkmem, var, oldobj, newobj) );
5794  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
5795 
5796  return SCIP_OKAY;
5797 }
5798 
5799 /** changes objective value of variable */
5801  SCIP_VAR* var, /**< variable to change */
5802  BMS_BLKMEM* blkmem, /**< block memory */
5803  SCIP_SET* set, /**< global SCIP settings */
5804  SCIP_PROB* prob, /**< problem data */
5805  SCIP_PRIMAL* primal, /**< primal data */
5806  SCIP_LP* lp, /**< current LP data */
5807  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5808  SCIP_Real newobj /**< new objective value for variable */
5809  )
5810 {
5811  SCIP_Real oldobj;
5812 
5813  assert(var != NULL);
5814  assert(set != NULL);
5815  assert(var->scip == set->scip);
5816 
5817  SCIPsetDebugMsg(set, "changing objective value of <%s> from %g to %g\n", var->name, var->obj, newobj);
5818 
5819  if( !SCIPsetIsEQ(set, var->obj, newobj) )
5820  {
5821  switch( SCIPvarGetStatus(var) )
5822  {
5824  if( var->data.original.transvar != NULL )
5825  {
5826  assert(SCIPprobIsTransformed(prob));
5827 
5828  SCIP_CALL( SCIPvarChgObj(var->data.original.transvar, blkmem, set, prob, primal, lp, eventqueue,
5829  (SCIP_Real) prob->objsense * newobj/prob->objscale) );
5830  }
5831  else
5832  assert(set->stage == SCIP_STAGE_PROBLEM);
5833 
5834  var->obj = newobj;
5835  var->unchangedobj = newobj;
5836 
5837  break;
5838 
5839  case SCIP_VARSTATUS_LOOSE:
5840  case SCIP_VARSTATUS_COLUMN:
5841  oldobj = var->obj;
5842  var->obj = newobj;
5843 
5844  /* update unchanged objective value of variable */
5845  if( !lp->divingobjchg )
5846  var->unchangedobj = newobj;
5847 
5848  /* update the number of variables with non-zero objective coefficient;
5849  * we only want to do the update, if the variable is added to the problem;
5850  * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
5851  */
5852  if( SCIPvarIsActive(var) )
5853  SCIPprobUpdateNObjVars(prob, set, oldobj, var->obj);
5854 
5855  SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
5856  break;
5857 
5858  case SCIP_VARSTATUS_FIXED:
5862  SCIPerrorMessage("cannot change objective value of a fixed, aggregated, multi-aggregated, or negated variable\n");
5863  return SCIP_INVALIDDATA;
5864 
5865  default:
5866  SCIPerrorMessage("unknown variable status\n");
5867  return SCIP_INVALIDDATA;
5868  }
5869  }
5870 
5871  return SCIP_OKAY;
5872 }
5873 
5874 /** adds value to objective value of variable */
5876  SCIP_VAR* var, /**< variable to change */
5877  BMS_BLKMEM* blkmem, /**< block memory */
5878  SCIP_SET* set, /**< global SCIP settings */
5879  SCIP_STAT* stat, /**< problem statistics */
5880  SCIP_PROB* transprob, /**< transformed problem data */
5881  SCIP_PROB* origprob, /**< original problem data */
5882  SCIP_PRIMAL* primal, /**< primal data */
5883  SCIP_TREE* tree, /**< branch and bound tree */
5884  SCIP_REOPT* reopt, /**< reoptimization data structure */
5885  SCIP_LP* lp, /**< current LP data */
5886  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5887  SCIP_Real addobj /**< additional objective value for variable */
5888  )
5889 {
5890  assert(var != NULL);
5891  assert(set != NULL);
5892  assert(var->scip == set->scip);
5893  assert(set->stage < SCIP_STAGE_INITSOLVE);
5894 
5895  SCIPsetDebugMsg(set, "adding %g to objective value %g of <%s>\n", addobj, var->obj, var->name);
5896 
5897  if( !SCIPsetIsZero(set, addobj) )
5898  {
5899  SCIP_Real oldobj;
5900  int i;
5901 
5902  switch( SCIPvarGetStatus(var) )
5903  {
5905  if( var->data.original.transvar != NULL )
5906  {
5907  SCIP_CALL( SCIPvarAddObj(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
5908  reopt, lp, eventqueue, (SCIP_Real) transprob->objsense * addobj/transprob->objscale) );
5909  }
5910  else
5911  assert(set->stage == SCIP_STAGE_PROBLEM);
5912 
5913  var->obj += addobj;
5914  var->unchangedobj += addobj;
5915  assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
5916 
5917  break;
5918 
5919  case SCIP_VARSTATUS_LOOSE:
5920  case SCIP_VARSTATUS_COLUMN:
5921  oldobj = var->obj;
5922  var->obj += addobj;
5923 
5924  /* update unchanged objective value of variable */
5925  if( !lp->divingobjchg )
5926  {
5927  var->unchangedobj += addobj;
5928  assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
5929  }
5930 
5931  /* update the number of variables with non-zero objective coefficient;
5932  * we only want to do the update, if the variable is added to the problem;
5933  * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
5934  */
5935  if( SCIPvarIsActive(var) )
5936  SCIPprobUpdateNObjVars(transprob, set, oldobj, var->obj);
5937 
5938  SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
5939  break;
5940 
5941  case SCIP_VARSTATUS_FIXED:
5942  assert(SCIPsetIsEQ(set, var->locdom.lb, var->locdom.ub));
5943  SCIPprobAddObjoffset(transprob, var->locdom.lb * addobj);
5944  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, transprob, origprob, tree, reopt, lp) );
5945  break;
5946 
5948  /* x = a*y + c -> add a*addobj to obj. val. of y, and c*addobj to obj. offset of problem */
5949  SCIPprobAddObjoffset(transprob, var->data.aggregate.constant * addobj);
5950  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, transprob, origprob, tree, reopt, lp) );
5951  SCIP_CALL( SCIPvarAddObj(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
5952  lp, eventqueue, var->data.aggregate.scalar * addobj) );
5953  break;
5954 
5956  assert(!var->donotmultaggr);
5957  /* x = a_1*y_1 + ... + a_n*y_n + c -> add a_i*addobj to obj. val. of y_i, and c*addobj to obj. offset */
5958  SCIPprobAddObjoffset(transprob, var->data.multaggr.constant * addobj);
5959  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, transprob, origprob, tree, reopt, lp) );
5960  for( i = 0; i < var->data.multaggr.nvars; ++i )
5961  {
5962  SCIP_CALL( SCIPvarAddObj(var->data.multaggr.vars[i], blkmem, set, stat, transprob, origprob, primal, tree,
5963  reopt, lp, eventqueue, var->data.multaggr.scalars[i] * addobj) );
5964  }
5965  break;
5966 
5968  /* x' = offset - x -> add -addobj to obj. val. of x and offset*addobj to obj. offset of problem */
5969  assert(var->negatedvar != NULL);
5971  assert(var->negatedvar->negatedvar == var);
5972  SCIPprobAddObjoffset(transprob, var->data.negate.constant * addobj);
5973  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, transprob, origprob, tree, reopt, lp) );
5974  SCIP_CALL( SCIPvarAddObj(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5975  eventqueue, -addobj) );
5976  break;
5977 
5978  default:
5979  SCIPerrorMessage("unknown variable status\n");
5980  return SCIP_INVALIDDATA;
5981  }
5982  }
5983 
5984  return SCIP_OKAY;
5985 }
5986 
5987 /** changes objective value of variable in current dive */
5989  SCIP_VAR* var, /**< problem variable to change */
5990  SCIP_SET* set, /**< global SCIP settings */
5991  SCIP_LP* lp, /**< current LP data */
5992  SCIP_Real newobj /**< new objective value for variable */
5993  )
5994 {
5995  assert(var != NULL);
5996  assert(set != NULL);
5997  assert(var->scip == set->scip);
5998  assert(lp != NULL);
5999 
6000  SCIPsetDebugMsg(set, "changing objective of <%s> to %g in current dive\n", var->name, newobj);
6001 
6002  if( SCIPsetIsZero(set, newobj) )
6003  newobj = 0.0;
6004 
6005  /* change objective value of attached variables */
6006  switch( SCIPvarGetStatus(var) )
6007  {
6009  assert(var->data.original.transvar != NULL);
6010  SCIP_CALL( SCIPvarChgObjDive(var->data.original.transvar, set, lp, newobj) );
6011  break;
6012 
6013  case SCIP_VARSTATUS_COLUMN:
6014  assert(var->data.col != NULL);
6015  SCIP_CALL( SCIPcolChgObj(var->data.col, set, lp, newobj) );
6016  break;
6017 
6018  case SCIP_VARSTATUS_LOOSE:
6019  case SCIP_VARSTATUS_FIXED:
6020  /* nothing to do here: only the constant shift in objective function would change */
6021  break;
6022 
6023  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6024  assert(var->data.aggregate.var != NULL);
6025  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
6026  SCIP_CALL( SCIPvarChgObjDive(var->data.aggregate.var, set, lp, newobj / var->data.aggregate.scalar) );
6027  /* the constant can be ignored, because it would only affect the objective shift */
6028  break;
6029 
6031  SCIPerrorMessage("cannot change diving objective value of a multi-aggregated variable\n");
6032  return SCIP_INVALIDDATA;
6033 
6034  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6035  assert(var->negatedvar != NULL);
6037  assert(var->negatedvar->negatedvar == var);
6038  SCIP_CALL( SCIPvarChgObjDive(var->negatedvar, set, lp, -newobj) );
6039  /* the offset can be ignored, because it would only affect the objective shift */
6040  break;
6041 
6042  default:
6043  SCIPerrorMessage("unknown variable status\n");
6044  return SCIP_INVALIDDATA;
6045  }
6046 
6047  return SCIP_OKAY;
6048 }
6049 
6050 /** adjust lower bound to integral value, if variable is integral */
6051 void SCIPvarAdjustLb(
6052  SCIP_VAR* var, /**< problem variable */
6053  SCIP_SET* set, /**< global SCIP settings */
6054  SCIP_Real* lb /**< pointer to lower bound to adjust */
6055  )
6056 {
6057  assert(var != NULL);
6058  assert(set != NULL);
6059  assert(var->scip == set->scip);
6060  assert(lb != NULL);
6061 
6062  SCIPsetDebugMsg(set, "adjust lower bound %g of <%s>\n", *lb, var->name);
6063 
6064  *lb = adjustedLb(set, SCIPvarGetType(var), *lb);
6065 }
6066 
6067 /** adjust upper bound to integral value, if variable is integral */
6068 void SCIPvarAdjustUb(
6069  SCIP_VAR* var, /**< problem variable */
6070  SCIP_SET* set, /**< global SCIP settings */
6071  SCIP_Real* ub /**< pointer to upper bound to adjust */
6072  )
6073 {
6074  assert(var != NULL);
6075  assert(set != NULL);
6076  assert(var->scip == set->scip);
6077  assert(ub != NULL);
6078 
6079  SCIPsetDebugMsg(set, "adjust upper bound %g of <%s>\n", *ub, var->name);
6080 
6081  *ub = adjustedUb(set, SCIPvarGetType(var), *ub);
6082 }
6083 
6084 /** adjust lower or upper bound to integral value, if variable is integral */
6085 void SCIPvarAdjustBd(
6086  SCIP_VAR* var, /**< problem variable */
6087  SCIP_SET* set, /**< global SCIP settings */
6088  SCIP_BOUNDTYPE boundtype, /**< type of bound to adjust */
6089  SCIP_Real* bd /**< pointer to bound to adjust */
6090  )
6091 {
6092  assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
6093 
6094  if( boundtype == SCIP_BOUNDTYPE_LOWER )
6095  SCIPvarAdjustLb(var, set, bd);
6096  else
6097  SCIPvarAdjustUb(var, set, bd);
6098 }
6099 
6100 /** changes lower bound of original variable in original problem */
6102  SCIP_VAR* var, /**< problem variable to change */
6103  SCIP_SET* set, /**< global SCIP settings */
6104  SCIP_Real newbound /**< new bound for variable */
6105  )
6106 {
6107  int i;
6108 
6109  assert(var != NULL);
6110  assert(!SCIPvarIsTransformed(var));
6112  assert(set != NULL);
6113  assert(var->scip == set->scip);
6114  assert(set->stage == SCIP_STAGE_PROBLEM);
6115 
6116  /* check that the bound is feasible */
6117  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsLE(set, newbound, SCIPvarGetUbOriginal(var)));
6118  /* adjust bound to integral value if variable is of integral type */
6119  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6120 
6121  if( SCIPsetIsZero(set, newbound) )
6122  newbound = 0.0;
6123 
6124  /* original domains are only stored for ORIGINAL variables, not for NEGATED */
6126  {
6127  SCIPsetDebugMsg(set, "changing original lower bound of <%s> from %g to %g\n",
6128  var->name, var->data.original.origdom.lb, newbound);
6129 
6130  if( SCIPsetIsEQ(set, var->data.original.origdom.lb, newbound) )
6131  return SCIP_OKAY;
6132 
6133  /* change the bound */
6134  var->data.original.origdom.lb = newbound;
6135  }
6136  else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
6137  {
6138  assert( var->negatedvar != NULL );
6139  SCIP_CALL( SCIPvarChgUbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
6140  }
6141 
6142  /* process parent variables */
6143  for( i = 0; i < var->nparentvars; ++i )
6144  {
6145  SCIP_VAR* parentvar;
6146 
6147  parentvar = var->parentvars[i];
6148  assert(parentvar != NULL);
6149  assert(SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_NEGATED);
6150  assert(parentvar->negatedvar == var);
6151  assert(var->negatedvar == parentvar);
6152 
6153  SCIP_CALL( SCIPvarChgUbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
6154  }
6155 
6156  return SCIP_OKAY;
6157 }
6158 
6159 /** changes upper bound of original variable in original problem */
6161  SCIP_VAR* var, /**< problem variable to change */
6162  SCIP_SET* set, /**< global SCIP settings */
6163  SCIP_Real newbound /**< new bound for variable */
6164  )
6165 {
6166  int i;
6167 
6168  assert(var != NULL);
6169  assert(!SCIPvarIsTransformed(var));
6171  assert(set != NULL);
6172  assert(var->scip == set->scip);
6173  assert(set->stage == SCIP_STAGE_PROBLEM);
6174 
6175  /* check that the bound is feasible */
6176  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsGE(set, newbound, SCIPvarGetLbOriginal(var)));
6177  /* adjust bound to integral value if variable is of integral type */
6178  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
6179 
6180  if( SCIPsetIsZero(set, newbound) )
6181  newbound = 0.0;
6182 
6183  /* original domains are only stored for ORIGINAL variables, not for NEGATED */
6185  {
6186  SCIPsetDebugMsg(set, "changing original upper bound of <%s> from %g to %g\n",
6187  var->name, var->data.original.origdom.ub, newbound);
6188 
6189  if( SCIPsetIsEQ(set, var->data.original.origdom.ub, newbound) )
6190  return SCIP_OKAY;
6191 
6192  /* change the bound */
6193  var->data.original.origdom.ub = newbound;
6194  }
6195  else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
6196  {
6197  assert( var->negatedvar != NULL );
6198  SCIP_CALL( SCIPvarChgLbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
6199  }
6200 
6201  /* process parent variables */
6202  for( i = 0; i < var->nparentvars; ++i )
6203  {
6204  SCIP_VAR* parentvar;
6205 
6206  parentvar = var->parentvars[i];
6207  assert(parentvar != NULL);
6208  assert(SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_NEGATED);
6209  assert(parentvar->negatedvar == var);
6210  assert(var->negatedvar == parentvar);
6211 
6212  SCIP_CALL( SCIPvarChgLbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
6213  }
6214 
6215  return SCIP_OKAY;
6216 }
6217 
6218 /** appends GLBCHANGED event to the event queue */
6219 static
6221  SCIP_VAR* var, /**< problem variable to change */
6222  BMS_BLKMEM* blkmem, /**< block memory */
6223  SCIP_SET* set, /**< global SCIP settings */
6224  SCIP_LP* lp, /**< current LP data */
6225  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6226  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6227  SCIP_Real oldbound, /**< old lower bound for variable */
6228  SCIP_Real newbound /**< new lower bound for variable */
6229  )
6230 {
6231  assert(var != NULL);
6232  assert(var->eventfilter != NULL);
6233  assert(SCIPvarIsTransformed(var));
6234  assert(!SCIPsetIsEQ(set, oldbound, newbound));
6235  assert(set != NULL);
6236  assert(var->scip == set->scip);
6237 
6238  /* check, if the variable is being tracked for bound changes
6239  * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
6240  */
6241  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GLBCHANGED) != 0)
6244  {
6245  SCIP_EVENT* event;
6246 
6247  SCIPsetDebugMsg(set, "issue GLBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
6248 
6249  SCIP_CALL( SCIPeventCreateGlbChanged(&event, blkmem, var, oldbound, newbound) );
6250  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
6251  }
6252 
6253  return SCIP_OKAY;
6254 }
6255 
6256 /** appends GUBCHANGED event to the event queue */
6257 static
6259  SCIP_VAR* var, /**< problem variable to change */
6260  BMS_BLKMEM* blkmem, /**< block memory */
6261  SCIP_SET* set, /**< global SCIP settings */
6262  SCIP_LP* lp, /**< current LP data */
6263  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6264  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6265  SCIP_Real oldbound, /**< old lower bound for variable */
6266  SCIP_Real newbound /**< new lower bound for variable */
6267  )
6268 {
6269  assert(var != NULL);
6270  assert(var->eventfilter != NULL);
6271  assert(SCIPvarIsTransformed(var));
6272  assert(!SCIPsetIsEQ(set, oldbound, newbound));
6273  assert(set != NULL);
6274  assert(var->scip == set->scip);
6275 
6276  /* check, if the variable is being tracked for bound changes
6277  * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
6278  */
6279  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GUBCHANGED) != 0)
6282  {
6283  SCIP_EVENT* event;
6284 
6285  SCIPsetDebugMsg(set, "issue GUBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
6286 
6287  SCIP_CALL( SCIPeventCreateGubChanged(&event, blkmem, var, oldbound, newbound) );
6288  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
6289  }
6290 
6291  return SCIP_OKAY;
6292 }
6293 
6294 /** appends GHOLEADDED event to the event queue */
6295 static
6297  SCIP_VAR* var, /**< problem variable to change */
6298  BMS_BLKMEM* blkmem, /**< block memory */
6299  SCIP_SET* set, /**< global SCIP settings */
6300  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6301  SCIP_Real left, /**< left bound of open interval in new hole */
6302  SCIP_Real right /**< right bound of open interval in new hole */
6303  )
6304 {
6305  assert(var != NULL);
6306  assert(var->eventfilter != NULL);
6307  assert(SCIPvarIsTransformed(var));
6308  assert(set != NULL);
6309  assert(var->scip == set->scip);
6310  assert(SCIPsetIsLT(set, left, right));
6311 
6312  /* check, if the variable is being tracked for bound changes */
6313  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GHOLEADDED) != 0) )
6314  {
6315  SCIP_EVENT* event;
6316 
6317  SCIPsetDebugMsg(set, "issue GHOLEADDED event for variable <%s>: (%.15g,%.15g)\n", var->name, left, right);
6318 
6319  SCIP_CALL( SCIPeventCreateGholeAdded(&event, blkmem, var, left, right) );
6320  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
6321  }
6322 
6323  return SCIP_OKAY;
6324 }
6325 
6326 /** increases root bound change statistics after a global bound change */
6327 static
6328 void varIncRootboundchgs(
6329  SCIP_VAR* var, /**< problem variable to change */
6330  SCIP_SET* set, /**< global SCIP settings */
6331  SCIP_STAT* stat /**< problem statistics */
6332  )
6333 {
6334  assert(var != NULL);
6335  assert(set != NULL);
6336  assert(var->scip == set->scip);
6337  assert(stat != NULL);
6338 
6339  if( SCIPvarIsActive(var) && SCIPvarIsTransformed(var) && set->stage == SCIP_STAGE_SOLVING )
6340  {
6341  stat->nrootboundchgs++;
6342  stat->nrootboundchgsrun++;
6343  if( SCIPvarIsIntegral(var) && SCIPvarGetLbGlobal(var) + 0.5 > SCIPvarGetUbGlobal(var) )
6344  {
6345  stat->nrootintfixings++;
6346  stat->nrootintfixingsrun++;
6347  }
6348  }
6349 }
6350 
6351 /* forward declaration, because both methods call each other recursively */
6352 
6353 /* performs the current change in upper bound, changes all parents accordingly */
6354 static
6356  SCIP_VAR* var, /**< problem variable to change */
6357  BMS_BLKMEM* blkmem, /**< block memory */
6358  SCIP_SET* set, /**< global SCIP settings */
6359  SCIP_STAT* stat, /**< problem statistics */
6360  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6361  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6362  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6363  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6364  SCIP_Real newbound /**< new bound for variable */
6365  );
6366 
6367 /** performs the current change in lower bound, changes all parents accordingly */
6368 static
6370  SCIP_VAR* var, /**< problem variable to change */
6371  BMS_BLKMEM* blkmem, /**< block memory */
6372  SCIP_SET* set, /**< global SCIP settings */
6373  SCIP_STAT* stat, /**< problem statistics */
6374  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6375  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6376  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6377  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6378  SCIP_Real newbound /**< new bound for variable */
6379  )
6380 {
6381  SCIP_VAR* parentvar;
6382  SCIP_Real oldbound;
6383  int i;
6384 
6385  assert(var != NULL);
6386  /* local domains can violate global bounds but not more than feasibility epsilon */
6387  assert(SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb));
6388  assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
6389  assert(blkmem != NULL);
6390  assert(set != NULL);
6391  assert(var->scip == set->scip);
6392  assert(stat != NULL);
6393 
6394  /* adjust bound to integral value if variable is of integral type */
6395  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6396 
6397  /* check that the bound is feasible */
6398  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound > var->glbdom.ub )
6399  {
6400  /* due to numerics we only want to be feasible in feasibility tolerance */
6401  assert(SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
6402  newbound = var->glbdom.ub;
6403  }
6404  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6405 
6406  assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
6407 
6408  SCIPsetDebugMsg(set, "process changing global lower bound of <%s> from %f to %f\n", var->name, var->glbdom.lb, newbound);
6409 
6410  if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) )
6411  return SCIP_OKAY;
6412 
6413  /* check bound on debugging solution */
6414  SCIP_CALL( SCIPdebugCheckLbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
6415 
6416  /* change the bound */
6417  oldbound = var->glbdom.lb;
6418  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
6419  var->glbdom.lb = newbound;
6420  assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
6421  assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
6422 
6423  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6424  {
6425  /* merges overlapping holes into single holes, moves bounds respectively */
6426  domMerge(&var->glbdom, blkmem, set, &newbound, NULL);
6427  }
6428 
6429  /* update the root bound changes counters */
6430  varIncRootboundchgs(var, set, stat);
6431 
6432  /* update the lbchginfos array by replacing worse local bounds with the new global bound and changing the
6433  * redundant bound changes to be branching decisions
6434  */
6435  for( i = 0; i < var->nlbchginfos; ++i )
6436  {
6437  assert(var->lbchginfos[i].var == var);
6438 
6439  if( var->lbchginfos[i].oldbound < var->glbdom.lb )
6440  {
6441  SCIPsetDebugMsg(set, " -> adjust lower bound change <%s>: %g -> %g due to new global lower bound %g\n",
6442  SCIPvarGetName(var), var->lbchginfos[i].oldbound, var->lbchginfos[i].newbound, var->glbdom.lb);
6443  var->lbchginfos[i].oldbound = var->glbdom.lb;
6444  if( SCIPsetIsLE(set, var->lbchginfos[i].newbound, var->glbdom.lb) )
6445  {
6446  /* this bound change is redundant due to the new global bound */
6447  var->lbchginfos[i].newbound = var->glbdom.lb;
6448  var->lbchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
6449  var->lbchginfos[i].redundant = TRUE;
6450  }
6451  else
6452  break; /* from now on, the remaining local bound changes are not redundant */
6453  }
6454  else
6455  break; /* from now on, the remaining local bound changes are not redundant */
6456  }
6457 
6458  /* remove redundant implications and variable bounds */
6460  && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
6461  {
6462  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
6463  }
6464 
6465  /* issue bound change event */
6466  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
6467  if( var->eventfilter != NULL )
6468  {
6469  SCIP_CALL( varEventGlbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
6470  }
6471 
6472  /* process parent variables */
6473  for( i = 0; i < var->nparentvars; ++i )
6474  {
6475  parentvar = var->parentvars[i];
6476  assert(parentvar != NULL);
6477 
6478  switch( SCIPvarGetStatus(parentvar) )
6479  {
6481  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6482  break;
6483 
6484  case SCIP_VARSTATUS_COLUMN:
6485  case SCIP_VARSTATUS_LOOSE:
6486  case SCIP_VARSTATUS_FIXED:
6488  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
6489  return SCIP_INVALIDDATA;
6490 
6491  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6492  assert(parentvar->data.aggregate.var == var);
6493  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
6494  {
6495  SCIP_Real parentnewbound;
6496 
6497  /* a > 0 -> change lower bound of y */
6498  assert((SCIPsetIsInfinity(set, -parentvar->glbdom.lb) && SCIPsetIsInfinity(set, -oldbound))
6499  || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
6500  || (SCIPsetIsZero(set, parentvar->glbdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
6501 
6502  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6503  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6504  else
6505  parentnewbound = newbound;
6506  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6507  }
6508  else
6509  {
6510  SCIP_Real parentnewbound;
6511 
6512  /* a < 0 -> change upper bound of y */
6513  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
6514  assert((SCIPsetIsInfinity(set, parentvar->glbdom.ub) && SCIPsetIsInfinity(set, -oldbound))
6515  || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
6516  || (SCIPsetIsZero(set, parentvar->glbdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
6517 
6518  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6519  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6520  else
6521  parentnewbound = -newbound;
6522  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6523  }
6524  break;
6525 
6526  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6527  assert(parentvar->negatedvar != NULL);
6528  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
6529  assert(parentvar->negatedvar->negatedvar == parentvar);
6530  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6531  parentvar->data.negate.constant - newbound) );
6532  break;
6533 
6534  default:
6535  SCIPerrorMessage("unknown variable status\n");
6536  return SCIP_INVALIDDATA;
6537  }
6538  }
6539 
6540  return SCIP_OKAY;
6541 }
6542 
6543 /** performs the current change in upper bound, changes all parents accordingly */
6544 static
6546  SCIP_VAR* var, /**< problem variable to change */
6547  BMS_BLKMEM* blkmem, /**< block memory */
6548  SCIP_SET* set, /**< global SCIP settings */
6549  SCIP_STAT* stat, /**< problem statistics */
6550  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6551  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6552  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6553  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6554  SCIP_Real newbound /**< new bound for variable */
6555  )
6556 {
6557  SCIP_VAR* parentvar;
6558  SCIP_Real oldbound;
6559  int i;
6560 
6561  assert(var != NULL);
6562  /* local domains can violate global bounds but not more than feasibility epsilon */
6563  assert(SCIPsetIsFeasLE(set, var->glbdom.lb , var->locdom.lb));
6564  assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
6565  assert(blkmem != NULL);
6566  assert(set != NULL);
6567  assert(var->scip == set->scip);
6568  assert(stat != NULL);
6569 
6570  /* adjust bound to integral value if variable is of integral type */
6571  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
6572 
6573  /* check that the bound is feasible */
6574  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound < var->glbdom.lb )
6575  {
6576  /* due to numerics we only want to be feasible in feasibility tolerance */
6577  assert(SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
6578  newbound = var->glbdom.lb;
6579  }
6580  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6581 
6582  assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
6583 
6584  SCIPsetDebugMsg(set, "process changing global upper bound of <%s> from %f to %f\n", var->name, var->glbdom.ub, newbound);
6585 
6586  if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) )
6587  return SCIP_OKAY;
6588 
6589  /* check bound on debugging solution */
6590  SCIP_CALL( SCIPdebugCheckUbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
6591 
6592  /* change the bound */
6593  oldbound = var->glbdom.ub;
6594  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
6595  var->glbdom.ub = newbound;
6596  assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
6597  assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
6598 
6599  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6600  {
6601  /* merges overlapping holes into single holes, moves bounds respectively */
6602  domMerge(&var->glbdom, blkmem, set, NULL, &newbound);
6603  }
6604 
6605  /* update the root bound changes counters */
6606  varIncRootboundchgs(var, set, stat);
6607 
6608  /* update the ubchginfos array by replacing worse local bounds with the new global bound and changing the
6609  * redundant bound changes to be branching decisions
6610  */
6611  for( i = 0; i < var->nubchginfos; ++i )
6612  {
6613  assert(var->ubchginfos[i].var == var);
6614  if( var->ubchginfos[i].oldbound > var->glbdom.ub )
6615  {
6616  SCIPsetDebugMsg(set, " -> adjust upper bound change <%s>: %g -> %g due to new global upper bound %g\n",
6617  SCIPvarGetName(var), var->ubchginfos[i].oldbound, var->ubchginfos[i].newbound, var->glbdom.ub);
6618  var->ubchginfos[i].oldbound = var->glbdom.ub;
6619  if( SCIPsetIsGE(set, var->ubchginfos[i].newbound, var->glbdom.ub) )
6620  {
6621  /* this bound change is redundant due to the new global bound */
6622  var->ubchginfos[i].newbound = var->glbdom.ub;
6623  var->ubchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
6624  var->ubchginfos[i].redundant = TRUE;
6625  }
6626  else
6627  break; /* from now on, the remaining local bound changes are not redundant */
6628  }
6629  else
6630  break; /* from now on, the remaining local bound changes are not redundant */
6631  }
6632 
6633  /* remove redundant implications and variable bounds */
6635  && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
6636  {
6637  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
6638  }
6639 
6640  /* issue bound change event */
6641  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
6642  if( var->eventfilter != NULL )
6643  {
6644  SCIP_CALL( varEventGubChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
6645  }
6646 
6647  /* process parent variables */
6648  for( i = 0; i < var->nparentvars; ++i )
6649  {
6650  parentvar = var->parentvars[i];
6651  assert(parentvar != NULL);
6652 
6653  switch( SCIPvarGetStatus(parentvar) )
6654  {
6656  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6657  break;
6658 
6659  case SCIP_VARSTATUS_COLUMN:
6660  case SCIP_VARSTATUS_LOOSE:
6661  case SCIP_VARSTATUS_FIXED:
6663  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
6664  return SCIP_INVALIDDATA;
6665 
6666  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6667  assert(parentvar->data.aggregate.var == var);
6668  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
6669  {
6670  SCIP_Real parentnewbound;
6671 
6672  /* a > 0 -> change upper bound of y */
6673  assert((SCIPsetIsInfinity(set, parentvar->glbdom.ub) && SCIPsetIsInfinity(set, oldbound))
6674  || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub,
6675  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
6676  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6677  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6678  else
6679  parentnewbound = newbound;
6680  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6681  }
6682  else
6683  {
6684  SCIP_Real parentnewbound;
6685 
6686  /* a < 0 -> change lower bound of y */
6687  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
6688  assert((SCIPsetIsInfinity(set, -parentvar->glbdom.lb) && SCIPsetIsInfinity(set, oldbound))
6689  || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb,
6690  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
6691  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6692  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6693  else
6694  parentnewbound = -newbound;
6695  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6696  }
6697  break;
6698 
6699  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6700  assert(parentvar->negatedvar != NULL);
6701  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
6702  assert(parentvar->negatedvar->negatedvar == parentvar);
6703  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6704  parentvar->data.negate.constant - newbound) );
6705  break;
6706 
6707  default:
6708  SCIPerrorMessage("unknown variable status\n");
6709  return SCIP_INVALIDDATA;
6710  }
6711  }
6712 
6713  return SCIP_OKAY;
6714 }
6715 
6716 /** changes global lower bound of variable; if possible, adjusts bound to integral value;
6717  * updates local lower bound if the global bound is tighter
6718  */
6720  SCIP_VAR* var, /**< problem variable to change */
6721  BMS_BLKMEM* blkmem, /**< block memory */
6722  SCIP_SET* set, /**< global SCIP settings */
6723  SCIP_STAT* stat, /**< problem statistics */
6724  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6725  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6726  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6727  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6728  SCIP_Real newbound /**< new bound for variable */
6729  )
6730 {
6731  assert(var != NULL);
6732  assert(blkmem != NULL);
6733  assert(set != NULL);
6734  assert(var->scip == set->scip);
6735 
6736  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
6737  * of the domain within feastol
6738  */
6739  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
6740 
6741  /* adjust bound to integral value if variable is of integral type */
6742  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6743 
6744  /* check that the adjusted bound is feasible
6745  * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
6746  * here because we reset bounds to their original value!
6747  */
6748  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
6749 
6750  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6751  {
6752  /* we do not want to exceed the upperbound, which could have happened due to numerics */
6753  newbound = MIN(newbound, var->glbdom.ub);
6754  }
6755  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6756 
6757  /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
6758  * SCIPvarFix() allows fixings that are outside of the domain within feastol
6759  */
6760  assert(lp == NULL || SCIPsetIsFeasLE(set, var->glbdom.lb, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
6761 
6762  SCIPsetDebugMsg(set, "changing global lower bound of <%s> from %g to %g\n", var->name, var->glbdom.lb, newbound);
6763 
6764  if( SCIPsetIsEQ(set, var->glbdom.lb, newbound) )
6765  return SCIP_OKAY;
6766 
6767  /* change bounds of attached variables */
6768  switch( SCIPvarGetStatus(var) )
6769  {
6771  if( var->data.original.transvar != NULL )
6772  {
6773  SCIP_CALL( SCIPvarChgLbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
6774  cliquetable, newbound) );
6775  }
6776  else
6777  {
6778  assert(set->stage == SCIP_STAGE_PROBLEM);
6779  if( newbound > SCIPvarGetLbLocal(var) )
6780  {
6781  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
6782  }
6783  SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6784  }
6785  break;
6786 
6787  case SCIP_VARSTATUS_COLUMN:
6788  case SCIP_VARSTATUS_LOOSE:
6789  if( newbound > SCIPvarGetLbLocal(var) )
6790  {
6791  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
6792  }
6793  SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6794  break;
6795 
6796  case SCIP_VARSTATUS_FIXED:
6797  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
6798  return SCIP_INVALIDDATA;
6799 
6800  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6801  assert(var->data.aggregate.var != NULL);
6802  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
6803  {
6804  SCIP_Real childnewbound;
6805 
6806  /* a > 0 -> change lower bound of y */
6807  assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, -var->data.aggregate.var->glbdom.lb))
6808  || SCIPsetIsFeasEQ(set, var->glbdom.lb,
6810  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6811  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
6812  else
6813  childnewbound = newbound;
6814  SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6815  childnewbound) );
6816  }
6817  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
6818  {
6819  SCIP_Real childnewbound;
6820 
6821  /* a < 0 -> change upper bound of y */
6822  assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
6823  || SCIPsetIsFeasEQ(set, var->glbdom.lb,
6825  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6826  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
6827  else
6828  childnewbound = -newbound;
6829  SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6830  childnewbound) );
6831  }
6832  else
6833  {
6834  SCIPerrorMessage("scalar is zero in aggregation\n");
6835  return SCIP_INVALIDDATA;
6836  }
6837  break;
6838 
6840  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
6841  return SCIP_INVALIDDATA;
6842 
6843  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6844  assert(var->negatedvar != NULL);
6846  assert(var->negatedvar->negatedvar == var);
6847  SCIP_CALL( SCIPvarChgUbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6848  var->data.negate.constant - newbound) );
6849  break;
6850 
6851  default:
6852  SCIPerrorMessage("unknown variable status\n");
6853  return SCIP_INVALIDDATA;
6854  }
6855 
6856  return SCIP_OKAY;
6857 }
6858 
6859 /** changes global upper bound of variable; if possible, adjusts bound to integral value;
6860  * updates local upper bound if the global bound is tighter
6861  */
6863  SCIP_VAR* var, /**< problem variable to change */
6864  BMS_BLKMEM* blkmem, /**< block memory */
6865  SCIP_SET* set, /**< global SCIP settings */
6866  SCIP_STAT* stat, /**< problem statistics */
6867  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6868  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6869  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6870  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6871  SCIP_Real newbound /**< new bound for variable */
6872  )
6873 {
6874  assert(var != NULL);
6875  assert(blkmem != NULL);
6876  assert(set != NULL);
6877  assert(var->scip == set->scip);
6878 
6879  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
6880  * of the domain within feastol
6881  */
6882  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
6883 
6884  /* adjust bound to integral value if variable is of integral type */
6885  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
6886 
6887  /* check that the adjusted bound is feasible
6888  * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
6889  * here because we reset bounds to their original value!
6890  */
6891  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
6892 
6893  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6894  {
6895  /* we do not want to undercut the lowerbound, which could have happened due to numerics */
6896  newbound = MAX(newbound, var->glbdom.lb);
6897  }
6898  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6899 
6900  /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
6901  * SCIPvarFix() allows fixings that are outside of the domain within feastol
6902  */
6903  assert(lp == NULL || SCIPsetIsFeasGE(set, var->glbdom.ub, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
6904 
6905  SCIPsetDebugMsg(set, "changing global upper bound of <%s> from %g to %g\n", var->name, var->glbdom.ub, newbound);
6906 
6907  if( SCIPsetIsEQ(set, var->glbdom.ub, newbound) )
6908  return SCIP_OKAY;
6909 
6910  /* change bounds of attached variables */
6911  switch( SCIPvarGetStatus(var) )
6912  {
6914  if( var->data.original.transvar != NULL )
6915  {
6916  SCIP_CALL( SCIPvarChgUbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6917  newbound) );
6918  }
6919  else
6920  {
6921  assert(set->stage == SCIP_STAGE_PROBLEM);
6922  if( newbound < SCIPvarGetUbLocal(var) )
6923  {
6924  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
6925  }
6926  SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6927  }
6928  break;
6929 
6930  case SCIP_VARSTATUS_COLUMN:
6931  case SCIP_VARSTATUS_LOOSE:
6932  if( newbound < SCIPvarGetUbLocal(var) )
6933  {
6934  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
6935  }
6936  SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6937  break;
6938 
6939  case SCIP_VARSTATUS_FIXED:
6940  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
6941  return SCIP_INVALIDDATA;
6942 
6943  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6944  assert(var->data.aggregate.var != NULL);
6945  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
6946  {
6947  SCIP_Real childnewbound;
6948 
6949  /* a > 0 -> change lower bound of y */
6950  assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
6951  || SCIPsetIsFeasEQ(set, var->glbdom.ub,
6953  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6954  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
6955  else
6956  childnewbound = newbound;
6957  SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6958  childnewbound) );
6959  }
6960  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
6961  {
6962  SCIP_Real childnewbound;
6963 
6964  /* a < 0 -> change upper bound of y */
6965  assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, -var->data.aggregate.var->glbdom.lb))
6966  || SCIPsetIsFeasEQ(set, var->glbdom.ub,
6968  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6969  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
6970  else
6971  childnewbound = -newbound;
6972  SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6973  childnewbound) );
6974  }
6975  else
6976  {
6977  SCIPerrorMessage("scalar is zero in aggregation\n");
6978  return SCIP_INVALIDDATA;
6979  }
6980  break;
6981 
6983  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
6984  return SCIP_INVALIDDATA;
6985 
6986  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6987  assert(var->negatedvar != NULL);
6989  assert(var->negatedvar->negatedvar == var);
6990  SCIP_CALL( SCIPvarChgLbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6991  var->data.negate.constant - newbound) );
6992  break;
6993 
6994  default:
6995  SCIPerrorMessage("unknown variable status\n");
6996  return SCIP_INVALIDDATA;
6997  }
6998 
6999  return SCIP_OKAY;
7000 }
7001 
7002 /** changes lazy lower bound of the variable, this is only possible if the variable is not in the LP yet */
7004  SCIP_VAR* var, /**< problem variable */
7005  SCIP_SET* set, /**< global SCIP settings */
7006  SCIP_Real lazylb /**< the lazy lower bound to be set */
7007  )
7008 {
7009  assert(var != NULL);
7010  assert(var->probindex != -1);
7011  assert(SCIPsetIsFeasGE(set, var->glbdom.ub, lazylb));
7012  assert(SCIPsetIsFeasGE(set, var->lazyub, lazylb));
7013  assert(set != NULL);
7014  assert(var->scip == set->scip);
7015 
7016  /* variable should not be in the LP */
7018  return SCIP_INVALIDCALL;
7019 
7020  var->lazylb = lazylb;
7021 
7022  return SCIP_OKAY;
7023 }
7024 
7025 /** changes lazy upper bound of the variable, this is only possible if the variable is not in the LP yet */
7027  SCIP_VAR* var, /**< problem variable */
7028  SCIP_SET* set, /**< global SCIP settings */
7029  SCIP_Real lazyub /**< the lazy lower bound to be set */
7030  )
7031 {
7032  assert(var != NULL);
7033  assert(var->probindex != -1);
7034  assert(SCIPsetIsFeasGE(set, lazyub, var->glbdom.lb));
7035  assert(SCIPsetIsFeasGE(set, lazyub, var->lazylb));
7036  assert(set != NULL);
7037  assert(var->scip == set->scip);
7038 
7039  /* variable should not be in the LP */
7041  return SCIP_INVALIDCALL;
7042 
7043  var->lazyub = lazyub;
7044 
7045  return SCIP_OKAY;
7046 }
7047 
7048 
7049 /** changes global bound of variable; if possible, adjusts bound to integral value;
7050  * updates local bound if the global bound is tighter
7051  */
7053  SCIP_VAR* var, /**< problem variable to change */
7054  BMS_BLKMEM* blkmem, /**< block memory */
7055  SCIP_SET* set, /**< global SCIP settings */
7056  SCIP_STAT* stat, /**< problem statistics */
7057  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7058  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7059  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7060  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7061  SCIP_Real newbound, /**< new bound for variable */
7062  SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
7063  )
7064 {
7065  /* apply bound change to the LP data */
7066  switch( boundtype )
7067  {
7068  case SCIP_BOUNDTYPE_LOWER:
7069  return SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
7070  case SCIP_BOUNDTYPE_UPPER:
7071  return SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
7072  default:
7073  SCIPerrorMessage("unknown bound type\n");
7074  return SCIP_INVALIDDATA;
7075  }
7076 }
7077 
7078 /** appends LBTIGHTENED or LBRELAXED event to the event queue */
7079 static
7081  SCIP_VAR* var, /**< problem variable to change */
7082  BMS_BLKMEM* blkmem, /**< block memory */
7083  SCIP_SET* set, /**< global SCIP settings */
7084  SCIP_LP* lp, /**< current LP data */
7085  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7086  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7087  SCIP_Real oldbound, /**< old lower bound for variable */
7088  SCIP_Real newbound /**< new lower bound for variable */
7089  )
7090 {
7091  assert(var != NULL);
7092  assert(var->eventfilter != NULL);
7093  assert(SCIPvarIsTransformed(var));
7094  assert(!SCIPsetIsEQ(set, oldbound, newbound));
7095  assert(set != NULL);
7096  assert(var->scip == set->scip);
7097 
7098  /* check, if the variable is being tracked for bound changes
7099  * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
7100  */
7101  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_LBCHANGED) != 0)
7104  {
7105  SCIP_EVENT* event;
7106 
7107  SCIPsetDebugMsg(set, "issue LBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
7108 
7109  SCIP_CALL( SCIPeventCreateLbChanged(&event, blkmem, var, oldbound, newbound) );
7110  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
7111  }
7112 
7113  return SCIP_OKAY;
7114 }
7115 
7116 /** appends UBTIGHTENED or UBRELAXED event to the event queue */
7117 static
7119  SCIP_VAR* var, /**< problem variable to change */
7120  BMS_BLKMEM* blkmem, /**< block memory */
7121  SCIP_SET* set, /**< global SCIP settings */
7122  SCIP_LP* lp, /**< current LP data */
7123  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7124  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7125  SCIP_Real oldbound, /**< old upper bound for variable */
7126  SCIP_Real newbound /**< new upper bound for variable */
7127  )
7128 {
7129  assert(var != NULL);
7130  assert(var->eventfilter != NULL);
7131  assert(SCIPvarIsTransformed(var));
7132  assert(!SCIPsetIsEQ(set, oldbound, newbound));
7133  assert(set != NULL);
7134  assert(var->scip == set->scip);
7135 
7136  /* check, if the variable is being tracked for bound changes
7137  * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
7138  */
7139  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_UBCHANGED) != 0)
7142  {
7143  SCIP_EVENT* event;
7144 
7145  SCIPsetDebugMsg(set, "issue UBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
7146 
7147  SCIP_CALL( SCIPeventCreateUbChanged(&event, blkmem, var, oldbound, newbound) );
7148  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
7149  }
7150 
7151  return SCIP_OKAY;
7152 }
7153 
7154 /* forward declaration, because both methods call each other recursively */
7155 
7156 /* performs the current change in upper bound, changes all parents accordingly */
7157 static
7159  SCIP_VAR* var, /**< problem variable to change */
7160  BMS_BLKMEM* blkmem, /**< block memory */
7161  SCIP_SET* set, /**< global SCIP settings */
7162  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7163  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7164  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7165  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7166  SCIP_Real newbound /**< new bound for variable */
7167  );
7168 
7169 /** performs the current change in lower bound, changes all parents accordingly */
7170 static
7172  SCIP_VAR* var, /**< problem variable to change */
7173  BMS_BLKMEM* blkmem, /**< block memory */
7174  SCIP_SET* set, /**< global SCIP settings */
7175  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7176  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7177  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7178  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7179  SCIP_Real newbound /**< new bound for variable */
7180  )
7181 {
7182  SCIP_VAR* parentvar;
7183  SCIP_Real oldbound;
7184  int i;
7185 
7186  assert(var != NULL);
7187  assert(set != NULL);
7188  assert(var->scip == set->scip);
7189  assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)))
7190  || (SCIPvarGetType(var) < SCIP_VARTYPE_CONTINUOUS && SCIPsetIsIntegral(set, newbound))
7192 
7193  /* check that the bound is feasible */
7194  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsLE(set, newbound, var->glbdom.ub));
7195  /* adjust bound to integral value if variable is of integral type */
7196  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7197 
7198  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7199  {
7200  /* we do not want to exceed the upper bound, which could have happened due to numerics */
7201  newbound = MIN(newbound, var->locdom.ub);
7202 
7203  /* we do not want to undercut the global lower bound, which could have happened due to numerics */
7204  newbound = MAX(newbound, var->glbdom.lb);
7205  }
7206  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7207 
7208  SCIPsetDebugMsg(set, "process changing lower bound of <%s> from %g to %g\n", var->name, var->locdom.lb, newbound);
7209 
7210  if( SCIPsetIsEQ(set, newbound, var->locdom.lb) )
7211  return SCIP_OKAY;
7212  if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) )
7213  newbound = var->glbdom.lb;
7214 
7215  /* change the bound */
7216  oldbound = var->locdom.lb;
7217  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->locdom.ub));
7218  var->locdom.lb = newbound;
7219 
7220  /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
7221  * once update the statistic
7222  */
7223  if( stat != NULL )
7224  SCIPstatIncrement(stat, set, domchgcount);
7225 
7226  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7227  {
7228  /* merges overlapping holes into single holes, moves bounds respectively */
7229  domMerge(&var->locdom, blkmem, set, &newbound, NULL);
7230  }
7231 
7232  /* issue bound change event */
7233  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7234  if( var->eventfilter != NULL )
7235  {
7236  SCIP_CALL( varEventLbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7237  }
7238 
7239  /* process parent variables */
7240  for( i = 0; i < var->nparentvars; ++i )
7241  {
7242  parentvar = var->parentvars[i];
7243  assert(parentvar != NULL);
7244 
7245  switch( SCIPvarGetStatus(parentvar) )
7246  {
7248  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
7249  break;
7250 
7251  case SCIP_VARSTATUS_COLUMN:
7252  case SCIP_VARSTATUS_LOOSE:
7253  case SCIP_VARSTATUS_FIXED:
7255  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7256  return SCIP_INVALIDDATA;
7257 
7258  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7259  assert(parentvar->data.aggregate.var == var);
7260  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7261  {
7262  SCIP_Real parentnewbound;
7263 
7264  /* a > 0 -> change lower bound of y */
7265  assert((SCIPsetIsInfinity(set, -parentvar->locdom.lb) && SCIPsetIsInfinity(set, -oldbound))
7266  || SCIPsetIsFeasEQ(set, parentvar->locdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
7267  || (SCIPsetIsZero(set, parentvar->locdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
7268 
7269  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7270  {
7271  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7272  /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
7273  * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
7274  * as a result, the parent's lower bound is set to it's upper bound, and not above
7275  */
7276  if( parentnewbound > parentvar->glbdom.ub )
7277  {
7278  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7279  assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
7280  parentnewbound = parentvar->glbdom.ub;
7281  }
7282  }
7283  else
7284  parentnewbound = newbound;
7285  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7286  }
7287  else
7288  {
7289  SCIP_Real parentnewbound;
7290 
7291  /* a < 0 -> change upper bound of y */
7292  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7293  assert((SCIPsetIsInfinity(set, parentvar->locdom.ub) && SCIPsetIsInfinity(set, -oldbound))
7294  || SCIPsetIsFeasEQ(set, parentvar->locdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
7295  || (SCIPsetIsZero(set, parentvar->locdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
7296 
7297  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7298  {
7299  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7300  /* if parent's new upper bound is below its lower bound, then this could be due to numerical difficulties, e.g., if numbers are large
7301  * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
7302  * as a result, the parent's upper bound is set to it's lower bound, and not below
7303  */
7304  if( parentnewbound < parentvar->glbdom.lb )
7305  {
7306  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7307  assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
7308  parentnewbound = parentvar->glbdom.lb;
7309  }
7310  }
7311  else
7312  parentnewbound = -newbound;
7313  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7314  }
7315  break;
7316 
7317  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
7318  assert(parentvar->negatedvar != NULL);
7319  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7320  assert(parentvar->negatedvar->negatedvar == parentvar);
7321  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
7322  parentvar->data.negate.constant - newbound) );
7323  break;
7324 
7325  default:
7326  SCIPerrorMessage("unknown variable status\n");
7327  return SCIP_INVALIDDATA;
7328  }
7329  }
7330 
7331  return SCIP_OKAY;
7332 }
7333 
7334 /** performs the current change in upper bound, changes all parents accordingly */
7335 static
7337  SCIP_VAR* var, /**< problem variable to change */
7338  BMS_BLKMEM* blkmem, /**< block memory */
7339  SCIP_SET* set, /**< global SCIP settings */
7340  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7341  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7342  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7343  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7344  SCIP_Real newbound /**< new bound for variable */
7345  )
7346 {
7347  SCIP_VAR* parentvar;
7348  SCIP_Real oldbound;
7349  int i;
7350 
7351  assert(var != NULL);
7352  assert(set != NULL);
7353  assert(var->scip == set->scip);
7354  assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)))
7355  || (SCIPvarGetType(var) < SCIP_VARTYPE_CONTINUOUS && SCIPsetIsIntegral(set, newbound))
7357 
7358  /* check that the bound is feasible */
7359  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsGE(set, newbound, var->glbdom.lb));
7360  /* adjust bound to integral value if variable is of integral type */
7361  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7362 
7363  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7364  {
7365  /* we do not want to undercut the lower bound, which could have happened due to numerics */
7366  newbound = MAX(newbound, var->locdom.lb);
7367 
7368  /* we do not want to exceed the global upper bound, which could have happened due to numerics */
7369  newbound = MIN(newbound, var->glbdom.ub);
7370  }
7371  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7372 
7373  SCIPsetDebugMsg(set, "process changing upper bound of <%s> from %g to %g\n", var->name, var->locdom.ub, newbound);
7374 
7375  if( SCIPsetIsEQ(set, newbound, var->locdom.ub) )
7376  return SCIP_OKAY;
7377  if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) )
7378  newbound = var->glbdom.ub;
7379 
7380  /* change the bound */
7381  oldbound = var->locdom.ub;
7382  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->locdom.lb));
7383  var->locdom.ub = newbound;
7384 
7385  /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
7386  * once update the statistic
7387  */
7388  if( stat != NULL )
7389  SCIPstatIncrement(stat, set, domchgcount);
7390 
7391  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7392  {
7393  /* merges overlapping holes into single holes, moves bounds respectively */
7394  domMerge(&var->locdom, blkmem, set, NULL, &newbound);
7395  }
7396 
7397  /* issue bound change event */
7398  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7399  if( var->eventfilter != NULL )
7400  {
7401  SCIP_CALL( varEventUbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7402  }
7403 
7404  /* process parent variables */
7405  for( i = 0; i < var->nparentvars; ++i )
7406  {
7407  parentvar = var->parentvars[i];
7408  assert(parentvar != NULL);
7409 
7410  switch( SCIPvarGetStatus(parentvar) )
7411  {
7413  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
7414  break;
7415 
7416  case SCIP_VARSTATUS_COLUMN:
7417  case SCIP_VARSTATUS_LOOSE:
7418  case SCIP_VARSTATUS_FIXED:
7420  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7421  return SCIP_INVALIDDATA;
7422 
7423  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7424  assert(parentvar->data.aggregate.var == var);
7425  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7426  {
7427  SCIP_Real parentnewbound;
7428 
7429  /* a > 0 -> change upper bound of x */
7430  assert((SCIPsetIsInfinity(set, parentvar->locdom.ub) && SCIPsetIsInfinity(set, oldbound))
7431  || SCIPsetIsFeasEQ(set, parentvar->locdom.ub,
7432  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7433  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7434  {
7435  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7436  /* if parent's new upper bound is below its lower bound, then this could be due to numerical difficulties, e.g., if numbers are large
7437  * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
7438  * as a result, the parent's upper bound is set to it's lower bound, and not below
7439  */
7440  if( parentnewbound < parentvar->glbdom.lb )
7441  {
7442  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7443  assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
7444  parentnewbound = parentvar->glbdom.lb;
7445  }
7446  }
7447  else
7448  parentnewbound = newbound;
7449  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7450  }
7451  else
7452  {
7453  SCIP_Real parentnewbound;
7454 
7455  /* a < 0 -> change lower bound of x */
7456  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7457  assert((SCIPsetIsInfinity(set, -parentvar->locdom.lb) && SCIPsetIsInfinity(set, oldbound))
7458  || SCIPsetIsFeasEQ(set, parentvar->locdom.lb,
7459  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7460  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7461  {
7462  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7463  /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
7464  * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
7465  * as a result, the parent's lower bound is set to it's upper bound, and not above
7466  */
7467  if( parentnewbound > parentvar->glbdom.ub )
7468  {
7469  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7470  assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
7471  parentnewbound = parentvar->glbdom.ub;
7472  }
7473  }
7474  else
7475  parentnewbound = -newbound;
7476  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7477  }
7478  break;
7479 
7480  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
7481  assert(parentvar->negatedvar != NULL);
7482  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7483  assert(parentvar->negatedvar->negatedvar == parentvar);
7484  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
7485  parentvar->data.negate.constant - newbound) );
7486  break;
7487 
7488  default:
7489  SCIPerrorMessage("unknown variable status\n");
7490  return SCIP_INVALIDDATA;
7491  }
7492  }
7493 
7494  return SCIP_OKAY;
7495 }
7496 
7497 /** changes current local lower bound of variable; if possible, adjusts bound to integral value; stores inference
7498  * information in variable
7499  */
7501  SCIP_VAR* var, /**< problem variable to change */
7502  BMS_BLKMEM* blkmem, /**< block memory */
7503  SCIP_SET* set, /**< global SCIP settings */
7504  SCIP_STAT* stat, /**< problem statistics */
7505  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7506  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7507  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7508  SCIP_Real newbound /**< new bound for variable */
7509  )
7510 {
7511  assert(var != NULL);
7512  assert(blkmem != NULL);
7513  assert(set != NULL);
7514  assert(var->scip == set->scip);
7515 
7516  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7517  * of the domain within feastol
7518  */
7519  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
7520 
7521  /* adjust bound to integral value if variable is of integral type */
7522  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7523 
7524  /* check that the adjusted bound is feasible */
7525  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
7526 
7527  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7528  {
7529  /* we do not want to exceed the upperbound, which could have happened due to numerics */
7530  newbound = MIN(newbound, var->locdom.ub);
7531  }
7532  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7533 
7534  SCIPsetDebugMsg(set, "changing lower bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
7535 
7536  if( SCIPsetIsEQ(set, var->locdom.lb, newbound) )
7537  return SCIP_OKAY;
7538 
7539  /* change bounds of attached variables */
7540  switch( SCIPvarGetStatus(var) )
7541  {
7543  if( var->data.original.transvar != NULL )
7544  {
7545  SCIP_CALL( SCIPvarChgLbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
7546  newbound) );
7547  }
7548  else
7549  {
7550  assert(set->stage == SCIP_STAGE_PROBLEM);
7551  SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7552  }
7553  break;
7554 
7555  case SCIP_VARSTATUS_COLUMN:
7556  case SCIP_VARSTATUS_LOOSE:
7557  SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7558  break;
7559 
7560  case SCIP_VARSTATUS_FIXED:
7561  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7562  return SCIP_INVALIDDATA;
7563 
7564  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7565  assert(var->data.aggregate.var != NULL);
7566  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7567  {
7568  SCIP_Real childnewbound;
7569 
7570  /* a > 0 -> change lower bound of y */
7571  assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, -var->data.aggregate.var->locdom.lb))
7572  || SCIPsetIsFeasEQ(set, var->locdom.lb,
7574  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7575  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7576  else
7577  childnewbound = newbound;
7578  SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7579  childnewbound) );
7580  }
7581  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7582  {
7583  SCIP_Real childnewbound;
7584 
7585  /* a < 0 -> change upper bound of y */
7586  assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->locdom.ub))
7587  || SCIPsetIsFeasEQ(set, var->locdom.lb,
7589  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7590  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7591  else
7592  childnewbound = -newbound;
7593  SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7594  childnewbound) );
7595  }
7596  else
7597  {
7598  SCIPerrorMessage("scalar is zero in aggregation\n");
7599  return SCIP_INVALIDDATA;
7600  }
7601  break;
7602 
7604  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7605  return SCIP_INVALIDDATA;
7606 
7607  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7608  assert(var->negatedvar != NULL);
7610  assert(var->negatedvar->negatedvar == var);
7611  SCIP_CALL( SCIPvarChgUbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
7612  var->data.negate.constant - newbound) );
7613  break;
7614 
7615  default:
7616  SCIPerrorMessage("unknown variable status\n");
7617  return SCIP_INVALIDDATA;
7618  }
7619 
7620  return SCIP_OKAY;
7621 }
7622 
7623 /** changes current local upper bound of variable; if possible, adjusts bound to integral value; stores inference
7624  * information in variable
7625  */
7627  SCIP_VAR* var, /**< problem variable to change */
7628  BMS_BLKMEM* blkmem, /**< block memory */
7629  SCIP_SET* set, /**< global SCIP settings */
7630  SCIP_STAT* stat, /**< problem statistics */
7631  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7632  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7633  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7634  SCIP_Real newbound /**< new bound for variable */
7635  )
7636 {
7637  assert(var != NULL);
7638  assert(blkmem != NULL);
7639  assert(set != NULL);
7640  assert(var->scip == set->scip);
7641 
7642  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7643  * of the domain within feastol
7644  */
7645  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
7646 
7647  /* adjust bound to integral value if variable is of integral type */
7648  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7649 
7650  /* check that the adjusted bound is feasible */
7651  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
7652 
7653  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7654  {
7655  /* we do not want to undercut the lowerbound, which could have happened due to numerics */
7656  newbound = MAX(newbound, var->locdom.lb);
7657  }
7658  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7659 
7660  SCIPsetDebugMsg(set, "changing upper bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
7661 
7662  if( SCIPsetIsEQ(set, var->locdom.ub, newbound) )
7663  return SCIP_OKAY;
7664 
7665  /* change bounds of attached variables */
7666  switch( SCIPvarGetStatus(var) )
7667  {
7669  if( var->data.original.transvar != NULL )
7670  {
7671  SCIP_CALL( SCIPvarChgUbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7672  }
7673  else
7674  {
7675  assert(set->stage == SCIP_STAGE_PROBLEM);
7676  SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7677  }
7678  break;
7679 
7680  case SCIP_VARSTATUS_COLUMN:
7681  case SCIP_VARSTATUS_LOOSE:
7682  SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7683  break;
7684 
7685  case SCIP_VARSTATUS_FIXED:
7686  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7687  return SCIP_INVALIDDATA;
7688 
7689  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7690  assert(var->data.aggregate.var != NULL);
7691  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7692  {
7693  SCIP_Real childnewbound;
7694 
7695  /* a > 0 -> change upper bound of y */
7696  assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, var->data.aggregate.var->locdom.ub))
7697  || SCIPsetIsFeasEQ(set, var->locdom.ub,
7699  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7700  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7701  else
7702  childnewbound = newbound;
7703  SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7704  childnewbound) );
7705  }
7706  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7707  {
7708  SCIP_Real childnewbound;
7709 
7710  /* a < 0 -> change lower bound of y */
7711  assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, -var->data.aggregate.var->locdom.lb))
7712  || SCIPsetIsFeasEQ(set, var->locdom.ub,
7714  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7715  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7716  else
7717  childnewbound = -newbound;
7718  SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7719  childnewbound) );
7720  }
7721  else
7722  {
7723  SCIPerrorMessage("scalar is zero in aggregation\n");
7724  return SCIP_INVALIDDATA;
7725  }
7726  break;
7727 
7729  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7730  return SCIP_INVALIDDATA;
7731 
7732  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7733  assert(var->negatedvar != NULL);
7735  assert(var->negatedvar->negatedvar == var);
7736  SCIP_CALL( SCIPvarChgLbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
7737  var->data.negate.constant - newbound) );
7738  break;
7739 
7740  default:
7741  SCIPerrorMessage("unknown variable status\n");
7742  return SCIP_INVALIDDATA;
7743  }
7744 
7745  return SCIP_OKAY;
7746 }
7747 
7748 /** changes current local bound of variable; if possible, adjusts bound to integral value; stores inference
7749  * information in variable
7750  */
7752  SCIP_VAR* var, /**< problem variable to change */
7753  BMS_BLKMEM* blkmem, /**< block memory */
7754  SCIP_SET* set, /**< global SCIP settings */
7755  SCIP_STAT* stat, /**< problem statistics */
7756  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7757  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7758  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7759  SCIP_Real newbound, /**< new bound for variable */
7760  SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
7761  )
7762 {
7763  /* apply bound change to the LP data */
7764  switch( boundtype )
7765  {
7766  case SCIP_BOUNDTYPE_LOWER:
7767  return SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
7768  case SCIP_BOUNDTYPE_UPPER:
7769  return SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
7770  default:
7771  SCIPerrorMessage("unknown bound type\n");
7772  return SCIP_INVALIDDATA;
7773  }
7774 }
7775 
7776 /** changes lower bound of variable in current dive; if possible, adjusts bound to integral value */
7778  SCIP_VAR* var, /**< problem variable to change */
7779  SCIP_SET* set, /**< global SCIP settings */
7780  SCIP_LP* lp, /**< current LP data */
7781  SCIP_Real newbound /**< new bound for variable */
7782  )
7783 {
7784  assert(var != NULL);
7785  assert(set != NULL);
7786  assert(var->scip == set->scip);
7787  assert(lp != NULL);
7788  assert(SCIPlpDiving(lp));
7789 
7790  /* adjust bound for integral variables */
7791  SCIPvarAdjustLb(var, set, &newbound);
7792 
7793  SCIPsetDebugMsg(set, "changing lower bound of <%s> to %g in current dive\n", var->name, newbound);
7794 
7795  /* change bounds of attached variables */
7796  switch( SCIPvarGetStatus(var) )
7797  {
7799  assert(var->data.original.transvar != NULL);
7800  SCIP_CALL( SCIPvarChgLbDive(var->data.original.transvar, set, lp, newbound) );
7801  break;
7802 
7803  case SCIP_VARSTATUS_COLUMN:
7804  assert(var->data.col != NULL);
7805  SCIP_CALL( SCIPcolChgLb(var->data.col, set, lp, newbound) );
7806  break;
7807 
7808  case SCIP_VARSTATUS_LOOSE:
7809  SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
7810  return SCIP_INVALIDDATA;
7811 
7812  case SCIP_VARSTATUS_FIXED:
7813  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7814  return SCIP_INVALIDDATA;
7815 
7816  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7817  assert(var->data.aggregate.var != NULL);
7818  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7819  {
7820  SCIP_Real childnewbound;
7821 
7822  /* a > 0 -> change lower bound of y */
7823  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7824  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7825  else
7826  childnewbound = newbound;
7827  SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
7828  }
7829  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7830  {
7831  SCIP_Real childnewbound;
7832 
7833  /* a < 0 -> change upper bound of y */
7834  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7835  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7836  else
7837  childnewbound = -newbound;
7838  SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
7839  }
7840  else
7841  {
7842  SCIPerrorMessage("scalar is zero in aggregation\n");
7843  return SCIP_INVALIDDATA;
7844  }
7845  break;
7846 
7848  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7849  return SCIP_INVALIDDATA;
7850 
7851  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7852  assert(var->negatedvar != NULL);
7854  assert(var->negatedvar->negatedvar == var);
7855  SCIP_CALL( SCIPvarChgUbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
7856  break;
7857 
7858  default:
7859  SCIPerrorMessage("unknown variable status\n");
7860  return SCIP_INVALIDDATA;
7861  }
7862 
7863  return SCIP_OKAY;
7864 }
7865 
7866 /** changes upper bound of variable in current dive; if possible, adjusts bound to integral value */
7868  SCIP_VAR* var, /**< problem variable to change */
7869  SCIP_SET* set, /**< global SCIP settings */
7870  SCIP_LP* lp, /**< current LP data */
7871  SCIP_Real newbound /**< new bound for variable */
7872  )
7873 {
7874  assert(var != NULL);
7875  assert(set != NULL);
7876  assert(var->scip == set->scip);
7877  assert(lp != NULL);
7878  assert(SCIPlpDiving(lp));
7879 
7880  /* adjust bound for integral variables */
7881  SCIPvarAdjustUb(var, set, &newbound);
7882 
7883  SCIPsetDebugMsg(set, "changing upper bound of <%s> to %g in current dive\n", var->name, newbound);
7884 
7885  /* change bounds of attached variables */
7886  switch( SCIPvarGetStatus(var) )
7887  {
7889  assert(var->data.original.transvar != NULL);
7890  SCIP_CALL( SCIPvarChgUbDive(var->data.original.transvar, set, lp, newbound) );
7891  break;
7892 
7893  case SCIP_VARSTATUS_COLUMN:
7894  assert(var->data.col != NULL);
7895  SCIP_CALL( SCIPcolChgUb(var->data.col, set, lp, newbound) );
7896  break;
7897 
7898  case SCIP_VARSTATUS_LOOSE:
7899  SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
7900  return SCIP_INVALIDDATA;
7901 
7902  case SCIP_VARSTATUS_FIXED:
7903  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7904  return SCIP_INVALIDDATA;
7905 
7906  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7907  assert(var->data.aggregate.var != NULL);
7908  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7909  {
7910  SCIP_Real childnewbound;
7911 
7912  /* a > 0 -> change upper bound of y */
7913  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7914  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7915  else
7916  childnewbound = newbound;
7917  SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
7918  }
7919  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7920  {
7921  SCIP_Real childnewbound;
7922 
7923  /* a < 0 -> change lower bound of y */
7924  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7925  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7926  else
7927  childnewbound = -newbound;
7928  SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
7929  }
7930  else
7931  {
7932  SCIPerrorMessage("scalar is zero in aggregation\n");
7933  return SCIP_INVALIDDATA;
7934  }
7935  break;
7936 
7938  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7939  return SCIP_INVALIDDATA;
7940 
7941  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7942  assert(var->negatedvar != NULL);
7944  assert(var->negatedvar->negatedvar == var);
7945  SCIP_CALL( SCIPvarChgLbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
7946  break;
7947 
7948  default:
7949  SCIPerrorMessage("unknown variable status\n");
7950  return SCIP_INVALIDDATA;
7951  }
7952 
7953  return SCIP_OKAY;
7954 }
7955 
7956 /** for a multi-aggregated variable, gives the local lower bound computed by adding the local bounds from all
7957  * aggregation variables, this lower bound may be tighter than the one given by SCIPvarGetLbLocal, since the latter is
7958  * not updated if bounds of aggregation variables are changing
7959  *
7960  * calling this function for a non-multi-aggregated variable is not allowed
7961  */
7963  SCIP_VAR* var, /**< problem variable */
7964  SCIP_SET* set /**< global SCIP settings */
7965  )
7966 {
7967  int i;
7968  SCIP_Real lb;
7969  SCIP_Real bnd;
7970  SCIP_VAR* aggrvar;
7971  SCIP_Bool posinf;
7972  SCIP_Bool neginf;
7973 
7974  assert(var != NULL);
7975  assert(set != NULL);
7976  assert(var->scip == set->scip);
7978 
7979  posinf = FALSE;
7980  neginf = FALSE;
7981  lb = var->data.multaggr.constant;
7982  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
7983  {
7984  aggrvar = var->data.multaggr.vars[i];
7985  if( var->data.multaggr.scalars[i] > 0.0 )
7986  {
7987  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbLocal(aggrvar, set) : SCIPvarGetLbLocal(aggrvar);
7988 
7989  if( SCIPsetIsInfinity(set, bnd) )
7990  posinf = TRUE;
7991  else if( SCIPsetIsInfinity(set, -bnd) )
7992  neginf = TRUE;
7993  else
7994  lb += var->data.multaggr.scalars[i] * bnd;
7995  }
7996  else
7997  {
7998  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbLocal(aggrvar, set) : SCIPvarGetUbLocal(aggrvar);
7999 
8000  if( SCIPsetIsInfinity(set, -bnd) )
8001  posinf = TRUE;
8002  else if( SCIPsetIsInfinity(set, bnd) )
8003  neginf = TRUE;
8004  else
8005  lb += var->data.multaggr.scalars[i] * bnd;
8006  }
8007 
8008  /* stop if two diffrent infinities (or a -infinity) were found and return local lower bound of multi aggregated
8009  * variable
8010  */
8011  if( neginf )
8012  return SCIPvarGetLbLocal(var);
8013  }
8014 
8015  /* if positive infinity flag was set to true return infinity */
8016  if( posinf )
8017  return SCIPsetInfinity(set);
8018 
8019  return (MAX(lb, SCIPvarGetLbLocal(var))); /*lint !e666*/
8020 }
8021 
8022 /** for a multi-aggregated variable, gives the local upper bound computed by adding the local bounds from all
8023  * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbLocal, since the latter is
8024  * not updated if bounds of aggregation variables are changing
8025  *
8026  * calling this function for a non-multi-aggregated variable is not allowed
8027  */
8029  SCIP_VAR* var, /**< problem variable */
8030  SCIP_SET* set /**< global SCIP settings */
8031  )
8032 {
8033  int i;
8034  SCIP_Real ub;
8035  SCIP_Real bnd;
8036  SCIP_VAR* aggrvar;
8037  SCIP_Bool posinf;
8038  SCIP_Bool neginf;
8039 
8040  assert(var != NULL);
8041  assert(set != NULL);
8042  assert(var->scip == set->scip);
8044 
8045  posinf = FALSE;
8046  neginf = FALSE;
8047  ub = var->data.multaggr.constant;
8048  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8049  {
8050  aggrvar = var->data.multaggr.vars[i];
8051  if( var->data.multaggr.scalars[i] > 0.0 )
8052  {
8053  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbLocal(aggrvar, set) : SCIPvarGetUbLocal(aggrvar);
8054 
8055  if( SCIPsetIsInfinity(set, bnd) )
8056  posinf = TRUE;
8057  else if( SCIPsetIsInfinity(set, -bnd) )
8058  neginf = TRUE;
8059  else
8060  ub += var->data.multaggr.scalars[i] * bnd;
8061  }
8062  else
8063  {
8064  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbLocal(aggrvar, set) : SCIPvarGetLbLocal(aggrvar);
8065 
8066  if( SCIPsetIsInfinity(set, -bnd) )
8067  posinf = TRUE;
8068  else if( SCIPsetIsInfinity(set, bnd) )
8069  neginf = TRUE;
8070  else
8071  ub += var->data.multaggr.scalars[i] * bnd;
8072  }
8073 
8074  /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
8075  * variable
8076  */
8077  if( posinf )
8078  return SCIPvarGetUbLocal(var);
8079  }
8080 
8081  /* if negative infinity flag was set to true return -infinity */
8082  if( neginf )
8083  return -SCIPsetInfinity(set);
8084 
8085  return (MIN(ub, SCIPvarGetUbLocal(var))); /*lint !e666*/
8086 }
8087 
8088 /** for a multi-aggregated variable, gives the global lower bound computed by adding the global bounds from all
8089  * aggregation variables, this global bound may be tighter than the one given by SCIPvarGetLbGlobal, since the latter is
8090  * not updated if bounds of aggregation variables are changing
8091  *
8092  * calling this function for a non-multi-aggregated variable is not allowed
8093  */
8095  SCIP_VAR* var, /**< problem variable */
8096  SCIP_SET* set /**< global SCIP settings */
8097  )
8098 {
8099  int i;
8100  SCIP_Real lb;
8101  SCIP_Real bnd;
8102  SCIP_VAR* aggrvar;
8103  SCIP_Bool posinf;
8104  SCIP_Bool neginf;
8105 
8106  assert(var != NULL);
8107  assert(set != NULL);
8108  assert(var->scip == set->scip);
8110 
8111  posinf = FALSE;
8112  neginf = FALSE;
8113  lb = var->data.multaggr.constant;
8114  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8115  {
8116  aggrvar = var->data.multaggr.vars[i];
8117  if( var->data.multaggr.scalars[i] > 0.0 )
8118  {
8119  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbGlobal(aggrvar, set) : SCIPvarGetLbGlobal(aggrvar);
8120 
8121  if( SCIPsetIsInfinity(set, bnd) )
8122  posinf = TRUE;
8123  else if( SCIPsetIsInfinity(set, -bnd) )
8124  neginf = TRUE;
8125  else
8126  lb += var->data.multaggr.scalars[i] * bnd;
8127  }
8128  else
8129  {
8130  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbGlobal(aggrvar, set) : SCIPvarGetUbGlobal(aggrvar);
8131 
8132  if( SCIPsetIsInfinity(set, -bnd) )
8133  posinf = TRUE;
8134  else if( SCIPsetIsInfinity(set, bnd) )
8135  neginf = TRUE;
8136  else
8137  lb += var->data.multaggr.scalars[i] * bnd;
8138  }
8139 
8140  /* stop if two diffrent infinities (or a -infinity) were found and return global lower bound of multi aggregated
8141  * variable
8142  */
8143  if( neginf )
8144  return SCIPvarGetLbGlobal(var);
8145  }
8146 
8147  /* if positive infinity flag was set to true return infinity */
8148  if( posinf )
8149  return SCIPsetInfinity(set);
8150 
8151  return (MAX(lb, SCIPvarGetLbGlobal(var))); /*lint !e666*/
8152 }
8153 
8154 /** for a multi-aggregated variable, gives the global upper bound computed by adding the global bounds from all
8155  * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbGlobal, since the latter is
8156  * not updated if bounds of aggregation variables are changing
8157  *
8158  * calling this function for a non-multi-aggregated variable is not allowed
8159  */
8161  SCIP_VAR* var, /**< problem variable */
8162  SCIP_SET* set /**< global SCIP settings */
8163  )
8164 {
8165  int i;
8166  SCIP_Real ub;
8167  SCIP_Real bnd;
8168  SCIP_VAR* aggrvar;
8169  SCIP_Bool posinf;
8170  SCIP_Bool neginf;
8171 
8172  assert(var != NULL);
8173  assert(set != NULL);
8174  assert(var->scip == set->scip);
8176 
8177  posinf = FALSE;
8178  neginf = FALSE;
8179  ub = var->data.multaggr.constant;
8180  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8181  {
8182  aggrvar = var->data.multaggr.vars[i];
8183  if( var->data.multaggr.scalars[i] > 0.0 )
8184  {
8185  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbGlobal(aggrvar, set) : SCIPvarGetUbGlobal(aggrvar);
8186 
8187  if( SCIPsetIsInfinity(set, bnd) )
8188  posinf = TRUE;
8189  else if( SCIPsetIsInfinity(set, -bnd) )
8190  neginf = TRUE;
8191  else
8192  ub += var->data.multaggr.scalars[i] * bnd;
8193  }
8194  else
8195  {
8196  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbGlobal(aggrvar, set) : SCIPvarGetLbGlobal(aggrvar);
8197 
8198  if( SCIPsetIsInfinity(set, -bnd) )
8199  posinf = TRUE;
8200  else if( SCIPsetIsInfinity(set, bnd) )
8201  neginf = TRUE;
8202  else
8203  ub += var->data.multaggr.scalars[i] * bnd;
8204  }
8205 
8206  /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
8207  * variable
8208  */
8209  if( posinf )
8210  return SCIPvarGetUbGlobal(var);
8211  }
8212 
8213  /* if negative infinity flag was set to true return -infinity */
8214  if( neginf )
8215  return -SCIPsetInfinity(set);
8216 
8217  return (MIN(ub, SCIPvarGetUbGlobal(var))); /*lint !e666*/
8218 }
8219 
8220 /** adds a hole to the original domain of the variable */
8222  SCIP_VAR* var, /**< problem variable */
8223  BMS_BLKMEM* blkmem, /**< block memory */
8224  SCIP_SET* set, /**< global SCIP settings */
8225  SCIP_Real left, /**< left bound of open interval in new hole */
8226  SCIP_Real right /**< right bound of open interval in new hole */
8227  )
8228 {
8229  SCIP_Bool added;
8230 
8231  assert(var != NULL);
8232  assert(!SCIPvarIsTransformed(var));
8234  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8235  assert(set != NULL);
8236  assert(var->scip == set->scip);
8237  assert(set->stage == SCIP_STAGE_PROBLEM);
8238 
8239  SCIPsetDebugMsg(set, "adding original hole (%g,%g) to <%s>\n", left, right, var->name);
8240 
8241  if( SCIPsetIsEQ(set, left, right) )
8242  return SCIP_OKAY;
8243 
8244  /* the interval should not be empty */
8245  assert(SCIPsetIsLT(set, left, right));
8246 
8247  /* the the interval bound should already be adjusted */
8248  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8249  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8250 
8251  /* the the interval should lay between the lower and upper bound */
8252  assert(SCIPsetIsGE(set, left, SCIPvarGetLbOriginal(var)));
8253  assert(SCIPsetIsLE(set, right, SCIPvarGetUbOriginal(var)));
8254 
8255  /* add domain hole */
8256  SCIP_CALL( domAddHole(&var->data.original.origdom, blkmem, set, left, right, &added) );
8257 
8258  /* merges overlapping holes into single holes, moves bounds respectively if hole was added */
8259  if( added )
8260  {
8261  domMerge(&var->data.original.origdom, blkmem, set, NULL, NULL);
8262  }
8263 
8264  /**@todo add hole in parent and child variables (just like with bound changes);
8265  * warning! original vars' holes are in original blkmem, transformed vars' holes in transformed blkmem
8266  */
8267 
8268  return SCIP_OKAY;
8269 }
8270 
8271 /** performs the current add of domain, changes all parents accordingly */
8272 static
8274  SCIP_VAR* var, /**< problem variable */
8275  BMS_BLKMEM* blkmem, /**< block memory */
8276  SCIP_SET* set, /**< global SCIP settings */
8277  SCIP_STAT* stat, /**< problem statistics */
8278  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8279  SCIP_Real left, /**< left bound of open interval in new hole */
8280  SCIP_Real right, /**< right bound of open interval in new hole */
8281  SCIP_Bool* added /**< pointer to store whether the hole was added */
8282  )
8283 {
8284  SCIP_VAR* parentvar;
8285  SCIP_Real newlb;
8286  SCIP_Real newub;
8287  int i;
8288 
8289  assert(var != NULL);
8290  assert(added != NULL);
8291  assert(blkmem != NULL);
8292 
8293  /* the interval should not be empty */
8294  assert(SCIPsetIsLT(set, left, right));
8295 
8296  /* the interval bound should already be adjusted */
8297  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8298  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8299 
8300  /* the interval should lay between the lower and upper bound */
8301  assert(SCIPsetIsGE(set, left, SCIPvarGetLbGlobal(var)));
8302  assert(SCIPsetIsLE(set, right, SCIPvarGetUbGlobal(var)));
8303 
8304  /* @todo add debugging mechanism for holes when using a debugging solution */
8305 
8306  /* add hole to hole list */
8307  SCIP_CALL( domAddHole(&var->glbdom, blkmem, set, left, right, added) );
8308 
8309  /* check if the hole is redundant */
8310  if( !(*added) )
8311  return SCIP_OKAY;
8312 
8313  /* current bounds */
8314  newlb = var->glbdom.lb;
8315  newub = var->glbdom.ub;
8316 
8317  /* merge domain holes */
8318  domMerge(&var->glbdom, blkmem, set, &newlb, &newub);
8319 
8320  /* the bound should not be changed */
8321  assert(SCIPsetIsEQ(set, newlb, var->glbdom.lb));
8322  assert(SCIPsetIsEQ(set, newub, var->glbdom.ub));
8323 
8324  /* issue bound change event */
8325  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
8326  if( var->eventfilter != NULL )
8327  {
8328  SCIP_CALL( varEventGholeAdded(var, blkmem, set, eventqueue, left, right) );
8329  }
8330 
8331  /* process parent variables */
8332  for( i = 0; i < var->nparentvars; ++i )
8333  {
8334  SCIP_Real parentnewleft;
8335  SCIP_Real parentnewright;
8336  SCIP_Bool localadded;
8337 
8338  parentvar = var->parentvars[i];
8339  assert(parentvar != NULL);
8340 
8341  switch( SCIPvarGetStatus(parentvar) )
8342  {
8344  parentnewleft = left;
8345  parentnewright = right;
8346  break;
8347 
8348  case SCIP_VARSTATUS_COLUMN:
8349  case SCIP_VARSTATUS_LOOSE:
8350  case SCIP_VARSTATUS_FIXED:
8352  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
8353  return SCIP_INVALIDDATA;
8354 
8355  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8356  assert(parentvar->data.aggregate.var == var);
8357 
8358  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
8359  {
8360  /* a > 0 -> change upper bound of x */
8361  parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8362  parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8363  }
8364  else
8365  {
8366  /* a < 0 -> change lower bound of x */
8367  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
8368 
8369  parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8370  parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8371  }
8372  break;
8373 
8374  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
8375  assert(parentvar->negatedvar != NULL);
8376  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
8377  assert(parentvar->negatedvar->negatedvar == parentvar);
8378 
8379  parentnewright = -left + parentvar->data.negate.constant;
8380  parentnewleft = -right + parentvar->data.negate.constant;
8381  break;
8382 
8383  default:
8384  SCIPerrorMessage("unknown variable status\n");
8385  return SCIP_INVALIDDATA;
8386  }
8387 
8388  SCIPsetDebugMsg(set, "add global hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
8389 
8390  /* perform hole added for parent variable */
8391  assert(blkmem != NULL);
8392  assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
8393  SCIP_CALL( varProcessAddHoleGlobal(parentvar, blkmem, set, stat, eventqueue,
8394  parentnewleft, parentnewright, &localadded) );
8395  assert(localadded);
8396  }
8397 
8398  return SCIP_OKAY;
8399 }
8400 
8401 /** adds a hole to the variable's global and local domain */
8403  SCIP_VAR* var, /**< problem variable */
8404  BMS_BLKMEM* blkmem, /**< block memory */
8405  SCIP_SET* set, /**< global SCIP settings */
8406  SCIP_STAT* stat, /**< problem statistics */
8407  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8408  SCIP_Real left, /**< left bound of open interval in new hole */
8409  SCIP_Real right, /**< right bound of open interval in new hole */
8410  SCIP_Bool* added /**< pointer to store whether the hole was added */
8411  )
8412 {
8413  SCIP_Real childnewleft;
8414  SCIP_Real childnewright;
8415 
8416  assert(var != NULL);
8417  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8418  assert(blkmem != NULL);
8419  assert(added != NULL);
8420 
8421  SCIPsetDebugMsg(set, "adding global hole (%g,%g) to <%s>\n", left, right, var->name);
8422 
8423  /* the interval should not be empty */
8424  assert(SCIPsetIsLT(set, left, right));
8425 
8426  /* the the interval bound should already be adjusted */
8427  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8428  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8429 
8430  /* the the interval should lay between the lower and upper bound */
8431  assert(SCIPsetIsGE(set, left, SCIPvarGetLbGlobal(var)));
8432  assert(SCIPsetIsLE(set, right, SCIPvarGetUbGlobal(var)));
8433 
8434  /* change bounds of attached variables */
8435  switch( SCIPvarGetStatus(var) )
8436  {
8438  if( var->data.original.transvar != NULL )
8439  {
8440  SCIP_CALL( SCIPvarAddHoleGlobal(var->data.original.transvar, blkmem, set, stat, eventqueue,
8441  left, right, added) );
8442  }
8443  else
8444  {
8445  assert(set->stage == SCIP_STAGE_PROBLEM);
8446 
8447  SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
8448  if( *added )
8449  {
8450  SCIP_Bool localadded;
8451 
8452  SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
8453  }
8454  }
8455  break;
8456 
8457  case SCIP_VARSTATUS_COLUMN:
8458  case SCIP_VARSTATUS_LOOSE:
8459  SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
8460  if( *added )
8461  {
8462  SCIP_Bool localadded;
8463 
8464  SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
8465  }
8466  break;
8467 
8468  case SCIP_VARSTATUS_FIXED:
8469  SCIPerrorMessage("cannot add hole of a fixed variable\n");
8470  return SCIP_INVALIDDATA;
8471 
8472  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8473  assert(var->data.aggregate.var != NULL);
8474 
8475  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8476  {
8477  /* a > 0 -> change lower bound of y */
8478  childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8479  childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8480  }
8481  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8482  {
8483  childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8484  childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8485  }
8486  else
8487  {
8488  SCIPerrorMessage("scalar is zero in aggregation\n");
8489  return SCIP_INVALIDDATA;
8490  }
8491  SCIP_CALL( SCIPvarAddHoleGlobal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
8492  childnewleft, childnewright, added) );
8493  break;
8494 
8496  SCIPerrorMessage("cannot add a hole of a multi-aggregated variable.\n");
8497  return SCIP_INVALIDDATA;
8498 
8499  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8500  assert(var->negatedvar != NULL);
8502  assert(var->negatedvar->negatedvar == var);
8503 
8504  childnewright = -left + var->data.negate.constant;
8505  childnewleft = -right + var->data.negate.constant;
8506 
8507  SCIP_CALL( SCIPvarAddHoleGlobal(var->negatedvar, blkmem, set, stat, eventqueue,
8508  childnewleft, childnewright, added) );
8509  break;
8510 
8511  default:
8512  SCIPerrorMessage("unknown variable status\n");
8513  return SCIP_INVALIDDATA;
8514  }
8515 
8516  return SCIP_OKAY;
8517 }
8518 
8519 /** performs the current add of domain, changes all parents accordingly */
8520 static
8522  SCIP_VAR* var, /**< problem variable */
8523  BMS_BLKMEM* blkmem, /**< block memory */
8524  SCIP_SET* set, /**< global SCIP settings */
8525  SCIP_STAT* stat, /**< problem statistics */
8526  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8527  SCIP_Real left, /**< left bound of open interval in new hole */
8528  SCIP_Real right, /**< right bound of open interval in new hole */
8529  SCIP_Bool* added /**< pointer to store whether the hole was added, or NULL */
8530  )
8531 {
8532  SCIP_VAR* parentvar;
8533  SCIP_Real newlb;
8534  SCIP_Real newub;
8535  int i;
8536 
8537  assert(var != NULL);
8538  assert(added != NULL);
8539  assert(blkmem != NULL);
8540 
8541  /* the interval should not be empty */
8542  assert(SCIPsetIsLT(set, left, right));
8543 
8544  /* the the interval bound should already be adjusted */
8545  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8546  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8547 
8548  /* the the interval should lay between the lower and upper bound */
8549  assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
8550  assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
8551 
8552  /* add hole to hole list */
8553  SCIP_CALL( domAddHole(&var->locdom, blkmem, set, left, right, added) );
8554 
8555  /* check if the hole is redundant */
8556  if( !(*added) )
8557  return SCIP_OKAY;
8558 
8559  /* current bounds */
8560  newlb = var->locdom.lb;
8561  newub = var->locdom.ub;
8562 
8563  /* merge domain holes */
8564  domMerge(&var->locdom, blkmem, set, &newlb, &newub);
8565 
8566  /* the bound should not be changed */
8567  assert(SCIPsetIsEQ(set, newlb, var->locdom.lb));
8568  assert(SCIPsetIsEQ(set, newub, var->locdom.ub));
8569 
8570 #if 0
8571  /* issue bound change event */
8572  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
8573  if( var->eventfilter != NULL )
8574  {
8575  SCIP_CALL( varEventLholeAdded(var, blkmem, set, lp, branchcand, eventqueue, left, right) );
8576  }
8577 #endif
8578 
8579  /* process parent variables */
8580  for( i = 0; i < var->nparentvars; ++i )
8581  {
8582  SCIP_Real parentnewleft;
8583  SCIP_Real parentnewright;
8584  SCIP_Bool localadded;
8585 
8586  parentvar = var->parentvars[i];
8587  assert(parentvar != NULL);
8588 
8589  switch( SCIPvarGetStatus(parentvar) )
8590  {
8592  parentnewleft = left;
8593  parentnewright = right;
8594  break;
8595 
8596  case SCIP_VARSTATUS_COLUMN:
8597  case SCIP_VARSTATUS_LOOSE:
8598  case SCIP_VARSTATUS_FIXED:
8600  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
8601  return SCIP_INVALIDDATA;
8602 
8603  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8604  assert(parentvar->data.aggregate.var == var);
8605 
8606  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
8607  {
8608  /* a > 0 -> change upper bound of x */
8609  parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8610  parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8611  }
8612  else
8613  {
8614  /* a < 0 -> change lower bound of x */
8615  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
8616 
8617  parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8618  parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8619  }
8620  break;
8621 
8622  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
8623  assert(parentvar->negatedvar != NULL);
8624  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
8625  assert(parentvar->negatedvar->negatedvar == parentvar);
8626 
8627  parentnewright = -left + parentvar->data.negate.constant;
8628  parentnewleft = -right + parentvar->data.negate.constant;
8629  break;
8630 
8631  default:
8632  SCIPerrorMessage("unknown variable status\n");
8633  return SCIP_INVALIDDATA;
8634  }
8635 
8636  SCIPsetDebugMsg(set, "add local hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
8637 
8638  /* perform hole added for parent variable */
8639  assert(blkmem != NULL);
8640  assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
8641  SCIP_CALL( varProcessAddHoleLocal(parentvar, blkmem, set, stat, eventqueue,
8642  parentnewleft, parentnewright, &localadded) );
8643  assert(localadded);
8644  }
8645 
8646  return SCIP_OKAY;
8647 }
8648 
8649 /** adds a hole to the variable's current local domain */
8651  SCIP_VAR* var, /**< problem variable */
8652  BMS_BLKMEM* blkmem, /**< block memory */
8653  SCIP_SET* set, /**< global SCIP settings */
8654  SCIP_STAT* stat, /**< problem statistics */
8655  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8656  SCIP_Real left, /**< left bound of open interval in new hole */
8657  SCIP_Real right, /**< right bound of open interval in new hole */
8658  SCIP_Bool* added /**< pointer to store whether the hole was added */
8659  )
8660 {
8661  SCIP_Real childnewleft;
8662  SCIP_Real childnewright;
8663 
8664  assert(var != NULL);
8665 
8666  SCIPsetDebugMsg(set, "adding local hole (%g,%g) to <%s>\n", left, right, var->name);
8667 
8668  assert(set != NULL);
8669  assert(var->scip == set->scip);
8670  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8671  assert(blkmem != NULL);
8672  assert(added != NULL);
8673 
8674  /* the interval should not be empty */
8675  assert(SCIPsetIsLT(set, left, right));
8676 
8677  /* the the interval bound should already be adjusted */
8678  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8679  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8680 
8681  /* the the interval should lay between the lower and upper bound */
8682  assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
8683  assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
8684 
8685  /* change bounds of attached variables */
8686  switch( SCIPvarGetStatus(var) )
8687  {
8689  if( var->data.original.transvar != NULL )
8690  {
8691  SCIP_CALL( SCIPvarAddHoleLocal(var->data.original.transvar, blkmem, set, stat, eventqueue,
8692  left, right, added) );
8693  }
8694  else
8695  {
8696  assert(set->stage == SCIP_STAGE_PROBLEM);
8697  SCIPstatIncrement(stat, set, domchgcount);
8698  SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
8699  }
8700  break;
8701 
8702  case SCIP_VARSTATUS_COLUMN:
8703  case SCIP_VARSTATUS_LOOSE:
8704  SCIPstatIncrement(stat, set, domchgcount);
8705  SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
8706  break;
8707 
8708  case SCIP_VARSTATUS_FIXED:
8709  SCIPerrorMessage("cannot add domain hole to a fixed variable\n");
8710  return SCIP_INVALIDDATA;
8711 
8712  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8713  assert(var->data.aggregate.var != NULL);
8714 
8715  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8716  {
8717  /* a > 0 -> change lower bound of y */
8718  childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8719  childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8720  }
8721  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8722  {
8723  childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8724  childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8725  }
8726  else
8727  {
8728  SCIPerrorMessage("scalar is zero in aggregation\n");
8729  return SCIP_INVALIDDATA;
8730  }
8731  SCIP_CALL( SCIPvarAddHoleLocal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
8732  childnewleft, childnewright, added) );
8733  break;
8734 
8736  SCIPerrorMessage("cannot add domain hole to a multi-aggregated variable.\n");
8737  return SCIP_INVALIDDATA;
8738 
8739  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8740  assert(var->negatedvar != NULL);
8742  assert(var->negatedvar->negatedvar == var);
8743 
8744  childnewright = -left + var->data.negate.constant;
8745  childnewleft = -right + var->data.negate.constant;
8746 
8747  SCIP_CALL( SCIPvarAddHoleLocal(var->negatedvar, blkmem, set, stat, eventqueue, childnewleft, childnewright, added) );
8748  break;
8749 
8750  default:
8751  SCIPerrorMessage("unknown variable status\n");
8752  return SCIP_INVALIDDATA;
8753  }
8754 
8755  return SCIP_OKAY;
8756 }
8757 
8758 /** resets the global and local bounds of original variable to their original values */
8760  SCIP_VAR* var, /**< problem variable */
8761  BMS_BLKMEM* blkmem, /**< block memory */
8762  SCIP_SET* set, /**< global SCIP settings */
8763  SCIP_STAT* stat /**< problem statistics */
8764  )
8765 {
8766  assert(var != NULL);
8767  assert(set != NULL);
8768  assert(var->scip == set->scip);
8769  assert(SCIPvarIsOriginal(var));
8770  /* resetting of bounds on original variables which have a transformed counterpart easily fails if, e.g.,
8771  * the transformed variable has been fixed */
8772  assert(SCIPvarGetTransVar(var) == NULL);
8773 
8774  /* copy the original bounds back to the global and local bounds */
8775  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.lb) );
8776  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.ub) );
8777  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.lb) );
8778  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.ub) );
8779 
8780  /* free the global and local holelists and duplicate the original ones */
8781  /**@todo this has also to be called recursively with methods similar to SCIPvarChgLbGlobal() */
8782  holelistFree(&var->glbdom.holelist, blkmem);
8783  holelistFree(&var->locdom.holelist, blkmem);
8784  SCIP_CALL( holelistDuplicate(&var->glbdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
8785  SCIP_CALL( holelistDuplicate(&var->locdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
8786 
8787  return SCIP_OKAY;
8788 }
8789 
8790 /** issues a IMPLADDED event on the given variable */
8791 static
8793  SCIP_VAR* var, /**< problem variable to change */
8794  BMS_BLKMEM* blkmem, /**< block memory */
8795  SCIP_SET* set, /**< global SCIP settings */
8796  SCIP_EVENTQUEUE* eventqueue /**< event queue */
8797  )
8798 {
8799  SCIP_EVENT* event;
8800 
8801  assert(var != NULL);
8802 
8803  /* issue IMPLADDED event on variable */
8804  SCIP_CALL( SCIPeventCreateImplAdded(&event, blkmem, var) );
8805  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
8806 
8807  return SCIP_OKAY;
8808 }
8809 
8810 /** actually performs the addition of a variable bound to the variable's vbound arrays */
8811 static
8813  SCIP_VAR* var, /**< problem variable x in x <= b*z + d or x >= b*z + d */
8814  BMS_BLKMEM* blkmem, /**< block memory */
8815  SCIP_SET* set, /**< global SCIP settings */
8816  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
8817  SCIP_BOUNDTYPE vbtype, /**< type of variable bound (LOWER or UPPER) */
8818  SCIP_VAR* vbvar, /**< variable z in x <= b*z + d or x >= b*z + d */
8819  SCIP_Real vbcoef, /**< coefficient b in x <= b*z + d or x >= b*z + d */
8820  SCIP_Real vbconstant /**< constant d in x <= b*z + d or x >= b*z + d */
8821  )
8822 {
8823  SCIP_Bool added;
8824 
8825  /* It can happen that the variable "var" and the variable "vbvar" are the same variable. For example if a variable
8826  * gets aggregated, the variable bounds (vbound) of that variable are copied to the other variable. A variable bound
8827  * variable of the aggregated variable might be the same as the one its gets aggregated too.
8828  *
8829  * If the variable "var" and the variable "vbvar" are the same, the variable bound which should be added here has to
8830  * be redundant. This is the case since an infeasibility should have be detected in the previous methods. As well as
8831  * the bounds of the variable which should be also already be tightened in the previous methods. Therefore, the
8832  * variable bound can be ignored.
8833  *
8834  * From the way the the variable bound system is implemented (detecting infeasibility, tighten bounds), the
8835  * equivalence of the variables should be checked here.
8836  */
8837  if( var == vbvar )
8838  {
8839  /* in this case the variable bound has to be redundant, this means for possible assignments to this variable; this
8840  * can be checked via the global bounds of the variable */
8841 #ifndef NDEBUG
8842  SCIP_Real lb;
8843  SCIP_Real ub;
8844 
8845  lb = SCIPvarGetLbGlobal(var);
8846  ub = SCIPvarGetUbGlobal(var);
8847 
8848  if(vbtype == SCIP_BOUNDTYPE_LOWER)
8849  {
8850  if( vbcoef > 0.0 )
8851  {
8852  assert(SCIPsetIsGE(set, lb, lb * vbcoef + vbconstant) );
8853  assert(SCIPsetIsGE(set, ub, ub * vbcoef + vbconstant) );
8854  }
8855  else
8856  {
8857  assert(SCIPsetIsGE(set, lb, ub * vbcoef + vbconstant) );
8858  assert(SCIPsetIsGE(set, ub, lb * vbcoef + vbconstant) );
8859  }
8860  }
8861  else
8862  {
8863  assert(vbtype == SCIP_BOUNDTYPE_UPPER);
8864  if( vbcoef > 0.0 )
8865  {
8866  assert(SCIPsetIsLE(set, lb, lb * vbcoef + vbconstant) );
8867  assert(SCIPsetIsLE(set, ub, ub * vbcoef + vbconstant) );
8868  }
8869  else
8870  {
8871  assert(SCIPsetIsLE(set, lb, ub * vbcoef + vbconstant) );
8872  assert(SCIPsetIsLE(set, ub, lb * vbcoef + vbconstant) );
8873  }
8874  }
8875 #endif
8876  SCIPsetDebugMsg(set, "redundant variable bound: <%s> %s %g<%s> %+g\n",
8877  SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
8878 
8879  return SCIP_OKAY;
8880  }
8881 
8882  SCIPsetDebugMsg(set, "adding variable bound: <%s> %s %g<%s> %+g\n",
8883  SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
8884 
8885  /* check variable bound on debugging solution */
8886  SCIP_CALL( SCIPdebugCheckVbound(set, var, vbtype, vbvar, vbcoef, vbconstant) ); /*lint !e506 !e774*/
8887 
8888  /* perform the addition */
8889  if( vbtype == SCIP_BOUNDTYPE_LOWER )
8890  {
8891  SCIP_CALL( SCIPvboundsAdd(&var->vlbs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
8892  }
8893  else
8894  {
8895  SCIP_CALL( SCIPvboundsAdd(&var->vubs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
8896  }
8897  var->closestvblpcount = -1;
8898 
8899  if( added )
8900  {
8901  /* issue IMPLADDED event */
8902  SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
8903  }
8904 
8905  return SCIP_OKAY;
8906 }
8907 
8908 /** checks whether the given implication is redundant or infeasible w.r.t. the implied variables global bounds */
8909 static
8910 void checkImplic(
8911  SCIP_SET* set, /**< global SCIP settings */
8912  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
8913  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
8914  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
8915  SCIP_Bool* redundant, /**< pointer to store whether the implication is redundant */
8916  SCIP_Bool* infeasible /**< pointer to store whether the implication is infeasible */
8917  )
8918 {
8919  SCIP_Real impllb;
8920  SCIP_Real implub;
8921 
8922  assert(redundant != NULL);
8923  assert(infeasible != NULL);
8924 
8925  impllb = SCIPvarGetLbGlobal(implvar);
8926  implub = SCIPvarGetUbGlobal(implvar);
8927  if( impltype == SCIP_BOUNDTYPE_LOWER )
8928  {
8929  *infeasible = SCIPsetIsFeasGT(set, implbound, implub);
8930  *redundant = SCIPsetIsFeasLE(set, implbound, impllb);
8931  }
8932  else
8933  {
8934  *infeasible = SCIPsetIsFeasLT(set, implbound, impllb);
8935  *redundant = SCIPsetIsFeasGE(set, implbound, implub);
8936  }
8937 }
8938 
8939 /** applies the given implication, if it is not redundant */
8940 static
8942  BMS_BLKMEM* blkmem, /**< block memory */
8943  SCIP_SET* set, /**< global SCIP settings */
8944  SCIP_STAT* stat, /**< problem statistics */
8945  SCIP_PROB* transprob, /**< transformed problem */
8946  SCIP_PROB* origprob, /**< original problem */
8947  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
8948  SCIP_REOPT* reopt, /**< reoptimization data structure */
8949  SCIP_LP* lp, /**< current LP data */
8950  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
8951  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
8952  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
8953  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
8954  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
8955  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
8956  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
8957  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
8958  )
8959 {
8960  SCIP_Real implub;
8961  SCIP_Real impllb;
8962 
8963  assert(infeasible != NULL);
8964 
8965  *infeasible = FALSE;
8966 
8967  implub = SCIPvarGetUbGlobal(implvar);
8968  impllb = SCIPvarGetLbGlobal(implvar);
8969  if( impltype == SCIP_BOUNDTYPE_LOWER )
8970  {
8971  if( SCIPsetIsFeasGT(set, implbound, implub) )
8972  {
8973  /* the implication produces a conflict: the problem is infeasible */
8974  *infeasible = TRUE;
8975  }
8976  else if( SCIPsetIsFeasGT(set, implbound, impllb) )
8977  {
8978  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
8979  * with the local bound, in this case we need to store the bound change as pending bound change
8980  */
8981  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
8982  {
8983  assert(tree != NULL);
8984  assert(transprob != NULL);
8985  assert(SCIPprobIsTransformed(transprob));
8986 
8987  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
8988  tree, reopt, lp, branchcand, eventqueue, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
8989  }
8990  else
8991  {
8992  SCIP_CALL( SCIPvarChgLbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
8993  }
8994 
8995  if( nbdchgs != NULL )
8996  (*nbdchgs)++;
8997  }
8998  }
8999  else
9000  {
9001  if( SCIPsetIsFeasLT(set, implbound, impllb) )
9002  {
9003  /* the implication produces a conflict: the problem is infeasible */
9004  *infeasible = TRUE;
9005  }
9006  else if( SCIPsetIsFeasLT(set, implbound, implub) )
9007  {
9008  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9009  * with the local bound, in this case we need to store the bound change as pending bound change
9010  */
9011  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9012  {
9013  assert(tree != NULL);
9014  assert(transprob != NULL);
9015  assert(SCIPprobIsTransformed(transprob));
9016 
9017  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9018  tree, reopt, lp, branchcand, eventqueue, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
9019  }
9020  else
9021  {
9022  SCIP_CALL( SCIPvarChgUbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
9023  }
9024 
9025  if( nbdchgs != NULL )
9026  (*nbdchgs)++;
9027  }
9028  }
9029 
9030  return SCIP_OKAY;
9031 }
9032 
9033 /** actually performs the addition of an implication to the variable's implication arrays,
9034  * and adds the corresponding implication or variable bound to the implied variable;
9035  * if the implication is conflicting, the variable is fixed to the opposite value;
9036  * if the variable is already fixed to the given value, the implication is performed immediately;
9037  * if the implication is redundant with respect to the variables' global bounds, it is ignored
9038  */
9039 static
9041  SCIP_VAR* var, /**< problem variable */
9042  BMS_BLKMEM* blkmem, /**< block memory */
9043  SCIP_SET* set, /**< global SCIP settings */
9044  SCIP_STAT* stat, /**< problem statistics */
9045  SCIP_PROB* transprob, /**< transformed problem */
9046  SCIP_PROB* origprob, /**< original problem */
9047  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9048  SCIP_REOPT* reopt, /**< reoptimization data structure */
9049  SCIP_LP* lp, /**< current LP data */
9050  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9051  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9052  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9053  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9054  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9055  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9056  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9057  SCIP_Bool isshortcut, /**< is the implication a shortcut, i.e., added as part of the transitive closure of another implication? */
9058  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9059  int* nbdchgs, /**< pointer to count the number of performed bound changes, or NULL */
9060  SCIP_Bool* added /**< pointer to store whether an implication was added */
9061  )
9062 {
9063  SCIP_Bool redundant;
9064  SCIP_Bool conflict;
9065 
9066  assert(var != NULL);
9067  assert(SCIPvarIsActive(var));
9069  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
9070  assert(SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED);
9071  assert(infeasible != NULL);
9072  assert(added != NULL);
9073 
9074  /* check implication on debugging solution */
9075  SCIP_CALL( SCIPdebugCheckImplic(set, var, varfixing, implvar, impltype, implbound) ); /*lint !e506 !e774*/
9076 
9077  *infeasible = FALSE;
9078  *added = FALSE;
9079 
9080  /* check, if the implication is redundant or infeasible */
9081  checkImplic(set, implvar, impltype, implbound, &redundant, &conflict);
9082  assert(!redundant || !conflict);
9083  if( redundant )
9084  return SCIP_OKAY;
9085 
9086  if( var == implvar )
9087  {
9088  /* special cases appear were a bound to a variable implies itself to be outside the bounds:
9089  * x == varfixing => x < 0 or x > 1
9090  */
9091  if( SCIPsetIsLT(set, implbound, 0.0) || SCIPsetIsGT(set, implbound, 1.0) )
9092  conflict = TRUE;
9093  else
9094  {
9095  /* variable implies itself: x == varfixing => x == (impltype == SCIP_BOUNDTYPE_LOWER) */
9096  assert(SCIPsetIsZero(set, implbound) || SCIPsetIsEQ(set, implbound, 1.0));
9097  assert(SCIPsetIsZero(set, implbound) == (impltype == SCIP_BOUNDTYPE_UPPER));
9098  assert(SCIPsetIsEQ(set, implbound, 1.0) == (impltype == SCIP_BOUNDTYPE_LOWER));
9099  conflict = conflict || ((varfixing == TRUE) == (impltype == SCIP_BOUNDTYPE_UPPER));
9100  if( !conflict )
9101  return SCIP_OKAY;
9102  }
9103  }
9104 
9105  /* check, if the variable is already fixed */
9106  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
9107  {
9108  /* if the variable is fixed to the given value, perform the implication; otherwise, ignore the implication */
9109  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
9110  {
9111  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
9112  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
9113  }
9114  return SCIP_OKAY;
9115  }
9116 
9117  assert((impltype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, implbound, SCIPvarGetLbGlobal(implvar)))
9118  || (impltype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, implbound, SCIPvarGetUbGlobal(implvar))));
9119 
9120  if( !conflict )
9121  {
9122  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9123 
9124  if( SCIPvarIsBinary(implvar) )
9125  {
9126  SCIP_VAR* vars[2];
9127  SCIP_Bool vals[2];
9128 
9129  assert(SCIPsetIsFeasEQ(set, implbound, 1.0) || SCIPsetIsFeasZero(set, implbound));
9130  assert((impltype == SCIP_BOUNDTYPE_UPPER) == SCIPsetIsFeasZero(set, implbound));
9131 
9132  vars[0] = var;
9133  vars[1] = implvar;
9134  vals[0] = varfixing;
9135  vals[1] = (impltype == SCIP_BOUNDTYPE_UPPER);
9136 
9137  /* add the clique to the clique table */
9138  SCIP_CALL( SCIPcliquetableAdd(cliquetable, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
9139  eventqueue, vars, vals, 2, FALSE, &conflict, nbdchgs) );
9140 
9141  if( !conflict )
9142  return SCIP_OKAY;
9143  }
9144  else
9145  {
9146  /* add implication x == 0/1 -> y <= b / y >= b to the implications list of x */
9147  SCIPsetDebugMsg(set, "adding implication: <%s> == %u ==> <%s> %s %g\n",
9148  SCIPvarGetName(var), varfixing,
9149  SCIPvarGetName(implvar), impltype == SCIP_BOUNDTYPE_UPPER ? "<=" : ">=", implbound);
9150  SCIP_CALL( SCIPimplicsAdd(&var->implics, blkmem, set, stat, varfixing, implvar, impltype, implbound,
9151  isshortcut, &conflict, added) );
9152  }
9153  }
9154  assert(!conflict || !(*added));
9155 
9156  /* on conflict, fix the variable to the opposite value */
9157  if( conflict )
9158  {
9159  SCIPsetDebugMsg(set, " -> implication yields a conflict: fix <%s> == %d\n", SCIPvarGetName(var), !varfixing);
9160 
9161  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9162  * with the local bound, in this case we need to store the bound change as pending bound change
9163  */
9164  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9165  {
9166  assert(tree != NULL);
9167  assert(transprob != NULL);
9168  assert(SCIPprobIsTransformed(transprob));
9169 
9170  if( varfixing )
9171  {
9172  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9173  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
9174  }
9175  else
9176  {
9177  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9178  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
9179  }
9180  }
9181  else
9182  {
9183  if( varfixing )
9184  {
9185  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
9186  }
9187  else
9188  {
9189  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
9190  }
9191  }
9192  if( nbdchgs != NULL )
9193  (*nbdchgs)++;
9194 
9195  return SCIP_OKAY;
9196  }
9197  else if( *added )
9198  {
9199  /* issue IMPLADDED event */
9200  SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
9201  }
9202  else
9203  {
9204  /* the implication was redundant: the inverse is also redundant */
9205  return SCIP_OKAY;
9206  }
9207 
9208  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9209 
9210  /* check, whether implied variable is binary */
9211  if( !SCIPvarIsBinary(implvar) )
9212  {
9213  SCIP_Real lb;
9214  SCIP_Real ub;
9215 
9216  /* add inverse variable bound to the variable bounds of y with global bounds y \in [lb,ub]:
9217  * x == 0 -> y <= b <-> y <= (ub - b)*x + b
9218  * x == 1 -> y <= b <-> y <= (b - ub)*x + ub
9219  * x == 0 -> y >= b <-> y >= (lb - b)*x + b
9220  * x == 1 -> y >= b <-> y >= (b - lb)*x + lb
9221  * for numerical reasons, ignore variable bounds with large absolute coefficient
9222  */
9223  lb = SCIPvarGetLbGlobal(implvar);
9224  ub = SCIPvarGetUbGlobal(implvar);
9225  if( impltype == SCIP_BOUNDTYPE_UPPER )
9226  {
9227  if( REALABS(implbound - ub) <= MAXABSVBCOEF )
9228  {
9229  SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, var,
9230  varfixing ? implbound - ub : ub - implbound, varfixing ? ub : implbound) );
9231  }
9232  }
9233  else
9234  {
9235  if( REALABS(implbound - lb) <= MAXABSVBCOEF )
9236  {
9237  SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, var,
9238  varfixing ? implbound - lb : lb - implbound, varfixing ? lb : implbound) );
9239  }
9240  }
9241  }
9242 
9243  return SCIP_OKAY;
9244 }
9245 
9246 /** adds transitive closure for binary implication x = a -> y = b */
9247 static
9249  SCIP_VAR* var, /**< problem variable */
9250  BMS_BLKMEM* blkmem, /**< block memory */
9251  SCIP_SET* set, /**< global SCIP settings */
9252  SCIP_STAT* stat, /**< problem statistics */
9253  SCIP_PROB* transprob, /**< transformed problem */
9254  SCIP_PROB* origprob, /**< original problem */
9255  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9256  SCIP_REOPT* reopt, /**< reoptimization data structure */
9257  SCIP_LP* lp, /**< current LP data */
9258  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9259  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9260  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9261  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9262  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9263  SCIP_Bool implvarfixing, /**< fixing b in implication */
9264  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9265  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9266  )
9267 {
9268  SCIP_VAR** implvars;
9269  SCIP_BOUNDTYPE* impltypes;
9270  SCIP_Real* implbounds;
9271  int nimpls;
9272  int i;
9273 
9274  *infeasible = FALSE;
9275 
9276  /* binary variable: implications of implvar */
9277  nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
9278  implvars = SCIPimplicsGetVars(implvar->implics, implvarfixing);
9279  impltypes = SCIPimplicsGetTypes(implvar->implics, implvarfixing);
9280  implbounds = SCIPimplicsGetBounds(implvar->implics, implvarfixing);
9281 
9282  /* if variable has too many implications, the implication graph may become too dense */
9283  i = MIN(nimpls, MAXIMPLSCLOSURE) - 1;
9284 
9285  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9286  * implvars[i] is fixed, s.t. the implication y == varfixing -> z <= b / z >= b is deleted; this affects the
9287  * array over which we currently iterate; the only thing that can happen, is that elements of the array are
9288  * deleted; in this case, the subsequent elements are moved to the front; if we iterate from back to front, the
9289  * only thing that can happen is that we add the same implication twice - this does no harm
9290  */
9291  while ( i >= 0 && !(*infeasible) )
9292  {
9293  SCIP_Bool added;
9294 
9295  assert(implvars[i] != implvar);
9296 
9297  /* we have x == varfixing -> y == implvarfixing -> z <= b / z >= b:
9298  * add implication x == varfixing -> z <= b / z >= b to the implications list of x
9299  */
9300  if( SCIPvarIsActive(implvars[i]) )
9301  {
9302  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
9303  eventqueue, varfixing, implvars[i], impltypes[i], implbounds[i], TRUE, infeasible, nbdchgs, &added) );
9304  assert(SCIPimplicsGetNImpls(implvar->implics, implvarfixing) <= nimpls);
9305  nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
9306  i = MIN(i, nimpls); /* some elements from the array could have been removed */
9307  }
9308  --i;
9309  }
9310 
9311  return SCIP_OKAY;
9312 }
9313 
9314 /** adds given implication to the variable's implication list, and adds all implications directly implied by this
9315  * implication to the variable's implication list;
9316  * if the implication is conflicting, the variable is fixed to the opposite value;
9317  * if the variable is already fixed to the given value, the implication is performed immediately;
9318  * if the implication is redundant with respect to the variables' global bounds, it is ignored
9319  */
9320 static
9322  SCIP_VAR* var, /**< problem variable */
9323  BMS_BLKMEM* blkmem, /**< block memory */
9324  SCIP_SET* set, /**< global SCIP settings */
9325  SCIP_STAT* stat, /**< problem statistics */
9326  SCIP_PROB* transprob, /**< transformed problem */
9327  SCIP_PROB* origprob, /**< original problem */
9328  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9329  SCIP_REOPT* reopt, /**< reoptimization data structure */
9330  SCIP_LP* lp, /**< current LP data */
9331  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9332  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9333  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9334  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9335  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9336  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9337  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9338  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
9339  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9340  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9341  )
9342 {
9343  SCIP_Bool added;
9344 
9345  assert(var != NULL);
9346  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
9347  assert(SCIPvarIsActive(var));
9348  assert(implvar != NULL);
9349  assert(SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED);
9350  assert(infeasible != NULL);
9351 
9352  /* add implication x == varfixing -> y <= b / y >= b to the implications list of x */
9353  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
9354  eventqueue, varfixing, implvar, impltype, implbound, FALSE, infeasible, nbdchgs, &added) );
9355 
9356  if( *infeasible || var == implvar || !transitive || !added )
9357  return SCIP_OKAY;
9358 
9359  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9360 
9361  /* add transitive closure */
9362  if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
9363  {
9364  SCIP_Bool implvarfixing;
9365 
9366  implvarfixing = (impltype == SCIP_BOUNDTYPE_LOWER);
9367 
9368  /* binary variable: implications of implvar */
9369  SCIP_CALL( varAddTransitiveBinaryClosureImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9370  cliquetable, branchcand, eventqueue, varfixing, implvar, implvarfixing, infeasible, nbdchgs) );
9371 
9372  /* inverse implication */
9373  if( !(*infeasible) )
9374  {
9375  SCIP_CALL( varAddTransitiveBinaryClosureImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9376  cliquetable, branchcand, eventqueue, !implvarfixing, var, !varfixing, infeasible, nbdchgs) );
9377  }
9378  }
9379  else
9380  {
9381  /* non-binary variable: variable lower bounds of implvar */
9382  if( impltype == SCIP_BOUNDTYPE_UPPER && implvar->vlbs != NULL )
9383  {
9384  SCIP_VAR** vlbvars;
9385  SCIP_Real* vlbcoefs;
9386  SCIP_Real* vlbconstants;
9387  int nvlbvars;
9388  int i;
9389 
9390  nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
9391  vlbvars = SCIPvboundsGetVars(implvar->vlbs);
9392  vlbcoefs = SCIPvboundsGetCoefs(implvar->vlbs);
9393  vlbconstants = SCIPvboundsGetConstants(implvar->vlbs);
9394 
9395  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9396  * vlbvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
9397  * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
9398  * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
9399  * is that we add the same implication twice - this does no harm
9400  */
9401  i = nvlbvars-1;
9402  while ( i >= 0 && !(*infeasible) )
9403  {
9404  assert(vlbvars[i] != implvar);
9405  assert(!SCIPsetIsZero(set, vlbcoefs[i]));
9406 
9407  /* we have x == varfixing -> y <= b and y >= c*z + d:
9408  * c > 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
9409  * c < 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
9410  *
9411  * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
9412  * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
9413  * aggregation variable (the one which will stay active);
9414  *
9415  * W.l.o.g. we consider the variable upper bounds for now. Let "vubvar" be a variable upper bound of
9416  * the aggregated variable "aggvar"; During that copying of that variable upper bound variable
9417  * "vubvar" the variable lower and upper bounds of this variable "vubvar" are also considered; note
9418  * that the "aggvar" can be a variable lower bound variable of the variable "vubvar"; Due to that
9419  * situation it can happen that we reach that code place where "vlbvars[i] == aggvar". In particular
9420  * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
9421  * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
9422  * have to explicitly check that the active variable has not a variable status
9423  * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
9424  */
9425  if( SCIPvarIsActive(vlbvars[i]) && SCIPvarGetStatus(vlbvars[i]) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(vlbvars[i]) != SCIP_VARSTATUS_NEGATED )
9426  {
9427  SCIP_Real vbimplbound;
9428 
9429  vbimplbound = (implbound - vlbconstants[i])/vlbcoefs[i];
9430  if( vlbcoefs[i] >= 0.0 )
9431  {
9432  vbimplbound = adjustedUb(set, SCIPvarGetType(vlbvars[i]), vbimplbound);
9433  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9434  branchcand, eventqueue, varfixing, vlbvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
9435  infeasible, nbdchgs, &added) );
9436  }
9437  else
9438  {
9439  vbimplbound = adjustedLb(set, SCIPvarGetType(vlbvars[i]), vbimplbound);
9440  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9441  branchcand, eventqueue, varfixing, vlbvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
9442  infeasible, nbdchgs, &added) );
9443  }
9444  nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
9445  i = MIN(i, nvlbvars); /* some elements from the array could have been removed */
9446  }
9447  --i;
9448  }
9449  }
9450 
9451  /* non-binary variable: variable upper bounds of implvar */
9452  if( impltype == SCIP_BOUNDTYPE_LOWER && implvar->vubs != NULL )
9453  {
9454  SCIP_VAR** vubvars;
9455  SCIP_Real* vubcoefs;
9456  SCIP_Real* vubconstants;
9457  int nvubvars;
9458  int i;
9459 
9460  nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
9461  vubvars = SCIPvboundsGetVars(implvar->vubs);
9462  vubcoefs = SCIPvboundsGetCoefs(implvar->vubs);
9463  vubconstants = SCIPvboundsGetConstants(implvar->vubs);
9464 
9465  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9466  * vubvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
9467  * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
9468  * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
9469  * is that we add the same implication twice - this does no harm
9470  */
9471  i = nvubvars-1;
9472  while ( i >= 0 && !(*infeasible) )
9473  {
9474  assert(vubvars[i] != implvar);
9475  assert(!SCIPsetIsZero(set, vubcoefs[i]));
9476 
9477  /* we have x == varfixing -> y >= b and y <= c*z + d:
9478  * c > 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
9479  * c < 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
9480  *
9481  * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
9482  * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
9483  * aggregation variable (the one which will stay active);
9484  *
9485  * W.l.o.g. we consider the variable lower bounds for now. Let "vlbvar" be a variable lower bound of
9486  * the aggregated variable "aggvar"; During that copying of that variable lower bound variable
9487  * "vlbvar" the variable lower and upper bounds of this variable "vlbvar" are also considered; note
9488  * that the "aggvar" can be a variable upper bound variable of the variable "vlbvar"; Due to that
9489  * situation it can happen that we reach that code place where "vubvars[i] == aggvar". In particular
9490  * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
9491  * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
9492  * have to explicitly check that the active variable has not a variable status
9493  * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
9494  */
9495  if( SCIPvarIsActive(vubvars[i]) && SCIPvarGetStatus(vubvars[i]) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(vubvars[i]) != SCIP_VARSTATUS_NEGATED )
9496  {
9497  SCIP_Real vbimplbound;
9498 
9499  vbimplbound = (implbound - vubconstants[i])/vubcoefs[i];
9500  if( vubcoefs[i] >= 0.0 )
9501  {
9502  vbimplbound = adjustedLb(set, SCIPvarGetType(vubvars[i]), vbimplbound);
9503  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9504  branchcand, eventqueue, varfixing, vubvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
9505  infeasible, nbdchgs, &added) );
9506  }
9507  else
9508  {
9509  vbimplbound = adjustedUb(set, SCIPvarGetType(vubvars[i]), vbimplbound);
9510  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9511  branchcand, eventqueue, varfixing, vubvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
9512  infeasible, nbdchgs, &added) );
9513  }
9514  nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
9515  i = MIN(i, nvubvars); /* some elements from the array could have been removed */
9516  }
9517  --i;
9518  }
9519  }
9520  }
9521 
9522  return SCIP_OKAY;
9523 }
9524 
9525 /** informs variable x about a globally valid variable lower bound x >= b*z + d with integer variable z;
9526  * if z is binary, the corresponding valid implication for z is also added;
9527  * improves the global bounds of the variable and the vlb variable if possible
9528  */
9530  SCIP_VAR* var, /**< problem variable */
9531  BMS_BLKMEM* blkmem, /**< block memory */
9532  SCIP_SET* set, /**< global SCIP settings */
9533  SCIP_STAT* stat, /**< problem statistics */
9534  SCIP_PROB* transprob, /**< transformed problem */
9535  SCIP_PROB* origprob, /**< original problem */
9536  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9537  SCIP_REOPT* reopt, /**< reoptimization data structure */
9538  SCIP_LP* lp, /**< current LP data */
9539  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9540  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9541  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9542  SCIP_VAR* vlbvar, /**< variable z in x >= b*z + d */
9543  SCIP_Real vlbcoef, /**< coefficient b in x >= b*z + d */
9544  SCIP_Real vlbconstant, /**< constant d in x >= b*z + d */
9545  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
9546  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9547  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
9548  )
9549 {
9550  assert(var != NULL);
9551  assert(set != NULL);
9552  assert(var->scip == set->scip);
9553  assert(SCIPvarGetType(vlbvar) != SCIP_VARTYPE_CONTINUOUS);
9554  assert(infeasible != NULL);
9555 
9556  SCIPsetDebugMsg(set, "adding variable lower bound <%s> >= %g<%s> + %g\n", SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
9557 
9558  *infeasible = FALSE;
9559  if( nbdchgs != NULL )
9560  *nbdchgs = 0;
9561 
9562  switch( SCIPvarGetStatus(var) )
9563  {
9565  assert(var->data.original.transvar != NULL);
9566  SCIP_CALL( SCIPvarAddVlb(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9567  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef, vlbconstant, transitive, infeasible, nbdchgs) );
9568  break;
9569 
9570  case SCIP_VARSTATUS_COLUMN:
9571  case SCIP_VARSTATUS_LOOSE:
9572  case SCIP_VARSTATUS_FIXED:
9573  /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
9574  SCIP_CALL( SCIPvarGetProbvarSum(&vlbvar, set, &vlbcoef, &vlbconstant) );
9575  SCIPsetDebugMsg(set, " -> transformed to variable lower bound <%s> >= %g<%s> + %g\n", SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
9576 
9577  /* if the vlb coefficient is zero, just update the lower bound of the variable */
9578  if( SCIPsetIsZero(set, vlbcoef) )
9579  {
9580  if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetUbGlobal(var)) )
9581  *infeasible = TRUE;
9582  else if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetLbGlobal(var)) )
9583  {
9584  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9585  * with the local bound, in this case we need to store the bound change as pending bound change
9586  */
9587  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9588  {
9589  assert(tree != NULL);
9590  assert(transprob != NULL);
9591  assert(SCIPprobIsTransformed(transprob));
9592 
9593  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9594  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vlbconstant, SCIP_BOUNDTYPE_LOWER, FALSE) );
9595  }
9596  else
9597  {
9598  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vlbconstant) );
9599  }
9600 
9601  if( nbdchgs != NULL )
9602  (*nbdchgs)++;
9603  }
9604  }
9605  else if( SCIPvarIsActive(vlbvar) )
9606  {
9607  SCIP_Real xlb;
9608  SCIP_Real xub;
9609  SCIP_Real zlb;
9610  SCIP_Real zub;
9611  SCIP_Real minvlb;
9612  SCIP_Real maxvlb;
9613 
9615  assert(vlbcoef != 0.0);
9616 
9617  minvlb = -SCIPsetInfinity(set);
9618  maxvlb = SCIPsetInfinity(set);
9619 
9620  xlb = SCIPvarGetLbGlobal(var);
9621  xub = SCIPvarGetUbGlobal(var);
9622  zlb = SCIPvarGetLbGlobal(vlbvar);
9623  zub = SCIPvarGetUbGlobal(vlbvar);
9624 
9625  /* improve global bounds of vlb variable, and calculate minimal and maximal value of variable bound */
9626  if( vlbcoef >= 0.0 )
9627  {
9628  SCIP_Real newzub;
9629 
9630  if( !SCIPsetIsInfinity(set, xub) )
9631  {
9632  /* x >= b*z + d -> z <= (x-d)/b */
9633  newzub = (xub - vlbconstant)/vlbcoef;
9634 
9635  /* return if the new bound is less than -infinity */
9636  if( SCIPsetIsInfinity(set, REALABS(newzub)) )
9637  return SCIP_OKAY;
9638 
9639  if( SCIPsetIsFeasLT(set, newzub, zlb) )
9640  {
9641  *infeasible = TRUE;
9642  return SCIP_OKAY;
9643  }
9644  if( SCIPsetIsFeasLT(set, newzub, zub) )
9645  {
9646  /* bound might be adjusted due to integrality condition */
9647  newzub = adjustedUb(set, SCIPvarGetType(vlbvar), newzub);
9648 
9649  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9650  * with the local bound, in this case we need to store the bound change as pending bound change
9651  */
9652  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9653  {
9654  assert(tree != NULL);
9655  assert(transprob != NULL);
9656  assert(SCIPprobIsTransformed(transprob));
9657 
9658  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9659  tree, reopt, lp, branchcand, eventqueue, cliquetable, vlbvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
9660  }
9661  else
9662  {
9663  SCIP_CALL( SCIPvarChgUbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
9664  }
9665  zub = newzub;
9666 
9667  if( nbdchgs != NULL )
9668  (*nbdchgs)++;
9669  }
9670  maxvlb = vlbcoef * zub + vlbconstant;
9671  if( !SCIPsetIsInfinity(set, -zlb) )
9672  minvlb = vlbcoef * zlb + vlbconstant;
9673  }
9674  else
9675  {
9676  if( !SCIPsetIsInfinity(set, zub) )
9677  maxvlb = vlbcoef * zub + vlbconstant;
9678  if( !SCIPsetIsInfinity(set, -zlb) )
9679  minvlb = vlbcoef * zlb + vlbconstant;
9680  }
9681  }
9682  else
9683  {
9684  SCIP_Real newzlb;
9685 
9686  if( !SCIPsetIsInfinity(set, xub) )
9687  {
9688  /* x >= b*z + d -> z >= (x-d)/b */
9689  newzlb = (xub - vlbconstant)/vlbcoef;
9690 
9691  /* return if the new bound is larger than infinity */
9692  if( SCIPsetIsInfinity(set, REALABS(newzlb)) )
9693  return SCIP_OKAY;
9694 
9695  if( SCIPsetIsFeasGT(set, newzlb, zub) )
9696  {
9697  *infeasible = TRUE;
9698  return SCIP_OKAY;
9699  }
9700  if( SCIPsetIsFeasGT(set, newzlb, zlb) )
9701  {
9702  /* bound might be adjusted due to integrality condition */
9703  newzlb = adjustedLb(set, SCIPvarGetType(vlbvar), newzlb);
9704 
9705  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9706  * with the local bound, in this case we need to store the bound change as pending bound change
9707  */
9708  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9709  {
9710  assert(tree != NULL);
9711  assert(transprob != NULL);
9712  assert(SCIPprobIsTransformed(transprob));
9713 
9714  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9715  tree, reopt, lp, branchcand, eventqueue, cliquetable, vlbvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
9716  }
9717  else
9718  {
9719  SCIP_CALL( SCIPvarChgLbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
9720  }
9721  zlb = newzlb;
9722 
9723  if( nbdchgs != NULL )
9724  (*nbdchgs)++;
9725  }
9726  maxvlb = vlbcoef * zlb + vlbconstant;
9727  if( !SCIPsetIsInfinity(set, zub) )
9728  minvlb = vlbcoef * zub + vlbconstant;
9729  }
9730  else
9731  {
9732  if( !SCIPsetIsInfinity(set, -zlb) )
9733  maxvlb = vlbcoef * zlb + vlbconstant;
9734  if( !SCIPsetIsInfinity(set, zub) )
9735  minvlb = vlbcoef * zub + vlbconstant;
9736  }
9737  }
9738  if( maxvlb < minvlb )
9739  maxvlb = minvlb;
9740 
9741  /* adjust bounds due to integrality of variable */
9742  minvlb = adjustedLb(set, SCIPvarGetType(var), minvlb);
9743  maxvlb = adjustedLb(set, SCIPvarGetType(var), maxvlb);
9744 
9745  /* check bounds for feasibility */
9746  if( SCIPsetIsFeasGT(set, minvlb, xub) || (var == vlbvar && SCIPsetIsEQ(set, vlbcoef, 1.0) && SCIPsetIsFeasPositive(set, vlbconstant)) )
9747  {
9748  *infeasible = TRUE;
9749  return SCIP_OKAY;
9750  }
9751  /* improve global lower bound of variable */
9752  if( SCIPsetIsFeasGT(set, minvlb, xlb) )
9753  {
9754  /* bound might be adjusted due to integrality condition */
9755  minvlb = adjustedLb(set, SCIPvarGetType(var), minvlb);
9756 
9757  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9758  * with the local bound, in this case we need to store the bound change as pending bound change
9759  */
9760  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9761  {
9762  assert(tree != NULL);
9763  assert(transprob != NULL);
9764  assert(SCIPprobIsTransformed(transprob));
9765 
9766  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9767  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, minvlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
9768  }
9769  else
9770  {
9771  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, minvlb) );
9772  }
9773  xlb = minvlb;
9774 
9775  if( nbdchgs != NULL )
9776  (*nbdchgs)++;
9777  }
9778  minvlb = xlb;
9779 
9780  /* improve variable bound for binary z by moving the variable's global bound to the vlb constant */
9781  if( SCIPvarGetType(vlbvar) == SCIP_VARTYPE_BINARY )
9782  {
9783  /* b > 0: x >= (maxvlb - minvlb) * z + minvlb
9784  * b < 0: x >= (minvlb - maxvlb) * z + maxvlb
9785  */
9786 
9787  assert(!SCIPsetIsInfinity(set, maxvlb) && !SCIPsetIsInfinity(set, -minvlb));
9788 
9789  if( vlbcoef >= 0.0 )
9790  {
9791  vlbcoef = maxvlb - minvlb;
9792  vlbconstant = minvlb;
9793  }
9794  else
9795  {
9796  vlbcoef = minvlb - maxvlb;
9797  vlbconstant = maxvlb;
9798  }
9799  }
9800 
9801  /* add variable bound to the variable bounds list */
9802  if( SCIPsetIsFeasGT(set, maxvlb, xlb) )
9803  {
9804  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED);
9805  assert(!SCIPsetIsZero(set, vlbcoef));
9806 
9807  /* if one of the variables is binary, add the corresponding implication to the variable's implication
9808  * list, thereby also adding the variable bound (or implication) to the other variable
9809  */
9810  if( SCIPvarGetType(vlbvar) == SCIP_VARTYPE_BINARY )
9811  {
9812  /* add corresponding implication:
9813  * b > 0, x >= b*z + d <-> z == 1 -> x >= b+d
9814  * b < 0, x >= b*z + d <-> z == 0 -> x >= d
9815  */
9816  SCIP_CALL( varAddTransitiveImplic(vlbvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9817  cliquetable, branchcand, eventqueue, (vlbcoef >= 0.0), var, SCIP_BOUNDTYPE_LOWER, maxvlb, transitive,
9818  infeasible, nbdchgs) );
9819  }
9820  else if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
9821  {
9822  /* add corresponding implication:
9823  * b > 0, x >= b*z + d <-> x == 0 -> z <= -d/b
9824  * b < 0, x >= b*z + d <-> x == 0 -> z >= -d/b
9825  */
9826  SCIP_Real implbound;
9827  implbound = -vlbconstant/vlbcoef;
9828 
9829  /* tighten the implication bound if the variable is integer */
9830  if( SCIPvarIsIntegral(vlbvar) )
9831  {
9832  if( vlbcoef >= 0 )
9833  implbound = SCIPsetFloor(set, implbound);
9834  else
9835  implbound = SCIPsetCeil(set, implbound);
9836  }
9837  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9838  cliquetable, branchcand, eventqueue, FALSE, vlbvar, (vlbcoef >= 0.0 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER),
9839  implbound, transitive, infeasible, nbdchgs) );
9840  }
9841  else
9842  {
9843  SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, vlbvar, vlbcoef, vlbconstant) );
9844  }
9845  }
9846  }
9847  break;
9848 
9850  /* x = a*y + c: x >= b*z + d <=> a*y + c >= b*z + d <=> y >= b/a * z + (d-c)/a, if a > 0
9851  * y <= b/a * z + (d-c)/a, if a < 0
9852  */
9853  assert(var->data.aggregate.var != NULL);
9854  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
9855  {
9856  /* a > 0 -> add variable lower bound */
9857  SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9858  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef/var->data.aggregate.scalar,
9859  (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
9860  }
9861  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
9862  {
9863  /* a < 0 -> add variable upper bound */
9864  SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9865  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef/var->data.aggregate.scalar,
9866  (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
9867  }
9868  else
9869  {
9870  SCIPerrorMessage("scalar is zero in aggregation\n");
9871  return SCIP_INVALIDDATA;
9872  }
9873  break;
9874 
9876  /* nothing to do here */
9877  break;
9878 
9880  /* x = offset - x': x >= b*z + d <=> offset - x' >= b*z + d <=> x' <= -b*z + (offset-d) */
9881  assert(var->negatedvar != NULL);
9883  assert(var->negatedvar->negatedvar == var);
9884  SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9885  branchcand, eventqueue, vlbvar, -vlbcoef, var->data.negate.constant - vlbconstant, transitive, infeasible,
9886  nbdchgs) );
9887  break;
9888 
9889  default:
9890  SCIPerrorMessage("unknown variable status\n");
9891  return SCIP_INVALIDDATA;
9892  }
9893 
9894  return SCIP_OKAY;
9895 }
9896 
9897 /** informs variable x about a globally valid variable upper bound x <= b*z + d with integer variable z;
9898  * if z is binary, the corresponding valid implication for z is also added;
9899  * updates the global bounds of the variable and the vub variable correspondingly
9900  */
9902  SCIP_VAR* var, /**< problem variable */
9903  BMS_BLKMEM* blkmem, /**< block memory */
9904  SCIP_SET* set, /**< global SCIP settings */
9905  SCIP_STAT* stat, /**< problem statistics */
9906  SCIP_PROB* transprob, /**< transformed problem */
9907  SCIP_PROB* origprob, /**< original problem */
9908  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9909  SCIP_REOPT* reopt, /**< reoptimization data structure */
9910  SCIP_LP* lp, /**< current LP data */
9911  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9912  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9913  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9914  SCIP_VAR* vubvar, /**< variable z in x <= b*z + d */
9915  SCIP_Real vubcoef, /**< coefficient b in x <= b*z + d */
9916  SCIP_Real vubconstant, /**< constant d in x <= b*z + d */
9917  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
9918  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9919  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
9920  )
9921 {
9922  assert(var != NULL);
9923  assert(set != NULL);
9924  assert(var->scip == set->scip);
9925  assert(SCIPvarGetType(vubvar) != SCIP_VARTYPE_CONTINUOUS);
9926  assert(infeasible != NULL);
9927 
9928  SCIPsetDebugMsg(set, "adding variable upper bound <%s> <= %g<%s> + %g\n", SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
9929 
9930  *infeasible = FALSE;
9931  if( nbdchgs != NULL )
9932  *nbdchgs = 0;
9933 
9934  switch( SCIPvarGetStatus(var) )
9935  {
9937  assert(var->data.original.transvar != NULL);
9938  SCIP_CALL( SCIPvarAddVub(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9939  cliquetable, branchcand, eventqueue, vubvar, vubcoef, vubconstant, transitive, infeasible, nbdchgs) );
9940  break;
9941 
9942  case SCIP_VARSTATUS_COLUMN:
9943  case SCIP_VARSTATUS_LOOSE:
9944  case SCIP_VARSTATUS_FIXED:
9945  /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
9946  SCIP_CALL( SCIPvarGetProbvarSum(&vubvar, set, &vubcoef, &vubconstant) );
9947  SCIPsetDebugMsg(set, " -> transformed to variable upper bound <%s> <= %g<%s> + %g\n",
9948  SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
9949 
9950  /* if the vub coefficient is zero, just update the upper bound of the variable */
9951  if( SCIPsetIsZero(set, vubcoef) )
9952  {
9953  if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetLbGlobal(var)) )
9954  *infeasible = TRUE;
9955  else if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetUbGlobal(var)) )
9956  {
9957  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9958  * with the local bound, in this case we need to store the bound change as pending bound change
9959  */
9960  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9961  {
9962  assert(tree != NULL);
9963  assert(transprob != NULL);
9964  assert(SCIPprobIsTransformed(transprob));
9965 
9966  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9967  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vubconstant, SCIP_BOUNDTYPE_UPPER, FALSE) );
9968  }
9969  else
9970  {
9971  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vubconstant) );
9972  }
9973 
9974  if( nbdchgs != NULL )
9975  (*nbdchgs)++;
9976  }
9977  }
9978  else if( SCIPvarIsActive(vubvar) )
9979  {
9980  SCIP_Real xlb;
9981  SCIP_Real xub;
9982  SCIP_Real zlb;
9983  SCIP_Real zub;
9984  SCIP_Real minvub;
9985  SCIP_Real maxvub;
9986 
9988  assert(vubcoef != 0.0);
9989 
9990  minvub = -SCIPsetInfinity(set);
9991  maxvub = SCIPsetInfinity(set);
9992 
9993  xlb = SCIPvarGetLbGlobal(var);
9994  xub = SCIPvarGetUbGlobal(var);
9995  zlb = SCIPvarGetLbGlobal(vubvar);
9996  zub = SCIPvarGetUbGlobal(vubvar);
9997 
9998  /* improve global bounds of vub variable, and calculate minimal and maximal value of variable bound */
9999  if( vubcoef >= 0.0 )
10000  {
10001  SCIP_Real newzlb;
10002 
10003  if( !SCIPsetIsInfinity(set, -xlb) )
10004  {
10005  /* x <= b*z + d -> z >= (x-d)/b */
10006  newzlb = (xlb - vubconstant)/vubcoef;
10007  if( SCIPsetIsFeasGT(set, newzlb, zub) )
10008  {
10009  *infeasible = TRUE;
10010  return SCIP_OKAY;
10011  }
10012  if( SCIPsetIsFeasGT(set, newzlb, zlb) )
10013  {
10014  /* bound might be adjusted due to integrality condition */
10015  newzlb = adjustedLb(set, SCIPvarGetType(vubvar), newzlb);
10016 
10017  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10018  * with the local bound, in this case we need to store the bound change as pending bound change
10019  */
10020  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10021  {
10022  assert(tree != NULL);
10023  assert(transprob != NULL);
10024  assert(SCIPprobIsTransformed(transprob));
10025 
10026  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10027  tree, reopt, lp, branchcand, eventqueue, cliquetable, vubvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10028  }
10029  else
10030  {
10031  SCIP_CALL( SCIPvarChgLbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
10032  }
10033  zlb = newzlb;
10034 
10035  if( nbdchgs != NULL )
10036  (*nbdchgs)++;
10037  }
10038  minvub = vubcoef * zlb + vubconstant;
10039  if( !SCIPsetIsInfinity(set, zub) )
10040  maxvub = vubcoef * zub + vubconstant;
10041  }
10042  else
10043  {
10044  if( !SCIPsetIsInfinity(set, zub) )
10045  maxvub = vubcoef * zub + vubconstant;
10046  if( !SCIPsetIsInfinity(set, -zlb) )
10047  minvub = vubcoef * zlb + vubconstant;
10048  }
10049  }
10050  else
10051  {
10052  SCIP_Real newzub;
10053 
10054  if( !SCIPsetIsInfinity(set, -xlb) )
10055  {
10056  /* x <= b*z + d -> z <= (x-d)/b */
10057  newzub = (xlb - vubconstant)/vubcoef;
10058  if( SCIPsetIsFeasLT(set, newzub, zlb) )
10059  {
10060  *infeasible = TRUE;
10061  return SCIP_OKAY;
10062  }
10063  if( SCIPsetIsFeasLT(set, newzub, zub) )
10064  {
10065  /* bound might be adjusted due to integrality condition */
10066  newzub = adjustedUb(set, SCIPvarGetType(vubvar), newzub);
10067 
10068  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10069  * with the local bound, in this case we need to store the bound change as pending bound change
10070  */
10071  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10072  {
10073  assert(tree != NULL);
10074  assert(transprob != NULL);
10075  assert(SCIPprobIsTransformed(transprob));
10076 
10077  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10078  tree, reopt, lp, branchcand, eventqueue, cliquetable, vubvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10079  }
10080  else
10081  {
10082  SCIP_CALL( SCIPvarChgUbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
10083  }
10084  zub = newzub;
10085 
10086  if( nbdchgs != NULL )
10087  (*nbdchgs)++;
10088  }
10089  minvub = vubcoef * zub + vubconstant;
10090  if( !SCIPsetIsInfinity(set, -zlb) )
10091  maxvub = vubcoef * zlb + vubconstant;
10092  }
10093  else
10094  {
10095  if( !SCIPsetIsInfinity(set, zub) )
10096  minvub = vubcoef * zub + vubconstant;
10097  if( !SCIPsetIsInfinity(set, -zlb) )
10098  maxvub = vubcoef * zlb + vubconstant;
10099  }
10100 
10101  }
10102  if( minvub > maxvub )
10103  minvub = maxvub;
10104 
10105  /* adjust bounds due to integrality of vub variable */
10106  minvub = adjustedUb(set, SCIPvarGetType(var), minvub);
10107  maxvub = adjustedUb(set, SCIPvarGetType(var), maxvub);
10108 
10109  /* check bounds for feasibility */
10110  if( SCIPsetIsFeasLT(set, maxvub, xlb) || (var == vubvar && SCIPsetIsEQ(set, vubcoef, 1.0) && SCIPsetIsFeasNegative(set, vubconstant)) )
10111  {
10112  *infeasible = TRUE;
10113  return SCIP_OKAY;
10114  }
10115  /* improve global upper bound of variable */
10116  if( SCIPsetIsFeasLT(set, maxvub, xub) )
10117  {
10118  /* bound might be adjusted due to integrality condition */
10119  maxvub = adjustedUb(set, SCIPvarGetType(var), maxvub);
10120 
10121  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10122  * with the local bound, in this case we need to store the bound change as pending bound change
10123  */
10124  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10125  {
10126  assert(tree != NULL);
10127  assert(transprob != NULL);
10128  assert(SCIPprobIsTransformed(transprob));
10129 
10130  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10131  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, maxvub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10132  }
10133  else
10134  {
10135  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, maxvub) );
10136  }
10137  xub = maxvub;
10138 
10139  if( nbdchgs != NULL )
10140  (*nbdchgs)++;
10141  }
10142  maxvub = xub;
10143 
10144  /* improve variable bound for binary z by moving the variable's global bound to the vub constant */
10145  if( SCIPvarIsBinary(vubvar) )
10146  {
10147  /* b > 0: x <= (maxvub - minvub) * z + minvub
10148  * b < 0: x <= (minvub - maxvub) * z + maxvub
10149  */
10150 
10151  assert(!SCIPsetIsInfinity(set, maxvub) && !SCIPsetIsInfinity(set, -minvub));
10152 
10153  if( vubcoef >= 0.0 )
10154  {
10155  vubcoef = maxvub - minvub;
10156  vubconstant = minvub;
10157  }
10158  else
10159  {
10160  vubcoef = minvub - maxvub;
10161  vubconstant = maxvub;
10162  }
10163  }
10164 
10165  /* add variable bound to the variable bounds list */
10166  if( SCIPsetIsFeasLT(set, minvub, xub) )
10167  {
10168  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED);
10169  assert(!SCIPsetIsZero(set, vubcoef));
10170 
10171  /* if one of the variables is binary, add the corresponding implication to the variable's implication
10172  * list, thereby also adding the variable bound (or implication) to the other variable
10173  */
10174  if( SCIPvarGetType(vubvar) == SCIP_VARTYPE_BINARY )
10175  {
10176  /* add corresponding implication:
10177  * b > 0, x <= b*z + d <-> z == 0 -> x <= d
10178  * b < 0, x <= b*z + d <-> z == 1 -> x <= b+d
10179  */
10180  SCIP_CALL( varAddTransitiveImplic(vubvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10181  cliquetable, branchcand, eventqueue, (vubcoef < 0.0), var, SCIP_BOUNDTYPE_UPPER, minvub, transitive,
10182  infeasible, nbdchgs) );
10183  }
10184  else if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
10185  {
10186  /* add corresponding implication:
10187  * b > 0, x <= b*z + d <-> x == 1 -> z >= (1-d)/b
10188  * b < 0, x <= b*z + d <-> x == 1 -> z <= (1-d)/b
10189  */
10190  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10191  cliquetable, branchcand, eventqueue, TRUE, vubvar, (vubcoef >= 0.0 ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER),
10192  (1.0-vubconstant)/vubcoef, transitive, infeasible, nbdchgs) );
10193  }
10194  else
10195  {
10196  SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, vubvar, vubcoef, vubconstant) );
10197  }
10198  }
10199  }
10200  break;
10201 
10203  /* x = a*y + c: x <= b*z + d <=> a*y + c <= b*z + d <=> y <= b/a * z + (d-c)/a, if a > 0
10204  * y >= b/a * z + (d-c)/a, if a < 0
10205  */
10206  assert(var->data.aggregate.var != NULL);
10207  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
10208  {
10209  /* a > 0 -> add variable upper bound */
10210  SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10211  cliquetable, branchcand, eventqueue, vubvar, vubcoef/var->data.aggregate.scalar,
10212  (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10213  }
10214  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
10215  {
10216  /* a < 0 -> add variable lower bound */
10217  SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10218  cliquetable, branchcand, eventqueue, vubvar, vubcoef/var->data.aggregate.scalar,
10219  (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10220  }
10221  else
10222  {
10223  SCIPerrorMessage("scalar is zero in aggregation\n");
10224  return SCIP_INVALIDDATA;
10225  }
10226  break;
10227 
10229  /* nothing to do here */
10230  break;
10231 
10233  /* x = offset - x': x <= b*z + d <=> offset - x' <= b*z + d <=> x' >= -b*z + (offset-d) */
10234  assert(var->negatedvar != NULL);
10236  assert(var->negatedvar->negatedvar == var);
10237  SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10238  branchcand, eventqueue, vubvar, -vubcoef, var->data.negate.constant - vubconstant, transitive, infeasible,
10239  nbdchgs) );
10240  break;
10241 
10242  default:
10243  SCIPerrorMessage("unknown variable status\n");
10244  return SCIP_INVALIDDATA;
10245  }
10246 
10247  return SCIP_OKAY;
10248 }
10249 
10250 /** informs binary variable x about a globally valid implication: x == 0 or x == 1 ==> y <= b or y >= b;
10251  * also adds the corresponding implication or variable bound to the implied variable;
10252  * if the implication is conflicting, the variable is fixed to the opposite value;
10253  * if the variable is already fixed to the given value, the implication is performed immediately;
10254  * if the implication is redundant with respect to the variables' global bounds, it is ignored
10255  */
10257  SCIP_VAR* var, /**< problem variable */
10258  BMS_BLKMEM* blkmem, /**< block memory */
10259  SCIP_SET* set, /**< global SCIP settings */
10260  SCIP_STAT* stat, /**< problem statistics */
10261  SCIP_PROB* transprob, /**< transformed problem */
10262  SCIP_PROB* origprob, /**< original problem */
10263  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10264  SCIP_REOPT* reopt, /**< reoptimization data structure */
10265  SCIP_LP* lp, /**< current LP data */
10266  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10267  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10268  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10269  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
10270  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
10271  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
10272  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
10273  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
10274  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10275  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
10276  )
10277 {
10278  assert(var != NULL);
10279  assert(set != NULL);
10280  assert(var->scip == set->scip);
10281  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
10282  assert(infeasible != NULL);
10283 
10284  *infeasible = FALSE;
10285  if( nbdchgs != NULL )
10286  *nbdchgs = 0;
10287 
10288  switch( SCIPvarGetStatus(var) )
10289  {
10291  assert(var->data.original.transvar != NULL);
10292  SCIP_CALL( SCIPvarAddImplic(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10293  cliquetable, branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible,
10294  nbdchgs) );
10295  break;
10296 
10297  case SCIP_VARSTATUS_COLUMN:
10298  case SCIP_VARSTATUS_LOOSE:
10299  /* if the variable is fixed (although it has no FIXED status), and varfixing corresponds to the fixed value of
10300  * the variable, the implication can be applied directly;
10301  * otherwise, add implication to the implications list (and add inverse of implication to the implied variable)
10302  */
10303  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
10304  {
10305  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
10306  {
10307  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
10308  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
10309  }
10310  }
10311  else
10312  {
10313  SCIP_CALL( SCIPvarGetProbvarBound(&implvar, &implbound, &impltype) );
10314  SCIPvarAdjustBd(implvar, set, impltype, &implbound);
10315  if( SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED )
10316  {
10317  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10318  branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
10319  }
10320  }
10321  break;
10322 
10323  case SCIP_VARSTATUS_FIXED:
10324  /* if varfixing corresponds to the fixed value of the variable, the implication can be applied directly */
10325  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
10326  {
10327  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
10328  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
10329  }
10330  break;
10331 
10333  /* implication added for x == 1:
10334  * x == 1 && x = 1*z + 0 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10335  * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10336  * implication added for x == 0:
10337  * x == 0 && x = 1*z + 0 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10338  * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10339  *
10340  * use only binary variables z
10341  */
10342  assert(var->data.aggregate.var != NULL);
10343  if( SCIPvarIsBinary(var->data.aggregate.var) )
10344  {
10345  assert( (SCIPsetIsEQ(set, var->data.aggregate.scalar, 1.0) && SCIPsetIsZero(set, var->data.aggregate.constant))
10346  || (SCIPsetIsEQ(set, var->data.aggregate.scalar, -1.0) && SCIPsetIsEQ(set, var->data.aggregate.constant, 1.0)) );
10347 
10348  if( var->data.aggregate.scalar > 0 )
10349  {
10350  SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10351  cliquetable, branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible,
10352  nbdchgs) );
10353  }
10354  else
10355  {
10356  SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10357  cliquetable, branchcand, eventqueue, !varfixing, implvar, impltype, implbound, transitive, infeasible,
10358  nbdchgs) );
10359  }
10360  }
10361  break;
10362 
10364  /* nothing to do here */
10365  break;
10366 
10368  /* implication added for x == 1:
10369  * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10370  * implication added for x == 0:
10371  * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10372  */
10373  assert(var->negatedvar != NULL);
10375  assert(var->negatedvar->negatedvar == var);
10376  assert(SCIPvarIsBinary(var->negatedvar));
10377 
10379  {
10380  SCIP_CALL( SCIPvarAddImplic(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10381  cliquetable, branchcand, eventqueue, !varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
10382  }
10383  /* in case one both variables are not of binary type we have to add the implication as variable bounds */
10384  else
10385  {
10386  /* if the implied variable is of binary type exchange the variables */
10387  if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
10388  {
10389  SCIP_CALL( SCIPvarAddImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10390  branchcand, eventqueue, (impltype == SCIP_BOUNDTYPE_UPPER) ? TRUE : FALSE, var->negatedvar,
10391  varfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER, varfixing ? 1.0 : 0.0, transitive,
10392  infeasible, nbdchgs) );
10393  }
10394  else
10395  {
10396  /* both variables are not of binary type but are implicit binary; in that case we can only add this
10397  * implication as variable bounds
10398  */
10399 
10400  /* add variable lower bound on the negation of var */
10401  if( varfixing )
10402  {
10403  /* (x = 1 => i) z = 0 ii) z = 1) <=> ( i) z = 1 ii) z = 0 => ~x = 1), this is done by adding ~x >= b*z + d
10404  * as variable lower bound
10405  */
10406  SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10407  cliquetable, branchcand, eventqueue, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : -1.0,
10408  (impltype == SCIP_BOUNDTYPE_UPPER) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
10409  }
10410  else
10411  {
10412  /* (x = 0 => i) z = 0 ii) z = 1) <=> ( i) z = 1 ii) z = 0 => ~x = 0), this is done by adding ~x <= b*z + d
10413  * as variable upper bound
10414  */
10415  SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10416  cliquetable, branchcand, eventqueue, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? -1.0 : 1.0,
10417  (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : 0.0, transitive, infeasible, nbdchgs) );
10418  }
10419 
10420  /* add variable bound on implvar */
10421  if( impltype == SCIP_BOUNDTYPE_UPPER )
10422  {
10423  /* (z = 1 => i) x = 0 ii) x = 1) <=> ( i) ~x = 0 ii) ~x = 1 => z = 0), this is done by adding z <= b*~x + d
10424  * as variable upper bound
10425  */
10426  SCIP_CALL( SCIPvarAddVub(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10427  branchcand, eventqueue, var->negatedvar, (varfixing) ? 1.0 : -1.0,
10428  (varfixing) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
10429  }
10430  else
10431  {
10432  /* (z = 0 => i) x = 0 ii) x = 1) <=> ( i) ~x = 0 ii) ~x = 1 => z = 1), this is done by adding z >= b*~x + d
10433  * as variable upper bound
10434  */
10435  SCIP_CALL( SCIPvarAddVlb(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10436  branchcand, eventqueue, var->negatedvar, (varfixing) ? -1.0 : 1.0, (varfixing) ? 1.0 : 0.0,
10437  transitive, infeasible, nbdchgs) );
10438  }
10439  }
10440  }
10441  break;
10442 
10443  default:
10444  SCIPerrorMessage("unknown variable status\n");
10445  return SCIP_INVALIDDATA;
10446  }
10447 
10448  return SCIP_OKAY;
10449 }
10450 
10451 /** returns whether there is an implication x == varfixing -> y <= b or y >= b in the implication graph;
10452  * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
10453  * both variables must be active, variable x must be binary
10454  */
10456  SCIP_VAR* var, /**< problem variable x */
10457  SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
10458  SCIP_VAR* implvar, /**< variable y to search for */
10459  SCIP_BOUNDTYPE impltype /**< type of implication y <=/>= b to search for */
10460  )
10461 {
10462  assert(var != NULL);
10463  assert(implvar != NULL);
10464  assert(SCIPvarIsActive(var));
10465  assert(SCIPvarIsActive(implvar));
10466  assert(SCIPvarIsBinary(var));
10467 
10468  return var->implics != NULL && SCIPimplicsContainsImpl(var->implics, varfixing, implvar, impltype);
10469 }
10470 
10471 /** returns whether there is an implication x == varfixing -> y == implvarfixing in the implication graph;
10472  * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
10473  * both variables must be active binary variables
10474  */
10476  SCIP_VAR* var, /**< problem variable x */
10477  SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
10478  SCIP_VAR* implvar, /**< variable y to search for */
10479  SCIP_Bool implvarfixing /**< value of the implied variable to search for */
10480  )
10481 {
10482  assert(SCIPvarIsBinary(implvar));
10483 
10484  return SCIPvarHasImplic(var, varfixing, implvar, implvarfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER);
10485 }
10486 
10487 /** fixes the bounds of a binary variable to the given value, counting bound changes and detecting infeasibility */
10489  SCIP_VAR* var, /**< problem variable */
10490  BMS_BLKMEM* blkmem, /**< block memory */
10491  SCIP_SET* set, /**< global SCIP settings */
10492  SCIP_STAT* stat, /**< problem statistics */
10493  SCIP_PROB* transprob, /**< transformed problem */
10494  SCIP_PROB* origprob, /**< original problem */
10495  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10496  SCIP_REOPT* reopt, /**< reoptimization data structure */
10497  SCIP_LP* lp, /**< current LP data */
10498  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10499  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10500  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10501  SCIP_Bool value, /**< value to fix variable to */
10502  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10503  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
10504  )
10505 {
10506  assert(var != NULL);
10507  assert(set != NULL);
10508  assert(var->scip == set->scip);
10509  assert(infeasible != NULL);
10510 
10511  *infeasible = FALSE;
10512 
10513  if( value == FALSE )
10514  {
10515  if( var->glbdom.lb > 0.5 )
10516  *infeasible = TRUE;
10517  else if( var->glbdom.ub > 0.5 )
10518  {
10519  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10520  * with the local bound, in this case we need to store the bound change as pending bound change
10521  */
10522  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10523  {
10524  assert(tree != NULL);
10525  assert(transprob != NULL);
10526  assert(SCIPprobIsTransformed(transprob));
10527 
10528  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10529  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
10530  }
10531  else
10532  {
10533  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
10534  }
10535 
10536  if( nbdchgs != NULL )
10537  (*nbdchgs)++;
10538  }
10539  }
10540  else
10541  {
10542  if( var->glbdom.ub < 0.5 )
10543  *infeasible = TRUE;
10544  else if( var->glbdom.lb < 0.5 )
10545  {
10546  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10547  * with the local bound, in this case we need to store the bound change as pending bound change
10548  */
10549  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10550  {
10551  assert(tree != NULL);
10552  assert(transprob != NULL);
10553  assert(SCIPprobIsTransformed(transprob));
10554 
10555  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10556  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
10557  }
10558  else
10559  {
10560  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
10561  }
10562 
10563  if( nbdchgs != NULL )
10564  (*nbdchgs)++;
10565  }
10566  }
10567 
10568  /* during presolving, the variable should have been removed immediately from all its cliques */
10569  assert(SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING || var->cliquelist == NULL);
10570 
10571  return SCIP_OKAY;
10572 }
10573 
10574 /** adds the variable to the given clique and updates the list of cliques the binary variable is member of;
10575  * if the variable now appears twice in the clique with the same value, it is fixed to the opposite value;
10576  * if the variable now appears twice in the clique with opposite values, all other variables are fixed to
10577  * the opposite of the value they take in the clique
10578  */
10580  SCIP_VAR* var, /**< problem variable */
10581  BMS_BLKMEM* blkmem, /**< block memory */
10582  SCIP_SET* set, /**< global SCIP settings */
10583  SCIP_STAT* stat, /**< problem statistics */
10584  SCIP_PROB* transprob, /**< transformed problem */
10585  SCIP_PROB* origprob, /**< original problem */
10586  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10587  SCIP_REOPT* reopt, /**< reoptimization data structure */
10588  SCIP_LP* lp, /**< current LP data */
10589  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10590  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10591  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10592  SCIP_Bool value, /**< value of the variable in the clique */
10593  SCIP_CLIQUE* clique, /**< clique the variable should be added to */
10594  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10595  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
10596  )
10597 {
10598  assert(var != NULL);
10599  assert(set != NULL);
10600  assert(var->scip == set->scip);
10601  assert(SCIPvarIsBinary(var));
10602  assert(infeasible != NULL);
10603 
10604  *infeasible = FALSE;
10605 
10606  /* get corresponding active problem variable */
10607  SCIP_CALL( SCIPvarGetProbvarBinary(&var, &value) );
10612  assert(SCIPvarIsBinary(var));
10613 
10614  /* only column and loose variables may be member of a clique */
10616  {
10617  SCIP_Bool doubleentry;
10618  SCIP_Bool oppositeentry;
10619 
10620  /* add variable to clique */
10621  SCIP_CALL( SCIPcliqueAddVar(clique, blkmem, set, var, value, &doubleentry, &oppositeentry) );
10622 
10623  /* add clique to variable's clique list */
10624  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
10625 
10626  /* check consistency of cliquelist */
10627  SCIPcliquelistCheck(var->cliquelist, var);
10628 
10629  /* if the variable now appears twice with the same value in the clique, it can be fixed to the opposite value */
10630  if( doubleentry )
10631  {
10632  SCIP_CALL( SCIPvarFixBinary(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
10633  eventqueue, cliquetable, !value, infeasible, nbdchgs) );
10634  }
10635 
10636  /* if the variable appears with both values in the clique, all other variables of the clique can be fixed
10637  * to the opposite of the value they take in the clique
10638  */
10639  if( oppositeentry )
10640  {
10641  SCIP_VAR** vars;
10642  SCIP_Bool* values;
10643  int nvars;
10644  int i;
10645 
10646  nvars = SCIPcliqueGetNVars(clique);
10647  vars = SCIPcliqueGetVars(clique);
10648  values = SCIPcliqueGetValues(clique);
10649  for( i = 0; i < nvars && !(*infeasible); ++i )
10650  {
10651  if( vars[i] == var )
10652  continue;
10653 
10654  SCIP_CALL( SCIPvarFixBinary(vars[i], blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
10655  eventqueue, cliquetable, !values[i], infeasible, nbdchgs) );
10656  }
10657  }
10658  }
10659 
10660  return SCIP_OKAY;
10661 }
10662 
10663 /** adds a filled clique to the cliquelists of all corresponding variables */
10665  SCIP_VAR** vars, /**< problem variables */
10666  SCIP_Bool* values, /**< values of the variables in the clique */
10667  int nvars, /**< number of problem variables */
10668  BMS_BLKMEM* blkmem, /**< block memory */
10669  SCIP_SET* set, /**< global SCIP settings */
10670  SCIP_CLIQUE* clique /**< clique that contains all given variables and values */
10671  )
10672 {
10673  SCIP_VAR* var;
10674  int v;
10675 
10676  assert(vars != NULL);
10677  assert(values != NULL);
10678  assert(nvars > 0);
10679  assert(set != NULL);
10680  assert(blkmem != NULL);
10681  assert(clique != NULL);
10682 
10683  for( v = nvars - 1; v >= 0; --v )
10684  {
10685  var = vars[v];
10686  assert(SCIPvarIsBinary(var));
10688 
10689  /* add clique to variable's clique list */
10690  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, values[v], clique) );
10691 
10692  /* check consistency of cliquelist */
10693  SCIPcliquelistCheck(var->cliquelist, var);
10694  }
10695 
10696  return SCIP_OKAY;
10697 }
10698 
10699 /** adds a clique to the list of cliques of the given binary variable, but does not change the clique
10700  * itself
10701  */
10703  SCIP_VAR* var, /**< problem variable */
10704  BMS_BLKMEM* blkmem, /**< block memory */
10705  SCIP_SET* set, /**< global SCIP settings */
10706  SCIP_Bool value, /**< value of the variable in the clique */
10707  SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
10708  )
10709 {
10710  assert(var != NULL);
10711  assert(SCIPvarIsBinary(var));
10713 
10714  /* add clique to variable's clique list */
10715  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
10716 
10717  return SCIP_OKAY;
10718 }
10719 
10720 
10721 /** deletes a clique from the list of cliques the binary variable is member of, but does not change the clique
10722  * itself
10723  */
10725  SCIP_VAR* var, /**< problem variable */
10726  BMS_BLKMEM* blkmem, /**< block memory */
10727  SCIP_Bool value, /**< value of the variable in the clique */
10728  SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
10729  )
10730 {
10731  assert(var != NULL);
10732  assert(SCIPvarIsBinary(var));
10733 
10734  /* delete clique from variable's clique list */
10735  SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
10736 
10737  return SCIP_OKAY;
10738 }
10739 
10740 /** deletes the variable from the given clique and updates the list of cliques the binary variable is member of */
10742  SCIP_VAR* var, /**< problem variable */
10743  BMS_BLKMEM* blkmem, /**< block memory */
10744  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10745  SCIP_Bool value, /**< value of the variable in the clique */
10746  SCIP_CLIQUE* clique /**< clique the variable should be removed from */
10747  )
10748 {
10749  assert(var != NULL);
10750  assert(SCIPvarIsBinary(var));
10751 
10752  /* get corresponding active problem variable */
10753  SCIP_CALL( SCIPvarGetProbvarBinary(&var, &value) );
10758  assert(SCIPvarIsBinary(var));
10759 
10760  /* only column and loose variables may be member of a clique */
10762  {
10763  /* delete clique from variable's clique list */
10764  SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
10765 
10766  /* delete variable from clique */
10767  SCIPcliqueDelVar(clique, cliquetable, var, value);
10768 
10769  /* check consistency of cliquelist */
10770  SCIPcliquelistCheck(var->cliquelist, var);
10771  }
10772 
10773  return SCIP_OKAY;
10774 }
10775 
10776 /** returns whether there is a clique that contains both given variable/value pairs;
10777  * the variables must be active binary variables;
10778  * if regardimplics is FALSE, only the cliques in the clique table are looked at;
10779  * if regardimplics is TRUE, both the cliques and the implications of the implication graph are regarded
10780  *
10781  * @note a variable with it's negated variable are NOT! in a clique
10782  * @note a variable with itself are in a clique
10783  */
10785  SCIP_VAR* var1, /**< first variable */
10786  SCIP_Bool value1, /**< value of first variable */
10787  SCIP_VAR* var2, /**< second variable */
10788  SCIP_Bool value2, /**< value of second variable */
10789  SCIP_Bool regardimplics /**< should the implication graph also be searched for a clique? */
10790  )
10791 {
10792  assert(var1 != NULL);
10793  assert(var2 != NULL);
10794  assert(SCIPvarIsActive(var1));
10795  assert(SCIPvarIsActive(var2));
10796  assert(SCIPvarIsBinary(var1));
10797  assert(SCIPvarIsBinary(var2));
10798 
10799  return (SCIPcliquelistsHaveCommonClique(var1->cliquelist, value1, var2->cliquelist, value2)
10800  || (regardimplics && SCIPvarHasImplic(var1, value1, var2, value2 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER)));
10801 }
10802 
10803 /** actually changes the branch factor of the variable and of all parent variables */
10804 static
10806  SCIP_VAR* var, /**< problem variable */
10807  SCIP_SET* set, /**< global SCIP settings */
10808  SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
10809  )
10810 {
10811  SCIP_VAR* parentvar;
10812  SCIP_Real eps;
10813  int i;
10814 
10815  assert(var != NULL);
10816  assert(set != NULL);
10817  assert(var->scip == set->scip);
10818 
10819  /* only use positive values */
10820  eps = SCIPsetEpsilon(set);
10821  branchfactor = MAX(branchfactor, eps);
10822 
10823  SCIPsetDebugMsg(set, "process changing branch factor of <%s> from %f to %f\n", var->name, var->branchfactor, branchfactor);
10824 
10825  if( SCIPsetIsEQ(set, branchfactor, var->branchfactor) )
10826  return SCIP_OKAY;
10827 
10828  /* change the branch factor */
10829  var->branchfactor = branchfactor;
10830 
10831  /* process parent variables */
10832  for( i = 0; i < var->nparentvars; ++i )
10833  {
10834  parentvar = var->parentvars[i];
10835  assert(parentvar != NULL);
10836 
10837  switch( SCIPvarGetStatus(parentvar) )
10838  {
10840  /* do not change priorities across the border between transformed and original problem */
10841  break;
10842 
10843  case SCIP_VARSTATUS_COLUMN:
10844  case SCIP_VARSTATUS_LOOSE:
10845  case SCIP_VARSTATUS_FIXED:
10847  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
10848  SCIPABORT();
10849  return SCIP_INVALIDDATA; /*lint !e527*/
10850 
10853  SCIP_CALL( varProcessChgBranchFactor(parentvar, set, branchfactor) );
10854  break;
10855 
10856  default:
10857  SCIPerrorMessage("unknown variable status\n");
10858  SCIPABORT();
10859  return SCIP_ERROR; /*lint !e527*/
10860  }
10861  }
10862 
10863  return SCIP_OKAY;
10864 }
10865 
10866 /** sets the branch factor of the variable; this value can be used in the branching methods to scale the score
10867  * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
10868  */
10870  SCIP_VAR* var, /**< problem variable */
10871  SCIP_SET* set, /**< global SCIP settings */
10872  SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
10873  )
10874 {
10875  int v;
10876 
10877  assert(var != NULL);
10878  assert(set != NULL);
10879  assert(var->scip == set->scip);
10880  assert(branchfactor >= 0.0);
10881 
10882  SCIPdebugMessage("changing branch factor of <%s> from %g to %g\n", var->name, var->branchfactor, branchfactor);
10883 
10884  if( SCIPsetIsEQ(set, var->branchfactor, branchfactor) )
10885  return SCIP_OKAY;
10886 
10887  /* change priorities of attached variables */
10888  switch( SCIPvarGetStatus(var) )
10889  {
10891  if( var->data.original.transvar != NULL )
10892  {
10893  SCIP_CALL( SCIPvarChgBranchFactor(var->data.original.transvar, set, branchfactor) );
10894  }
10895  else
10896  {
10897  assert(set->stage == SCIP_STAGE_PROBLEM);
10898  var->branchfactor = branchfactor;
10899  }
10900  break;
10901 
10902  case SCIP_VARSTATUS_COLUMN:
10903  case SCIP_VARSTATUS_LOOSE:
10904  case SCIP_VARSTATUS_FIXED:
10905  SCIP_CALL( varProcessChgBranchFactor(var, set, branchfactor) );
10906  break;
10907 
10909  assert(var->data.aggregate.var != NULL);
10910  SCIP_CALL( SCIPvarChgBranchFactor(var->data.aggregate.var, set, branchfactor) );
10911  break;
10912 
10914  assert(!var->donotmultaggr);
10915  for( v = 0; v < var->data.multaggr.nvars; ++v )
10916  {
10917  SCIP_CALL( SCIPvarChgBranchFactor(var->data.multaggr.vars[v], set, branchfactor) );
10918  }
10919  break;
10920 
10922  assert(var->negatedvar != NULL);
10924  assert(var->negatedvar->negatedvar == var);
10925  SCIP_CALL( SCIPvarChgBranchFactor(var->negatedvar, set, branchfactor) );
10926  break;
10927 
10928  default:
10929  SCIPerrorMessage("unknown variable status\n");
10930  SCIPABORT();
10931  return SCIP_ERROR; /*lint !e527*/
10932  }
10933 
10934  return SCIP_OKAY;
10935 }
10936 
10937 /** actually changes the branch priority of the variable and of all parent variables */
10938 static
10940  SCIP_VAR* var, /**< problem variable */
10941  int branchpriority /**< branching priority of the variable */
10942  )
10943 {
10944  SCIP_VAR* parentvar;
10945  int i;
10946 
10947  assert(var != NULL);
10948 
10949  SCIPdebugMessage("process changing branch priority of <%s> from %d to %d\n",
10950  var->name, var->branchpriority, branchpriority);
10951 
10952  if( branchpriority == var->branchpriority )
10953  return SCIP_OKAY;
10954 
10955  /* change the branch priority */
10956  var->branchpriority = branchpriority;
10957 
10958  /* process parent variables */
10959  for( i = 0; i < var->nparentvars; ++i )
10960  {
10961  parentvar = var->parentvars[i];
10962  assert(parentvar != NULL);
10963 
10964  switch( SCIPvarGetStatus(parentvar) )
10965  {
10967  /* do not change priorities across the border between transformed and original problem */
10968  break;
10969 
10970  case SCIP_VARSTATUS_COLUMN:
10971  case SCIP_VARSTATUS_LOOSE:
10972  case SCIP_VARSTATUS_FIXED:
10974  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
10975  SCIPABORT();
10976  return SCIP_INVALIDDATA; /*lint !e527*/
10977 
10980  SCIP_CALL( varProcessChgBranchPriority(parentvar, branchpriority) );
10981  break;
10982 
10983  default:
10984  SCIPerrorMessage("unknown variable status\n");
10985  return SCIP_ERROR;
10986  }
10987  }
10988 
10989  return SCIP_OKAY;
10990 }
10991 
10992 /** sets the branch priority of the variable; variables with higher branch priority are always preferred to variables
10993  * with lower priority in selection of branching variable
10994  */
10996  SCIP_VAR* var, /**< problem variable */
10997  int branchpriority /**< branching priority of the variable */
10998  )
10999 {
11000  int v;
11001 
11002  assert(var != NULL);
11003 
11004  SCIPdebugMessage("changing branch priority of <%s> from %d to %d\n", var->name, var->branchpriority, branchpriority);
11005 
11006  if( var->branchpriority == branchpriority )
11007  return SCIP_OKAY;
11008 
11009  /* change priorities of attached variables */
11010  switch( SCIPvarGetStatus(var) )
11011  {
11013  if( var->data.original.transvar != NULL )
11014  {
11015  SCIP_CALL( SCIPvarChgBranchPriority(var->data.original.transvar, branchpriority) );
11016  }
11017  else
11018  var->branchpriority = branchpriority;
11019  break;
11020 
11021  case SCIP_VARSTATUS_COLUMN:
11022  case SCIP_VARSTATUS_LOOSE:
11023  case SCIP_VARSTATUS_FIXED:
11024  SCIP_CALL( varProcessChgBranchPriority(var, branchpriority) );
11025  break;
11026 
11028  assert(var->data.aggregate.var != NULL);
11029  SCIP_CALL( SCIPvarChgBranchPriority(var->data.aggregate.var, branchpriority) );
11030  break;
11031 
11033  assert(!var->donotmultaggr);
11034  for( v = 0; v < var->data.multaggr.nvars; ++v )
11035  {
11036  SCIP_CALL( SCIPvarChgBranchPriority(var->data.multaggr.vars[v], branchpriority) );
11037  }
11038  break;
11039 
11041  assert(var->negatedvar != NULL);
11043  assert(var->negatedvar->negatedvar == var);
11044  SCIP_CALL( SCIPvarChgBranchPriority(var->negatedvar, branchpriority) );
11045  break;
11046 
11047  default:
11048  SCIPerrorMessage("unknown variable status\n");
11049  SCIPABORT();
11050  return SCIP_ERROR; /*lint !e527*/
11051  }
11052 
11053  return SCIP_OKAY;
11054 }
11055 
11056 /** actually changes the branch direction of the variable and of all parent variables */
11057 static
11059  SCIP_VAR* var, /**< problem variable */
11060  SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
11061  )
11062 {
11063  SCIP_VAR* parentvar;
11064  int i;
11065 
11066  assert(var != NULL);
11067 
11068  SCIPdebugMessage("process changing branch direction of <%s> from %u to %d\n",
11069  var->name, var->branchdirection, branchdirection);
11070 
11071  if( branchdirection == (SCIP_BRANCHDIR)var->branchdirection )
11072  return SCIP_OKAY;
11073 
11074  /* change the branch direction */
11075  var->branchdirection = branchdirection; /*lint !e641*/
11076 
11077  /* process parent variables */
11078  for( i = 0; i < var->nparentvars; ++i )
11079  {
11080  parentvar = var->parentvars[i];
11081  assert(parentvar != NULL);
11082 
11083  switch( SCIPvarGetStatus(parentvar) )
11084  {
11086  /* do not change directions across the border between transformed and original problem */
11087  break;
11088 
11089  case SCIP_VARSTATUS_COLUMN:
11090  case SCIP_VARSTATUS_LOOSE:
11091  case SCIP_VARSTATUS_FIXED:
11093  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11094  SCIPABORT();
11095  return SCIP_INVALIDDATA; /*lint !e527*/
11096 
11098  if( parentvar->data.aggregate.scalar > 0.0 )
11099  {
11100  SCIP_CALL( varProcessChgBranchDirection(parentvar, branchdirection) );
11101  }
11102  else
11103  {
11104  SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
11105  }
11106  break;
11107 
11109  SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
11110  break;
11111 
11112  default:
11113  SCIPerrorMessage("unknown variable status\n");
11114  SCIPABORT();
11115  return SCIP_ERROR; /*lint !e527*/
11116  }
11117  }
11118 
11119  return SCIP_OKAY;
11120 }
11121 
11122 /** sets the branch direction of the variable; variables with higher branch direction are always preferred to variables
11123  * with lower direction in selection of branching variable
11124  */
11126  SCIP_VAR* var, /**< problem variable */
11127  SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
11128  )
11129 {
11130  int v;
11131 
11132  assert(var != NULL);
11133 
11134  SCIPdebugMessage("changing branch direction of <%s> from %u to %d\n", var->name, var->branchdirection, branchdirection);
11135 
11136  if( (SCIP_BRANCHDIR)var->branchdirection == branchdirection )
11137  return SCIP_OKAY;
11138 
11139  /* change directions of attached variables */
11140  switch( SCIPvarGetStatus(var) )
11141  {
11143  if( var->data.original.transvar != NULL )
11144  {
11145  SCIP_CALL( SCIPvarChgBranchDirection(var->data.original.transvar, branchdirection) );
11146  }
11147  else
11148  var->branchdirection = branchdirection; /*lint !e641*/
11149  break;
11150 
11151  case SCIP_VARSTATUS_COLUMN:
11152  case SCIP_VARSTATUS_LOOSE:
11153  case SCIP_VARSTATUS_FIXED:
11154  SCIP_CALL( varProcessChgBranchDirection(var, branchdirection) );
11155  break;
11156 
11158  assert(var->data.aggregate.var != NULL);
11159  if( var->data.aggregate.scalar > 0.0 )
11160  {
11161  SCIP_CALL( SCIPvarChgBranchDirection(var->data.aggregate.var, branchdirection) );
11162  }
11163  else
11164  {
11166  }
11167  break;
11168 
11170  assert(!var->donotmultaggr);
11171  for( v = 0; v < var->data.multaggr.nvars; ++v )
11172  {
11173  /* only update branching direction of aggregation variables, if they don't have a preferred direction yet */
11174  assert(var->data.multaggr.vars[v] != NULL);
11176  {
11177  if( var->data.multaggr.scalars[v] > 0.0 )
11178  {
11179  SCIP_CALL( SCIPvarChgBranchDirection(var->data.multaggr.vars[v], branchdirection) );
11180  }
11181  else
11182  {
11184  }
11185  }
11186  }
11187  break;
11188 
11190  assert(var->negatedvar != NULL);
11192  assert(var->negatedvar->negatedvar == var);
11194  break;
11195 
11196  default:
11197  SCIPerrorMessage("unknown variable status\n");
11198  SCIPABORT();
11199  return SCIP_ERROR; /*lint !e527*/
11200  }
11201 
11202  return SCIP_OKAY;
11203 }
11204 
11205 /** compares the index of two variables, only active, fixed or negated variables are allowed, if a variable
11206  * is negated then the index of the corresponding active variable is taken, returns -1 if first is
11207  * smaller than, and +1 if first is greater than second variable index; returns 0 if both indices
11208  * are equal, which means both variables are equal
11209  */
11211  SCIP_VAR* var1, /**< first problem variable */
11212  SCIP_VAR* var2 /**< second problem variable */
11213  )
11214 {
11215  assert(var1 != NULL);
11216  assert(var2 != NULL);
11219 
11221  var1 = SCIPvarGetNegatedVar(var1);
11223  var2 = SCIPvarGetNegatedVar(var2);
11224 
11225  assert(var1 != NULL);
11226  assert(var2 != NULL);
11227 
11228  if( SCIPvarGetIndex(var1) < SCIPvarGetIndex(var2) )
11229  return -1;
11230  else if( SCIPvarGetIndex(var1) > SCIPvarGetIndex(var2) )
11231  return +1;
11232 
11233  assert(var1 == var2);
11234  return 0;
11235 }
11236 
11237 /** comparison method for sorting active and negated variables by non-decreasing index, active and negated
11238  * variables are handled as the same variables
11239  */
11240 SCIP_DECL_SORTPTRCOMP(SCIPvarCompActiveAndNegated)
11242  return SCIPvarCompareActiveAndNegated((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
11243 }
11244 
11245 /** compares the index of two variables, returns -1 if first is smaller than, and +1 if first is greater than second
11246  * variable index; returns 0 if both indices are equal, which means both variables are equal
11247  */
11248 int SCIPvarCompare(
11249  SCIP_VAR* var1, /**< first problem variable */
11250  SCIP_VAR* var2 /**< second problem variable */
11251  )
11252 {
11253  assert(var1 != NULL);
11254  assert(var2 != NULL);
11255 
11256  if( var1->index < var2->index )
11257  return -1;
11258  else if( var1->index > var2->index )
11259  return +1;
11260  else
11261  {
11262  assert(var1 == var2);
11263  return 0;
11264  }
11265 }
11266 
11267 /** comparison method for sorting variables by non-decreasing index */
11268 SCIP_DECL_SORTPTRCOMP(SCIPvarComp)
11270  return SCIPvarCompare((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
11271 }
11272 
11273 /** comparison method for sorting variables by non-decreasing objective coefficient */
11274 SCIP_DECL_SORTPTRCOMP(SCIPvarCompObj)
11276  SCIP_Real obj1;
11277  SCIP_Real obj2;
11278 
11279  obj1 = SCIPvarGetObj((SCIP_VAR*)elem1);
11280  obj2 = SCIPvarGetObj((SCIP_VAR*)elem2);
11281 
11282  if( obj1 < obj2 )
11283  return -1;
11284  else if( obj1 > obj2 )
11285  return +1;
11286  else
11287  return 0;
11288 }
11289 
11290 /** hash key retrieval function for variables */
11291 SCIP_DECL_HASHGETKEY(SCIPvarGetHashkey)
11292 { /*lint --e{715}*/
11293  return elem;
11294 }
11295 
11296 /** returns TRUE iff the indices of both variables are equal */
11297 SCIP_DECL_HASHKEYEQ(SCIPvarIsHashkeyEq)
11298 { /*lint --e{715}*/
11299  if( key1 == key2 )
11300  return TRUE;
11301  return FALSE;
11302 }
11303 
11304 /** returns the hash value of the key */
11305 SCIP_DECL_HASHKEYVAL(SCIPvarGetHashkeyVal)
11306 { /*lint --e{715}*/
11307  assert( SCIPvarGetIndex((SCIP_VAR*) key) >= 0 );
11308  return (unsigned int) SCIPvarGetIndex((SCIP_VAR*) key);
11309 }
11310 
11311 /** return for given variables all their active counterparts; all active variables will be pairwise different */
11313  SCIP_SET* set, /**< global SCIP settings */
11314  SCIP_VAR** vars, /**< variable array with given variables and as output all active
11315  * variables, if enough slots exist
11316  */
11317  int* nvars, /**< number of given variables, and as output number of active variables,
11318  * if enough slots exist
11319  */
11320  int varssize, /**< available slots in vars array */
11321  int* requiredsize /**< pointer to store the required array size for the active variables */
11322  )
11323 {
11324  SCIP_VAR** activevars;
11325  int nactivevars;
11326  int activevarssize;
11327 
11328  SCIP_VAR* var;
11329  int v;
11330 
11331  SCIP_VAR** tmpvars;
11332  SCIP_VAR** multvars;
11333  int tmpvarssize;
11334  int ntmpvars;
11335  int noldtmpvars;
11336  int nmultvars;
11337 
11338  assert(set != NULL);
11339  assert(nvars != NULL);
11340  assert(vars != NULL || *nvars == 0);
11341  assert(varssize >= *nvars);
11342  assert(requiredsize != NULL);
11343 
11344  *requiredsize = 0;
11345 
11346  if( *nvars == 0 )
11347  return SCIP_OKAY;
11348 
11349  nactivevars = 0;
11350  activevarssize = *nvars;
11351  ntmpvars = *nvars;
11352  tmpvarssize = *nvars;
11353 
11354  /* temporary memory */
11355  SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
11356  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
11357 
11358  noldtmpvars = ntmpvars;
11359 
11360  /* sort all variables to combine equal variables easily */
11361  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11362  for( v = ntmpvars - 1; v > 0; --v )
11363  {
11364  /* combine same variables */
11365  if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
11366  {
11367  --ntmpvars;
11368  tmpvars[v] = tmpvars[ntmpvars];
11369  }
11370  }
11371  /* sort all variables again to combine equal variables later on */
11372  if( noldtmpvars > ntmpvars )
11373  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11374 
11375  /* collect for each variable the representation in active variables */
11376  while( ntmpvars >= 1 )
11377  {
11378  --ntmpvars;
11379  var = tmpvars[ntmpvars];
11380  assert( var != NULL );
11381 
11382  switch( SCIPvarGetStatus(var) )
11383  {
11385  if( var->data.original.transvar == NULL )
11386  {
11387  SCIPerrorMessage("original variable has no transformed variable attached\n");
11388  SCIPABORT();
11389  return SCIP_INVALIDDATA; /*lint !e527*/
11390  }
11391  tmpvars[ntmpvars] = var->data.original.transvar;
11392  ++ntmpvars;
11393  break;
11394 
11396  tmpvars[ntmpvars] = var->data.aggregate.var;
11397  ++ntmpvars;
11398  break;
11399 
11401  tmpvars[ntmpvars] = var->negatedvar;
11402  ++ntmpvars;
11403  break;
11404 
11405  case SCIP_VARSTATUS_LOOSE:
11406  case SCIP_VARSTATUS_COLUMN:
11407  /* check for space in temporary memory */
11408  if( nactivevars >= activevarssize )
11409  {
11410  activevarssize *= 2;
11411  SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
11412  assert(nactivevars < activevarssize);
11413  }
11414  activevars[nactivevars] = var;
11415  nactivevars++;
11416  break;
11417 
11419  /* x = a_1*y_1 + ... + a_n*y_n + c */
11420  nmultvars = var->data.multaggr.nvars;
11421  multvars = var->data.multaggr.vars;
11422 
11423  /* check for space in temporary memory */
11424  if( nmultvars + ntmpvars > tmpvarssize )
11425  {
11426  while( nmultvars + ntmpvars > tmpvarssize )
11427  tmpvarssize *= 2;
11428  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
11429  assert(nmultvars + ntmpvars <= tmpvarssize);
11430  }
11431 
11432  /* copy all multi-aggregation variables into our working array */
11433  BMScopyMemoryArray(&tmpvars[ntmpvars], multvars, nmultvars); /*lint !e866*/
11434 
11435  /* get active, fixed or multi-aggregated corresponding variables for all new ones */
11436  SCIPvarsGetProbvar(&tmpvars[ntmpvars], nmultvars);
11437 
11438  ntmpvars += nmultvars;
11439  noldtmpvars = ntmpvars;
11440 
11441  /* sort all variables to combine equal variables easily */
11442  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11443  for( v = ntmpvars - 1; v > 0; --v )
11444  {
11445  /* combine same variables */
11446  if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
11447  {
11448  --ntmpvars;
11449  tmpvars[v] = tmpvars[ntmpvars];
11450  }
11451  }
11452  /* sort all variables again to combine equal variables later on */
11453  if( noldtmpvars > ntmpvars )
11454  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11455 
11456  break;
11457 
11458  case SCIP_VARSTATUS_FIXED:
11459  /* no need for memorizing fixed variables */
11460  break;
11461 
11462  default:
11463  SCIPerrorMessage("unknown variable status\n");
11464  SCIPABORT();
11465  return SCIP_INVALIDDATA; /*lint !e527*/
11466  }
11467  }
11468 
11469  /* sort variable array by variable index */
11470  SCIPsortPtr((void**)activevars, SCIPvarComp, nactivevars);
11471 
11472  /* eliminate duplicates and count required size */
11473  v = nactivevars - 1;
11474  while( v > 0 )
11475  {
11476  /* combine both variable since they are the same */
11477  if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
11478  {
11479  --nactivevars;
11480  activevars[v] = activevars[nactivevars];
11481  }
11482  --v;
11483  }
11484  *requiredsize = nactivevars;
11485 
11486  if( varssize >= *requiredsize )
11487  {
11488  assert(vars != NULL);
11489 
11490  *nvars = *requiredsize;
11491  BMScopyMemoryArray(vars, activevars, nactivevars);
11492  }
11493 
11494  SCIPsetFreeBufferArray(set, &tmpvars);
11495  SCIPsetFreeBufferArray(set, &activevars);
11496 
11497  return SCIP_OKAY;
11498 }
11499 
11500 /** gets corresponding active, fixed, or multi-aggregated problem variables of given variables,
11501  * @note the content of the given array will/might change
11502  */
11503 void SCIPvarsGetProbvar(
11504  SCIP_VAR** vars, /**< array of problem variables */
11505  int nvars /**< number of variables */
11506  )
11507 {
11508  int v;
11509 
11510  assert(vars != NULL || nvars == 0);
11511 
11512  for( v = nvars - 1; v >= 0; --v )
11513  {
11514  assert(vars != NULL);
11515  assert(vars[v] != NULL);
11516 
11517  vars[v] = SCIPvarGetProbvar(vars[v]);
11518  assert(vars[v] != NULL);
11519  }
11520 }
11521 
11522 /** gets corresponding active, fixed, or multi-aggregated problem variable of a variable */
11524  SCIP_VAR* var /**< problem variable */
11525  )
11526 {
11527  SCIP_VAR* retvar;
11528 
11529  assert(var != NULL);
11530 
11531  retvar = var;
11532 
11533  SCIPdebugMessage("get problem variable of <%s>\n", var->name);
11534 
11535  while( TRUE ) /*lint !e716 */
11536  {
11537  assert(retvar != NULL);
11538 
11539  switch( SCIPvarGetStatus(retvar) )
11540  {
11542  if( retvar->data.original.transvar == NULL )
11543  {
11544  SCIPerrorMessage("original variable has no transformed variable attached\n");
11545  SCIPABORT();
11546  return NULL; /*lint !e527 */
11547  }
11548  retvar = retvar->data.original.transvar;
11549  break;
11550 
11551  case SCIP_VARSTATUS_LOOSE:
11552  case SCIP_VARSTATUS_COLUMN:
11553  case SCIP_VARSTATUS_FIXED:
11554  return retvar;
11555 
11557  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
11558  if ( retvar->data.multaggr.nvars == 1 )
11559  retvar = retvar->data.multaggr.vars[0];
11560  else
11561  return retvar;
11562  break;
11563 
11565  retvar = retvar->data.aggregate.var;
11566  break;
11567 
11569  retvar = retvar->negatedvar;
11570  break;
11571 
11572  default:
11573  SCIPerrorMessage("unknown variable status\n");
11574  SCIPABORT();
11575  return NULL; /*lint !e527*/
11576  }
11577  }
11578 }
11579 
11580 /** gets corresponding active, fixed, or multi-aggregated problem variables of binary variables and updates the given
11581  * negation status of each variable
11582  */
11584  SCIP_VAR*** vars, /**< pointer to binary problem variables */
11585  SCIP_Bool** negatedarr, /**< pointer to corresponding array to update the negation status */
11586  int nvars /**< number of variables and values in vars and negated array */
11587  )
11588 {
11589  SCIP_VAR** var;
11590  SCIP_Bool* negated;
11591  int v;
11592 
11593  assert(vars != NULL);
11594  assert(*vars != NULL || nvars == 0);
11595  assert(negatedarr != NULL);
11596  assert(*negatedarr != NULL || nvars == 0);
11597 
11598  for( v = nvars - 1; v >= 0; --v )
11599  {
11600  var = &((*vars)[v]);
11601  negated = &((*negatedarr)[v]);
11602 
11603  /* get problem variable */
11604  SCIP_CALL( SCIPvarGetProbvarBinary(var, negated) );
11605  }
11606 
11607  return SCIP_OKAY;
11608 }
11609 
11610 
11611 /** gets corresponding active, fixed, or multi-aggregated problem variable of a binary variable and updates the given
11612  * negation status (this means you have to assign a value to SCIP_Bool negated before calling this method, usually
11613  * FALSE is used)
11614  */
11616  SCIP_VAR** var, /**< pointer to binary problem variable */
11617  SCIP_Bool* negated /**< pointer to update the negation status */
11618  )
11619 {
11621 #ifndef NDEBUG
11622  SCIP_Real constant = 0.0;
11623  SCIP_Bool orignegated;
11624 #endif
11625 
11626  assert(var != NULL);
11627  assert(*var != NULL);
11628  assert(negated != NULL);
11629  assert(SCIPvarIsBinary(*var));
11630 
11631 #ifndef NDEBUG
11632  orignegated = *negated;
11633 #endif
11634 
11635  while( !active && *var != NULL )
11636  {
11637  switch( SCIPvarGetStatus(*var) )
11638  {
11640  if( (*var)->data.original.transvar == NULL )
11641  return SCIP_OKAY;
11642  *var = (*var)->data.original.transvar;
11643  break;
11644 
11645  case SCIP_VARSTATUS_LOOSE:
11646  case SCIP_VARSTATUS_COLUMN:
11647  case SCIP_VARSTATUS_FIXED:
11648  active = TRUE;
11649  break;
11650 
11652  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
11653  if ( (*var)->data.multaggr.nvars == 1 )
11654  {
11655  assert( (*var)->data.multaggr.vars != NULL );
11656  assert( (*var)->data.multaggr.scalars != NULL );
11657  assert( SCIPvarIsBinary((*var)->data.multaggr.vars[0]) );
11658  assert(!EPSZ((*var)->data.multaggr.scalars[0], 1e-06));
11659 
11660  /* if not all variables were fully propagated, it might happen that a variable is multi-aggregated to
11661  * another variable which needs to be fixed
11662  *
11663  * e.g. x = y - 1 => (x = 0 && y = 1)
11664  * e.g. x = y + 1 => (x = 1 && y = 0)
11665  *
11666  * is this special case we need to return the muti-aggregation
11667  */
11668  if( EPSEQ((*var)->data.multaggr.constant, -1.0, 1e-06) || (EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06) && EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06)) )
11669  {
11670  assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06));
11671  }
11672  else
11673  {
11674  /* @note due to fixations, a multi-aggregation can have a constant of zero and a negative scalar or even
11675  * a scalar in absolute value unequal to one, in this case this aggregation variable needs to be
11676  * fixed to zero, but this should be done by another enforcement; so not depending on the scalar,
11677  * we will return the aggregated variable;
11678  */
11679  if( !EPSEQ(REALABS((*var)->data.multaggr.scalars[0]), 1.0, 1e-06) )
11680  {
11681  active = TRUE;
11682  break;
11683  }
11684 
11685  /* @note it may also happen that the constant is larger than 1 or smaller than 0, in that case the
11686  * aggregation variable needs to be fixed to one, but this should be done by another enforcement;
11687  * so if this is the case, we will return the aggregated variable
11688  */
11689  assert(EPSZ((*var)->data.multaggr.constant, 1e-06) || EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06)
11690  || EPSZ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1e-06)
11691  || EPSEQ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1.0, 1e-06));
11692 
11693  if( !EPSZ((*var)->data.multaggr.constant, 1e-06) && !EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06) )
11694  {
11695  active = TRUE;
11696  break;
11697  }
11698 
11699  assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06) || EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
11700 
11701  if( EPSZ((*var)->data.multaggr.constant, 1e-06) )
11702  {
11703  /* if the scalar is negative, either the aggregation variable is already fixed to zero or has at
11704  * least one uplock (that hopefully will enforce this fixation to zero); can it happen that this
11705  * variable itself is multi-aggregated again?
11706  */
11707  assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06) ?
11708  ((SCIPvarGetUbGlobal((*var)->data.multaggr.vars[0]) < 0.5) ||
11709  SCIPvarGetNLocksUp((*var)->data.multaggr.vars[0]) > 0) : TRUE);
11710  }
11711  else
11712  {
11713  assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
11714 #ifndef NDEBUG
11715  constant += (*negated) != orignegated ? -1.0 : 1.0;
11716 #endif
11717 
11718  *negated = !(*negated);
11719  }
11720  *var = (*var)->data.multaggr.vars[0];
11721  break;
11722  }
11723  }
11724  active = TRUE;
11725  break;
11726 
11727  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
11728  assert((*var)->data.aggregate.var != NULL);
11729  assert(EPSEQ((*var)->data.aggregate.scalar, 1.0, 1e-06) || EPSEQ((*var)->data.aggregate.scalar, -1.0, 1e-06));
11730  assert(EPSLE((*var)->data.aggregate.var->glbdom.ub - (*var)->data.aggregate.var->glbdom.lb, 1.0, 1e-06));
11731 #ifndef NDEBUG
11732  constant += (*negated) != orignegated ? -(*var)->data.aggregate.constant : (*var)->data.aggregate.constant;
11733 #endif
11734 
11735  *negated = ((*var)->data.aggregate.scalar > 0.0) ? *negated : !(*negated);
11736  *var = (*var)->data.aggregate.var;
11737  break;
11738 
11739  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
11740  assert((*var)->negatedvar != NULL);
11741 #ifndef NDEBUG
11742  constant += (*negated) != orignegated ? -1.0 : 1.0;
11743 #endif
11744 
11745  *negated = !(*negated);
11746  *var = (*var)->negatedvar;
11747  break;
11748 
11749  default:
11750  SCIPerrorMessage("unknown variable status\n");
11751  return SCIP_INVALIDDATA;
11752  }
11753  }
11754  assert(active == (*var != NULL));
11755 
11756  if( active )
11757  {
11758  assert(SCIPvarIsBinary(*var));
11759  assert(EPSZ(constant, 1e-06) || EPSEQ(constant, 1.0, 1e-06));
11760  assert(EPSZ(constant, 1e-06) == ((*negated) == orignegated));
11761 
11762  return SCIP_OKAY;
11763  }
11764  else
11765  {
11766  SCIPerrorMessage("active variable path leads to NULL pointer\n");
11767  return SCIP_INVALIDDATA;
11768  }
11769 }
11770 
11771 /** transforms given variable, boundtype and bound to the corresponding active, fixed, or multi-aggregated variable
11772  * values
11773  */
11775  SCIP_VAR** var, /**< pointer to problem variable */
11776  SCIP_Real* bound, /**< pointer to bound value to transform */
11777  SCIP_BOUNDTYPE* boundtype /**< pointer to type of bound: lower or upper bound */
11778  )
11779 {
11780  assert(var != NULL);
11781  assert(*var != NULL);
11782  assert(bound != NULL);
11783  assert(boundtype != NULL);
11784 
11785  SCIPdebugMessage("get probvar bound %g of type %d of variable <%s>\n", *bound, *boundtype, (*var)->name);
11786 
11787  switch( SCIPvarGetStatus(*var) )
11788  {
11790  if( (*var)->data.original.transvar == NULL )
11791  {
11792  SCIPerrorMessage("original variable has no transformed variable attached\n");
11793  return SCIP_INVALIDDATA;
11794  }
11795  *var = (*var)->data.original.transvar;
11796  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
11797  break;
11798 
11799  case SCIP_VARSTATUS_LOOSE:
11800  case SCIP_VARSTATUS_COLUMN:
11801  case SCIP_VARSTATUS_FIXED:
11802  break;
11803 
11805  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
11806  if ( (*var)->data.multaggr.nvars == 1 )
11807  {
11808  assert( (*var)->data.multaggr.vars != NULL );
11809  assert( (*var)->data.multaggr.scalars != NULL );
11810  assert( (*var)->data.multaggr.scalars[0] != 0.0 );
11811 
11812  (*bound) /= (*var)->data.multaggr.scalars[0];
11813  (*bound) -= (*var)->data.multaggr.constant/(*var)->data.multaggr.scalars[0];
11814  if ( (*var)->data.multaggr.scalars[0] < 0.0 )
11815  {
11816  if ( *boundtype == SCIP_BOUNDTYPE_LOWER )
11817  *boundtype = SCIP_BOUNDTYPE_UPPER;
11818  else
11819  *boundtype = SCIP_BOUNDTYPE_LOWER;
11820  }
11821  *var = (*var)->data.multaggr.vars[0];
11822  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
11823  }
11824  break;
11825 
11826  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
11827  assert((*var)->data.aggregate.var != NULL);
11828  assert((*var)->data.aggregate.scalar != 0.0);
11829 
11830  (*bound) /= (*var)->data.aggregate.scalar;
11831  (*bound) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
11832  if( (*var)->data.aggregate.scalar < 0.0 )
11833  {
11834  if( *boundtype == SCIP_BOUNDTYPE_LOWER )
11835  *boundtype = SCIP_BOUNDTYPE_UPPER;
11836  else
11837  *boundtype = SCIP_BOUNDTYPE_LOWER;
11838  }
11839  *var = (*var)->data.aggregate.var;
11840  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
11841  break;
11842 
11843  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
11844  assert((*var)->negatedvar != NULL);
11845  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
11846  assert((*var)->negatedvar->negatedvar == *var);
11847  (*bound) = (*var)->data.negate.constant - *bound;
11848  if( *boundtype == SCIP_BOUNDTYPE_LOWER )
11849  *boundtype = SCIP_BOUNDTYPE_UPPER;
11850  else
11851  *boundtype = SCIP_BOUNDTYPE_LOWER;
11852  *var = (*var)->negatedvar;
11853  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
11854  break;
11855 
11856  default:
11857  SCIPerrorMessage("unknown variable status\n");
11858  return SCIP_INVALIDDATA;
11859  }
11860 
11861  return SCIP_OKAY;
11862 }
11863 
11864 /** transforms given variable and domain hole to the corresponding active, fixed, or multi-aggregated variable
11865  * values
11866  */
11868  SCIP_VAR** var, /**< pointer to problem variable */
11869  SCIP_Real* left, /**< pointer to left bound of open interval in hole to transform */
11870  SCIP_Real* right /**< pointer to right bound of open interval in hole to transform */
11871  )
11872 {
11873  assert(var != NULL);
11874  assert(*var != NULL);
11875  assert(left != NULL);
11876  assert(right != NULL);
11877 
11878  SCIPdebugMessage("get probvar hole (%g,%g) of variable <%s>\n", *left, *right, (*var)->name);
11879 
11880  switch( SCIPvarGetStatus(*var) )
11881  {
11883  if( (*var)->data.original.transvar == NULL )
11884  {
11885  SCIPerrorMessage("original variable has no transformed variable attached\n");
11886  return SCIP_INVALIDDATA;
11887  }
11888  *var = (*var)->data.original.transvar;
11889  SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
11890  break;
11891 
11892  case SCIP_VARSTATUS_LOOSE:
11893  case SCIP_VARSTATUS_COLUMN:
11894  case SCIP_VARSTATUS_FIXED:
11896  break;
11897 
11898  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
11899  assert((*var)->data.aggregate.var != NULL);
11900  assert((*var)->data.aggregate.scalar != 0.0);
11901 
11902  /* scale back */
11903  (*left) /= (*var)->data.aggregate.scalar;
11904  (*right) /= (*var)->data.aggregate.scalar;
11905 
11906  /* shift back */
11907  (*left) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
11908  (*right) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
11909 
11910  *var = (*var)->data.aggregate.var;
11911 
11912  /* check if the interval bounds have to swapped */
11913  if( (*var)->data.aggregate.scalar < 0.0 )
11914  {
11915  SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
11916  }
11917  else
11918  {
11919  SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
11920  }
11921  break;
11922 
11923  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
11924  assert((*var)->negatedvar != NULL);
11925  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
11926  assert((*var)->negatedvar->negatedvar == *var);
11927 
11928  /* shift and scale back */
11929  (*left) = (*var)->data.negate.constant - (*left);
11930  (*right) = (*var)->data.negate.constant - (*right);
11931 
11932  *var = (*var)->negatedvar;
11933 
11934  /* through the negated variable the left and right interval bound have to swapped */
11935  SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
11936  break;
11937 
11938  default:
11939  SCIPerrorMessage("unknown variable status\n");
11940  return SCIP_INVALIDDATA;
11941  }
11942 
11943  return SCIP_OKAY;
11944 }
11945 
11946 /** transforms given variable, scalar and constant to the corresponding active, fixed, or
11947  * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed variable,
11948  * "scalar" will be 0.0 and the value of the sum will be stored in "constant"; a multi-aggregation
11949  * with only one active variable (this can happen due to fixings after the multi-aggregation),
11950  * is treated like an aggregation; if the multi-aggregation constant is infinite, "scalar" will be 0.0
11951  */
11953  SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
11954  SCIP_SET* set, /**< global SCIP settings */
11955  SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
11956  SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
11957  )
11958 {
11959  assert(var != NULL);
11960  assert(scalar != NULL);
11961  assert(constant != NULL);
11962 
11963  while( *var != NULL )
11964  {
11965  switch( SCIPvarGetStatus(*var) )
11966  {
11968  if( (*var)->data.original.transvar == NULL )
11969  {
11970  SCIPerrorMessage("original variable has no transformed variable attached\n");
11971  return SCIP_INVALIDDATA;
11972  }
11973  *var = (*var)->data.original.transvar;
11974  break;
11975 
11976  case SCIP_VARSTATUS_LOOSE:
11977  case SCIP_VARSTATUS_COLUMN:
11978  return SCIP_OKAY;
11979 
11980  case SCIP_VARSTATUS_FIXED: /* x = c' => a*x + c == (a*c' + c) */
11981  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
11982  {
11983  if( SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)) )
11984  {
11985  assert(*scalar != 0.0);
11986  if( (*scalar) * (*var)->glbdom.lb > 0.0 )
11987  (*constant) = SCIPsetInfinity(set);
11988  else
11989  (*constant) = -SCIPsetInfinity(set);
11990  }
11991  else
11992  (*constant) += *scalar * (*var)->glbdom.lb;
11993  }
11994 #ifndef NDEBUG
11995  else
11996  {
11997  assert(!SCIPsetIsInfinity(set, (*constant)) || !((*scalar) * (*var)->glbdom.lb < 0.0 &&
11998  (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
11999  assert(!SCIPsetIsInfinity(set, -(*constant)) || !((*scalar) * (*var)->glbdom.lb > 0.0 &&
12000  (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
12001  }
12002 #endif
12003  *scalar = 0.0;
12004  return SCIP_OKAY;
12005 
12007  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12008  if ( (*var)->data.multaggr.nvars == 1 )
12009  {
12010  assert((*var)->data.multaggr.vars != NULL);
12011  assert((*var)->data.multaggr.scalars != NULL);
12012  assert((*var)->data.multaggr.vars[0] != NULL);
12013  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12014  {
12015  /* the multi-aggregation constant can be infinite, if one of the multi-aggregation variables
12016  * was fixed to +/-infinity; ensure that the constant is set to +/-infinity, too, and the scalar
12017  * is set to 0.0, because the multi-aggregated variable can be seen as fixed, too
12018  */
12019  if( SCIPsetIsInfinity(set, (*var)->data.multaggr.constant)
12020  || SCIPsetIsInfinity(set, -((*var)->data.multaggr.constant)) )
12021  {
12022  if( (*scalar) * (*var)->data.multaggr.constant > 0 )
12023  {
12024  assert(!SCIPsetIsInfinity(set, -(*constant)));
12025  (*constant) = SCIPsetInfinity(set);
12026  }
12027  else
12028  {
12029  assert(!SCIPsetIsInfinity(set, *constant));
12030  (*constant) = -SCIPsetInfinity(set);
12031  }
12032  (*scalar) = 0.0;
12033  }
12034  else
12035  (*constant) += *scalar * (*var)->data.multaggr.constant;
12036  }
12037  (*scalar) *= (*var)->data.multaggr.scalars[0];
12038  *var = (*var)->data.multaggr.vars[0];
12039  break;
12040  }
12041  return SCIP_OKAY;
12042 
12043  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
12044  assert((*var)->data.aggregate.var != NULL);
12045  assert(!SCIPsetIsInfinity(set, (*var)->data.aggregate.constant)
12046  && !SCIPsetIsInfinity(set, (*var)->data.aggregate.constant));
12047  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12048  (*constant) += *scalar * (*var)->data.aggregate.constant;
12049  (*scalar) *= (*var)->data.aggregate.scalar;
12050  *var = (*var)->data.aggregate.var;
12051  break;
12052 
12053  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
12054  assert((*var)->negatedvar != NULL);
12055  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12056  assert((*var)->negatedvar->negatedvar == *var);
12057  assert(!SCIPsetIsInfinity(set, (*var)->data.negate.constant)
12058  && !SCIPsetIsInfinity(set, (*var)->data.negate.constant));
12059  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12060  (*constant) += *scalar * (*var)->data.negate.constant;
12061  (*scalar) *= -1.0;
12062  *var = (*var)->negatedvar;
12063  break;
12064 
12065  default:
12066  SCIPerrorMessage("unknown variable status\n");
12067  SCIPABORT();
12068  return SCIP_INVALIDDATA; /*lint !e527*/
12069  }
12070  }
12071  *scalar = 0.0;
12072 
12073  return SCIP_OKAY;
12074 }
12075 
12076 /** retransforms given variable, scalar and constant to the corresponding original variable, scalar
12077  * and constant, if possible; if the retransformation is impossible, NULL is returned as variable
12078  */
12080  SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
12081  SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
12082  SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
12083  )
12084 {
12085  SCIP_VAR* parentvar;
12086 
12087  assert(var != NULL);
12088  assert(*var != NULL);
12089  assert(scalar != NULL);
12090  assert(constant != NULL);
12091 
12092  while( !SCIPvarIsOriginal(*var) )
12093  {
12094  /* if the variable has no parent variables, it was generated during solving and has no corresponding original
12095  * var
12096  */
12097  if( (*var)->nparentvars == 0 )
12098  {
12099  /* negated variables do not need to have a parent variables, and negated variables can exist in original
12100  * space
12101  */
12103  ((*var)->negatedvar->nparentvars == 0 || (*var)->negatedvar->parentvars[0] != *var) )
12104  {
12105  *scalar *= -1.0;
12106  *constant -= (*var)->data.negate.constant * (*scalar);
12107  *var = (*var)->negatedvar;
12108 
12109  continue;
12110  }
12111  /* if the variables does not have any parent the variables was created during solving and has no original
12112  * counterpart
12113  */
12114  else
12115  {
12116  *var = NULL;
12117 
12118  return SCIP_OKAY;
12119  }
12120  }
12121 
12122  /* follow the link to the first parent variable */
12123  parentvar = (*var)->parentvars[0];
12124  assert(parentvar != NULL);
12125 
12126  switch( SCIPvarGetStatus(parentvar) )
12127  {
12129  break;
12130 
12131  case SCIP_VARSTATUS_COLUMN:
12132  case SCIP_VARSTATUS_LOOSE:
12133  case SCIP_VARSTATUS_FIXED:
12135  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
12136  return SCIP_INVALIDDATA;
12137 
12138  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + b -> y = (x-b)/a, s*y + c = (s/a)*x + c-b*s/a */
12139  assert(parentvar->data.aggregate.var == *var);
12140  assert(parentvar->data.aggregate.scalar != 0.0);
12141  *scalar /= parentvar->data.aggregate.scalar;
12142  *constant -= parentvar->data.aggregate.constant * (*scalar);
12143  break;
12144 
12145  case SCIP_VARSTATUS_NEGATED: /* x = b - y -> y = b - x, s*y + c = -s*x + c+b*s */
12146  assert(parentvar->negatedvar != NULL);
12147  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
12148  assert(parentvar->negatedvar->negatedvar == parentvar);
12149  *scalar *= -1.0;
12150  *constant -= parentvar->data.negate.constant * (*scalar);
12151  break;
12152 
12153  default:
12154  SCIPerrorMessage("unknown variable status\n");
12155  return SCIP_INVALIDDATA;
12156  }
12157 
12158  assert( parentvar != NULL );
12159  *var = parentvar;
12160  }
12161 
12162  return SCIP_OKAY;
12163 }
12164 
12165 /** returns whether the given variable is the direct counterpart of an original problem variable */
12167  SCIP_VAR* var /**< problem variable */
12168  )
12169 {
12170  SCIP_VAR* parentvar;
12171  assert(var != NULL);
12172 
12173  if( !SCIPvarIsTransformed(var) || var->nparentvars < 1 )
12174  return FALSE;
12175 
12176  assert(var->parentvars != NULL);
12177  parentvar = var->parentvars[0];
12178  assert(parentvar != NULL);
12179 
12180  /* we follow the aggregation tree to the root unless an original variable has been found - the first entries in the parentlist are candidates */
12181  while( parentvar->nparentvars >= 1 && SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL )
12182  parentvar = parentvar->parentvars[0];
12183  assert( parentvar != NULL );
12184 
12185  return ( SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_ORIGINAL );
12186 }
12187 
12188 /** gets objective value of variable in current SCIP_LP; the value can be different from the objective value stored in
12189  * the variable's own data due to diving, that operate only on the LP without updating the variables
12190  */
12192  SCIP_VAR* var /**< problem variable */
12193  )
12194 {
12195  assert(var != NULL);
12196 
12197  /* get bounds of attached variables */
12198  switch( SCIPvarGetStatus(var) )
12199  {
12201  assert(var->data.original.transvar != NULL);
12202  return SCIPvarGetObjLP(var->data.original.transvar);
12203 
12204  case SCIP_VARSTATUS_COLUMN:
12205  assert(var->data.col != NULL);
12206  return SCIPcolGetObj(var->data.col);
12207 
12208  case SCIP_VARSTATUS_LOOSE:
12209  case SCIP_VARSTATUS_FIXED:
12210  return var->obj;
12211 
12212  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12213  assert(var->data.aggregate.var != NULL);
12214  return var->data.aggregate.scalar * SCIPvarGetObjLP(var->data.aggregate.var);
12215 
12217  SCIPerrorMessage("cannot get the objective value of a multiple aggregated variable\n");
12218  SCIPABORT();
12219  return 0.0; /*lint !e527*/
12220 
12221  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12222  assert(var->negatedvar != NULL);
12224  assert(var->negatedvar->negatedvar == var);
12225  return -SCIPvarGetObjLP(var->negatedvar);
12226 
12227  default:
12228  SCIPerrorMessage("unknown variable status\n");
12229  SCIPABORT();
12230  return 0.0; /*lint !e527*/
12231  }
12232 }
12233 
12234 /** gets lower bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
12235  * data due to diving or conflict analysis, that operate only on the LP without updating the variables
12236  */
12238  SCIP_VAR* var, /**< problem variable */
12239  SCIP_SET* set /**< global SCIP settings */
12240  )
12241 {
12242  assert(var != NULL);
12243  assert(set != NULL);
12244  assert(var->scip == set->scip);
12245 
12246  /* get bounds of attached variables */
12247  switch( SCIPvarGetStatus(var) )
12248  {
12250  assert(var->data.original.transvar != NULL);
12251  return SCIPvarGetLbLP(var->data.original.transvar, set);
12252 
12253  case SCIP_VARSTATUS_COLUMN:
12254  assert(var->data.col != NULL);
12255  return SCIPcolGetLb(var->data.col);
12256 
12257  case SCIP_VARSTATUS_LOOSE:
12258  case SCIP_VARSTATUS_FIXED:
12259  return var->locdom.lb;
12260 
12261  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12262  assert(var->data.aggregate.var != NULL);
12263  if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set)))
12264  || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set))) )
12265  {
12266  return -SCIPsetInfinity(set);
12267  }
12268  else if( var->data.aggregate.scalar > 0.0 )
12269  {
12270  /* a > 0 -> get lower bound of y */
12271  return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12272  }
12273  else if( var->data.aggregate.scalar < 0.0 )
12274  {
12275  /* a < 0 -> get upper bound of y */
12276  return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12277  }
12278  else
12279  {
12280  SCIPerrorMessage("scalar is zero in aggregation\n");
12281  SCIPABORT();
12282  return SCIP_INVALID; /*lint !e527*/
12283  }
12284 
12286  /**@todo get the sides of the corresponding linear constraint */
12287  SCIPerrorMessage("getting the bounds of a multiple aggregated variable is not implemented yet\n");
12288  SCIPABORT();
12289  return SCIP_INVALID; /*lint !e527*/
12290 
12291  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12292  assert(var->negatedvar != NULL);
12294  assert(var->negatedvar->negatedvar == var);
12295  return var->data.negate.constant - SCIPvarGetUbLP(var->negatedvar, set);
12296 
12297  default:
12298  SCIPerrorMessage("unknown variable status\n");
12299  SCIPABORT();
12300  return SCIP_INVALID; /*lint !e527*/
12301  }
12302 }
12303 
12304 /** gets upper bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
12305  * data due to diving or conflict analysis, that operate only on the LP without updating the variables
12306  */
12308  SCIP_VAR* var, /**< problem variable */
12309  SCIP_SET* set /**< global SCIP settings */
12310  )
12311 {
12312  assert(var != NULL);
12313  assert(set != NULL);
12314  assert(var->scip == set->scip);
12315 
12316  /* get bounds of attached variables */
12317  switch( SCIPvarGetStatus(var) )
12318  {
12320  assert(var->data.original.transvar != NULL);
12321  return SCIPvarGetUbLP(var->data.original.transvar, set);
12322 
12323  case SCIP_VARSTATUS_COLUMN:
12324  assert(var->data.col != NULL);
12325  return SCIPcolGetUb(var->data.col);
12326 
12327  case SCIP_VARSTATUS_LOOSE:
12328  case SCIP_VARSTATUS_FIXED:
12329  return var->locdom.ub;
12330 
12331  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12332  assert(var->data.aggregate.var != NULL);
12333  if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set)))
12334  || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set))) )
12335  {
12336  return SCIPsetInfinity(set);
12337  }
12338  if( var->data.aggregate.scalar > 0.0 )
12339  {
12340  /* a > 0 -> get upper bound of y */
12341  return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12342  }
12343  else if( var->data.aggregate.scalar < 0.0 )
12344  {
12345  /* a < 0 -> get lower bound of y */
12346  return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12347  }
12348  else
12349  {
12350  SCIPerrorMessage("scalar is zero in aggregation\n");
12351  SCIPABORT();
12352  return SCIP_INVALID; /*lint !e527*/
12353  }
12354 
12356  SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
12357  SCIPABORT();
12358  return SCIP_INVALID; /*lint !e527*/
12359 
12360  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12361  assert(var->negatedvar != NULL);
12363  assert(var->negatedvar->negatedvar == var);
12364  return var->data.negate.constant - SCIPvarGetLbLP(var->negatedvar, set);
12365 
12366  default:
12367  SCIPerrorMessage("unknown variable status\n");
12368  SCIPABORT();
12369  return SCIP_INVALID; /*lint !e527*/
12370  }
12371 }
12372 
12373 /** gets primal LP solution value of variable */
12375  SCIP_VAR* var /**< problem variable */
12376  )
12377 {
12378  assert(var != NULL);
12379 
12380  switch( SCIPvarGetStatus(var) )
12381  {
12383  if( var->data.original.transvar == NULL )
12384  return SCIP_INVALID;
12385  return SCIPvarGetLPSol(var->data.original.transvar);
12386 
12387  case SCIP_VARSTATUS_LOOSE:
12388  return SCIPvarGetBestBoundLocal(var);
12389 
12390  case SCIP_VARSTATUS_COLUMN:
12391  assert(var->data.col != NULL);
12392  return SCIPcolGetPrimsol(var->data.col);
12393 
12394  case SCIP_VARSTATUS_FIXED:
12395  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
12396  return var->locdom.lb;
12397 
12399  {
12400  SCIP_Real lpsolval;
12401 
12402  assert(var->data.aggregate.var != NULL);
12403  lpsolval = SCIPvarGetLPSol(var->data.aggregate.var);
12404 
12405  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
12406  * corresponding infinity value instead of performing an arithmetical transformation (compare method
12407  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
12408  * (or is called by) a public interface method; instead, we only assert that values are finite
12409  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
12410  * positives and negatives if the parameter <numerics/infinity> is modified by the user
12411  */
12412  assert(lpsolval > -SCIP_DEFAULT_INFINITY);
12413  assert(lpsolval < +SCIP_DEFAULT_INFINITY);
12414  return var->data.aggregate.scalar * lpsolval + var->data.aggregate.constant;
12415  }
12417  {
12418  SCIP_Real primsol;
12419  int i;
12420 
12421  assert(!var->donotmultaggr);
12422  assert(var->data.multaggr.vars != NULL);
12423  assert(var->data.multaggr.scalars != NULL);
12424  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
12425  * assert(var->data.multaggr.nvars >= 2);
12426  */
12427  primsol = var->data.multaggr.constant;
12428  for( i = 0; i < var->data.multaggr.nvars; ++i )
12429  primsol += var->data.multaggr.scalars[i] * SCIPvarGetLPSol(var->data.multaggr.vars[i]);
12430  return primsol;
12431  }
12432  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12433  assert(var->negatedvar != NULL);
12435  assert(var->negatedvar->negatedvar == var);
12436  return var->data.negate.constant - SCIPvarGetLPSol(var->negatedvar);
12437 
12438  default:
12439  SCIPerrorMessage("unknown variable status\n");
12440  SCIPABORT();
12441  return SCIP_INVALID; /*lint !e527*/
12442  }
12443 }
12444 
12445 /** gets primal NLP solution value of variable */
12447  SCIP_VAR* var /**< problem variable */
12448  )
12449 {
12450  SCIP_Real solval;
12451  int i;
12452 
12453  assert(var != NULL);
12454 
12455  /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
12456  switch( SCIPvarGetStatus(var) )
12457  {
12459  return SCIPvarGetNLPSol(var->data.original.transvar);
12460 
12461  case SCIP_VARSTATUS_LOOSE:
12462  case SCIP_VARSTATUS_COLUMN:
12463  return var->nlpsol;
12464 
12465  case SCIP_VARSTATUS_FIXED:
12466  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
12467  assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
12468  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
12469  return SCIPvarGetLbGlobal(var);
12470 
12471  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
12472  solval = SCIPvarGetNLPSol(var->data.aggregate.var);
12473  return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
12474 
12476  solval = var->data.multaggr.constant;
12477  for( i = 0; i < var->data.multaggr.nvars; ++i )
12478  solval += var->data.multaggr.scalars[i] * SCIPvarGetNLPSol(var->data.multaggr.vars[i]);
12479  return solval;
12480 
12482  solval = SCIPvarGetNLPSol(var->negatedvar);
12483  return var->data.negate.constant - solval;
12484 
12485  default:
12486  SCIPerrorMessage("unknown variable status\n");
12487  SCIPABORT();
12488  return SCIP_INVALID; /*lint !e527*/
12489  }
12490 }
12491 
12492 /** gets pseudo solution value of variable at current node */
12493 static
12495  SCIP_VAR* var /**< problem variable */
12496  )
12497 {
12498  SCIP_Real pseudosol;
12499  int i;
12500 
12501  assert(var != NULL);
12502 
12503  switch( SCIPvarGetStatus(var) )
12504  {
12506  if( var->data.original.transvar == NULL )
12507  return SCIP_INVALID;
12509 
12510  case SCIP_VARSTATUS_LOOSE:
12511  case SCIP_VARSTATUS_COLUMN:
12512  return SCIPvarGetBestBoundLocal(var);
12513 
12514  case SCIP_VARSTATUS_FIXED:
12515  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
12516  return var->locdom.lb;
12517 
12519  {
12520  SCIP_Real pseudosolval;
12521  assert(var->data.aggregate.var != NULL);
12522  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
12523  * corresponding infinity value instead of performing an arithmetical transformation (compare method
12524  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
12525  * (or is called by) a public interface method; instead, we only assert that values are finite
12526  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
12527  * positives and negatives if the parameter <numerics/infinity> is modified by the user
12528  */
12529  pseudosolval = SCIPvarGetPseudoSol(var->data.aggregate.var);
12530  assert(pseudosolval > -SCIP_DEFAULT_INFINITY);
12531  assert(pseudosolval < +SCIP_DEFAULT_INFINITY);
12532  return var->data.aggregate.scalar * pseudosolval + var->data.aggregate.constant;
12533  }
12535  assert(!var->donotmultaggr);
12536  assert(var->data.multaggr.vars != NULL);
12537  assert(var->data.multaggr.scalars != NULL);
12538  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
12539  * assert(var->data.multaggr.nvars >= 2);
12540  */
12541  pseudosol = var->data.multaggr.constant;
12542  for( i = 0; i < var->data.multaggr.nvars; ++i )
12543  pseudosol += var->data.multaggr.scalars[i] * SCIPvarGetPseudoSol(var->data.multaggr.vars[i]);
12544  return pseudosol;
12545 
12546  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12547  assert(var->negatedvar != NULL);
12549  assert(var->negatedvar->negatedvar == var);
12550  return var->data.negate.constant - SCIPvarGetPseudoSol(var->negatedvar);
12551 
12552  default:
12553  SCIPerrorMessage("unknown variable status\n");
12554  SCIPABORT();
12555  return SCIP_INVALID; /*lint !e527*/
12556  }
12557 }
12558 
12559 /** gets current LP or pseudo solution value of variable */
12561  SCIP_VAR* var, /**< problem variable */
12562  SCIP_Bool getlpval /**< should the LP solution value be returned? */
12563  )
12564 {
12565  if( getlpval )
12566  return SCIPvarGetLPSol(var);
12567  else
12568  return SCIPvarGetPseudoSol(var);
12569 }
12570 
12571 /** remembers the current solution as root solution in the problem variables */
12572 void SCIPvarStoreRootSol(
12573  SCIP_VAR* var, /**< problem variable */
12574  SCIP_Bool roothaslp /**< is the root solution from LP? */
12575  )
12576 {
12577  assert(var != NULL);
12578 
12579  var->rootsol = SCIPvarGetSol(var, roothaslp);
12580 }
12581 
12582 /** updates the current solution as best root solution of the given variable if it is better */
12584  SCIP_VAR* var, /**< problem variable */
12585  SCIP_SET* set, /**< global SCIP settings */
12586  SCIP_Real rootsol, /**< root solution value */
12587  SCIP_Real rootredcost, /**< root reduced cost */
12588  SCIP_Real rootlpobjval /**< objective value of the root LP */
12589  )
12590 {
12591  assert(var != NULL);
12592  assert(set != NULL);
12593  assert(var->scip == set->scip);
12594 
12595  /* if reduced cost are zero nothing to update */
12596  if( SCIPsetIsDualfeasZero(set, rootredcost) )
12597  return;
12598 
12599  /* check if we have already a best combination stored */
12600  if( !SCIPsetIsDualfeasZero(set, var->bestrootredcost) )
12601  {
12602  SCIP_Real currcutoffbound;
12603  SCIP_Real cutoffbound;
12604  SCIP_Real bound;
12605 
12606  /* compute the cutoff bound which would improve the corresponding bound with the current stored root solution,
12607  * root reduced cost, and root LP objective value combination
12608  */
12609  if( var->bestrootredcost > 0.0 )
12610  bound = SCIPvarGetUbGlobal(var);
12611  else
12612  bound = SCIPvarGetLbGlobal(var);
12613 
12614  currcutoffbound = (bound - var->bestrootsol) * var->bestrootredcost + var->bestrootlpobjval;
12615 
12616  /* compute the cutoff bound which would improve the corresponding bound with new root solution, root reduced
12617  * cost, and root LP objective value combination
12618  */
12619  if( rootredcost > 0.0 )
12620  bound = SCIPvarGetUbGlobal(var);
12621  else
12622  bound = SCIPvarGetLbGlobal(var);
12623 
12624  cutoffbound = (bound - rootsol) * rootredcost + rootlpobjval;
12625 
12626  /* check if an improving root solution, root reduced cost, and root LP objective value is at hand */
12627  if( cutoffbound > currcutoffbound )
12628  {
12629  SCIPsetDebugMsg(set, "-> <%s> update potential cutoff bound <%g> -> <%g>\n",
12630  SCIPvarGetName(var), currcutoffbound, cutoffbound);
12631 
12632  var->bestrootsol = rootsol;
12633  var->bestrootredcost = rootredcost;
12634  var->bestrootlpobjval = rootlpobjval;
12635  }
12636  }
12637  else
12638  {
12639  SCIPsetDebugMsg(set, "-> <%s> initialize best root reduced cost information\n", SCIPvarGetName(var));
12640  SCIPsetDebugMsg(set, " -> rootsol <%g>\n", rootsol);
12641  SCIPsetDebugMsg(set, " -> rootredcost <%g>\n", rootredcost);
12642  SCIPsetDebugMsg(set, " -> rootlpobjval <%g>\n", rootlpobjval);
12643 
12644  var->bestrootsol = rootsol;
12645  var->bestrootredcost = rootredcost;
12646  var->bestrootlpobjval = rootlpobjval;
12647  }
12648 }
12649 
12650 /** returns the solution of the variable in the last root node's relaxation, if the root relaxation is not yet
12651  * completely solved, zero is returned
12652  */
12654  SCIP_VAR* var /**< problem variable */
12655  )
12656 {
12657  SCIP_Real rootsol;
12658  int i;
12659 
12660  assert(var != NULL);
12661 
12662  switch( SCIPvarGetStatus(var) )
12663  {
12665  if( var->data.original.transvar == NULL )
12666  return 0.0;
12667  return SCIPvarGetRootSol(var->data.original.transvar);
12668 
12669  case SCIP_VARSTATUS_LOOSE:
12670  case SCIP_VARSTATUS_COLUMN:
12671  return var->rootsol;
12672 
12673  case SCIP_VARSTATUS_FIXED:
12674  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
12675  return var->locdom.lb;
12676 
12678  assert(var->data.aggregate.var != NULL);
12679  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
12680  * corresponding infinity value instead of performing an arithmetical transformation (compare method
12681  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
12682  * (or is called by) a public interface method; instead, we only assert that values are finite
12683  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
12684  * positives and negatives if the parameter <numerics/infinity> is modified by the user
12685  */
12689 
12691  assert(!var->donotmultaggr);
12692  assert(var->data.multaggr.vars != NULL);
12693  assert(var->data.multaggr.scalars != NULL);
12694  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
12695  * assert(var->data.multaggr.nvars >= 2);
12696  */
12697  rootsol = var->data.multaggr.constant;
12698  for( i = 0; i < var->data.multaggr.nvars; ++i )
12699  rootsol += var->data.multaggr.scalars[i] * SCIPvarGetRootSol(var->data.multaggr.vars[i]);
12700  return rootsol;
12701 
12702  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12703  assert(var->negatedvar != NULL);
12705  assert(var->negatedvar->negatedvar == var);
12706  return var->data.negate.constant - SCIPvarGetRootSol(var->negatedvar);
12707 
12708  default:
12709  SCIPerrorMessage("unknown variable status\n");
12710  SCIPABORT();
12711  return SCIP_INVALID; /*lint !e527*/
12712  }
12713 }
12714 
12715 /** returns for given variable the reduced cost */
12716 static
12718  SCIP_VAR* var, /**< problem variable */
12719  SCIP_SET* set, /**< global SCIP settings */
12720  SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
12721  SCIP_STAT* stat, /**< problem statistics */
12722  SCIP_LP* lp /**< current LP data */
12723  )
12724 {
12726  {
12727  SCIP_COL* col;
12728  SCIP_Real primsol;
12729  SCIP_BASESTAT basestat;
12730  SCIP_Bool lpissolbasic;
12731 
12732  col = SCIPvarGetCol(var);
12733  assert(col != NULL);
12734 
12735  basestat = SCIPcolGetBasisStatus(col);
12736  lpissolbasic = SCIPlpIsSolBasic(lp);
12737  primsol = SCIPcolGetPrimsol(col);
12738 
12739  if( (lpissolbasic && (basestat == SCIP_BASESTAT_LOWER || basestat == SCIP_BASESTAT_UPPER)) ||
12740  (!lpissolbasic && (SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol) || SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol))) )
12741  {
12742  SCIP_Real redcost = SCIPcolGetRedcost(col, stat, lp);
12743 
12744  assert(((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)) ||
12745  (lpissolbasic && basestat == SCIP_BASESTAT_LOWER)) ? (!SCIPsetIsDualfeasNegative(set, redcost) ||
12747  assert(((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)) ||
12748  (lpissolbasic && basestat == SCIP_BASESTAT_UPPER)) ? (!SCIPsetIsDualfeasPositive(set, redcost) ||
12749  SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var))) : TRUE);
12750 
12751  if( (varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_LOWER) ||
12752  (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)))) ||
12753  (!varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_UPPER) ||
12754  (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)))) )
12755  return redcost;
12756  else
12757  return 0.0;
12758  }
12759 
12760  return 0.0;
12761  }
12762 
12763  return 0.0;
12764 }
12765 
12766 #define MAX_CLIQUELENGTH 50
12767 /** returns for the given binary variable the reduced cost which are given by the variable itself and its implication if
12768  * the binary variable is fixed to the given value
12769  */
12771  SCIP_VAR* var, /**< problem variable */
12772  SCIP_SET* set, /**< global SCIP settings */
12773  SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
12774  SCIP_STAT* stat, /**< problem statistics */
12775  SCIP_PROB* prob, /**< transformed problem, or NULL */
12776  SCIP_LP* lp /**< current LP data */
12777  )
12778 {
12779  SCIP_Real implredcost;
12780  int ncliques;
12781  int nvars;
12782 
12783  assert(SCIPvarIsBinary(var));
12784  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
12785 
12786  if( !SCIPlpIsDualReliable(lp) )
12787  return 0.0;
12788 
12789  /* get reduced cost of given variable */
12790  implredcost = getImplVarRedcost(var, set, varfixing, stat, lp);
12791 
12792 #ifdef SCIP_MORE_DEBUG
12793  SCIPsetDebugMsg(set, "variable <%s> itself has reduced cost of %g\n", SCIPvarGetName(var), implredcost);
12794 #endif
12795 
12796  /* the following algorithm is expensive */
12797  ncliques = SCIPvarGetNCliques(var, varfixing);
12798 
12799  if( ncliques > 0 )
12800  {
12801  SCIP_CLIQUE** cliques;
12802  SCIP_CLIQUE* clique;
12803  SCIP_VAR** clqvars;
12804  SCIP_VAR** probvars;
12805  SCIP_VAR* clqvar;
12806  SCIP_Bool* clqvalues;
12807  int* entries;
12808  int* ids;
12809  SCIP_Real redcost;
12810  SCIP_Bool cleanedup;
12811  int nclqvars;
12812  int nentries;
12813  int nids;
12814  int id;
12815  int c;
12816  int v;
12817 
12818  assert(prob != NULL);
12819  assert(SCIPprobIsTransformed(prob));
12820 
12821  nentries = SCIPprobGetNVars(prob) - SCIPprobGetNContVars(prob) + 1;
12822 
12823  SCIP_CALL_ABORT( SCIPsetAllocBufferArray(set, &ids, nentries) );
12824  nids = 0;
12825  SCIP_CALL_ABORT( SCIPsetAllocCleanBufferArray(set, &entries, nentries) );
12826 
12827  cliques = SCIPvarGetCliques(var, varfixing);
12828  assert(cliques != NULL);
12829 
12830  for( c = ncliques - 1; c >= 0; --c )
12831  {
12832  clique = cliques[c];
12833  assert(clique != NULL);
12834  nclqvars = SCIPcliqueGetNVars(clique);
12835  assert(nclqvars > 0);
12836 
12837  if( nclqvars > MAX_CLIQUELENGTH )
12838  continue;
12839 
12840  clqvars = SCIPcliqueGetVars(clique);
12841  clqvalues = SCIPcliqueGetValues(clique);
12842  assert(clqvars != NULL);
12843  assert(clqvalues != NULL);
12844 
12845  cleanedup = SCIPcliqueIsCleanedUp(clique);
12846 
12847  for( v = nclqvars - 1; v >= 0; --v )
12848  {
12849  clqvar = clqvars[v];
12850  assert(clqvar != NULL);
12851 
12852  /* ignore binary variable which are fixed */
12853  if( clqvar != var && (cleanedup || SCIPvarIsActive(clqvar)) &&
12854  (SCIPvarGetLbLocal(clqvar) < 0.5 && SCIPvarGetUbLocal(clqvar) > 0.5) )
12855  {
12856  int probindex = SCIPvarGetProbindex(clqvar) + 1;
12857  assert(0 < probindex && probindex < nentries);
12858 
12859 #if 0
12860  /* check that the variable was not yet visited or does not appear with two contradicting implications, ->
12861  * can appear since there is no guarantee that all these infeasible bounds were found
12862  */
12863  assert(!entries[probindex] || entries[probindex] == (clqvalues[v] ? probindex : -probindex));
12864 #endif
12865  if( entries[probindex] == 0 )
12866  {
12867  ids[nids] = probindex;
12868  ++nids;
12869 
12870  /* mark variable as visited */
12871  entries[probindex] = (clqvalues[v] ? probindex : -probindex);
12872  }
12873  }
12874  }
12875  }
12876 
12877  probvars = SCIPprobGetVars(prob);
12878  assert(probvars != NULL);
12879 
12880  /* add all implied reduced cost */
12881  for( v = nids - 1; v >= 0; --v )
12882  {
12883  id = ids[v];
12884  assert(0 < id && id < nentries);
12885  assert(entries[id] != 0);
12886  assert(probvars[id - 1] != NULL);
12887  assert(SCIPvarIsActive(probvars[id - 1]));
12888  assert(SCIPvarIsBinary(probvars[id - 1]));
12889  assert(SCIPvarGetLbLocal(probvars[id - 1]) < 0.5 && SCIPvarGetUbLocal(probvars[id - 1]) > 0.5);
12890 
12891  if( (entries[id] > 0) != varfixing )
12892  redcost = getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
12893  else
12894  redcost = -getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
12895 
12896  if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
12897  implredcost += redcost;
12898 
12899  /* reset entries clear buffer array */
12900  entries[id] = 0;
12901  }
12902 
12903  SCIPsetFreeCleanBufferArray(set, &entries);
12904  SCIPsetFreeBufferArray(set, &ids);
12905  }
12906 
12907 #ifdef SCIP_MORE_DEBUG
12908  SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) has implied reduced cost of %g\n", SCIPvarGetName(var), ncliques,
12909  implredcost);
12910 #endif
12911 
12912  /* collect non-binary implication information */
12913  nvars = SCIPimplicsGetNImpls(var->implics, varfixing);
12914 
12915  if( nvars > 0 )
12916  {
12917  SCIP_VAR** vars;
12918  SCIP_VAR* implvar;
12919  SCIP_COL* col;
12920  SCIP_Real* bounds;
12921  SCIP_BOUNDTYPE* boundtypes;
12922  SCIP_Real redcost;
12923  SCIP_Real lb;
12924  SCIP_Real ub;
12925  SCIP_Bool lpissolbasic;
12926  int v;
12927 
12928  vars = SCIPimplicsGetVars(var->implics, varfixing);
12929  boundtypes = SCIPimplicsGetTypes(var->implics, varfixing);
12930  bounds = SCIPimplicsGetBounds(var->implics, varfixing);
12931  lpissolbasic = SCIPlpIsSolBasic(lp);
12932 
12933  for( v = nvars - 1; v >= 0; --v )
12934  {
12935  implvar = vars[v];
12936  assert(implvar != NULL);
12937 
12938  lb = SCIPvarGetLbLocal(implvar);
12939  ub = SCIPvarGetUbLocal(implvar);
12940 
12941  /* ignore binary variable which are fixed or not of column status */
12942  if( SCIPvarGetStatus(implvar) != SCIP_VARSTATUS_COLUMN || SCIPsetIsFeasEQ(set, lb, ub) )
12943  continue;
12944 
12945  col = SCIPvarGetCol(implvar);
12946  assert(col != NULL);
12947  redcost = 0.0;
12948 
12949  /* solved lp with basis information or not? */
12950  if( lpissolbasic )
12951  {
12952  SCIP_BASESTAT basestat = SCIPcolGetBasisStatus(col);
12953 
12954  /* check if the implication is not not yet applied */
12955  if( basestat == SCIP_BASESTAT_LOWER && boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGT(set, bounds[v], lb) )
12956  {
12957  redcost = SCIPcolGetRedcost(col, stat, lp);
12958  assert(!SCIPsetIsDualfeasNegative(set, redcost));
12959 
12960  if( !varfixing )
12961  redcost *= (lb - bounds[v]);
12962  else
12963  redcost *= (bounds[v] - lb);
12964  }
12965  else if( basestat == SCIP_BASESTAT_UPPER && boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLT(set, bounds[v], ub) )
12966  {
12967  redcost = SCIPcolGetRedcost(col, stat, lp);
12968  assert(!SCIPsetIsDualfeasPositive(set, redcost));
12969 
12970  if( varfixing )
12971  redcost *= (bounds[v] - ub);
12972  else
12973  redcost *= (ub - bounds[v]);
12974  }
12975  }
12976  else
12977  {
12978  SCIP_Real primsol = SCIPcolGetPrimsol(col);
12979 
12980  /* check if the implication is not not yet applied */
12981  if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasEQ(set, lb, primsol) && SCIPsetIsFeasGT(set, bounds[v], lb) )
12982  {
12983  redcost = SCIPcolGetRedcost(col, stat, lp);
12984  assert(!SCIPsetIsDualfeasNegative(set, redcost));
12985 
12986  if( varfixing )
12987  redcost *= (lb - bounds[v]);
12988  else
12989  redcost *= (bounds[v] - lb);
12990  }
12991  else if( boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasEQ(set, ub, primsol) && SCIPsetIsFeasLT(set, bounds[v], ub) )
12992  {
12993  redcost = SCIPcolGetRedcost(col, stat, lp);
12994  assert(!SCIPsetIsDualfeasPositive(set, redcost));
12995 
12996  if( varfixing )
12997  redcost *= (bounds[v] - ub);
12998  else
12999  redcost *= (ub - bounds[v]);
13000  }
13001  }
13002 
13003  /* improve implied reduced cost */
13004  if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
13005  implredcost += redcost;
13006  }
13007  }
13008 
13009 #ifdef SCIP_MORE_DEBUG
13010  SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) and implications (%d) has implied reduced cost of %g\n",
13011  SCIPvarGetName(var), ncliques, nvars, implredcost);
13012 #endif
13013 
13014  return implredcost;
13015 }
13016 
13017 /** returns the best solution (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation, if
13018  * the root relaxation is not yet completely solved, zero is returned
13019  */
13021  SCIP_VAR* var /**< problem variable */
13022  )
13023 {
13024  SCIP_Real rootsol;
13025  int i;
13026 
13027  assert(var != NULL);
13028 
13029  switch( SCIPvarGetStatus(var) )
13030  {
13032  if( var->data.original.transvar == NULL )
13033  return 0.0;
13035 
13036  case SCIP_VARSTATUS_LOOSE:
13037  case SCIP_VARSTATUS_COLUMN:
13038  return var->bestrootsol;
13039 
13040  case SCIP_VARSTATUS_FIXED:
13041  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13042  return var->locdom.lb;
13043 
13045  assert(var->data.aggregate.var != NULL);
13046  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13047  * corresponding infinity value instead of performing an arithmetical transformation (compare method
13048  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13049  * (or is called by) a public interface method; instead, we only assert that values are finite
13050  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13051  * positives and negatives if the parameter <numerics/infinity> is modified by the user
13052  */
13056 
13058  assert(!var->donotmultaggr);
13059  assert(var->data.multaggr.vars != NULL);
13060  assert(var->data.multaggr.scalars != NULL);
13061  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13062  * assert(var->data.multaggr.nvars >= 2);
13063  */
13064  rootsol = var->data.multaggr.constant;
13065  for( i = 0; i < var->data.multaggr.nvars; ++i )
13066  rootsol += var->data.multaggr.scalars[i] * SCIPvarGetBestRootSol(var->data.multaggr.vars[i]);
13067  return rootsol;
13068 
13069  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13070  assert(var->negatedvar != NULL);
13072  assert(var->negatedvar->negatedvar == var);
13073  return var->data.negate.constant - SCIPvarGetBestRootSol(var->negatedvar);
13074 
13075  default:
13076  SCIPerrorMessage("unknown variable status\n");
13077  SCIPABORT();
13078  return 0.0; /*lint !e527*/
13079  }
13080 }
13081 
13082 /** returns the best reduced costs (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation,
13083  * if the root relaxation is not yet completely solved, or the variable was no column of the root LP, SCIP_INVALID is
13084  * returned
13085  */
13087  SCIP_VAR* var /**< problem variable */
13088  )
13089 {
13090  assert(var != NULL);
13091 
13092  switch( SCIPvarGetStatus(var) )
13093  {
13095  if( var->data.original.transvar == NULL )
13096  return SCIP_INVALID;
13098 
13099  case SCIP_VARSTATUS_LOOSE:
13100  case SCIP_VARSTATUS_COLUMN:
13101  return var->bestrootredcost;
13102 
13103  case SCIP_VARSTATUS_FIXED:
13107  return 0.0;
13108 
13109  default:
13110  SCIPerrorMessage("unknown variable status\n");
13111  SCIPABORT();
13112  return 0.0; /*lint !e527*/
13113  }
13114 }
13115 
13116 /** returns the best objective value (w.r.t. root reduced cost propagation) of the root LP which belongs the root
13117  * reduced cost which is accessible via SCIPvarGetRootRedcost() or the variable was no column of the root LP,
13118  * SCIP_INVALID is returned
13119  */
13121  SCIP_VAR* var /**< problem variable */
13122  )
13123 {
13124  assert(var != NULL);
13125 
13126  switch( SCIPvarGetStatus(var) )
13127  {
13129  if( var->data.original.transvar == NULL )
13130  return SCIP_INVALID;
13132 
13133  case SCIP_VARSTATUS_LOOSE:
13134  case SCIP_VARSTATUS_COLUMN:
13135  return var->bestrootlpobjval;
13136 
13137  case SCIP_VARSTATUS_FIXED:
13141  return SCIP_INVALID;
13142 
13143  default:
13144  SCIPerrorMessage("unknown variable status\n");
13145  SCIPABORT();
13146  return SCIP_INVALID; /*lint !e527*/
13147  }
13148 }
13149 
13150 /** set the given solution as the best root solution w.r.t. root reduced cost propagation in the variables */
13152  SCIP_VAR* var, /**< problem variable */
13153  SCIP_Real rootsol, /**< root solution value */
13154  SCIP_Real rootredcost, /**< root reduced cost */
13155  SCIP_Real rootlpobjval /**< objective value of the root LP */
13156  )
13157 {
13158  assert(var != NULL);
13159 
13160  var->bestrootsol = rootsol;
13161  var->bestrootredcost = rootredcost;
13162  var->bestrootlpobjval = rootlpobjval;
13163 }
13164 
13165 /** stores the solution value as relaxation solution in the problem variable */
13167  SCIP_VAR* var, /**< problem variable */
13168  SCIP_SET* set, /**< global SCIP settings */
13169  SCIP_RELAXATION* relaxation, /**< global relaxation data */
13170  SCIP_Real solval, /**< solution value in the current relaxation solution */
13171  SCIP_Bool updateobj /**< should the objective value be updated? */
13172  )
13173 {
13174  assert(var != NULL);
13175  assert(relaxation != NULL);
13176  assert(set != NULL);
13177  assert(var->scip == set->scip);
13178 
13179  /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
13180  switch( SCIPvarGetStatus(var) )
13181  {
13183  SCIP_CALL( SCIPvarSetRelaxSol(var->data.original.transvar, set, relaxation, solval, updateobj) );
13184  break;
13185 
13186  case SCIP_VARSTATUS_LOOSE:
13187  case SCIP_VARSTATUS_COLUMN:
13188  if( updateobj )
13189  SCIPrelaxationSolObjAdd(relaxation, var->obj * (solval - var->relaxsol));
13190  var->relaxsol = solval;
13191  break;
13192 
13193  case SCIP_VARSTATUS_FIXED:
13194  if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
13195  {
13196  SCIPerrorMessage("cannot set relaxation solution value for variable <%s> fixed to %.15g to different value %.15g\n",
13197  SCIPvarGetName(var), var->glbdom.lb, solval);
13198  return SCIP_INVALIDDATA;
13199  }
13200  break;
13201 
13202  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13203  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
13204  SCIP_CALL( SCIPvarSetRelaxSol(var->data.aggregate.var, set, relaxation,
13205  (solval - var->data.aggregate.constant)/var->data.aggregate.scalar, updateobj) );
13206  break;
13208  SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
13209  return SCIP_INVALIDDATA;
13210 
13212  SCIP_CALL( SCIPvarSetRelaxSol(var->negatedvar, set, relaxation, var->data.negate.constant - solval, updateobj) );
13213  break;
13214 
13215  default:
13216  SCIPerrorMessage("unknown variable status\n");
13217  return SCIP_INVALIDDATA;
13218  }
13219 
13220  return SCIP_OKAY;
13221 }
13222 
13223 /** returns the solution value of the problem variable in the relaxation solution
13224  *
13225  * @todo Inline this function - similar to SCIPvarGetLPSol_rec.
13226  */
13228  SCIP_VAR* var, /**< problem variable */
13229  SCIP_SET* set /**< global SCIP settings */
13230  )
13231 {
13232  SCIP_Real solvalsum;
13233  SCIP_Real solval;
13234  int i;
13235 
13236  assert(var != NULL);
13237  assert(set != NULL);
13238  assert(var->scip == set->scip);
13239 
13240  /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
13241  switch( SCIPvarGetStatus(var) )
13242  {
13244  return SCIPvarGetRelaxSol(var->data.original.transvar, set);
13245 
13246  case SCIP_VARSTATUS_LOOSE:
13247  case SCIP_VARSTATUS_COLUMN:
13248  return var->relaxsol;
13249 
13250  case SCIP_VARSTATUS_FIXED:
13251  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
13252  assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
13253  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
13254  return SCIPvarGetLbGlobal(var);
13255 
13256  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13257  solval = SCIPvarGetRelaxSol(var->data.aggregate.var, set);
13258  if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
13259  {
13260  if( var->data.aggregate.scalar * solval > 0.0 )
13261  return SCIPsetInfinity(set);
13262  if( var->data.aggregate.scalar * solval < 0.0 )
13263  return -SCIPsetInfinity(set);
13264  }
13265  return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
13266 
13268  solvalsum = var->data.multaggr.constant;
13269  for( i = 0; i < var->data.multaggr.nvars; ++i )
13270  {
13271  solval = SCIPvarGetRelaxSol(var->data.multaggr.vars[i], set);
13272  if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
13273  {
13274  if( var->data.multaggr.scalars[i] * solval > 0.0 )
13275  return SCIPsetInfinity(set);
13276  if( var->data.multaggr.scalars[i] * solval < 0.0 )
13277  return -SCIPsetInfinity(set);
13278  }
13279  solvalsum += var->data.multaggr.scalars[i] * solval;
13280  }
13281  return solvalsum;
13282 
13284  solval = SCIPvarGetRelaxSol(var->negatedvar, set);
13285  if( SCIPsetIsInfinity(set, solval) )
13286  return -SCIPsetInfinity(set);
13287  if( SCIPsetIsInfinity(set, -solval) )
13288  return SCIPsetInfinity(set);
13289  return var->data.negate.constant - solval;
13290 
13291  default:
13292  SCIPerrorMessage("unknown variable status\n");
13293  SCIPABORT();
13294  return SCIP_INVALID; /*lint !e527*/
13295  }
13296 }
13297 
13298 /** returns the solution value of the transformed problem variable in the relaxation solution */
13300  SCIP_VAR* var /**< problem variable */
13301  )
13302 {
13303  assert(var != NULL);
13305 
13306  return var->relaxsol;
13307 }
13308 
13309 /** stores the solution value as NLP solution in the problem variable */
13311  SCIP_VAR* var, /**< problem variable */
13312  SCIP_SET* set, /**< global SCIP settings */
13313  SCIP_Real solval /**< solution value in the current NLP solution */
13314  )
13315 {
13316  assert(var != NULL);
13317  assert(set != NULL);
13318  assert(var->scip == set->scip);
13319 
13320  /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
13321  switch( SCIPvarGetStatus(var) )
13322  {
13324  SCIP_CALL( SCIPvarSetNLPSol(var->data.original.transvar, set, solval) );
13325  break;
13326 
13327  case SCIP_VARSTATUS_LOOSE:
13328  case SCIP_VARSTATUS_COLUMN:
13329  var->nlpsol = solval;
13330  break;
13331 
13332  case SCIP_VARSTATUS_FIXED:
13333  if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
13334  {
13335  SCIPerrorMessage("cannot set NLP solution value for variable <%s> fixed to %.15g to different value %.15g\n",
13336  SCIPvarGetName(var), var->glbdom.lb, solval);
13337  SCIPABORT();
13338  return SCIP_INVALIDCALL; /*lint !e527*/
13339  }
13340  break;
13341 
13342  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13343  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
13344  SCIP_CALL( SCIPvarSetNLPSol(var->data.aggregate.var, set, (solval - var->data.aggregate.constant)/var->data.aggregate.scalar) );
13345  break;
13346 
13348  SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
13349  SCIPABORT();
13350  return SCIP_INVALIDCALL; /*lint !e527*/
13351 
13353  SCIP_CALL( SCIPvarSetNLPSol(var->negatedvar, set, var->data.negate.constant - solval) );
13354  break;
13355 
13356  default:
13357  SCIPerrorMessage("unknown variable status\n");
13358  SCIPABORT();
13359  return SCIP_ERROR; /*lint !e527*/
13360  }
13361 
13362  return SCIP_OKAY;
13363 }
13364 
13365 /** returns a weighted average solution value of the variable in all feasible primal solutions found so far */
13367  SCIP_VAR* var /**< problem variable */
13368  )
13369 {
13370  SCIP_Real avgsol;
13371  int i;
13372 
13373  assert(var != NULL);
13374 
13375  switch( SCIPvarGetStatus(var) )
13376  {
13378  if( var->data.original.transvar == NULL )
13379  return 0.0;
13380  return SCIPvarGetAvgSol(var->data.original.transvar);
13381 
13382  case SCIP_VARSTATUS_LOOSE:
13383  case SCIP_VARSTATUS_COLUMN:
13384  avgsol = var->primsolavg;
13385  avgsol = MAX(avgsol, var->glbdom.lb);
13386  avgsol = MIN(avgsol, var->glbdom.ub);
13387  return avgsol;
13388 
13389  case SCIP_VARSTATUS_FIXED:
13390  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13391  return var->locdom.lb;
13392 
13394  assert(var->data.aggregate.var != NULL);
13395  return var->data.aggregate.scalar * SCIPvarGetAvgSol(var->data.aggregate.var)
13396  + var->data.aggregate.constant;
13397 
13399  assert(!var->donotmultaggr);
13400  assert(var->data.multaggr.vars != NULL);
13401  assert(var->data.multaggr.scalars != NULL);
13402  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13403  * assert(var->data.multaggr.nvars >= 2);
13404  */
13405  avgsol = var->data.multaggr.constant;
13406  for( i = 0; i < var->data.multaggr.nvars; ++i )
13407  avgsol += var->data.multaggr.scalars[i] * SCIPvarGetAvgSol(var->data.multaggr.vars[i]);
13408  return avgsol;
13409 
13410  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13411  assert(var->negatedvar != NULL);
13413  assert(var->negatedvar->negatedvar == var);
13414  return var->data.negate.constant - SCIPvarGetAvgSol(var->negatedvar);
13415 
13416  default:
13417  SCIPerrorMessage("unknown variable status\n");
13418  SCIPABORT();
13419  return 0.0; /*lint !e527*/
13420  }
13421 }
13422 
13423 /** returns solution value and index of variable lower bound that is closest to the variable's value in the given primal solution
13424  * or current LP solution if no primal solution is given; returns an index of -1 if no variable lower bound is available
13425  */
13427  SCIP_VAR* var, /**< active problem variable */
13428  SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
13429  SCIP_SET* set, /**< global SCIP settings */
13430  SCIP_STAT* stat, /**< problem statistics */
13431  SCIP_Real* closestvlb, /**< pointer to store the value of the closest variable lower bound */
13432  int* closestvlbidx /**< pointer to store the index of the closest variable lower bound */
13433  )
13434 {
13435  int nvlbs;
13436 
13437  assert(var != NULL);
13438  assert(stat != NULL);
13439  assert(set != NULL);
13440  assert(var->scip == set->scip);
13441  assert(closestvlb != NULL);
13442  assert(closestvlbidx != NULL);
13443 
13444  *closestvlbidx = -1;
13445  *closestvlb = SCIP_REAL_MIN;
13446 
13447  nvlbs = SCIPvarGetNVlbs(var);
13448  if( nvlbs > 0 )
13449  {
13450  SCIP_VAR** vlbvars;
13451  SCIP_Real* vlbcoefs;
13452  SCIP_Real* vlbconsts;
13453  int i;
13454 
13455  vlbvars = SCIPvarGetVlbVars(var);
13456  vlbcoefs = SCIPvarGetVlbCoefs(var);
13457  vlbconsts = SCIPvarGetVlbConstants(var);
13458 
13459  /* check for cached values */
13460  if( var->closestvblpcount == stat->lpcount && var->closestvlbidx != -1 && sol == NULL)
13461  {
13462  i = var->closestvlbidx;
13463  assert(0 <= i && i < nvlbs);
13464  assert(SCIPvarIsActive(vlbvars[i]));
13465  *closestvlbidx = i;
13466  *closestvlb = vlbcoefs[i] * SCIPvarGetLPSol(vlbvars[i]) + vlbconsts[i];
13467  }
13468  else
13469  {
13470  /* search best VUB */
13471  for( i = 0; i < nvlbs; i++ )
13472  {
13473  if( SCIPvarIsActive(vlbvars[i]) )
13474  {
13475  SCIP_Real vlbsol;
13476 
13477  vlbsol = vlbcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vlbvars[i]) : SCIPsolGetVal(sol, set, stat, vlbvars[i])) + vlbconsts[i];
13478  if( vlbsol > *closestvlb )
13479  {
13480  *closestvlb = vlbsol;
13481  *closestvlbidx = i;
13482  }
13483  }
13484  }
13485 
13486  if( sol == NULL )
13487  {
13488  /* update cached value */
13489  if( var->closestvblpcount != stat->lpcount )
13490  var->closestvubidx = -1;
13491  var->closestvlbidx = *closestvlbidx;
13492  var->closestvblpcount = stat->lpcount;
13493  }
13494  }
13495  }
13496 }
13497 
13498 /** returns solution value and index of variable upper bound that is closest to the variable's value in the given primal solution;
13499  * or current LP solution if no primal solution is given; returns an index of -1 if no variable upper bound is available
13500  */
13502  SCIP_VAR* var, /**< active problem variable */
13503  SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
13504  SCIP_SET* set, /**< global SCIP settings */
13505  SCIP_STAT* stat, /**< problem statistics */
13506  SCIP_Real* closestvub, /**< pointer to store the value of the closest variable upper bound */
13507  int* closestvubidx /**< pointer to store the index of the closest variable upper bound */
13508  )
13509 {
13510  int nvubs;
13511 
13512  assert(var != NULL);
13513  assert(set != NULL);
13514  assert(var->scip == set->scip);
13515  assert(closestvub != NULL);
13516  assert(closestvubidx != NULL);
13517 
13518  *closestvubidx = -1;
13519  *closestvub = SCIP_REAL_MAX;
13520 
13521  nvubs = SCIPvarGetNVubs(var);
13522  if( nvubs > 0 )
13523  {
13524  SCIP_VAR** vubvars;
13525  SCIP_Real* vubcoefs;
13526  SCIP_Real* vubconsts;
13527  int i;
13528 
13529  vubvars = SCIPvarGetVubVars(var);
13530  vubcoefs = SCIPvarGetVubCoefs(var);
13531  vubconsts = SCIPvarGetVubConstants(var);
13532 
13533  /* check for cached values */
13534  if( var->closestvblpcount == stat->lpcount && var->closestvubidx != -1 && sol == NULL)
13535  {
13536  i = var->closestvubidx;
13537  assert(0 <= i && i < nvubs);
13538  assert(SCIPvarIsActive(vubvars[i]));
13539  *closestvubidx = i;
13540  *closestvub = vubcoefs[i] * SCIPvarGetLPSol(vubvars[i]) + vubconsts[i];
13541  }
13542  else
13543  {
13544  /* search best VUB */
13545  for( i = 0; i < nvubs; i++ )
13546  {
13547  if( SCIPvarIsActive(vubvars[i]) )
13548  {
13549  SCIP_Real vubsol;
13550 
13551  vubsol = vubcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vubvars[i]) : SCIPsolGetVal(sol, set, stat, vubvars[i])) + vubconsts[i];
13552  if( vubsol < *closestvub )
13553  {
13554  *closestvub = vubsol;
13555  *closestvubidx = i;
13556  }
13557  }
13558  }
13559 
13560  if( sol == NULL )
13561  {
13562  /* update cached value */
13563  if( var->closestvblpcount != stat->lpcount )
13564  var->closestvlbidx = -1;
13565  var->closestvubidx = *closestvubidx;
13566  var->closestvblpcount = stat->lpcount;
13567  }
13568  }
13569  }
13570 }
13571 
13572 /** resolves variable to columns and adds them with the coefficient to the row */
13574  SCIP_VAR* var, /**< problem variable */
13575  BMS_BLKMEM* blkmem, /**< block memory */
13576  SCIP_SET* set, /**< global SCIP settings */
13577  SCIP_STAT* stat, /**< problem statistics */
13578  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
13579  SCIP_PROB* prob, /**< problem data */
13580  SCIP_LP* lp, /**< current LP data */
13581  SCIP_ROW* row, /**< LP row */
13582  SCIP_Real val /**< value of coefficient */
13583  )
13584 {
13585  int i;
13586 
13587  assert(var != NULL);
13588  assert(set != NULL);
13589  assert(var->scip == set->scip);
13590  assert(row != NULL);
13591  assert(!SCIPsetIsInfinity(set, REALABS(val)));
13592 
13593  SCIPsetDebugMsg(set, "adding coefficient %g<%s> to row <%s>\n", val, var->name, row->name);
13594 
13595  if ( SCIPsetIsZero(set, val) )
13596  return SCIP_OKAY;
13597 
13598  switch( SCIPvarGetStatus(var) )
13599  {
13601  if( var->data.original.transvar == NULL )
13602  {
13603  SCIPerrorMessage("cannot add untransformed original variable <%s> to LP row <%s>\n", var->name, row->name);
13604  return SCIP_INVALIDDATA;
13605  }
13606  SCIP_CALL( SCIPvarAddToRow(var->data.original.transvar, blkmem, set, stat, eventqueue, prob, lp, row, val) );
13607  return SCIP_OKAY;
13608 
13609  case SCIP_VARSTATUS_LOOSE:
13610  /* add globally fixed variables as constant */
13611  if( SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub) )
13612  {
13613  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->glbdom.lb) );
13614  return SCIP_OKAY;
13615  }
13616  /* convert loose variable into column */
13617  SCIP_CALL( SCIPvarColumn(var, blkmem, set, stat, prob, lp) );
13618  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
13619  /*lint -fallthrough*/
13620 
13621  case SCIP_VARSTATUS_COLUMN:
13622  assert(var->data.col != NULL);
13623  assert(var->data.col->var == var);
13624  SCIP_CALL( SCIProwIncCoef(row, blkmem, set, eventqueue, lp, var->data.col, val) );
13625  return SCIP_OKAY;
13626 
13627  case SCIP_VARSTATUS_FIXED:
13628  assert(var->glbdom.lb == var->glbdom.ub); /*lint !e777*/
13629  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13630  assert(var->locdom.lb == var->glbdom.lb); /*lint !e777*/
13631  assert(!SCIPsetIsInfinity(set, REALABS(var->locdom.lb)));
13632  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->locdom.lb) );
13633  return SCIP_OKAY;
13634 
13636  assert(var->data.aggregate.var != NULL);
13637  SCIP_CALL( SCIPvarAddToRow(var->data.aggregate.var, blkmem, set, stat, eventqueue, prob, lp,
13638  row, var->data.aggregate.scalar * val) );
13639  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.aggregate.constant * val) );
13640  return SCIP_OKAY;
13641 
13643  assert(!var->donotmultaggr);
13644  assert(var->data.multaggr.vars != NULL);
13645  assert(var->data.multaggr.scalars != NULL);
13646  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13647  * assert(var->data.multaggr.nvars >= 2);
13648  */
13649  for( i = 0; i < var->data.multaggr.nvars; ++i )
13650  {
13651  SCIP_CALL( SCIPvarAddToRow(var->data.multaggr.vars[i], blkmem, set, stat, eventqueue, prob, lp,
13652  row, var->data.multaggr.scalars[i] * val) );
13653  }
13654  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.multaggr.constant * val) );
13655  return SCIP_OKAY;
13656 
13657  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13658  assert(var->negatedvar != NULL);
13660  assert(var->negatedvar->negatedvar == var);
13661  SCIP_CALL( SCIPvarAddToRow(var->negatedvar, blkmem, set, stat, eventqueue, prob, lp, row, -val) );
13662  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.negate.constant * val) );
13663  return SCIP_OKAY;
13664 
13665  default:
13666  SCIPerrorMessage("unknown variable status\n");
13667  return SCIP_INVALIDDATA;
13668  }
13669 }
13670 
13671 /* optionally, define this compiler flag to write complete variable histories to a file */
13672 #ifdef SCIP_HISTORYTOFILE
13673 SCIP_Longint counter = 0l;
13674 const char* historypath="."; /* allows for user-defined path; use '.' for calling directory of SCIP */
13675 #include "scip/scip.h"
13676 #endif
13677 
13678 /** updates the pseudo costs of the given variable and the global pseudo costs after a change of
13679  * "solvaldelta" in the variable's solution value and resulting change of "objdelta" in the in the LP's objective value
13680  */
13682  SCIP_VAR* var, /**< problem variable */
13683  SCIP_SET* set, /**< global SCIP settings */
13684  SCIP_STAT* stat, /**< problem statistics */
13685  SCIP_Real solvaldelta, /**< difference of variable's new LP value - old LP value */
13686  SCIP_Real objdelta, /**< difference of new LP's objective value - old LP's objective value */
13687  SCIP_Real weight /**< weight in (0,1] of this update in pseudo cost sum */
13688  )
13689 {
13690  SCIP_Real oldrootpseudocosts;
13691  assert(var != NULL);
13692  assert(set != NULL);
13693  assert(var->scip == set->scip);
13694  assert(stat != NULL);
13695 
13696  /* check if history statistics should be collected for a variable */
13697  if( !stat->collectvarhistory )
13698  return SCIP_OKAY;
13699 
13700  switch( SCIPvarGetStatus(var) )
13701  {
13703  if( var->data.original.transvar == NULL )
13704  {
13705  SCIPerrorMessage("cannot update pseudo costs of original untransformed variable\n");
13706  return SCIP_INVALIDDATA;
13707  }
13708  SCIP_CALL( SCIPvarUpdatePseudocost(var->data.original.transvar, set, stat, solvaldelta, objdelta, weight) );
13709  return SCIP_OKAY;
13710 
13711  case SCIP_VARSTATUS_LOOSE:
13712  case SCIP_VARSTATUS_COLUMN:
13713  /* store old pseudo-costs for root LP best-estimate update */
13714  oldrootpseudocosts = SCIPvarGetMinPseudocostScore(var, stat, set, SCIPvarGetRootSol(var));
13715 
13716  /* update history */
13717  SCIPhistoryUpdatePseudocost(var->history, set, solvaldelta, objdelta, weight);
13718  SCIPhistoryUpdatePseudocost(var->historycrun, set, solvaldelta, objdelta, weight);
13719  SCIPhistoryUpdatePseudocost(stat->glbhistory, set, solvaldelta, objdelta, weight);
13720  SCIPhistoryUpdatePseudocost(stat->glbhistorycrun, set, solvaldelta, objdelta, weight);
13721 
13722  /* update root LP best-estimate */
13723  SCIP_CALL( SCIPstatUpdateVarRootLPBestEstimate(stat, set, var, oldrootpseudocosts) );
13724 
13725  /* append history to file */
13726 #ifdef SCIP_HISTORYTOFILE
13727  {
13728  FILE* f;
13729  char filename[256];
13730  SCIP_NODE* currentnode;
13731  SCIP_NODE* parentnode;
13732  currentnode = SCIPgetFocusNode(set->scip);
13733  parentnode = SCIPnodeGetParent(currentnode);
13734 
13735  sprintf(filename, "%s/%s.pse", historypath, SCIPgetProbName(set->scip));
13736  f = fopen(filename, "a");
13737  if( NULL != f )
13738  {
13739  fprintf(f, "%lld %s \t %lld \t %lld \t %lld \t %d \t %15.9f \t %.3f\n",
13740  ++counter,
13741  SCIPvarGetName(var),
13742  SCIPnodeGetNumber(currentnode),
13743  parentnode != NULL ? SCIPnodeGetNumber(parentnode) : -1,
13744  SCIPgetNLPIterations(set->scip),
13745  SCIPgetDepth(set->scip),
13746  objdelta,
13747  solvaldelta);
13748  fclose(f);
13749  }
13750  }
13751 #endif
13752  return SCIP_OKAY;
13753 
13754  case SCIP_VARSTATUS_FIXED:
13755  SCIPerrorMessage("cannot update pseudo cost values of a fixed variable\n");
13756  return SCIP_INVALIDDATA;
13757 
13759  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
13761  solvaldelta/var->data.aggregate.scalar, objdelta, weight) );
13762  return SCIP_OKAY;
13763 
13765  SCIPerrorMessage("cannot update pseudo cost values of a multi-aggregated variable\n");
13766  return SCIP_INVALIDDATA;
13767 
13769  SCIP_CALL( SCIPvarUpdatePseudocost(var->negatedvar, set, stat, -solvaldelta, objdelta, weight) );
13770  return SCIP_OKAY;
13771 
13772  default:
13773  SCIPerrorMessage("unknown variable status\n");
13774  return SCIP_INVALIDDATA;
13775  }
13776 }
13777 
13778 /** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value */
13780  SCIP_VAR* var, /**< problem variable */
13781  SCIP_STAT* stat, /**< problem statistics */
13782  SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
13783  )
13784 {
13785  SCIP_BRANCHDIR dir;
13786 
13787  assert(var != NULL);
13788  assert(stat != NULL);
13789 
13790  switch( SCIPvarGetStatus(var) )
13791  {
13793  if( var->data.original.transvar == NULL )
13794  return SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
13795  else
13796  return SCIPvarGetPseudocost(var->data.original.transvar, stat, solvaldelta);
13797 
13798  case SCIP_VARSTATUS_LOOSE:
13799  case SCIP_VARSTATUS_COLUMN:
13800  dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
13801 
13802  return SCIPhistoryGetPseudocostCount(var->history, dir) > 0.0
13803  ? SCIPhistoryGetPseudocost(var->history, solvaldelta)
13804  : SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
13805 
13806  case SCIP_VARSTATUS_FIXED:
13807  return 0.0;
13808 
13810  return SCIPvarGetPseudocost(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
13811 
13813  return 0.0;
13814 
13816  return SCIPvarGetPseudocost(var->negatedvar, stat, -solvaldelta);
13817 
13818  default:
13819  SCIPerrorMessage("unknown variable status\n");
13820  SCIPABORT();
13821  return 0.0; /*lint !e527*/
13822  }
13823 }
13824 
13825 /** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value,
13826  * only using the pseudo cost information of the current run
13827  */
13829  SCIP_VAR* var, /**< problem variable */
13830  SCIP_STAT* stat, /**< problem statistics */
13831  SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
13832  )
13833 {
13834  SCIP_BRANCHDIR dir;
13835 
13836  assert(var != NULL);
13837  assert(stat != NULL);
13838 
13839  switch( SCIPvarGetStatus(var) )
13840  {
13842  if( var->data.original.transvar == NULL )
13843  return SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
13844  else
13845  return SCIPvarGetPseudocostCurrentRun(var->data.original.transvar, stat, solvaldelta);
13846 
13847  case SCIP_VARSTATUS_LOOSE:
13848  case SCIP_VARSTATUS_COLUMN:
13849  dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
13850 
13851  return SCIPhistoryGetPseudocostCount(var->historycrun, dir) > 0.0
13852  ? SCIPhistoryGetPseudocost(var->historycrun, solvaldelta)
13853  : SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
13854 
13855  case SCIP_VARSTATUS_FIXED:
13856  return 0.0;
13857 
13859  return SCIPvarGetPseudocostCurrentRun(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
13860 
13862  return 0.0;
13863 
13865  return SCIPvarGetPseudocostCurrentRun(var->negatedvar, stat, -solvaldelta);
13866 
13867  default:
13868  SCIPerrorMessage("unknown variable status\n");
13869  SCIPABORT();
13870  return 0.0; /*lint !e527*/
13871  }
13872 }
13873 
13874 /** gets the variable's (possible fractional) number of pseudo cost updates for the given direction */
13876  SCIP_VAR* var, /**< problem variable */
13877  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
13878  )
13879 {
13880  assert(var != NULL);
13881  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
13882 
13883  switch( SCIPvarGetStatus(var) )
13884  {
13886  if( var->data.original.transvar == NULL )
13887  return 0.0;
13888  else
13889  return SCIPvarGetPseudocostCount(var->data.original.transvar, dir);
13890 
13891  case SCIP_VARSTATUS_LOOSE:
13892  case SCIP_VARSTATUS_COLUMN:
13893  return SCIPhistoryGetPseudocostCount(var->history, dir);
13894 
13895  case SCIP_VARSTATUS_FIXED:
13896  return 0.0;
13897 
13899  if( var->data.aggregate.scalar > 0.0 )
13900  return SCIPvarGetPseudocostCount(var->data.aggregate.var, dir);
13901  else
13903 
13905  return 0.0;
13906 
13909 
13910  default:
13911  SCIPerrorMessage("unknown variable status\n");
13912  SCIPABORT();
13913  return 0.0; /*lint !e527*/
13914  }
13915 }
13916 
13917 /** gets the variable's (possible fractional) number of pseudo cost updates for the given direction,
13918  * only using the pseudo cost information of the current run
13919  */
13921  SCIP_VAR* var, /**< problem variable */
13922  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
13923  )
13924 {
13925  assert(var != NULL);
13926  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
13927 
13928  switch( SCIPvarGetStatus(var) )
13929  {
13931  if( var->data.original.transvar == NULL )
13932  return 0.0;
13933  else
13935 
13936  case SCIP_VARSTATUS_LOOSE:
13937  case SCIP_VARSTATUS_COLUMN:
13938  return SCIPhistoryGetPseudocostCount(var->historycrun, dir);
13939 
13940  case SCIP_VARSTATUS_FIXED:
13941  return 0.0;
13942 
13944  if( var->data.aggregate.scalar > 0.0 )
13946  else
13948 
13950  return 0.0;
13951 
13954 
13955  default:
13956  SCIPerrorMessage("unknown variable status\n");
13957  SCIPABORT();
13958  return 0.0; /*lint !e527*/
13959  }
13960 }
13961 
13962 /** compares both possible directions for rounding the given solution value and returns the minimum pseudo-costs of the variable */
13964  SCIP_VAR* var, /**< problem variable */
13965  SCIP_STAT* stat, /**< problem statistics */
13966  SCIP_SET* set, /**< global SCIP settings */
13967  SCIP_Real solval /**< solution value, e.g., LP solution value */
13968  )
13969 {
13970  SCIP_Real upscore;
13971  SCIP_Real downscore;
13972  SCIP_Real solvaldeltaup;
13973  SCIP_Real solvaldeltadown;
13974 
13975  /* LP root estimate only works for variables with fractional LP root solution */
13976  if( SCIPsetIsFeasIntegral(set, solval) )
13977  return 0.0;
13978 
13979  /* no min pseudo-cost score is calculated as long as the variable was not initialized in a direction */
13981  return 0.0;
13982 
13983  /* compute delta's to ceil and floor of root LP solution value */
13984  solvaldeltaup = SCIPsetCeil(set, solval) - solval;
13985  solvaldeltadown = SCIPsetFloor(set, solval) - solval;
13986 
13987 
13988  upscore = SCIPvarGetPseudocost(var, stat, solvaldeltaup);
13989  downscore = SCIPvarGetPseudocost(var, stat, solvaldeltadown);
13990 
13991  return MIN(upscore, downscore);
13992 }
13993 
13994 /** gets the an estimate of the variable's pseudo cost variance in direction \p dir */
13996  SCIP_VAR* var, /**< problem variable */
13997  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
13998  SCIP_Bool onlycurrentrun /**< return pseudo cost variance only for current branch and bound run */
13999  )
14000 {
14001  assert(var != NULL);
14002  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14003 
14004  switch( SCIPvarGetStatus(var) )
14005  {
14007  if( var->data.original.transvar == NULL )
14008  return 0.0;
14009  else
14010  return SCIPvarGetPseudocostVariance(var->data.original.transvar, dir, onlycurrentrun);
14011 
14012  case SCIP_VARSTATUS_LOOSE:
14013  case SCIP_VARSTATUS_COLUMN:
14014  if( onlycurrentrun )
14016  else
14017  return SCIPhistoryGetPseudocostVariance(var->history, dir);
14018 
14019  case SCIP_VARSTATUS_FIXED:
14020  return 0.0;
14021 
14023  if( var->data.aggregate.scalar > 0.0 )
14024  return SCIPvarGetPseudocostVariance(var->data.aggregate.var, dir, onlycurrentrun);
14025  else
14026  return SCIPvarGetPseudocostVariance(var->data.aggregate.var, SCIPbranchdirOpposite(dir), onlycurrentrun);
14027 
14029  return 0.0;
14030 
14032  return SCIPvarGetPseudocostVariance(var->negatedvar, SCIPbranchdirOpposite(dir), onlycurrentrun);
14033 
14034  default:
14035  SCIPerrorMessage("unknown variable status\n");
14036  SCIPABORT();
14037  return 0.0; /*lint !e527*/
14038  }
14039 }
14040 
14041 /** calculates a confidence bound for this variable under the assumption of normally distributed pseudo costs
14042  *
14043  * The confidence bound \f$ \theta \geq 0\f$ denotes the interval borders \f$ [X - \theta, \ X + \theta]\f$, which contains
14044  * the true pseudo costs of the variable, i.e., the expected value of the normal distribution, with a probability
14045  * of 2 * clevel - 1.
14046  *
14047  * @return value of confidence bound for this variable
14048  */
14050  SCIP_VAR* var, /**< variable in question */
14051  SCIP_SET* set, /**< global SCIP settings */
14052  SCIP_BRANCHDIR dir, /**< the branching direction for the confidence bound */
14053  SCIP_Bool onlycurrentrun, /**< should only the current run be taken into account */
14054  SCIP_CONFIDENCELEVEL clevel /**< confidence level for the interval */
14055  )
14056 {
14057  SCIP_Real confidencebound;
14058 
14059  confidencebound = SCIPvarGetPseudocostVariance(var, dir, onlycurrentrun);
14060  if( SCIPsetIsFeasPositive(set, confidencebound) )
14061  {
14062  SCIP_Real count;
14063 
14064  if( onlycurrentrun )
14065  count = SCIPvarGetPseudocostCountCurrentRun(var, dir);
14066  else
14067  count = SCIPvarGetPseudocostCount(var, dir);
14068  /* assertion is valid because variance is positive */
14069  assert(count >= 1.9);
14070 
14071  confidencebound /= count; /*lint !e414 division by zero can obviously not occur */
14072  confidencebound = sqrt(confidencebound);
14073 
14074  /* the actual, underlying distribution of the mean is a student-t-distribution with degrees of freedom equal to
14075  * the number of pseudo cost evaluations of this variable in the respective direction. */
14076  confidencebound *= SCIPstudentTGetCriticalValue(clevel, (int)SCIPsetFloor(set, count) - 1);
14077  }
14078  else
14079  confidencebound = 0.0;
14080 
14081  return confidencebound;
14082 }
14083 
14084 /** check if the current pseudo cost relative error in a direction violates the given threshold. The Relative
14085  * Error is calculated at a specific confidence level
14086  */
14088  SCIP_VAR* var, /**< variable in question */
14089  SCIP_SET* set, /**< global SCIP settings */
14090  SCIP_STAT* stat, /**< problem statistics */
14091  SCIP_Real threshold, /**< threshold for relative errors to be considered reliable (enough) */
14092  SCIP_CONFIDENCELEVEL clevel /**< a given confidence level */
14093  )
14094 {
14095  SCIP_Real downsize;
14096  SCIP_Real upsize;
14097  SCIP_Real size;
14098  SCIP_Real relerrorup;
14099  SCIP_Real relerrordown;
14100  SCIP_Real relerror;
14101 
14102  /* check, if the pseudo cost score of the variable is reliable */
14105  size = MIN(downsize, upsize);
14106 
14107  /* Pseudo costs relative error can only be reliable if both directions have been tried at least twice */
14108  if( size <= 1.9 )
14109  return FALSE;
14110 
14111  /* use the relative error between the current mean pseudo cost value of the candidate and its upper
14112  * confidence interval bound at confidence level of 95% for individual variable reliability.
14113  * this is only possible if we have at least 2 measurements and therefore a valid variance estimate.
14114  */
14115  if( downsize >= 1.9 )
14116  {
14117  SCIP_Real normval;
14118 
14119  relerrordown = SCIPvarCalcPscostConfidenceBound(var, set, SCIP_BRANCHDIR_DOWNWARDS, TRUE, clevel);
14120  normval = SCIPvarGetPseudocostCurrentRun(var, stat, -1.0);
14121  normval = MAX(1.0, normval);
14122 
14123  relerrordown /= normval;
14124  }
14125  else
14126  relerrordown = 0.0;
14127 
14128  if( upsize >= 1.9 )
14129  {
14130  SCIP_Real normval;
14131 
14132  relerrorup = SCIPvarCalcPscostConfidenceBound(var, set, SCIP_BRANCHDIR_UPWARDS, TRUE, clevel);
14133  normval = SCIPvarGetPseudocostCurrentRun(var, stat, +1.0);
14134  normval = MAX(1.0, normval);
14135  relerrorup /= normval;
14136  }
14137  else
14138  relerrorup = 0.0;
14139 
14140  /* consider the relative error threshold violated, if it is violated in at least one branching direction */
14141  relerror = MAX(relerrorup, relerrordown);
14142 
14143  return (relerror <= threshold);
14144 }
14145 
14146 /** check if variable pseudo-costs have a significant difference in location. The significance depends on
14147  * the choice of \p clevel and on the kind of tested hypothesis. The one-sided hypothesis, which
14148  * should be rejected, is that fracy * mu_y >= fracx * mu_x, where mu_y and mu_x denote the
14149  * unknown location means of the underlying pseudo-cost distributions of x and y.
14150  *
14151  * This method is applied best if variable x has a better pseudo-cost score than y. The method hypothesizes that y were actually
14152  * better than x (despite the current information), meaning that y can be expected to yield branching
14153  * decisions as least as good as x in the long run. If the method returns TRUE, the current history information is
14154  * sufficient to safely rely on the alternative hypothesis that x yields indeed a better branching score (on average)
14155  * than y.
14156  *
14157  * @note The order of x and y matters for the one-sided hypothesis
14158  *
14159  * @note set \p onesided to FALSE if you are not sure which variable is better. The hypothesis tested then reads
14160  * fracy * mu_y == fracx * mu_x vs the alternative hypothesis fracy * mu_y != fracx * mu_x.
14161  *
14162  * @return TRUE if the hypothesis can be safely rejected at the given confidence level
14163  */
14165  SCIP_SET* set, /**< global SCIP settings */
14166  SCIP_STAT* stat, /**< problem statistics */
14167  SCIP_VAR* varx, /**< variable x */
14168  SCIP_Real fracx, /**< the fractionality of variable x */
14169  SCIP_VAR* vary, /**< variable y */
14170  SCIP_Real fracy, /**< the fractionality of variable y */
14171  SCIP_BRANCHDIR dir, /**< branching direction */
14172  SCIP_CONFIDENCELEVEL clevel, /**< confidence level for rejecting hypothesis */
14173  SCIP_Bool onesided /**< should a one-sided hypothesis y >= x be tested? */
14174  )
14175 {
14176  SCIP_Real meanx;
14177  SCIP_Real meany;
14178  SCIP_Real variancex;
14179  SCIP_Real variancey;
14180  SCIP_Real countx;
14181  SCIP_Real county;
14182  SCIP_Real tresult;
14183  SCIP_Real realdirection;
14184 
14185 
14186  if( varx == vary )
14187  return FALSE;
14188 
14189  countx = SCIPvarGetPseudocostCount(varx, dir);
14190  county = SCIPvarGetPseudocostCount(vary, dir);
14191 
14192  /* if not at least 2 measurements were taken, return FALSE */
14193  if( countx <= 1.9 || county <= 1.9 )
14194  return FALSE;
14195 
14196  realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
14197 
14198  meanx = fracx * SCIPvarGetPseudocost(varx, stat, realdirection);
14199  meany = fracy * SCIPvarGetPseudocost(vary, stat, realdirection);
14200 
14201  variancex = SQR(fracx) * SCIPvarGetPseudocostVariance(varx, dir, FALSE);
14202  variancey = SQR(fracy) * SCIPvarGetPseudocostVariance(vary, dir, FALSE);
14203 
14204  /* if there is no variance, the means are taken from a constant distribution */
14205  if( SCIPsetIsFeasEQ(set, variancex + variancey, 0.0) )
14206  return (onesided ? SCIPsetIsFeasGT(set, meanx, meany) : !SCIPsetIsFeasEQ(set, meanx, meany));
14207 
14208  tresult = SCIPcomputeTwoSampleTTestValue(meanx, meany, variancex, variancey, countx, county);
14209 
14210  /* for the two-sided hypothesis, just take the absolute of t */
14211  if( !onesided )
14212  tresult = REALABS(tresult);
14213 
14214  return (tresult >= SCIPstudentTGetCriticalValue(clevel, (int)(countx + county - 2)));
14215 }
14216 
14217 /** tests at a given confidence level whether the variable pseudo-costs only have a small probability to
14218  * exceed a \p threshold. This is useful to determine if past observations provide enough evidence
14219  * to skip an expensive strong-branching step if there is already a candidate that has been proven to yield an improvement
14220  * of at least \p threshold.
14221  *
14222  * @note use \p clevel to adjust the level of confidence. For SCIP_CONFIDENCELEVEL_MIN, the method returns TRUE if
14223  * the estimated probability to exceed \p threshold is less than 25 %.
14224  *
14225  * @see SCIP_Confidencelevel for a list of available levels. The used probability limits refer to the one-sided levels
14226  * of confidence.
14227  *
14228  * @return TRUE if the variable pseudo-cost probabilistic model is likely to be smaller than \p threshold
14229  * at the given confidence level \p clevel.
14230  */
14232  SCIP_SET* set, /**< global SCIP settings */
14233  SCIP_STAT* stat, /**< problem statistics */
14234  SCIP_VAR* var, /**< variable x */
14235  SCIP_Real frac, /**< the fractionality of variable x */
14236  SCIP_Real threshold, /**< the threshold to test against */
14237  SCIP_BRANCHDIR dir, /**< branching direction */
14238  SCIP_CONFIDENCELEVEL clevel /**< confidence level for rejecting hypothesis */
14239  )
14240 {
14241  SCIP_Real mean;
14242  SCIP_Real variance;
14243  SCIP_Real count;
14244  SCIP_Real realdirection;
14245  SCIP_Real probability;
14246  SCIP_Real problimit;
14247 
14248  count = SCIPvarGetPseudocostCount(var, dir);
14249 
14250  /* if not at least 2 measurements were taken, return FALSE */
14251  if( count <= 1.9 )
14252  return FALSE;
14253 
14254  realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
14255 
14256  mean = frac * SCIPvarGetPseudocost(var, stat, realdirection);
14257  variance = SQR(frac) * SCIPvarGetPseudocostVariance(var, dir, FALSE);
14258 
14259  /* if mean is at least threshold, it has at least a 50% probability to exceed threshold, we therefore return FALSE */
14260  if( SCIPsetIsFeasGE(set, mean, threshold) )
14261  return FALSE;
14262 
14263  /* if there is no variance, the means are taken from a constant distribution */
14264  if( SCIPsetIsFeasEQ(set, variance, 0.0) )
14265  return SCIPsetIsFeasLT(set, mean, threshold);
14266 
14267  /* obtain probability of a normally distributed random variable at given mean and variance to yield at most threshold */
14268  probability = SCIPnormalCDF(mean, variance, threshold);
14269 
14270  /* determine a probability limit corresponding to the given confidence level */
14271  switch( clevel )
14272  {
14274  problimit = 0.75;
14275  break;
14277  problimit = 0.875;
14278  break;
14280  problimit = 0.9;
14281  break;
14283  problimit = 0.95;
14284  break;
14286  problimit = 0.975;
14287  break;
14288  default:
14289  problimit = -1;
14290  SCIPerrorMessage("Confidence level set to unknown value <%d>", (int)clevel);
14291  SCIPABORT();
14292  break;
14293  }
14294 
14295  return (probability >= problimit);
14296 }
14297 
14298 /** find the corresponding history entry if already existing, otherwise create new entry */
14299 static
14301  SCIP_VAR* var, /**< problem variable */
14302  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14303  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14304  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14305  SCIP_HISTORY** history /**< pointer to store the value based history, or NULL */
14306  )
14307 {
14308  assert(var != NULL);
14309  assert(blkmem != NULL);
14310  assert(set != NULL);
14311  assert(history != NULL);
14312 
14313  (*history) = NULL;
14314 
14315  if( var->valuehistory == NULL )
14316  {
14317  SCIP_CALL( SCIPvaluehistoryCreate(&var->valuehistory, blkmem) );
14318  }
14319 
14320  SCIP_CALL( SCIPvaluehistoryFind(var->valuehistory, blkmem, set, value, history) );
14321 
14322  return SCIP_OKAY;
14323 }
14324 
14325 /** check if value based history should be used */
14326 static
14328  SCIP_VAR* var, /**< problem variable */
14329  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14330  SCIP_SET* set /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14331  )
14332 {
14333  /* check if the domain value is unknown (not specific) */
14334  if( value == SCIP_UNKNOWN ) /*lint !e777*/
14335  return FALSE;
14336 
14337  assert(set != NULL);
14338 
14339  /* check if value based history should be collected */
14340  if( !set->history_valuebased )
14341  return FALSE;
14342 
14343  /* value based history is not collected for binary variable since the standard history already contains all information */
14344  if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
14345  return FALSE;
14346 
14347  /* value based history is not collected for continuous variables */
14349  return FALSE;
14350 
14351  return TRUE;
14352 }
14353 
14354 /** increases VSIDS of the variable by the given weight */
14356  SCIP_VAR* var, /**< problem variable */
14357  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14358  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14359  SCIP_STAT* stat, /**< problem statistics */
14360  SCIP_BRANCHDIR dir, /**< branching direction */
14361  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14362  SCIP_Real weight /**< weight of this update in VSIDS */
14363  )
14364 {
14365  assert(var != NULL);
14366  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14367 
14368  /* check if history statistics should be collected for a variable */
14369  if( !stat->collectvarhistory )
14370  return SCIP_OKAY;
14371 
14372  if( SCIPsetIsZero(set, weight) )
14373  return SCIP_OKAY;
14374 
14375  switch( SCIPvarGetStatus(var) )
14376  {
14378  if( var->data.original.transvar == NULL )
14379  {
14380  SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
14381  return SCIP_INVALIDDATA;
14382  }
14383  SCIP_CALL( SCIPvarIncVSIDS(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
14384  return SCIP_OKAY;
14385 
14386  case SCIP_VARSTATUS_LOOSE:
14387  case SCIP_VARSTATUS_COLUMN:
14388  {
14389  SCIPhistoryIncVSIDS(var->history, dir, weight);
14390  SCIPhistoryIncVSIDS(var->historycrun, dir, weight);
14391 
14392  if( useValuehistory(var, value, set) )
14393  {
14394  SCIP_HISTORY* history;
14395 
14396  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
14397  assert(history != NULL);
14398 
14399  SCIPhistoryIncVSIDS(history, dir, weight);
14400  SCIPsetDebugMsg(set, "variable (<%s> %s %g) + <%g> = <%g>\n", SCIPvarGetName(var), dir == SCIP_BRANCHDIR_UPWARDS ? ">=" : "<=",
14401  value, weight, SCIPhistoryGetVSIDS(history, dir));
14402  }
14403 
14404  return SCIP_OKAY;
14405  }
14406  case SCIP_VARSTATUS_FIXED:
14407  SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
14408  return SCIP_INVALIDDATA;
14409 
14411  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
14412 
14413  if( var->data.aggregate.scalar > 0.0 )
14414  {
14415  SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
14416  }
14417  else
14418  {
14419  assert(var->data.aggregate.scalar < 0.0);
14420  SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
14421  }
14422  return SCIP_OKAY;
14423 
14425  SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
14426  return SCIP_INVALIDDATA;
14427 
14429  value = 1.0 - value;
14430 
14431  SCIP_CALL( SCIPvarIncVSIDS(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
14432  return SCIP_OKAY;
14433 
14434  default:
14435  SCIPerrorMessage("unknown variable status\n");
14436  return SCIP_INVALIDDATA;
14437  }
14438 }
14439 
14440 /** scales the VSIDS of the variable by the given scalar */
14442  SCIP_VAR* var, /**< problem variable */
14443  SCIP_Real scalar /**< scalar to multiply the VSIDSs with */
14444  )
14445 {
14446  assert(var != NULL);
14447 
14448  switch( SCIPvarGetStatus(var) )
14449  {
14451  if( var->data.original.transvar == NULL )
14452  {
14453  SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
14454  return SCIP_INVALIDDATA;
14455  }
14457  return SCIP_OKAY;
14458 
14459  case SCIP_VARSTATUS_LOOSE:
14460  case SCIP_VARSTATUS_COLUMN:
14461  {
14462  SCIPhistoryScaleVSIDS(var->history, scalar);
14463  SCIPhistoryScaleVSIDS(var->historycrun, scalar);
14465 
14466  return SCIP_OKAY;
14467  }
14468  case SCIP_VARSTATUS_FIXED:
14469  SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
14470  return SCIP_INVALIDDATA;
14471 
14473  SCIP_CALL( SCIPvarScaleVSIDS(var->data.aggregate.var, scalar) );
14474  return SCIP_OKAY;
14475 
14477  SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
14478  return SCIP_INVALIDDATA;
14479 
14481  SCIP_CALL( SCIPvarScaleVSIDS(var->negatedvar, scalar) );
14482  return SCIP_OKAY;
14483 
14484  default:
14485  SCIPerrorMessage("unknown variable status\n");
14486  return SCIP_INVALIDDATA;
14487  }
14488 }
14489 
14490 /** increases the number of active conflicts by one and the overall length of the variable by the given length */
14492  SCIP_VAR* var, /**< problem variable */
14493  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14494  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14495  SCIP_STAT* stat, /**< problem statistics */
14496  SCIP_BRANCHDIR dir, /**< branching direction */
14497  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14498  SCIP_Real length /**< length of the conflict */
14499  )
14500 {
14501  assert(var != NULL);
14502  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14503 
14504  /* check if history statistics should be collected for a variable */
14505  if( !stat->collectvarhistory )
14506  return SCIP_OKAY;
14507 
14508  switch( SCIPvarGetStatus(var) )
14509  {
14511  if( var->data.original.transvar == NULL )
14512  {
14513  SCIPerrorMessage("cannot update conflict score of original untransformed variable\n");
14514  return SCIP_INVALIDDATA;
14515  }
14516  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.original.transvar, blkmem, set, stat, dir, value, length) );
14517  return SCIP_OKAY;
14518 
14519  case SCIP_VARSTATUS_LOOSE:
14520  case SCIP_VARSTATUS_COLUMN:
14521  {
14522  SCIPhistoryIncNActiveConflicts(var->history, dir, length);
14523  SCIPhistoryIncNActiveConflicts(var->historycrun, dir, length);
14524 
14525  if( useValuehistory(var, value, set) )
14526  {
14527  SCIP_HISTORY* history;
14528 
14529  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
14530  assert(history != NULL);
14531 
14532  SCIPhistoryIncNActiveConflicts(history, dir, length);
14533  }
14534 
14535  return SCIP_OKAY;
14536  }
14537  case SCIP_VARSTATUS_FIXED:
14538  SCIPerrorMessage("cannot update conflict score of a fixed variable\n");
14539  return SCIP_INVALIDDATA;
14540 
14542  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
14543 
14544  if( var->data.aggregate.scalar > 0.0 )
14545  {
14546  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, dir, value, length) );
14547  }
14548  else
14549  {
14550  assert(var->data.aggregate.scalar < 0.0);
14551  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
14552  }
14553  return SCIP_OKAY;
14554 
14556  SCIPerrorMessage("cannot update conflict score of a multi-aggregated variable\n");
14557  return SCIP_INVALIDDATA;
14558 
14560  value = 1.0 - value;
14561 
14562  SCIP_CALL( SCIPvarIncNActiveConflicts(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
14563  return SCIP_OKAY;
14564 
14565  default:
14566  SCIPerrorMessage("unknown variable status\n");
14567  return SCIP_INVALIDDATA;
14568  }
14569 }
14570 
14571 /** gets the number of active conflicts containing this variable in given direction */
14573  SCIP_VAR* var, /**< problem variable */
14574  SCIP_STAT* stat, /**< problem statistics */
14575  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14576  )
14577 {
14578  assert(var != NULL);
14579  assert(stat != NULL);
14580  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14581 
14582  switch( SCIPvarGetStatus(var) )
14583  {
14585  if( var->data.original.transvar == NULL )
14586  return 0;
14587  else
14588  return SCIPvarGetNActiveConflicts(var->data.original.transvar, stat, dir);
14589 
14590  case SCIP_VARSTATUS_LOOSE:
14591  case SCIP_VARSTATUS_COLUMN:
14592  return SCIPhistoryGetNActiveConflicts(var->history, dir);
14593 
14594  case SCIP_VARSTATUS_FIXED:
14595  return 0;
14596 
14598  if( var->data.aggregate.scalar > 0.0 )
14599  return SCIPvarGetNActiveConflicts(var->data.aggregate.var, stat, dir);
14600  else
14602 
14604  return 0;
14605 
14608 
14609  default:
14610  SCIPerrorMessage("unknown variable status\n");
14611  SCIPABORT();
14612  return 0; /*lint !e527*/
14613  }
14614 }
14615 
14616 /** gets the number of active conflicts containing this variable in given direction
14617  * in the current run
14618  */
14620  SCIP_VAR* var, /**< problem variable */
14621  SCIP_STAT* stat, /**< problem statistics */
14622  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14623  )
14624 {
14625  assert(var != NULL);
14626  assert(stat != NULL);
14627  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14628 
14629  switch( SCIPvarGetStatus(var) )
14630  {
14632  if( var->data.original.transvar == NULL )
14633  return 0;
14634  else
14636 
14637  case SCIP_VARSTATUS_LOOSE:
14638  case SCIP_VARSTATUS_COLUMN:
14639  return SCIPhistoryGetNActiveConflicts(var->historycrun, dir);
14640 
14641  case SCIP_VARSTATUS_FIXED:
14642  return 0;
14643 
14645  if( var->data.aggregate.scalar > 0.0 )
14646  return SCIPvarGetNActiveConflictsCurrentRun(var->data.aggregate.var, stat, dir);
14647  else
14649 
14651  return 0;
14652 
14655 
14656  default:
14657  SCIPerrorMessage("unknown variable status\n");
14658  SCIPABORT();
14659  return 0; /*lint !e527*/
14660  }
14661 }
14662 
14663 /** gets the average conflict length in given direction due to branching on the variable */
14665  SCIP_VAR* var, /**< problem variable */
14666  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14667  )
14668 {
14669  assert(var != NULL);
14670  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14671 
14672  switch( SCIPvarGetStatus(var) )
14673  {
14675  if( var->data.original.transvar == NULL )
14676  return 0.0;
14677  else
14679 
14680  case SCIP_VARSTATUS_LOOSE:
14681  case SCIP_VARSTATUS_COLUMN:
14682  return SCIPhistoryGetAvgConflictlength(var->history, dir);
14683  case SCIP_VARSTATUS_FIXED:
14684  return 0.0;
14685 
14687  if( var->data.aggregate.scalar > 0.0 )
14688  return SCIPvarGetAvgConflictlength(var->data.aggregate.var, dir);
14689  else
14691 
14693  return 0.0;
14694 
14697 
14698  default:
14699  SCIPerrorMessage("unknown variable status\n");
14700  SCIPABORT();
14701  return 0.0; /*lint !e527*/
14702  }
14703 }
14704 
14705 /** gets the average conflict length in given direction due to branching on the variable
14706  * in the current run
14707  */
14709  SCIP_VAR* var, /**< problem variable */
14710  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14711  )
14712 {
14713  assert(var != NULL);
14714  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14715 
14716  switch( SCIPvarGetStatus(var) )
14717  {
14719  if( var->data.original.transvar == NULL )
14720  return 0.0;
14721  else
14723 
14724  case SCIP_VARSTATUS_LOOSE:
14725  case SCIP_VARSTATUS_COLUMN:
14726  return SCIPhistoryGetAvgConflictlength(var->historycrun, dir);
14727 
14728  case SCIP_VARSTATUS_FIXED:
14729  return 0.0;
14730 
14732  if( var->data.aggregate.scalar > 0.0 )
14734  else
14736 
14738  return 0.0;
14739 
14742 
14743  default:
14744  SCIPerrorMessage("unknown variable status\n");
14745  SCIPABORT();
14746  return 0.0; /*lint !e527*/
14747  }
14748 }
14749 
14750 /** increases the number of branchings counter of the variable */
14752  SCIP_VAR* var, /**< problem variable */
14753  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14754  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14755  SCIP_STAT* stat, /**< problem statistics */
14756  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
14757  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14758  int depth /**< depth at which the bound change took place */
14759  )
14760 {
14761  assert(var != NULL);
14762  assert(stat != NULL);
14763  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14764 
14765  /* check if history statistics should be collected for a variable */
14766  if( !stat->collectvarhistory )
14767  return SCIP_OKAY;
14768 
14769  switch( SCIPvarGetStatus(var) )
14770  {
14772  if( var->data.original.transvar == NULL )
14773  {
14774  SCIPerrorMessage("cannot update branching counter of original untransformed variable\n");
14775  return SCIP_INVALIDDATA;
14776  }
14777  SCIP_CALL( SCIPvarIncNBranchings(var->data.original.transvar, blkmem, set, stat, dir, value, depth) );
14778  return SCIP_OKAY;
14779 
14780  case SCIP_VARSTATUS_LOOSE:
14781  case SCIP_VARSTATUS_COLUMN:
14782  {
14783  SCIPhistoryIncNBranchings(var->history, dir, depth);
14784  SCIPhistoryIncNBranchings(var->historycrun, dir, depth);
14785  SCIPhistoryIncNBranchings(stat->glbhistory, dir, depth);
14786  SCIPhistoryIncNBranchings(stat->glbhistorycrun, dir, depth);
14787 
14788  if( useValuehistory(var, value, set) )
14789  {
14790  SCIP_HISTORY* history;
14791 
14792  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
14793  assert(history != NULL);
14794 
14795  SCIPhistoryIncNBranchings(history, dir, depth);
14796  }
14797 
14798  return SCIP_OKAY;
14799  }
14800  case SCIP_VARSTATUS_FIXED:
14801  SCIPerrorMessage("cannot update branching counter of a fixed variable\n");
14802  return SCIP_INVALIDDATA;
14803 
14805  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
14806 
14807  if( var->data.aggregate.scalar > 0.0 )
14808  {
14809  SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, dir, value, depth) );
14810  }
14811  else
14812  {
14813  assert(var->data.aggregate.scalar < 0.0);
14814  SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
14815  }
14816  return SCIP_OKAY;
14817 
14819  SCIPerrorMessage("cannot update branching counter of a multi-aggregated variable\n");
14820  return SCIP_INVALIDDATA;
14821 
14823  value = 1.0 - value;
14824 
14825  SCIP_CALL( SCIPvarIncNBranchings(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
14826  return SCIP_OKAY;
14827 
14828  default:
14829  SCIPerrorMessage("unknown variable status\n");
14830  return SCIP_INVALIDDATA;
14831  }
14832 }
14833 
14834 /** increases the inference sum of the variable by the given weight */
14836  SCIP_VAR* var, /**< problem variable */
14837  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14838  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14839  SCIP_STAT* stat, /**< problem statistics */
14840  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
14841  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14842  SCIP_Real weight /**< weight of this update in inference score */
14843  )
14844 {
14845  assert(var != NULL);
14846  assert(stat != NULL);
14847  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14848 
14849  /* check if history statistics should be collected for a variable */
14850  if( !stat->collectvarhistory )
14851  return SCIP_OKAY;
14852 
14853  switch( SCIPvarGetStatus(var) )
14854  {
14856  if( var->data.original.transvar == NULL )
14857  {
14858  SCIPerrorMessage("cannot update inference counter of original untransformed variable\n");
14859  return SCIP_INVALIDDATA;
14860  }
14861  SCIP_CALL( SCIPvarIncInferenceSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
14862  return SCIP_OKAY;
14863 
14864  case SCIP_VARSTATUS_LOOSE:
14865  case SCIP_VARSTATUS_COLUMN:
14866  {
14867  SCIPhistoryIncInferenceSum(var->history, dir, weight);
14868  SCIPhistoryIncInferenceSum(var->historycrun, dir, weight);
14869  SCIPhistoryIncInferenceSum(stat->glbhistory, dir, weight);
14870  SCIPhistoryIncInferenceSum(stat->glbhistorycrun, dir, weight);
14871 
14872  if( useValuehistory(var, value, set) )
14873  {
14874  SCIP_HISTORY* history;
14875 
14876  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
14877  assert(history != NULL);
14878 
14879  SCIPhistoryIncInferenceSum(history, dir, weight);
14880  }
14881 
14882  return SCIP_OKAY;
14883  }
14884  case SCIP_VARSTATUS_FIXED:
14885  SCIPerrorMessage("cannot update inference counter of a fixed variable\n");
14886  return SCIP_INVALIDDATA;
14887 
14889  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
14890 
14891  if( var->data.aggregate.scalar > 0.0 )
14892  {
14893  SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
14894  }
14895  else
14896  {
14897  assert(var->data.aggregate.scalar < 0.0);
14898  SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
14899  }
14900  return SCIP_OKAY;
14901 
14903  SCIPerrorMessage("cannot update inference counter of a multi-aggregated variable\n");
14904  return SCIP_INVALIDDATA;
14905 
14907  value = 1.0 - value;
14908 
14909  SCIP_CALL( SCIPvarIncInferenceSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
14910  return SCIP_OKAY;
14911 
14912  default:
14913  SCIPerrorMessage("unknown variable status\n");
14914  return SCIP_INVALIDDATA;
14915  }
14916 }
14917 
14918 /** increases the cutoff sum of the variable by the given weight */
14920  SCIP_VAR* var, /**< problem variable */
14921  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14922  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14923  SCIP_STAT* stat, /**< problem statistics */
14924  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
14925  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14926  SCIP_Real weight /**< weight of this update in cutoff score */
14927  )
14928 {
14929  assert(var != NULL);
14930  assert(stat != NULL);
14931  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14932 
14933  /* check if history statistics should be collected for a variable */
14934  if( !stat->collectvarhistory )
14935  return SCIP_OKAY;
14936 
14937  switch( SCIPvarGetStatus(var) )
14938  {
14940  if( var->data.original.transvar == NULL )
14941  {
14942  SCIPerrorMessage("cannot update cutoff sum of original untransformed variable\n");
14943  return SCIP_INVALIDDATA;
14944  }
14945  SCIP_CALL( SCIPvarIncCutoffSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
14946  return SCIP_OKAY;
14947 
14948  case SCIP_VARSTATUS_LOOSE:
14949  case SCIP_VARSTATUS_COLUMN:
14950  {
14951  SCIPhistoryIncCutoffSum(var->history, dir, weight);
14952  SCIPhistoryIncCutoffSum(var->historycrun, dir, weight);
14953  SCIPhistoryIncCutoffSum(stat->glbhistory, dir, weight);
14954  SCIPhistoryIncCutoffSum(stat->glbhistorycrun, dir, weight);
14955 
14956  if( useValuehistory(var, value, set) )
14957  {
14958  SCIP_HISTORY* history;
14959 
14960  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
14961  assert(history != NULL);
14962 
14963  SCIPhistoryIncCutoffSum(history, dir, weight);
14964  }
14965 
14966  return SCIP_OKAY;
14967  }
14968  case SCIP_VARSTATUS_FIXED:
14969  SCIPerrorMessage("cannot update cutoff sum of a fixed variable\n");
14970  return SCIP_INVALIDDATA;
14971 
14973  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
14974 
14975  if( var->data.aggregate.scalar > 0.0 )
14976  {
14977  SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
14978  }
14979  else
14980  {
14981  assert(var->data.aggregate.scalar < 0.0);
14982  SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
14983  }
14984  return SCIP_OKAY;
14985 
14987  SCIPerrorMessage("cannot update cutoff sum of a multi-aggregated variable\n");
14988  return SCIP_INVALIDDATA;
14989 
14991  value = 1.0 - value;
14992 
14993  SCIP_CALL( SCIPvarIncCutoffSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
14994  return SCIP_OKAY;
14995 
14996  default:
14997  SCIPerrorMessage("unknown variable status\n");
14998  return SCIP_INVALIDDATA;
14999  }
15000 }
15001 
15002 /** returns the number of times, a bound of the variable was changed in given direction due to branching */
15004  SCIP_VAR* var, /**< problem variable */
15005  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15006  )
15007 {
15008  assert(var != NULL);
15009  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15010 
15011  switch( SCIPvarGetStatus(var) )
15012  {
15014  if( var->data.original.transvar == NULL )
15015  return 0;
15016  else
15017  return SCIPvarGetNBranchings(var->data.original.transvar, dir);
15018 
15019  case SCIP_VARSTATUS_LOOSE:
15020  case SCIP_VARSTATUS_COLUMN:
15021  return SCIPhistoryGetNBranchings(var->history, dir);
15022 
15023  case SCIP_VARSTATUS_FIXED:
15024  return 0;
15025 
15027  if( var->data.aggregate.scalar > 0.0 )
15028  return SCIPvarGetNBranchings(var->data.aggregate.var, dir);
15029  else
15031 
15033  return 0;
15034 
15037 
15038  default:
15039  SCIPerrorMessage("unknown variable status\n");
15040  SCIPABORT();
15041  return 0; /*lint !e527*/
15042  }
15043 }
15044 
15045 /** returns the number of times, a bound of the variable was changed in given direction due to branching
15046  * in the current run
15047  */
15049  SCIP_VAR* var, /**< problem variable */
15050  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15051  )
15052 {
15053  assert(var != NULL);
15054  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15055 
15056  switch( SCIPvarGetStatus(var) )
15057  {
15059  if( var->data.original.transvar == NULL )
15060  return 0;
15061  else
15063 
15064  case SCIP_VARSTATUS_LOOSE:
15065  case SCIP_VARSTATUS_COLUMN:
15066  return SCIPhistoryGetNBranchings(var->historycrun, dir);
15067 
15068  case SCIP_VARSTATUS_FIXED:
15069  return 0;
15070 
15072  if( var->data.aggregate.scalar > 0.0 )
15074  else
15076 
15078  return 0;
15079 
15082 
15083  default:
15084  SCIPerrorMessage("unknown variable status\n");
15085  SCIPABORT();
15086  return 0; /*lint !e527*/
15087  }
15088 }
15089 
15090 /** returns the average depth of bound changes in given direction due to branching on the variable */
15092  SCIP_VAR* var, /**< problem variable */
15093  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15094  )
15095 {
15096  assert(var != NULL);
15097  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15098 
15099  switch( SCIPvarGetStatus(var) )
15100  {
15102  if( var->data.original.transvar == NULL )
15103  return 0.0;
15104  else
15105  return SCIPvarGetAvgBranchdepth(var->data.original.transvar, dir);
15106 
15107  case SCIP_VARSTATUS_LOOSE:
15108  case SCIP_VARSTATUS_COLUMN:
15109  return SCIPhistoryGetAvgBranchdepth(var->history, dir);
15110 
15111  case SCIP_VARSTATUS_FIXED:
15112  return 0.0;
15113 
15115  if( var->data.aggregate.scalar > 0.0 )
15116  return SCIPvarGetAvgBranchdepth(var->data.aggregate.var, dir);
15117  else
15119 
15121  return 0.0;
15122 
15125 
15126  default:
15127  SCIPerrorMessage("unknown variable status\n");
15128  SCIPABORT();
15129  return 0.0; /*lint !e527*/
15130  }
15131 }
15132 
15133 /** returns the average depth of bound changes in given direction due to branching on the variable
15134  * in the current run
15135  */
15137  SCIP_VAR* var, /**< problem variable */
15138  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15139  )
15140 {
15141  assert(var != NULL);
15142  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15143 
15144  switch( SCIPvarGetStatus(var) )
15145  {
15147  if( var->data.original.transvar == NULL )
15148  return 0.0;
15149  else
15151 
15152  case SCIP_VARSTATUS_LOOSE:
15153  case SCIP_VARSTATUS_COLUMN:
15154  return SCIPhistoryGetAvgBranchdepth(var->historycrun, dir);
15155 
15156  case SCIP_VARSTATUS_FIXED:
15157  return 0.0;
15158 
15160  if( var->data.aggregate.scalar > 0.0 )
15162  else
15165 
15167  return 0.0;
15168 
15171  dir == SCIP_BRANCHDIR_DOWNWARDS ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
15172 
15173  default:
15174  SCIPerrorMessage("unknown variable status\n");
15175  SCIPABORT();
15176  return 0.0; /*lint !e527*/
15177  }
15178 }
15179 
15180 /** returns the variable's VSIDS score */
15182  SCIP_VAR* var, /**< problem variable */
15183  SCIP_STAT* stat, /**< problem statistics */
15184  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15185  )
15186 {
15187  assert(var != NULL);
15188  assert(stat != NULL);
15189  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15190 
15192  return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
15193 
15194  switch( SCIPvarGetStatus(var) )
15195  {
15197  if( var->data.original.transvar == NULL )
15198  return 0.0;
15199  else
15200  return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
15201 
15202  case SCIP_VARSTATUS_LOOSE:
15203  case SCIP_VARSTATUS_COLUMN:
15204  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE); /* column case already handled in if condition above */
15205  return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
15206 
15207  case SCIP_VARSTATUS_FIXED:
15208  return 0.0;
15209 
15211  if( var->data.aggregate.scalar > 0.0 )
15212  return SCIPvarGetVSIDS(var->data.aggregate.var, stat, dir);
15213  else
15214  return SCIPvarGetVSIDS(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
15215 
15217  return 0.0;
15218 
15220  return SCIPvarGetVSIDS(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15221 
15222  default:
15223  SCIPerrorMessage("unknown variable status\n");
15224  SCIPABORT();
15225  return 0.0; /*lint !e527*/
15226  }
15227 }
15228 
15229 /** returns the variable's VSIDS score only using conflicts of the current run */
15231  SCIP_VAR* var, /**< problem variable */
15232  SCIP_STAT* stat, /**< problem statistics */
15233  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15234  )
15235 {
15236  assert(var != NULL);
15237  assert(stat != NULL);
15238  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15239 
15240  switch( SCIPvarGetStatus(var) )
15241  {
15243  if( var->data.original.transvar == NULL )
15244  return 0.0;
15245  else
15246  return SCIPvarGetVSIDSCurrentRun(var->data.original.transvar, stat, dir);
15247 
15248  case SCIP_VARSTATUS_LOOSE:
15249  case SCIP_VARSTATUS_COLUMN:
15250  return SCIPhistoryGetVSIDS(var->historycrun, dir)/stat->vsidsweight;
15251 
15252  case SCIP_VARSTATUS_FIXED:
15253  return 0.0;
15254 
15256  if( var->data.aggregate.scalar > 0.0 )
15257  return SCIPvarGetVSIDSCurrentRun(var->data.aggregate.var, stat, dir);
15258  else
15260 
15262  return 0.0;
15263 
15266 
15267  default:
15268  SCIPerrorMessage("unknown variable status\n");
15269  SCIPABORT();
15270  return 0.0; /*lint !e527*/
15271  }
15272 }
15273 
15274 /** returns the number of inferences branching on this variable in given direction triggered */
15276  SCIP_VAR* var, /**< problem variable */
15277  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15278  )
15279 {
15280  assert(var != NULL);
15281  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15282 
15283  switch( SCIPvarGetStatus(var) )
15284  {
15286  if( var->data.original.transvar == NULL )
15287  return 0.0;
15288  else
15289  return SCIPvarGetInferenceSum(var->data.original.transvar, dir);
15290 
15291  case SCIP_VARSTATUS_LOOSE:
15292  case SCIP_VARSTATUS_COLUMN:
15293  return SCIPhistoryGetInferenceSum(var->history, dir);
15294 
15295  case SCIP_VARSTATUS_FIXED:
15296  return 0.0;
15297 
15299  if( var->data.aggregate.scalar > 0.0 )
15300  return SCIPvarGetInferenceSum(var->data.aggregate.var, dir);
15301  else
15303 
15305  return 0.0;
15306 
15309 
15310  default:
15311  SCIPerrorMessage("unknown variable status\n");
15312  SCIPABORT();
15313  return 0.0; /*lint !e527*/
15314  }
15315 }
15316 
15317 /** returns the number of inferences branching on this variable in given direction triggered
15318  * in the current run
15319  */
15321  SCIP_VAR* var, /**< problem variable */
15322  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15323  )
15324 {
15325  assert(var != NULL);
15326  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15327 
15328  switch( SCIPvarGetStatus(var) )
15329  {
15331  if( var->data.original.transvar == NULL )
15332  return 0.0;
15333  else
15335 
15336  case SCIP_VARSTATUS_LOOSE:
15337  case SCIP_VARSTATUS_COLUMN:
15338  return SCIPhistoryGetInferenceSum(var->historycrun, dir);
15339 
15340  case SCIP_VARSTATUS_FIXED:
15341  return 0.0;
15342 
15344  if( var->data.aggregate.scalar > 0.0 )
15346  else
15348 
15350  return 0.0;
15351 
15354 
15355  default:
15356  SCIPerrorMessage("unknown variable status\n");
15357  SCIPABORT();
15358  return 0.0; /*lint !e527*/
15359  }
15360 }
15361 
15362 /** returns the average number of inferences found after branching on the variable in given direction */
15364  SCIP_VAR* var, /**< problem variable */
15365  SCIP_STAT* stat, /**< problem statistics */
15366  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15367  )
15368 {
15369  assert(var != NULL);
15370  assert(stat != NULL);
15371  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15372 
15373  switch( SCIPvarGetStatus(var) )
15374  {
15376  if( var->data.original.transvar == NULL )
15377  return SCIPhistoryGetAvgInferences(stat->glbhistory, dir);
15378  else
15379  return SCIPvarGetAvgInferences(var->data.original.transvar, stat, dir);
15380 
15381  case SCIP_VARSTATUS_LOOSE:
15382  case SCIP_VARSTATUS_COLUMN:
15383  if( SCIPhistoryGetNBranchings(var->history, dir) > 0 )
15384  return SCIPhistoryGetAvgInferences(var->history, dir);
15385  else
15386  {
15387  int nimpls;
15388  int ncliques;
15389 
15390  nimpls = SCIPvarGetNImpls(var, dir == SCIP_BRANCHDIR_UPWARDS);
15391  ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
15392  return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistory, dir); /*lint !e790*/
15393  }
15394 
15395  case SCIP_VARSTATUS_FIXED:
15396  return 0.0;
15397 
15399  if( var->data.aggregate.scalar > 0.0 )
15400  return SCIPvarGetAvgInferences(var->data.aggregate.var, stat, dir);
15401  else
15403 
15405  return 0.0;
15406 
15408  return SCIPvarGetAvgInferences(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15409 
15410  default:
15411  SCIPerrorMessage("unknown variable status\n");
15412  SCIPABORT();
15413  return 0.0; /*lint !e527*/
15414  }
15415 }
15416 
15417 /** returns the average number of inferences found after branching on the variable in given direction
15418  * in the current run
15419  */
15421  SCIP_VAR* var, /**< problem variable */
15422  SCIP_STAT* stat, /**< problem statistics */
15423  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15424  )
15425 {
15426  assert(var != NULL);
15427  assert(stat != NULL);
15428  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15429 
15430  switch( SCIPvarGetStatus(var) )
15431  {
15433  if( var->data.original.transvar == NULL )
15434  return SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir);
15435  else
15436  return SCIPvarGetAvgInferencesCurrentRun(var->data.original.transvar, stat, dir);
15437 
15438  case SCIP_VARSTATUS_LOOSE:
15439  case SCIP_VARSTATUS_COLUMN:
15440  if( SCIPhistoryGetNBranchings(var->historycrun, dir) > 0 )
15441  return SCIPhistoryGetAvgInferences(var->historycrun, dir);
15442  else
15443  {
15444  int nimpls;
15445  int ncliques;
15446 
15447  nimpls = SCIPvarGetNImpls(var, dir == SCIP_BRANCHDIR_UPWARDS);
15448  ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
15449  return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir); /*lint !e790*/
15450  }
15451 
15452  case SCIP_VARSTATUS_FIXED:
15453  return 0.0;
15454 
15456  if( var->data.aggregate.scalar > 0.0 )
15457  return SCIPvarGetAvgInferencesCurrentRun(var->data.aggregate.var, stat, dir);
15458  else
15460 
15462  return 0.0;
15463 
15466 
15467  default:
15468  SCIPerrorMessage("unknown variable status\n");
15469  SCIPABORT();
15470  return 0.0; /*lint !e527*/
15471  }
15472 }
15473 
15474 /** returns the number of cutoffs branching on this variable in given direction produced */
15476  SCIP_VAR* var, /**< problem variable */
15477  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15478  )
15479 {
15480  assert(var != NULL);
15481  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15482 
15483  switch( SCIPvarGetStatus(var) )
15484  {
15486  if( var->data.original.transvar == NULL )
15487  return 0;
15488  else
15489  return SCIPvarGetCutoffSum(var->data.original.transvar, dir);
15490 
15491  case SCIP_VARSTATUS_LOOSE:
15492  case SCIP_VARSTATUS_COLUMN:
15493  return SCIPhistoryGetCutoffSum(var->history, dir);
15494 
15495  case SCIP_VARSTATUS_FIXED:
15496  return 0;
15497 
15499  if( var->data.aggregate.scalar > 0.0 )
15500  return SCIPvarGetCutoffSum(var->data.aggregate.var, dir);
15501  else
15503 
15505  return 0;
15506 
15509 
15510  default:
15511  SCIPerrorMessage("unknown variable status\n");
15512  SCIPABORT();
15513  return 0; /*lint !e527*/
15514  }
15515 }
15516 
15517 /** returns the number of cutoffs branching on this variable in given direction produced in the current run */
15519  SCIP_VAR* var, /**< problem variable */
15520  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15521  )
15522 {
15523  assert(var != NULL);
15524  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15525 
15526  switch( SCIPvarGetStatus(var) )
15527  {
15529  if( var->data.original.transvar == NULL )
15530  return 0;
15531  else
15533 
15534  case SCIP_VARSTATUS_LOOSE:
15535  case SCIP_VARSTATUS_COLUMN:
15536  return SCIPhistoryGetCutoffSum(var->historycrun, dir);
15537 
15538  case SCIP_VARSTATUS_FIXED:
15539  return 0;
15540 
15542  if( var->data.aggregate.scalar > 0.0 )
15543  return SCIPvarGetCutoffSumCurrentRun(var->data.aggregate.var, dir);
15544  else
15546 
15548  return 0;
15549 
15552 
15553  default:
15554  SCIPerrorMessage("unknown variable status\n");
15555  SCIPABORT();
15556  return 0; /*lint !e527*/
15557  }
15558 }
15559 
15560 /** returns the average number of cutoffs found after branching on the variable in given direction */
15562  SCIP_VAR* var, /**< problem variable */
15563  SCIP_STAT* stat, /**< problem statistics */
15564  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15565  )
15566 {
15567  assert(var != NULL);
15568  assert(stat != NULL);
15569  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15570 
15571  switch( SCIPvarGetStatus(var) )
15572  {
15574  if( var->data.original.transvar == NULL )
15575  return SCIPhistoryGetAvgCutoffs(stat->glbhistory, dir);
15576  else
15577  return SCIPvarGetAvgCutoffs(var->data.original.transvar, stat, dir);
15578 
15579  case SCIP_VARSTATUS_LOOSE:
15580  case SCIP_VARSTATUS_COLUMN:
15581  return SCIPhistoryGetNBranchings(var->history, dir) > 0
15582  ? SCIPhistoryGetAvgCutoffs(var->history, dir)
15583  : SCIPhistoryGetAvgCutoffs(stat->glbhistory, dir);
15584 
15585  case SCIP_VARSTATUS_FIXED:
15586  return 0.0;
15587 
15589  if( var->data.aggregate.scalar > 0.0 )
15590  return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, dir);
15591  else
15592  return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
15593 
15595  return 0.0;
15596 
15598  return SCIPvarGetAvgCutoffs(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15599 
15600  default:
15601  SCIPerrorMessage("unknown variable status\n");
15602  SCIPABORT();
15603  return 0.0; /*lint !e527*/
15604  }
15605 }
15606 
15607 /** returns the average number of cutoffs found after branching on the variable in given direction in the current run */
15609  SCIP_VAR* var, /**< problem variable */
15610  SCIP_STAT* stat, /**< problem statistics */
15611  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15612  )
15613 {
15614  assert(var != NULL);
15615  assert(stat != NULL);
15616  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15617 
15618  switch( SCIPvarGetStatus(var) )
15619  {
15621  if( var->data.original.transvar == NULL )
15622  return SCIPhistoryGetAvgCutoffs(stat->glbhistorycrun, dir);
15623  else
15624  return SCIPvarGetAvgCutoffsCurrentRun(var->data.original.transvar, stat, dir);
15625 
15626  case SCIP_VARSTATUS_LOOSE:
15627  case SCIP_VARSTATUS_COLUMN:
15628  return SCIPhistoryGetNBranchings(var->historycrun, dir) > 0
15631 
15632  case SCIP_VARSTATUS_FIXED:
15633  return 0.0;
15634 
15636  if( var->data.aggregate.scalar > 0.0 )
15637  return SCIPvarGetAvgCutoffsCurrentRun(var->data.aggregate.var, stat, dir);
15638  else
15640 
15642  return 0.0;
15643 
15646 
15647  default:
15648  SCIPerrorMessage("unknown variable status\n");
15649  SCIPABORT();
15650  return 0.0; /*lint !e527*/
15651  }
15652 }
15653 
15654 
15655 
15656 
15657 /*
15658  * information methods for bound changes
15659  */
15660 
15661 /** creates an artificial bound change information object with depth = INT_MAX and pos = -1 */
15663  SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
15664  BMS_BLKMEM* blkmem, /**< block memory */
15665  SCIP_VAR* var, /**< active variable that changed the bounds */
15666  SCIP_BOUNDTYPE boundtype, /**< type of bound for var: lower or upper bound */
15667  SCIP_Real oldbound, /**< old value for bound */
15668  SCIP_Real newbound /**< new value for bound */
15669  )
15670 {
15671  assert(bdchginfo != NULL);
15672 
15673  SCIP_ALLOC( BMSallocBlockMemory(blkmem, bdchginfo) );
15674  (*bdchginfo)->oldbound = oldbound;
15675  (*bdchginfo)->newbound = newbound;
15676  (*bdchginfo)->var = var;
15677  (*bdchginfo)->inferencedata.var = var;
15678  (*bdchginfo)->inferencedata.reason.prop = NULL;
15679  (*bdchginfo)->inferencedata.info = 0;
15680  (*bdchginfo)->bdchgidx.depth = INT_MAX;
15681  (*bdchginfo)->bdchgidx.pos = -1;
15682  (*bdchginfo)->pos = 0;
15683  (*bdchginfo)->boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
15684  (*bdchginfo)->boundtype = boundtype; /*lint !e641*/
15685  (*bdchginfo)->inferboundtype = boundtype; /*lint !e641*/
15686  (*bdchginfo)->redundant = FALSE;
15687 
15688  return SCIP_OKAY;
15689 }
15690 
15691 /** frees a bound change information object */
15692 void SCIPbdchginfoFree(
15693  SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
15694  BMS_BLKMEM* blkmem /**< block memory */
15695  )
15696 {
15697  assert(bdchginfo != NULL);
15698 
15699  BMSfreeBlockMemory(blkmem, bdchginfo);
15700 }
15701 
15702 /** returns the bound change information for the last lower bound change on given active problem variable before or
15703  * after the bound change with the given index was applied;
15704  * returns NULL, if no change to the lower bound was applied up to this point of time
15705  */
15707  SCIP_VAR* var, /**< active problem variable */
15708  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
15709  SCIP_Bool after /**< should the bound change with given index be included? */
15710  )
15711 {
15712  int i;
15713 
15714  assert(var != NULL);
15715  assert(SCIPvarIsActive(var));
15716 
15717  /* search the correct bound change information for the given bound change index */
15718  if( after )
15719  {
15720  for( i = var->nlbchginfos-1; i >= 0; --i )
15721  {
15722  assert(var->lbchginfos[i].var == var);
15724  assert(var->lbchginfos[i].pos == i);
15725 
15726  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
15727  if( var->lbchginfos[i].redundant )
15728  return NULL;
15729  assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
15730 
15731  /* if we reached the bound change index, return the current bound change info */
15732  if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->lbchginfos[i].bdchgidx) )
15733  return &var->lbchginfos[i];
15734  }
15735  }
15736  else
15737  {
15738  for( i = var->nlbchginfos-1; i >= 0; --i )
15739  {
15740  assert(var->lbchginfos[i].var == var);
15742  assert(var->lbchginfos[i].pos == i);
15743 
15744  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
15745  if( var->lbchginfos[i].redundant )
15746  return NULL;
15747  assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
15748 
15749  /* if we reached the bound change index, return the current bound change info */
15750  if( SCIPbdchgidxIsEarlier(&var->lbchginfos[i].bdchgidx, bdchgidx) )
15751  return &var->lbchginfos[i];
15752  }
15753  }
15754 
15755  return NULL;
15756 }
15757 
15758 /** returns the bound change information for the last upper bound change on given active problem variable before or
15759  * after the bound change with the given index was applied;
15760  * returns NULL, if no change to the upper bound was applied up to this point of time
15761  */
15763  SCIP_VAR* var, /**< active problem variable */
15764  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
15765  SCIP_Bool after /**< should the bound change with given index be included? */
15766  )
15767 {
15768  int i;
15769 
15770  assert(var != NULL);
15771  assert(SCIPvarIsActive(var));
15772 
15773  /* search the correct bound change information for the given bound change index */
15774  if( after )
15775  {
15776  for( i = var->nubchginfos-1; i >= 0; --i )
15777  {
15778  assert(var->ubchginfos[i].var == var);
15780  assert(var->ubchginfos[i].pos == i);
15781 
15782  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
15783  if( var->ubchginfos[i].redundant )
15784  return NULL;
15785  assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
15786 
15787  /* if we reached the bound change index, return the current bound change info */
15788  if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->ubchginfos[i].bdchgidx) )
15789  return &var->ubchginfos[i];
15790  }
15791  }
15792  else
15793  {
15794  for( i = var->nubchginfos-1; i >= 0; --i )
15795  {
15796  assert(var->ubchginfos[i].var == var);
15798  assert(var->ubchginfos[i].pos == i);
15799 
15800  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
15801  if( var->ubchginfos[i].redundant )
15802  return NULL;
15803  assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
15804 
15805  /* if we reached the bound change index, return the current bound change info */
15806  if( SCIPbdchgidxIsEarlier(&var->ubchginfos[i].bdchgidx, bdchgidx) )
15807  return &var->ubchginfos[i];
15808  }
15809  }
15810 
15811  return NULL;
15812 }
15813 
15814 /** returns the bound change information for the last lower or upper bound change on given active problem variable
15815  * before or after the bound change with the given index was applied;
15816  * returns NULL, if no change to the lower/upper bound was applied up to this point of time
15817  */
15819  SCIP_VAR* var, /**< active problem variable */
15820  SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
15821  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
15822  SCIP_Bool after /**< should the bound change with given index be included? */
15823  )
15824 {
15825  if( boundtype == SCIP_BOUNDTYPE_LOWER )
15826  return SCIPvarGetLbchgInfo(var, bdchgidx, after);
15827  else
15828  {
15829  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
15830  return SCIPvarGetUbchgInfo(var, bdchgidx, after);
15831  }
15832 }
15833 
15834 /** returns lower bound of variable directly before or after the bound change given by the bound change index
15835  * was applied
15836  *
15837  * @deprecated Please use SCIPgetVarLbAtIndex()
15838  */
15840  SCIP_VAR* var, /**< problem variable */
15841  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
15842  SCIP_Bool after /**< should the bound change with given index be included? */
15843  )
15844 {
15845  SCIP_VARSTATUS varstatus;
15846  assert(var != NULL);
15847 
15848  varstatus = SCIPvarGetStatus(var);
15849 
15850  if( varstatus == SCIP_VARSTATUS_COLUMN || varstatus == SCIP_VARSTATUS_LOOSE )
15851  {
15852  if( bdchgidx == NULL )
15853  return SCIPvarGetLbLocal(var);
15854  else
15855  {
15856  SCIP_BDCHGINFO* bdchginfo;
15857 
15858  bdchginfo = SCIPvarGetLbchgInfo(var, bdchgidx, after);
15859  if( bdchginfo != NULL )
15860  return SCIPbdchginfoGetNewbound(bdchginfo);
15861  else
15862  return var->glbdom.lb;
15863  }
15864  }
15865 
15866  /* get bounds of attached variables */
15867  switch( varstatus )
15868  {
15870  assert(var->data.original.transvar != NULL);
15871  return SCIPvarGetLbAtIndex(var->data.original.transvar, bdchgidx, after);
15872 
15873  case SCIP_VARSTATUS_FIXED:
15874  return var->glbdom.lb;
15875 
15876  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
15877  assert(var->data.aggregate.var != NULL);
15878  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
15879  * corresponding infinity value instead of performing an arithmetical transformation (compare method
15880  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
15881  * (or is called by) a public interface method; instead, we only assert that values are finite
15882  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
15883  * positives and negatives if the parameter <numerics/infinity> is modified by the user
15884  */
15885  if( var->data.aggregate.scalar > 0.0 )
15886  {
15887  /* a > 0 -> get lower bound of y */
15888  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
15889  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
15890  return var->data.aggregate.scalar * SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after)
15891  + var->data.aggregate.constant;
15892  }
15893  else if( var->data.aggregate.scalar < 0.0 )
15894  {
15895  /* a < 0 -> get upper bound of y */
15896  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
15897  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
15898  return var->data.aggregate.scalar * SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after)
15899  + var->data.aggregate.constant;
15900  }
15901  else
15902  {
15903  SCIPerrorMessage("scalar is zero in aggregation\n");
15904  SCIPABORT();
15905  return SCIP_INVALID; /*lint !e527*/
15906  }
15907 
15909  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
15910  if ( var->data.multaggr.nvars == 1 )
15911  {
15912  assert(var->data.multaggr.vars != NULL);
15913  assert(var->data.multaggr.scalars != NULL);
15914  assert(var->data.multaggr.vars[0] != NULL);
15915 
15916  if( var->data.multaggr.scalars[0] > 0.0 )
15917  {
15918  /* a > 0 -> get lower bound of y */
15919  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
15920  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
15921  return var->data.multaggr.scalars[0] * SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
15922  + var->data.multaggr.constant;
15923  }
15924  else if( var->data.multaggr.scalars[0] < 0.0 )
15925  {
15926  /* a < 0 -> get upper bound of y */
15927  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
15928  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
15929  return var->data.multaggr.scalars[0] * SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
15930  + var->data.multaggr.constant;
15931  }
15932  else
15933  {
15934  SCIPerrorMessage("scalar is zero in multi-aggregation\n");
15935  SCIPABORT();
15936  return SCIP_INVALID; /*lint !e527*/
15937  }
15938  }
15939  SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
15940  SCIPABORT();
15941  return SCIP_INVALID; /*lint !e527*/
15942 
15943  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
15944  assert(var->negatedvar != NULL);
15946  assert(var->negatedvar->negatedvar == var);
15947  return var->data.negate.constant - SCIPvarGetUbAtIndex(var->negatedvar, bdchgidx, after);
15948 
15949  case SCIP_VARSTATUS_COLUMN: /* for lint */
15950  case SCIP_VARSTATUS_LOOSE: /* for lint */
15951  default:
15952  SCIPerrorMessage("unknown variable status\n");
15953  SCIPABORT();
15954  return SCIP_INVALID; /*lint !e527*/
15955  }
15956 }
15957 
15958 /** returns upper bound of variable directly before or after the bound change given by the bound change index
15959  * was applied
15960  *
15961  * @deprecated Please use SCIPgetVarUbAtIndex()
15962  */
15964  SCIP_VAR* var, /**< problem variable */
15965  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
15966  SCIP_Bool after /**< should the bound change with given index be included? */
15967  )
15968 {
15969  SCIP_VARSTATUS varstatus;
15970  assert(var != NULL);
15971 
15972  varstatus = SCIPvarGetStatus(var);
15973 
15974  if( varstatus == SCIP_VARSTATUS_COLUMN || varstatus == SCIP_VARSTATUS_LOOSE )
15975  {
15976  if( bdchgidx == NULL )
15977  return SCIPvarGetUbLocal(var);
15978  else
15979  {
15980  SCIP_BDCHGINFO* bdchginfo;
15981 
15982  bdchginfo = SCIPvarGetUbchgInfo(var, bdchgidx, after);
15983  if( bdchginfo != NULL )
15984  return SCIPbdchginfoGetNewbound(bdchginfo);
15985  else
15986  return var->glbdom.ub;
15987  }
15988  }
15989 
15990  /* get bounds of attached variables */
15991  switch( varstatus )
15992  {
15994  assert(var->data.original.transvar != NULL);
15995  return SCIPvarGetUbAtIndex(var->data.original.transvar, bdchgidx, after);
15996 
15997  case SCIP_VARSTATUS_FIXED:
15998  return var->glbdom.ub;
15999 
16000  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
16001  assert(var->data.aggregate.var != NULL);
16002  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
16003  * corresponding infinity value instead of performing an arithmetical transformation (compare method
16004  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
16005  * (or is called by) a public interface method; instead, we only assert that values are finite
16006  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
16007  * positives and negatives if the parameter <numerics/infinity> is modified by the user
16008  */
16009  if( var->data.aggregate.scalar > 0.0 )
16010  {
16011  /* a > 0 -> get lower bound of y */
16012  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16013  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16014  return var->data.aggregate.scalar * SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after)
16015  + var->data.aggregate.constant;
16016  }
16017  else if( var->data.aggregate.scalar < 0.0 )
16018  {
16019  /* a < 0 -> get upper bound of y */
16020  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16021  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16022  return var->data.aggregate.scalar * SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after)
16023  + var->data.aggregate.constant;
16024  }
16025  else
16026  {
16027  SCIPerrorMessage("scalar is zero in aggregation\n");
16028  SCIPABORT();
16029  return SCIP_INVALID; /*lint !e527*/
16030  }
16031 
16033  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
16034  if ( var->data.multaggr.nvars == 1 )
16035  {
16036  assert(var->data.multaggr.vars != NULL);
16037  assert(var->data.multaggr.scalars != NULL);
16038  assert(var->data.multaggr.vars[0] != NULL);
16039 
16040  if( var->data.multaggr.scalars[0] > 0.0 )
16041  {
16042  /* a > 0 -> get lower bound of y */
16043  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16044  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16045  return var->data.multaggr.scalars[0] * SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16046  + var->data.multaggr.constant;
16047  }
16048  else if( var->data.multaggr.scalars[0] < 0.0 )
16049  {
16050  /* a < 0 -> get upper bound of y */
16051  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16052  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16053  return var->data.multaggr.scalars[0] * SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16054  + var->data.multaggr.constant;
16055  }
16056  else
16057  {
16058  SCIPerrorMessage("scalar is zero in multi-aggregation\n");
16059  SCIPABORT();
16060  return SCIP_INVALID; /*lint !e527*/
16061  }
16062  }
16063  SCIPerrorMessage("cannot get the bounds of a multiple aggregated variable.\n");
16064  SCIPABORT();
16065  return SCIP_INVALID; /*lint !e527*/
16066 
16067  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
16068  assert(var->negatedvar != NULL);
16070  assert(var->negatedvar->negatedvar == var);
16071  return var->data.negate.constant - SCIPvarGetLbAtIndex(var->negatedvar, bdchgidx, after);
16072 
16073  case SCIP_VARSTATUS_COLUMN: /* for lint */
16074  case SCIP_VARSTATUS_LOOSE: /* for lint */
16075  default:
16076  SCIPerrorMessage("unknown variable status\n");
16077  SCIPABORT();
16078  return SCIP_INVALID; /*lint !e527*/
16079  }
16080 }
16081 
16082 /** returns lower or upper bound of variable directly before or after the bound change given by the bound change index
16083  * was applied
16084  *
16085  * @deprecated Please use SCIPgetVarBdAtIndex()
16086  */
16088  SCIP_VAR* var, /**< problem variable */
16089  SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
16090  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16091  SCIP_Bool after /**< should the bound change with given index be included? */
16092  )
16093 {
16094  if( boundtype == SCIP_BOUNDTYPE_LOWER )
16095  return SCIPvarGetLbAtIndex(var, bdchgidx, after);
16096  else
16097  {
16098  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16099  return SCIPvarGetUbAtIndex(var, bdchgidx, after);
16100  }
16101 }
16102 
16103 /** returns whether the binary variable was fixed at the time given by the bound change index
16104  *
16105  * @deprecated Please use SCIPgetVarWasFixedAtIndex()
16106  */
16108  SCIP_VAR* var, /**< problem variable */
16109  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16110  SCIP_Bool after /**< should the bound change with given index be included? */
16111  )
16112 {
16113  assert(var != NULL);
16114  assert(SCIPvarIsBinary(var));
16115 
16116  /* check the current bounds first in order to decide at which bound change information we have to look
16117  * (which is expensive because we have to follow the aggregation tree to the active variable)
16118  */
16119  return ((SCIPvarGetLbLocal(var) > 0.5 && SCIPvarGetLbAtIndex(var, bdchgidx, after) > 0.5)
16120  || (SCIPvarGetUbLocal(var) < 0.5 && SCIPvarGetUbAtIndex(var, bdchgidx, after) < 0.5));
16121 }
16122 
16123 /** bound change index representing the initial time before any bound changes took place */
16124 static SCIP_BDCHGIDX initbdchgidx = {-2, 0};
16126 /** bound change index representing the presolving stage */
16127 static SCIP_BDCHGIDX presolvebdchgidx = {-1, 0};
16129 /** returns the last bound change index, at which the bounds of the given variable were tightened */
16131  SCIP_VAR* var /**< problem variable */
16132  )
16133 {
16134  SCIP_BDCHGIDX* lbchgidx;
16135  SCIP_BDCHGIDX* ubchgidx;
16136 
16137  assert(var != NULL);
16138 
16139  var = SCIPvarGetProbvar(var);
16140 
16141  /* check, if variable is original without transformed variable */
16142  if( var == NULL )
16143  return &initbdchgidx;
16144 
16145  /* check, if variable was fixed in presolving */
16146  if( !SCIPvarIsActive(var) )
16147  return &presolvebdchgidx;
16148 
16150 
16151  /* get depths of last bound change information for the lower and upper bound */
16152  lbchgidx = (var->nlbchginfos > 0 && !var->lbchginfos[var->nlbchginfos-1].redundant
16153  ? &var->lbchginfos[var->nlbchginfos-1].bdchgidx : &initbdchgidx);
16154  ubchgidx = (var->nubchginfos > 0 && !var->ubchginfos[var->nubchginfos-1].redundant
16155  ? &var->ubchginfos[var->nubchginfos-1].bdchgidx : &initbdchgidx);
16156 
16157  if( SCIPbdchgidxIsEarlierNonNull(lbchgidx, ubchgidx) )
16158  return ubchgidx;
16159  else
16160  return lbchgidx;
16161 }
16162 
16163 /** returns the last depth level, at which the bounds of the given variable were tightened;
16164  * returns -2, if the variable's bounds are still the global bounds
16165  * returns -1, if the variable was fixed in presolving
16166  */
16168  SCIP_VAR* var /**< problem variable */
16169  )
16170 {
16171  SCIP_BDCHGIDX* bdchgidx;
16172 
16173  bdchgidx = SCIPvarGetLastBdchgIndex(var);
16174  assert(bdchgidx != NULL);
16175 
16176  return bdchgidx->depth;
16177 }
16178 
16179 /** returns at which depth in the tree a bound change was applied to the variable that conflicts with the
16180  * given bound; returns -1 if the bound does not conflict with the current local bounds of the variable
16181  */
16183  SCIP_VAR* var, /**< problem variable */
16184  SCIP_SET* set, /**< global SCIP settings */
16185  SCIP_BOUNDTYPE boundtype, /**< bound type of the conflicting bound */
16186  SCIP_Real bound /**< conflicting bound */
16187  )
16188 {
16189  int i;
16190 
16191  assert(var != NULL);
16192  assert(set != NULL);
16193  assert(var->scip == set->scip);
16194 
16195  if( boundtype == SCIP_BOUNDTYPE_LOWER )
16196  {
16197  /* check if the bound is in conflict with the current local bounds */
16198  if( SCIPsetIsLE(set, bound, var->locdom.ub) )
16199  return -1;
16200 
16201  /* check if the bound is in conflict with the global bound */
16202  if( SCIPsetIsGT(set, bound, var->glbdom.ub) )
16203  return 0;
16204 
16205  /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
16206  assert(var->nubchginfos > 0);
16207  assert(SCIPsetIsGT(set, bound, var->ubchginfos[var->nubchginfos-1].newbound));
16208 
16209  /* search for the first conflicting bound change */
16210  for( i = var->nubchginfos-1; i > 0 && SCIPsetIsGT(set, bound, var->ubchginfos[i-1].newbound); --i )
16211  {
16212  assert(var->ubchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
16214  }
16215  assert(SCIPsetIsGT(set, bound, var->ubchginfos[i].newbound)); /* bound change i is conflicting */
16216  assert(i == 0 || SCIPsetIsLE(set, bound, var->ubchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
16217 
16218  /* return the depth at which the first conflicting bound change took place */
16219  return var->ubchginfos[i].bdchgidx.depth;
16220  }
16221  else
16222  {
16223  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16224 
16225  /* check if the bound is in conflict with the current local bounds */
16226  if( SCIPsetIsGE(set, bound, var->locdom.lb) )
16227  return -1;
16228 
16229  /* check if the bound is in conflict with the global bound */
16230  if( SCIPsetIsLT(set, bound, var->glbdom.lb) )
16231  return 0;
16232 
16233  /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
16234  assert(var->nlbchginfos > 0);
16235  assert(SCIPsetIsLT(set, bound, var->lbchginfos[var->nlbchginfos-1].newbound));
16236 
16237  /* search for the first conflicting bound change */
16238  for( i = var->nlbchginfos-1; i > 0 && SCIPsetIsLT(set, bound, var->lbchginfos[i-1].newbound); --i )
16239  {
16240  assert(var->lbchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
16242  }
16243  assert(SCIPsetIsLT(set, bound, var->lbchginfos[i].newbound)); /* bound change i is conflicting */
16244  assert(i == 0 || SCIPsetIsGE(set, bound, var->lbchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
16245 
16246  /* return the depth at which the first conflicting bound change took place */
16247  return var->lbchginfos[i].bdchgidx.depth;
16248  }
16249 }
16250 
16251 /** returns whether the first binary variable was fixed earlier than the second one;
16252  * returns FALSE, if the first variable is not fixed, and returns TRUE, if the first variable is fixed, but the
16253  * second one is not fixed
16254  */
16256  SCIP_VAR* var1, /**< first binary variable */
16257  SCIP_VAR* var2 /**< second binary variable */
16258  )
16259 {
16260  SCIP_BDCHGIDX* bdchgidx1;
16261  SCIP_BDCHGIDX* bdchgidx2;
16262 
16263  assert(var1 != NULL);
16264  assert(var2 != NULL);
16265  assert(SCIPvarIsBinary(var1));
16266  assert(SCIPvarIsBinary(var2));
16267 
16268  var1 = SCIPvarGetProbvar(var1);
16269  var2 = SCIPvarGetProbvar(var2);
16270  assert(var1 != NULL);
16271  assert(var2 != NULL);
16272 
16273  /* check, if variables are globally fixed */
16274  if( !SCIPvarIsActive(var2) || var2->glbdom.lb > 0.5 || var2->glbdom.ub < 0.5 )
16275  return FALSE;
16276  if( !SCIPvarIsActive(var1) || var1->glbdom.lb > 0.5 || var1->glbdom.ub < 0.5 )
16277  return TRUE;
16278 
16281  assert(SCIPvarIsBinary(var1));
16282  assert(SCIPvarIsBinary(var2));
16283  assert(var1->nlbchginfos + var1->nubchginfos <= 1);
16284  assert(var2->nlbchginfos + var2->nubchginfos <= 1);
16285  assert(var1->nlbchginfos == 0 || !var1->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
16286  assert(var1->nubchginfos == 0 || !var1->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
16287  assert(var2->nlbchginfos == 0 || !var2->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
16288  assert(var2->nubchginfos == 0 || !var2->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
16289 
16290  if( var1->nlbchginfos == 1 )
16291  bdchgidx1 = &var1->lbchginfos[0].bdchgidx;
16292  else if( var1->nubchginfos == 1 )
16293  bdchgidx1 = &var1->ubchginfos[0].bdchgidx;
16294  else
16295  bdchgidx1 = NULL;
16296 
16297  if( var2->nlbchginfos == 1 )
16298  bdchgidx2 = &var2->lbchginfos[0].bdchgidx;
16299  else if( var2->nubchginfos == 1 )
16300  bdchgidx2 = &var2->ubchginfos[0].bdchgidx;
16301  else
16302  bdchgidx2 = NULL;
16303 
16304  return SCIPbdchgidxIsEarlier(bdchgidx1, bdchgidx2);
16305 }
16306 
16307 
16308 
16309 /*
16310  * Hash functions
16311  */
16312 
16313 /** gets the key (i.e. the name) of the given variable */
16314 SCIP_DECL_HASHGETKEY(SCIPhashGetKeyVar)
16315 { /*lint --e{715}*/
16316  SCIP_VAR* var = (SCIP_VAR*)elem;
16317 
16318  assert(var != NULL);
16319  return var->name;
16320 }
16321 
16322 
16323 
16324 
16325 /*
16326  * simple functions implemented as defines
16327  */
16328 
16329 /* In debug mode, the following methods are implemented as function calls to ensure
16330  * type validity.
16331  * In optimized mode, the methods are implemented as defines to improve performance.
16332  * However, we want to have them in the library anyways, so we have to undef the defines.
16333  */
16334 
16335 #undef SCIPboundchgGetNewbound
16336 #undef SCIPboundchgGetVar
16337 #undef SCIPboundchgGetBoundchgtype
16338 #undef SCIPboundchgGetBoundtype
16339 #undef SCIPboundchgIsRedundant
16340 #undef SCIPdomchgGetNBoundchgs
16341 #undef SCIPdomchgGetBoundchg
16342 #undef SCIPholelistGetLeft
16343 #undef SCIPholelistGetRight
16344 #undef SCIPholelistGetNext
16345 #undef SCIPvarGetName
16346 #undef SCIPvarGetNUses
16347 #undef SCIPvarGetData
16348 #undef SCIPvarSetData
16349 #undef SCIPvarSetDelorigData
16350 #undef SCIPvarSetTransData
16351 #undef SCIPvarSetDeltransData
16352 #undef SCIPvarGetStatus
16353 #undef SCIPvarIsOriginal
16354 #undef SCIPvarIsTransformed
16355 #undef SCIPvarIsNegated
16356 #undef SCIPvarGetType
16357 #undef SCIPvarIsBinary
16358 #undef SCIPvarIsIntegral
16359 #undef SCIPvarIsInitial
16360 #undef SCIPvarIsRemovable
16361 #undef SCIPvarIsDeleted
16362 #undef SCIPvarIsDeletable
16363 #undef SCIPvarMarkDeletable
16364 #undef SCIPvarMarkNotDeletable
16365 #undef SCIPvarIsActive
16366 #undef SCIPvarGetIndex
16367 #undef SCIPvarGetProbindex
16368 #undef SCIPvarGetTransVar
16369 #undef SCIPvarGetCol
16370 #undef SCIPvarIsInLP
16371 #undef SCIPvarGetAggrVar
16372 #undef SCIPvarGetAggrScalar
16373 #undef SCIPvarGetAggrConstant
16374 #undef SCIPvarGetMultaggrNVars
16375 #undef SCIPvarGetMultaggrVars
16376 #undef SCIPvarGetMultaggrScalars
16377 #undef SCIPvarGetMultaggrConstant
16378 #undef SCIPvarGetNegatedVar
16379 #undef SCIPvarGetNegationVar
16380 #undef SCIPvarGetNegationConstant
16381 #undef SCIPvarGetObj
16382 #undef SCIPvarGetLbOriginal
16383 #undef SCIPvarGetUbOriginal
16384 #undef SCIPvarGetHolelistOriginal
16385 #undef SCIPvarGetLbGlobal
16386 #undef SCIPvarGetUbGlobal
16387 #undef SCIPvarGetHolelistGlobal
16388 #undef SCIPvarGetBestBoundGlobal
16389 #undef SCIPvarGetWorstBoundGlobal
16390 #undef SCIPvarGetLbLocal
16391 #undef SCIPvarGetUbLocal
16392 #undef SCIPvarGetHolelistLocal
16393 #undef SCIPvarGetBestBoundLocal
16394 #undef SCIPvarGetWorstBoundLocal
16395 #undef SCIPvarGetBestBoundType
16396 #undef SCIPvarGetWorstBoundType
16397 #undef SCIPvarGetLbLazy
16398 #undef SCIPvarGetUbLazy
16399 #undef SCIPvarGetBranchFactor
16400 #undef SCIPvarGetBranchPriority
16401 #undef SCIPvarGetBranchDirection
16402 #undef SCIPvarGetNVlbs
16403 #undef SCIPvarGetVlbVars
16404 #undef SCIPvarGetVlbCoefs
16405 #undef SCIPvarGetVlbConstants
16406 #undef SCIPvarGetNVubs
16407 #undef SCIPvarGetVubVars
16408 #undef SCIPvarGetVubCoefs
16409 #undef SCIPvarGetVubConstants
16410 #undef SCIPvarGetNImpls
16411 #undef SCIPvarGetImplVars
16412 #undef SCIPvarGetImplTypes
16413 #undef SCIPvarGetImplBounds
16414 #undef SCIPvarGetImplIds
16415 #undef SCIPvarGetNCliques
16416 #undef SCIPvarGetCliques
16417 #undef SCIPvarGetLPSol
16418 #undef SCIPvarGetNLPSol
16419 #undef SCIPvarGetBdchgInfoLb
16420 #undef SCIPvarGetNBdchgInfosLb
16421 #undef SCIPvarGetBdchgInfoUb
16422 #undef SCIPvarGetNBdchgInfosUb
16423 #undef SCIPvarGetValuehistory
16424 #undef SCIPvarGetPseudoSol
16425 #undef SCIPvarCatchEvent
16426 #undef SCIPvarDropEvent
16427 #undef SCIPvarGetVSIDS
16428 #undef SCIPvarGetCliqueComponentIdx
16429 #undef SCIPbdchgidxGetPos
16430 #undef SCIPbdchgidxIsEarlierNonNull
16431 #undef SCIPbdchgidxIsEarlier
16432 #undef SCIPbdchginfoGetOldbound
16433 #undef SCIPbdchginfoGetNewbound
16434 #undef SCIPbdchginfoGetVar
16435 #undef SCIPbdchginfoGetChgtype
16436 #undef SCIPbdchginfoGetBoundtype
16437 #undef SCIPbdchginfoGetDepth
16438 #undef SCIPbdchginfoGetPos
16439 #undef SCIPbdchginfoGetIdx
16440 #undef SCIPbdchginfoGetInferVar
16441 #undef SCIPbdchginfoGetInferCons
16442 #undef SCIPbdchginfoGetInferProp
16443 #undef SCIPbdchginfoGetInferInfo
16444 #undef SCIPbdchginfoGetInferBoundtype
16445 #undef SCIPbdchginfoIsRedundant
16446 #undef SCIPbdchginfoHasInferenceReason
16447 #undef SCIPbdchginfoIsTighter
16448 
16449 
16450 /** returns the new value of the bound in the bound change data */
16452  SCIP_BOUNDCHG* boundchg /**< bound change data */
16453  )
16454 {
16455  assert(boundchg != NULL);
16456 
16457  return boundchg->newbound;
16458 }
16459 
16460 /** returns the variable of the bound change in the bound change data */
16462  SCIP_BOUNDCHG* boundchg /**< bound change data */
16463  )
16464 {
16465  assert(boundchg != NULL);
16466 
16467  return boundchg->var;
16468 }
16469 
16470 /** returns the bound change type of the bound change in the bound change data */
16472  SCIP_BOUNDCHG* boundchg /**< bound change data */
16473  )
16474 {
16475  assert(boundchg != NULL);
16476 
16477  return (SCIP_BOUNDCHGTYPE)(boundchg->boundchgtype);
16478 }
16479 
16480 /** returns the bound type of the bound change in the bound change data */
16482  SCIP_BOUNDCHG* boundchg /**< bound change data */
16483  )
16484 {
16485  assert(boundchg != NULL);
16486 
16487  return (SCIP_BOUNDTYPE)(boundchg->boundtype);
16488 }
16489 
16490 /** returns whether the bound change is redundant due to a more global bound that is at least as strong */
16492  SCIP_BOUNDCHG* boundchg /**< bound change data */
16493  )
16494 {
16495  assert(boundchg != NULL);
16496 
16497  return boundchg->redundant;
16498 }
16499 
16500 /** returns the number of bound changes in the domain change data */
16502  SCIP_DOMCHG* domchg /**< domain change data */
16503  )
16504 {
16505  return domchg != NULL ? domchg->domchgbound.nboundchgs : 0;
16506 }
16507 
16508 /** returns a particular bound change in the domain change data */
16510  SCIP_DOMCHG* domchg, /**< domain change data */
16511  int pos /**< position of the bound change in the domain change data */
16512  )
16513 {
16514  assert(domchg != NULL);
16515  assert(0 <= pos && pos < (int)domchg->domchgbound.nboundchgs);
16516 
16517  return &domchg->domchgbound.boundchgs[pos];
16518 }
16519 
16520 /** returns left bound of open interval in hole */
16522  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
16523  )
16524 {
16525  assert(holelist != NULL);
16526 
16527  return holelist->hole.left;
16528 }
16529 
16530 /** returns right bound of open interval in hole */
16532  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
16533  )
16534 {
16535  assert(holelist != NULL);
16536 
16537  return holelist->hole.right;
16538 }
16539 
16540 /** returns next hole in list */
16542  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
16543  )
16544 {
16545  assert(holelist != NULL);
16546 
16547  return holelist->next;
16548 }
16549 
16550 /** returns the name of the variable
16551  *
16552  * @note to change the name of a variable, use SCIPchgVarName() from scip.h
16553  */
16554 const char* SCIPvarGetName(
16555  SCIP_VAR* var /**< problem variable */
16556  )
16557 {
16558  assert(var != NULL);
16559 
16560  return var->name;
16561 }
16562 
16563 /** gets number of times, the variable is currently captured */
16564 int SCIPvarGetNUses(
16565  SCIP_VAR* var /**< problem variable */
16566  )
16567 {
16568  assert(var != NULL);
16569 
16570  return var->nuses;
16571 }
16572 
16573 /** returns the user data of the variable */
16575  SCIP_VAR* var /**< problem variable */
16576  )
16577 {
16578  assert(var != NULL);
16579 
16580  return var->vardata;
16581 }
16582 
16583 /** sets the user data for the variable */
16584 void SCIPvarSetData(
16585  SCIP_VAR* var, /**< problem variable */
16586  SCIP_VARDATA* vardata /**< user variable data */
16587  )
16588 {
16589  assert(var != NULL);
16590 
16591  var->vardata = vardata;
16592 }
16593 
16594 /** sets method to free user data for the original variable */
16596  SCIP_VAR* var, /**< problem variable */
16597  SCIP_DECL_VARDELORIG ((*vardelorig)) /**< frees user data of original variable */
16598  )
16599 {
16600  assert(var != NULL);
16601  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
16602 
16603  var->vardelorig = vardelorig;
16604 }
16605 
16606 /** sets method to transform user data of the variable */
16607 void SCIPvarSetTransData(
16608  SCIP_VAR* var, /**< problem variable */
16609  SCIP_DECL_VARTRANS ((*vartrans)) /**< creates transformed user data by transforming original user data */
16610  )
16611 {
16612  assert(var != NULL);
16613  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
16614 
16615  var->vartrans = vartrans;
16616 }
16617 
16618 /** sets method to free transformed user data for the variable */
16620  SCIP_VAR* var, /**< problem variable */
16621  SCIP_DECL_VARDELTRANS ((*vardeltrans)) /**< frees user data of transformed variable */
16622  )
16623 {
16624  assert(var != NULL);
16625 
16626  var->vardeltrans = vardeltrans;
16627 }
16628 
16629 /** sets method to copy this variable into sub-SCIPs */
16630 void SCIPvarSetCopyData(
16631  SCIP_VAR* var, /**< problem variable */
16632  SCIP_DECL_VARCOPY ((*varcopy)) /**< copy method of the variable */
16633  )
16634 {
16635  assert(var != NULL);
16636 
16637  var->varcopy = varcopy;
16638 }
16639 
16640 /** sets the initial flag of a variable; only possible for original or loose variables */
16642  SCIP_VAR* var, /**< problem variable */
16643  SCIP_Bool initial /**< initial flag */
16644  )
16645 {
16646  assert(var != NULL);
16647 
16649  return SCIP_INVALIDCALL;
16650 
16651  var->initial = initial;
16652 
16653  return SCIP_OKAY;
16654 }
16655 
16656 /** sets the removable flag of a variable; only possible for original or loose variables */
16658  SCIP_VAR* var, /**< problem variable */
16659  SCIP_Bool removable /**< removable flag */
16660  )
16661 {
16662  assert(var != NULL);
16663 
16665  return SCIP_INVALIDCALL;
16666 
16667  var->removable = removable;
16668 
16669  return SCIP_OKAY;
16670 }
16671 
16672 /** gets status of variable */
16674  SCIP_VAR* var /**< problem variable */
16675  )
16676 {
16677  assert(var != NULL);
16678 
16679  return (SCIP_VARSTATUS)(var->varstatus);
16680 }
16681 
16682 /** returns whether the variable belongs to the original problem */
16684  SCIP_VAR* var /**< problem variable */
16685  )
16686 {
16687  assert(var != NULL);
16688  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED || var->negatedvar != NULL);
16689 
16693 }
16694 
16695 /** returns whether the variable belongs to the transformed problem */
16697  SCIP_VAR* var /**< problem variable */
16698  )
16699 {
16700  assert(var != NULL);
16701  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED || var->negatedvar != NULL);
16702 
16706 }
16707 
16708 /** returns whether the variable was created by negation of a different variable */
16710  SCIP_VAR* var /**< problem variable */
16711  )
16712 {
16713  assert(var != NULL);
16714 
16715  return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
16716 }
16717 
16718 /** gets type of variable */
16720  SCIP_VAR* var /**< problem variable */
16721  )
16722 {
16723  assert(var != NULL);
16724 
16725  return (SCIP_VARTYPE)(var->vartype);
16726 }
16727 
16728 /** returns TRUE if the variable is of binary type; this is the case if:
16729  * (1) variable type is binary
16730  * (2) variable type is integer or implicit integer and
16731  * (i) the lazy lower bound or the global lower bound is greater than or equal to zero
16732  * (ii) the lazy upper bound or the global upper bound is less than or equal to one
16733  */
16735  SCIP_VAR* var /**< problem variable */
16736  )
16737 {
16738  assert(var != NULL);
16739 
16740  return (SCIPvarGetType(var) == SCIP_VARTYPE_BINARY ||
16741  (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && MAX(var->glbdom.lb, var->lazylb) >= 0.0 && MIN(var->glbdom.ub, var->lazyub) <= 1.0));
16742 }
16743 
16744 /** returns whether variable is of integral type (binary, integer, or implicit integer) */
16746  SCIP_VAR* var /**< problem variable */
16747  )
16748 {
16749  assert(var != NULL);
16750 
16751  return (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
16752 }
16753 
16754 /** returns whether variable's column should be present in the initial root LP */
16756  SCIP_VAR* var /**< problem variable */
16757  )
16758 {
16759  assert(var != NULL);
16760 
16761  return var->initial;
16762 }
16763 
16764 /** returns whether variable's column is removable from the LP (due to aging or cleanup) */
16766  SCIP_VAR* var /**< problem variable */
16767  )
16768 {
16769  assert(var != NULL);
16770 
16771  return var->removable;
16772 }
16773 
16774 /** returns whether the variable was deleted from the problem */
16776  SCIP_VAR* var /**< problem variable */
16777  )
16778 {
16779  assert(var != NULL);
16780 
16781  return var->deleted;
16782 }
16783 
16784 /** marks the variable to be deletable, i.e., it may be deleted completely from the problem;
16785  * method can only be called before the variable is added to the problem by SCIPaddVar() or SCIPaddPricedVar()
16786  */
16788  SCIP_VAR* var /**< problem variable */
16789  )
16790 {
16791  assert(var != NULL);
16792  assert(var->probindex == -1);
16793 
16794  var->deletable = TRUE;
16795 }
16796 
16797 /** marks the variable to be not deletable from the problem */
16800  )
16801 {
16802  assert(var != NULL);
16803 
16804  var->deletable = FALSE;
16805 }
16806 
16807 /** marks variable to be deleted from global structures (cliques etc.) when cleaning up
16808  *
16809  * @note: this is not equivalent to marking the variable itself for deletion, this is done by using SCIPvarMarkDeletable()
16810  */
16812  SCIP_VAR* var /**< problem variable */
16813  )
16814 {
16815  assert(var != NULL);
16816 
16817  var->delglobalstructs = TRUE;
16818 }
16819 
16820 /** returns whether the variable was flagged for deletion from global structures (cliques etc.) */
16822  SCIP_VAR* var /**< problem variable */
16823  )
16824 {
16825  assert(var != NULL);
16826 
16827  return var->delglobalstructs;
16828 }
16829 
16830 /** returns whether variable is allowed to be deleted completely from the problem */
16833  )
16834 {
16835  assert(var != NULL);
16836 
16837  return var->deletable;
16838 }
16839 
16840 /** returns whether variable is an active (neither fixed nor aggregated) variable */
16842  SCIP_VAR* var /**< problem variable */
16843  )
16844 {
16845  assert(var != NULL);
16846 
16847  return (var->probindex >= 0);
16848 }
16849 
16850 /** gets unique index of variable */
16851 int SCIPvarGetIndex(
16852  SCIP_VAR* var /**< problem variable */
16853  )
16854 {
16855  assert(var != NULL);
16856 
16857  return var->index;
16858 }
16859 
16860 /** gets position of variable in problem, or -1 if variable is not active */
16862  SCIP_VAR* var /**< problem variable */
16863  )
16864 {
16865  assert(var != NULL);
16866 
16867  return var->probindex;
16868 }
16869 
16870 /** gets transformed variable of ORIGINAL variable */
16872  SCIP_VAR* var /**< problem variable */
16873  )
16874 {
16875  assert(var != NULL);
16876  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
16877 
16878  return var->data.original.transvar;
16879 }
16880 
16881 /** gets column of COLUMN variable */
16883  SCIP_VAR* var /**< problem variable */
16884  )
16885 {
16886  assert(var != NULL);
16887  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
16888 
16889  return var->data.col;
16890 }
16891 
16892 /** returns whether the variable is a COLUMN variable that is member of the current LP */
16894  SCIP_VAR* var /**< problem variable */
16895  )
16896 {
16897  assert(var != NULL);
16898 
16899  return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN && SCIPcolIsInLP(var->data.col));
16900 }
16901 
16902 /** gets aggregation variable y of an aggregated variable x = a*y + c */
16904  SCIP_VAR* var /**< problem variable */
16905  )
16906 {
16907  assert(var != NULL);
16909 
16910  return var->data.aggregate.var;
16911 }
16912 
16913 /** gets aggregation scalar a of an aggregated variable x = a*y + c */
16915  SCIP_VAR* var /**< problem variable */
16916  )
16917 {
16918  assert(var != NULL);
16920 
16921  return var->data.aggregate.scalar;
16922 }
16923 
16924 /** gets aggregation constant c of an aggregated variable x = a*y + c */
16926  SCIP_VAR* var /**< problem variable */
16927  )
16928 {
16929  assert(var != NULL);
16931 
16932  return var->data.aggregate.constant;
16933 }
16934 
16935 /** gets number n of aggregation variables of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
16937  SCIP_VAR* var /**< problem variable */
16938  )
16939 {
16940  assert(var != NULL);
16941  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
16942  assert(!var->donotmultaggr);
16943 
16944  return var->data.multaggr.nvars;
16945 }
16946 
16947 /** gets vector of aggregation variables y of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
16949  SCIP_VAR* var /**< problem variable */
16950  )
16951 {
16952  assert(var != NULL);
16953  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
16954  assert(!var->donotmultaggr);
16955 
16956  return var->data.multaggr.vars;
16957 }
16958 
16959 /** gets vector of aggregation scalars a of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
16961  SCIP_VAR* var /**< problem variable */
16962  )
16963 {
16964  assert(var != NULL);
16965  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
16966  assert(!var->donotmultaggr);
16967 
16968  return var->data.multaggr.scalars;
16969 }
16970 
16971 /** gets aggregation constant c of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
16973  SCIP_VAR* var /**< problem variable */
16974  )
16975 {
16976  assert(var != NULL);
16977  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
16978  assert(!var->donotmultaggr);
16979 
16980  return var->data.multaggr.constant;
16981 }
16982 
16983 /** gets the negation of the given variable; may return NULL, if no negation is existing yet */
16985  SCIP_VAR* var /**< negated problem variable */
16986  )
16987 {
16988  assert(var != NULL);
16989 
16990  return var->negatedvar;
16991 }
16992 
16993 /** gets the negation variable x of a negated variable x' = offset - x */
16995  SCIP_VAR* var /**< negated problem variable */
16996  )
16997 {
16998  assert(var != NULL);
16999  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17000 
17001  return var->negatedvar;
17002 }
17003 
17004 /** gets the negation offset of a negated variable x' = offset - x */
17006  SCIP_VAR* var /**< negated problem variable */
17007  )
17008 {
17009  assert(var != NULL);
17010  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17011 
17012  return var->data.negate.constant;
17013 }
17014 
17015 /** gets objective function value of variable */
17017  SCIP_VAR* var /**< problem variable */
17018  )
17019 {
17020  assert(var != NULL);
17021 
17022  return var->obj;
17023 }
17024 
17025 /** gets the unchanged objective function value of a variable (ignoring temproray changes performed in probing mode) */
17027  SCIP_VAR* var /**< problem variable */
17028  )
17029 {
17030  assert(var != NULL);
17031 
17032  return var->unchangedobj;
17033 }
17034 
17035 /** gets corresponding objective value of active, fixed, or multi-aggregated problem variable of given variable
17036  * e.g. obj(x) = 1 this method returns for ~x the value -1
17037  */
17039  SCIP_VAR* var, /**< problem variable */
17040  SCIP_Real* aggrobj /**< pointer to store the aggregated objective value */
17041  )
17042 {
17043  SCIP_VAR* probvar = var;
17044  SCIP_Real mult = 1.0;
17045 
17046  assert(probvar != NULL);
17047  assert(aggrobj != NULL);
17048 
17049  while( probvar != NULL )
17050  {
17051  switch( SCIPvarGetStatus(probvar) )
17052  {
17054  case SCIP_VARSTATUS_LOOSE:
17055  case SCIP_VARSTATUS_COLUMN:
17056  (*aggrobj) = mult * SCIPvarGetObj(probvar);
17057  return SCIP_OKAY;
17058 
17059  case SCIP_VARSTATUS_FIXED:
17060  assert(SCIPvarGetObj(probvar) == 0.0);
17061  (*aggrobj) = 0.0;
17062  return SCIP_OKAY;
17063 
17065  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
17066  if ( probvar->data.multaggr.nvars == 1 )
17067  {
17068  assert( probvar->data.multaggr.vars != NULL );
17069  assert( probvar->data.multaggr.scalars != NULL );
17070  assert( probvar->data.multaggr.vars[0] != NULL );
17071  mult *= probvar->data.multaggr.scalars[0];
17072  probvar = probvar->data.multaggr.vars[0];
17073  break;
17074  }
17075  else
17076  {
17077  SCIP_Real tmpobj;
17078  int v;
17079 
17080  (*aggrobj) = 0.0;
17081 
17082  for( v = probvar->data.multaggr.nvars - 1; v >= 0; --v )
17083  {
17084  SCIP_CALL( SCIPvarGetAggregatedObj(probvar->data.multaggr.vars[v], &tmpobj) );
17085  (*aggrobj) += probvar->data.multaggr.scalars[v] * tmpobj;
17086  }
17087  return SCIP_OKAY;
17088  }
17089 
17090  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
17091  assert(probvar->data.aggregate.var != NULL);
17092  mult *= probvar->data.aggregate.scalar;
17093  probvar = probvar->data.aggregate.var;
17094  break;
17095 
17096  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
17097  assert(probvar->negatedvar != NULL);
17098  assert(SCIPvarGetStatus(probvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
17099  assert(probvar->negatedvar->negatedvar == probvar);
17100  mult *= -1.0;
17101  probvar = probvar->negatedvar;
17102  break;
17103 
17104  default:
17105  SCIPABORT();
17106  return SCIP_INVALIDDATA; /*lint !e527*/
17107  }
17108  }
17109 
17110  return SCIP_INVALIDDATA;
17111 }
17112 
17113 /** gets original lower bound of original problem variable (i.e. the bound set in problem creation) */
17115  SCIP_VAR* var /**< original problem variable */
17116  )
17117 {
17118  assert(var != NULL);
17119  assert(SCIPvarIsOriginal(var));
17120 
17122  return var->data.original.origdom.lb;
17123  else
17124  {
17125  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17126  assert(var->negatedvar != NULL);
17128 
17129  return var->data.negate.constant - var->negatedvar->data.original.origdom.ub;
17130  }
17131 }
17132 
17133 /** gets original upper bound of original problem variable (i.e. the bound set in problem creation) */
17135  SCIP_VAR* var /**< original problem variable */
17136  )
17137 {
17138  assert(var != NULL);
17139  assert(SCIPvarIsOriginal(var));
17140 
17142  return var->data.original.origdom.ub;
17143  else
17144  {
17145  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17146  assert(var->negatedvar != NULL);
17148 
17149  return var->data.negate.constant - var->negatedvar->data.original.origdom.lb;
17150  }
17151 }
17152 
17153 /** gets the original hole list of an original variable */
17155  SCIP_VAR* var /**< problem variable */
17156  )
17157 {
17158  assert(var != NULL);
17159  assert(SCIPvarIsOriginal(var));
17160 
17162  return var->data.original.origdom.holelist;
17163 
17164  return NULL;
17165 }
17166 
17167 /** gets global lower bound of variable */
17169  SCIP_VAR* var /**< problem variable */
17170  )
17171 {
17172  assert(var != NULL);
17173 
17174  return var->glbdom.lb;
17175 }
17176 
17177 /** gets global upper bound of variable */
17179  SCIP_VAR* var /**< problem variable */
17180  )
17181 {
17182  assert(var != NULL);
17183 
17184  return var->glbdom.ub;
17185 }
17186 
17187 /** gets the global hole list of an active variable */
17189  SCIP_VAR* var /**< problem variable */
17190  )
17191 {
17192  assert(var != NULL);
17193 
17194  return var->glbdom.holelist;
17195 }
17196 
17197 /** gets best global bound of variable with respect to the objective function */
17199  SCIP_VAR* var /**< problem variable */
17200  )
17201 {
17202  assert(var != NULL);
17203 
17204  if( var->obj >= 0.0 )
17205  return var->glbdom.lb;
17206  else
17207  return var->glbdom.ub;
17208 }
17209 
17210 /** gets worst global bound of variable with respect to the objective function */
17212  SCIP_VAR* var /**< problem variable */
17213  )
17214 {
17215  assert(var != NULL);
17216 
17217  if( var->obj >= 0.0 )
17218  return var->glbdom.ub;
17219  else
17220  return var->glbdom.lb;
17221 }
17222 
17223 /** gets current lower bound of variable */
17225  SCIP_VAR* var /**< problem variable */
17226  )
17227 {
17228  assert(var != NULL);
17229 
17230  return var->locdom.lb;
17231 }
17232 
17233 /** gets current upper bound of variable */
17235  SCIP_VAR* var /**< problem variable */
17236  )
17237 {
17238  assert(var != NULL);
17239 
17240  return var->locdom.ub;
17241 }
17242 
17243 /** gets the current hole list of an active variable */
17245  SCIP_VAR* var /**< problem variable */
17246  )
17247 {
17248  assert(var != NULL);
17249 
17250  return var->locdom.holelist;
17251 }
17252 
17253 /** gets best local bound of variable with respect to the objective function */
17255  SCIP_VAR* var /**< problem variable */
17256  )
17257 {
17258  assert(var != NULL);
17259 
17260  if( var->obj >= 0.0 )
17261  return var->locdom.lb;
17262  else
17263  return var->locdom.ub;
17264 }
17265 
17266 /** gets worst local bound of variable with respect to the objective function */
17268  SCIP_VAR* var /**< problem variable */
17269  )
17270 {
17271  assert(var != NULL);
17272 
17273  if( var->obj >= 0.0 )
17274  return var->locdom.ub;
17275  else
17276  return var->locdom.lb;
17277 }
17278 
17279 /** gets type (lower or upper) of best bound of variable with respect to the objective function */
17281  SCIP_VAR* var /**< problem variable */
17282  )
17283 {
17284  assert(var != NULL);
17285 
17286  if( var->obj >= 0.0 )
17287  return SCIP_BOUNDTYPE_LOWER;
17288  else
17289  return SCIP_BOUNDTYPE_UPPER;
17290 }
17291 
17292 /** gets type (lower or upper) of worst bound of variable with respect to the objective function */
17294  SCIP_VAR* var /**< problem variable */
17295  )
17296 {
17297  assert(var != NULL);
17298 
17299  if( var->obj >= 0.0 )
17300  return SCIP_BOUNDTYPE_UPPER;
17301  else
17302  return SCIP_BOUNDTYPE_LOWER;
17303 }
17304 
17305 /** gets lazy lower bound of variable, returns -infinity if the variable has no lazy lower bound */
17307  SCIP_VAR* var /**< problem variable */
17308  )
17309 {
17310  assert(var != NULL);
17311 
17312  return var->lazylb;
17313 }
17314 
17315 /** gets lazy upper bound of variable, returns infinity if the variable has no lazy upper bound */
17317  SCIP_VAR* var /**< problem variable */
17318  )
17319 {
17320  assert(var != NULL);
17321 
17322  return var->lazyub;
17323 }
17324 
17325 /** gets the branch factor of the variable; this value can be used in the branching methods to scale the score
17326  * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
17327  */
17329  SCIP_VAR* var /**< problem variable */
17330  )
17331 {
17332  assert(var != NULL);
17333 
17334  return var->branchfactor;
17335 }
17336 
17337 /** gets the branch priority of the variable; variables with higher priority should always be preferred to variables
17338  * with lower priority
17339  */
17341  SCIP_VAR* var /**< problem variable */
17342  )
17343 {
17344  assert(var != NULL);
17345 
17346  return var->branchpriority;
17347 }
17348 
17349 /** gets the preferred branch direction of the variable (downwards, upwards, or auto) */
17351  SCIP_VAR* var /**< problem variable */
17352  )
17353 {
17354  assert(var != NULL);
17355 
17356  return (SCIP_BRANCHDIR)var->branchdirection;
17357 }
17358 
17359 /** gets number of variable lower bounds x >= b_i*z_i + d_i of given variable x */
17360 int SCIPvarGetNVlbs(
17361  SCIP_VAR* var /**< problem variable */
17362  )
17363 {
17364  assert(var != NULL);
17365 
17366  return SCIPvboundsGetNVbds(var->vlbs);
17367 }
17368 
17369 /** gets array with bounding variables z_i in variable lower bounds x >= b_i*z_i + d_i of given variable x;
17370  * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
17371  */
17373  SCIP_VAR* var /**< problem variable */
17374  )
17375 {
17376  assert(var != NULL);
17377 
17378  return SCIPvboundsGetVars(var->vlbs);
17379 }
17380 
17381 /** gets array with bounding coefficients b_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
17383  SCIP_VAR* var /**< problem variable */
17384  )
17385 {
17386  assert(var != NULL);
17387 
17388  return SCIPvboundsGetCoefs(var->vlbs);
17389 }
17390 
17391 /** gets array with bounding constants d_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
17393  SCIP_VAR* var /**< problem variable */
17394  )
17395 {
17396  assert(var != NULL);
17397 
17398  return SCIPvboundsGetConstants(var->vlbs);
17399 }
17400 
17401 /** gets number of variable upper bounds x <= b_i*z_i + d_i of given variable x */
17402 int SCIPvarGetNVubs(
17403  SCIP_VAR* var /**< problem variable */
17404  )
17405 {
17406  assert(var != NULL);
17407 
17408  return SCIPvboundsGetNVbds(var->vubs);
17409 }
17410 
17411 /** gets array with bounding variables z_i in variable upper bounds x <= b_i*z_i + d_i of given variable x;
17412  * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
17413  */
17415  SCIP_VAR* var /**< problem variable */
17416  )
17417 {
17418  assert(var != NULL);
17419 
17420  return SCIPvboundsGetVars(var->vubs);
17421 }
17422 
17423 /** gets array with bounding coefficients b_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
17425  SCIP_VAR* var /**< problem variable */
17426  )
17427 {
17428  assert(var != NULL);
17429 
17430  return SCIPvboundsGetCoefs(var->vubs);
17431 }
17432 
17433 /** gets array with bounding constants d_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
17435  SCIP_VAR* var /**< problem variable */
17436  )
17437 {
17438  assert(var != NULL);
17439 
17440  return SCIPvboundsGetConstants(var->vubs);
17441 }
17442 
17443 /** gets number of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
17444  * there are no implications for nonbinary variable x
17445  */
17446 int SCIPvarGetNImpls(
17447  SCIP_VAR* var, /**< active problem variable */
17448  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17449  )
17450 {
17451  assert(var != NULL);
17452  assert(SCIPvarIsActive(var));
17453 
17454  return SCIPimplicsGetNImpls(var->implics, varfixing);
17455 }
17456 
17457 /** gets array with implication variables y of implications y <= b or y >= b for x == 0 or x == 1 of given active
17458  * problem variable x, there are no implications for nonbinary variable x;
17459  * the implications are sorted such that implications with binary implied variables precede the ones with non-binary
17460  * implied variables, and as a second criteria, the implied variables are sorted by increasing variable index
17461  * (see SCIPvarGetIndex())
17462  */
17464  SCIP_VAR* var, /**< active problem variable */
17465  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17466  )
17467 {
17468  assert(var != NULL);
17469  assert(SCIPvarIsActive(var));
17470 
17471  return SCIPimplicsGetVars(var->implics, varfixing);
17472 }
17473 
17474 /** gets array with implication types of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
17475  * variable x (SCIP_BOUNDTYPE_UPPER if y <= b, SCIP_BOUNDTYPE_LOWER if y >= b),
17476  * there are no implications for nonbinary variable x
17477  */
17479  SCIP_VAR* var, /**< active problem variable */
17480  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17481  )
17482 {
17483  assert(var != NULL);
17484  assert(SCIPvarIsActive(var));
17485 
17486  return SCIPimplicsGetTypes(var->implics, varfixing);
17487 }
17488 
17489 /** gets array with implication bounds b of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
17490  * variable x, there are no implications for nonbinary variable x
17491  */
17493  SCIP_VAR* var, /**< active problem variable */
17494  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17495  )
17496 {
17497  assert(var != NULL);
17498  assert(SCIPvarIsActive(var));
17499 
17500  return SCIPimplicsGetBounds(var->implics, varfixing);
17501 }
17502 
17503 /** Gets array with unique ids of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
17504  * there are no implications for nonbinary variable x.
17505  * If an implication is a shortcut, i.e., it was added as part of the transitive closure of another implication,
17506  * its id is negative, otherwise it is nonnegative.
17507  */
17508 int* SCIPvarGetImplIds(
17509  SCIP_VAR* var, /**< active problem variable */
17510  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17511  )
17512 {
17513  assert(var != NULL);
17514  assert(SCIPvarIsActive(var));
17515 
17516  return SCIPimplicsGetIds(var->implics, varfixing);
17517 }
17518 
17519 /** gets number of cliques, the active variable is contained in */
17520 int SCIPvarGetNCliques(
17521  SCIP_VAR* var, /**< active problem variable */
17522  SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
17523  )
17524 {
17525  assert(var != NULL);
17526 
17527  return SCIPcliquelistGetNCliques(var->cliquelist, varfixing);
17528 }
17529 
17530 /** gets array of cliques, the active variable is contained in */
17532  SCIP_VAR* var, /**< active problem variable */
17533  SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
17534  )
17535 {
17536  assert(var != NULL);
17537 
17538  return SCIPcliquelistGetCliques(var->cliquelist, varfixing);
17539 }
17540 
17541 /** gets primal LP solution value of variable */
17543  SCIP_VAR* var /**< problem variable */
17544  )
17545 {
17546  assert(var != NULL);
17547 
17549  return SCIPcolGetPrimsol(var->data.col);
17550  else
17551  return SCIPvarGetLPSol_rec(var);
17552 }
17553 
17554 /** gets primal NLP solution value of variable */
17556  SCIP_VAR* var /**< problem variable */
17557  )
17558 {
17559  assert(var != NULL);
17560 
17562  return var->nlpsol;
17563  else
17564  return SCIPvarGetNLPSol_rec(var);
17565 }
17566 
17567 /** return lower bound change info at requested position */
17569  SCIP_VAR* var, /**< problem variable */
17570  int pos /**< requested position */
17571  )
17572 {
17573  assert(pos >= 0);
17574  assert(pos < var->nlbchginfos);
17575 
17576  return &var->lbchginfos[pos];
17577 }
17578 
17579 /** gets the number of lower bound change info array */
17581  SCIP_VAR* var /**< problem variable */
17582  )
17583 {
17584  return var->nlbchginfos;
17585 }
17586 
17587 /** return upper bound change info at requested position */
17589  SCIP_VAR* var, /**< problem variable */
17590  int pos /**< requested position */
17591  )
17592 {
17593  assert(pos >= 0);
17594  assert(pos < var->nubchginfos);
17595 
17596  return &var->ubchginfos[pos];
17597 }
17598 
17599 /** gets the number upper bound change info array */
17601  SCIP_VAR* var /**< problem variable */
17602  )
17603 {
17604  assert(var != NULL);
17605 
17606  return var->nubchginfos;
17607 }
17608 
17609 /** returns the value based history for the variable */
17611  SCIP_VAR* var /**< problem variable */
17612  )
17613 {
17614  assert(var != NULL);
17615 
17616  return var->valuehistory;
17617 }
17618 
17619 /** gets pseudo solution value of variable */
17621  SCIP_VAR* var /**< problem variable */
17622  )
17623 {
17624  assert(var != NULL);
17625 
17627  return SCIPvarGetBestBoundLocal(var);
17628  else
17629  return SCIPvarGetPseudoSol_rec(var);
17630 }
17631 
17632 /** returns the variable's VSIDS score */
17634  SCIP_VAR* var, /**< problem variable */
17635  SCIP_STAT* stat, /**< problem statistics */
17636  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
17637  )
17638 {
17639  assert(var != NULL);
17640 
17642  return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
17643  else
17644  return SCIPvarGetVSIDS_rec(var, stat, dir);
17645 }
17646 
17647 /** returns the index of the connected component of the clique graph that the variable belongs to, or -1 if not computed */
17649  SCIP_VAR* var /**< problem variable */
17650  )
17651 {
17652  assert(var != NULL);
17653  return var->clqcomponentidx;
17654 }
17655 
17656 /** sets the index of the connected component of the clique graph that the variable belongs to, or -1 if not computed */
17658  SCIP_VAR* var, /**< problem variable */
17659  int idx /**< clique component index of this variable */
17660  )
17661 {
17662  assert(var != NULL);
17663  var->clqcomponentidx = idx;
17664 }
17665 
17666 
17667 /** includes event handler with given data in variable's event filter */
17669  SCIP_VAR* var, /**< problem variable */
17670  BMS_BLKMEM* blkmem, /**< block memory */
17671  SCIP_SET* set, /**< global SCIP settings */
17672  SCIP_EVENTTYPE eventtype, /**< event type to catch */
17673  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
17674  SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
17675  int* filterpos /**< pointer to store position of event filter entry, or NULL */
17676  )
17677 {
17678  assert(var != NULL);
17679  assert(set != NULL);
17680  assert(var->scip == set->scip);
17681  assert(var->eventfilter != NULL);
17682  assert((eventtype & ~SCIP_EVENTTYPE_VARCHANGED) == 0);
17683  assert((eventtype & SCIP_EVENTTYPE_VARCHANGED) != 0);
17684  assert(SCIPvarIsTransformed(var));
17685 
17686  SCIPsetDebugMsg(set, "catch event of type 0x%" SCIP_EVENTTYPE_FORMAT " of variable <%s> with handler %p and data %p\n",
17687  eventtype, var->name, (void*)eventhdlr, (void*)eventdata);
17688 
17689  SCIP_CALL( SCIPeventfilterAdd(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
17690 
17691  return SCIP_OKAY;
17692 }
17693 
17694 /** deletes event handler with given data from variable's event filter */
17696  SCIP_VAR* var, /**< problem variable */
17697  BMS_BLKMEM* blkmem, /**< block memory */
17698  SCIP_SET* set, /**< global SCIP settings */
17699  SCIP_EVENTTYPE eventtype, /**< event type mask of dropped event */
17700  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
17701  SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
17702  int filterpos /**< position of event filter entry returned by SCIPvarCatchEvent(), or -1 */
17703  )
17704 {
17705  assert(var != NULL);
17706  assert(set != NULL);
17707  assert(var->scip == set->scip);
17708  assert(var->eventfilter != NULL);
17709  assert(SCIPvarIsTransformed(var));
17710 
17711  SCIPsetDebugMsg(set, "drop event of variable <%s> with handler %p and data %p\n", var->name, (void*)eventhdlr,
17712  (void*)eventdata);
17713 
17714  SCIP_CALL( SCIPeventfilterDel(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
17715 
17716  return SCIP_OKAY;
17717 }
17718 
17719 /** returns the position of the bound change index */
17720 int SCIPbdchgidxGetPos(
17721  SCIP_BDCHGIDX* bdchgidx /**< bound change index */
17722  )
17723 {
17724  assert(bdchgidx != NULL);
17725 
17726  return bdchgidx->pos;
17727 }
17728 
17729 /** returns whether first bound change index belongs to an earlier applied bound change than second one */
17731  SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index */
17732  SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index */
17733  )
17734 {
17735  assert(bdchgidx1 != NULL);
17736  assert(bdchgidx1->depth >= -2);
17737  assert(bdchgidx1->pos >= 0);
17738  assert(bdchgidx2 != NULL);
17739  assert(bdchgidx2->depth >= -2);
17740  assert(bdchgidx2->pos >= 0);
17741 
17742  return (bdchgidx1->depth < bdchgidx2->depth)
17743  || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
17744 }
17745 
17746 /** returns whether first bound change index belongs to an earlier applied bound change than second one;
17747  * if a bound change index is NULL, the bound change index represents the current time, i.e. the time after the
17748  * last bound change was applied to the current node
17749  */
17751  SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index, or NULL */
17752  SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index, or NULL */
17753  )
17754 {
17755  assert(bdchgidx1 == NULL || bdchgidx1->depth >= -2);
17756  assert(bdchgidx1 == NULL || bdchgidx1->pos >= 0);
17757  assert(bdchgidx2 == NULL || bdchgidx2->depth >= -2);
17758  assert(bdchgidx2 == NULL || bdchgidx2->pos >= 0);
17759 
17760  if( bdchgidx1 == NULL )
17761  return FALSE;
17762  else if( bdchgidx2 == NULL )
17763  return TRUE;
17764  else
17765  return (bdchgidx1->depth < bdchgidx2->depth)
17766  || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
17767 }
17768 
17769 /** returns old bound that was overwritten for given bound change information */
17771  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17772  )
17773 {
17774  assert(bdchginfo != NULL);
17775 
17776  return bdchginfo->oldbound;
17777 }
17778 
17779 /** returns new bound installed for given bound change information */
17781  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17782  )
17783 {
17784  assert(bdchginfo != NULL);
17785 
17786  return bdchginfo->newbound;
17787 }
17788 
17789 /** returns variable that belongs to the given bound change information */
17791  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17792  )
17793 {
17794  assert(bdchginfo != NULL);
17795 
17796  return bdchginfo->var;
17797 }
17798 
17799 /** returns whether the bound change information belongs to a branching decision or a deduction */
17801  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17802  )
17803 {
17804  assert(bdchginfo != NULL);
17805 
17806  return (SCIP_BOUNDCHGTYPE)(bdchginfo->boundchgtype);
17807 }
17808 
17809 /** returns whether the bound change information belongs to a lower or upper bound change */
17811  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17812  )
17813 {
17814  assert(bdchginfo != NULL);
17815 
17816  return (SCIP_BOUNDTYPE)(bdchginfo->boundtype);
17817 }
17818 
17819 /** returns depth level of given bound change information */
17821  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17822  )
17823 {
17824  assert(bdchginfo != NULL);
17825 
17826  return bdchginfo->bdchgidx.depth;
17827 }
17828 
17829 /** returns bound change position in its depth level of given bound change information */
17831  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17832  )
17833 {
17834  assert(bdchginfo != NULL);
17835 
17836  return bdchginfo->bdchgidx.pos;
17837 }
17838 
17839 /** returns bound change index of given bound change information */
17841  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17842  )
17843 {
17844  assert(bdchginfo != NULL);
17845 
17846  return &bdchginfo->bdchgidx;
17847 }
17848 
17849 /** returns inference variable of given bound change information */
17851  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17852  )
17853 {
17854  assert(bdchginfo != NULL);
17857 
17858  return bdchginfo->inferencedata.var;
17859 }
17860 
17861 /** returns inference constraint of given bound change information */
17863  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17864  )
17865 {
17866  assert(bdchginfo != NULL);
17868  assert(bdchginfo->inferencedata.reason.cons != NULL);
17869 
17870  return bdchginfo->inferencedata.reason.cons;
17871 }
17872 
17873 /** returns inference propagator of given bound change information, or NULL if no propagator was responsible */
17875  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17876  )
17877 {
17878  assert(bdchginfo != NULL);
17880 
17881  return bdchginfo->inferencedata.reason.prop;
17882 }
17883 
17884 /** returns inference user information of given bound change information */
17886  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17887  )
17888 {
17889  assert(bdchginfo != NULL);
17892 
17893  return bdchginfo->inferencedata.info;
17894 }
17895 
17896 /** returns inference bound of inference variable of given bound change information */
17898  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17899  )
17900 {
17901  assert(bdchginfo != NULL);
17904 
17905  return (SCIP_BOUNDTYPE)(bdchginfo->inferboundtype);
17906 }
17907 
17908 /** returns the relaxed bound change type */
17910  SCIP_BDCHGINFO* bdchginfo /**< bound change to add to the conflict set */
17911  )
17912 {
17913  return ((SCIP_BOUNDTYPE)(bdchginfo->boundtype) == SCIP_BOUNDTYPE_LOWER ? bdchginfo->var->conflictrelaxedlb : bdchginfo->var->conflictrelaxedub);
17914 }
17915 
17916 
17917 /** returns whether the bound change information belongs to a redundant bound change */
17919  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17920  )
17921 {
17922  assert(bdchginfo != NULL);
17923  assert(bdchginfo->redundant == (bdchginfo->oldbound == bdchginfo->newbound)); /*lint !e777*/
17924 
17925  return bdchginfo->redundant;
17926 }
17927 
17928 /** returns whether the bound change has an inference reason (constraint or propagator), that can be resolved */
17930  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17931  )
17932 {
17933  assert(bdchginfo != NULL);
17934 
17937  && bdchginfo->inferencedata.reason.prop != NULL);
17938 }
17939 
17940 /** for two bound change informations belonging to the same variable and bound, returns whether the first bound change
17941  * has a tighter new bound as the second bound change
17942  */
17944  SCIP_BDCHGINFO* bdchginfo1, /**< first bound change information */
17945  SCIP_BDCHGINFO* bdchginfo2 /**< second bound change information */
17946  )
17947 {
17948  assert(bdchginfo1 != NULL);
17949  assert(bdchginfo2 != NULL);
17950  assert(bdchginfo1->var == bdchginfo2->var);
17951  assert(bdchginfo1->boundtype == bdchginfo2->boundtype);
17952 
17953  return (SCIPbdchginfoGetBoundtype(bdchginfo1) == SCIP_BOUNDTYPE_LOWER
17954  ? bdchginfo1->newbound > bdchginfo2->newbound
17955  : bdchginfo1->newbound < bdchginfo2->newbound);
17956 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:52
SCIP_Real SCIPhistoryGetAvgConflictlength(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:555
SCIP_HOLELIST * holelist
Definition: struct_var.h:162
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:50
SCIP_RETCODE SCIPeventfilterCreate(SCIP_EVENTFILTER **eventfilter, BMS_BLKMEM *blkmem)
Definition: event.c:1693
SCIP_Real SCIPbdchginfoGetRelaxedBound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17910
void SCIPcliquelistRemoveFromCliques(SCIP_CLIQUELIST *cliquelist, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Bool irrelevantvar)
Definition: implics.c:1659
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:14709
SCIP_Real SCIPvarGetWorstBoundLocal(SCIP_VAR *var)
Definition: var.c:17268
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5517
SCIP_Real * SCIPvarGetVlbCoefs(SCIP_VAR *var)
Definition: var.c:17383
#define BMSfreeBlockMemoryArrayNull(mem, ptr, num)
Definition: memory.h:426
void SCIPvarGetClosestVlb(SCIP_VAR *var, SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *closestvlb, int *closestvlbidx)
Definition: var.c:13427
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:17294
static void checkImplic(SCIP_SET *set, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool *redundant, SCIP_Bool *infeasible)
Definition: var.c:8911
SCIP_RETCODE SCIPvarIncInferenceSum(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_BRANCHDIR dir, SCIP_Real value, SCIP_Real weight)
Definition: var.c:14836
SCIP_Bool SCIPvarsHaveCommonClique(SCIP_VAR *var1, SCIP_Bool value1, SCIP_VAR *var2, SCIP_Bool value2, SCIP_Bool regardimplics)
Definition: var.c:10785
SCIP_BRANCHINGDATA branchingdata
Definition: struct_var.h:86
void SCIPhistoryIncNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, int depth)
Definition: history.c:568
SCIP_VAR ** SCIPcliqueGetVars(SCIP_CLIQUE *clique)
Definition: implics.c:3304
SCIP_Bool SCIPsetIsLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5575
SCIP_Bool SCIPsetIsFeasZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6025
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:14356
static SCIP_RETCODE varEventImplAdded(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:8793
SCIP_RETCODE SCIPvarAddVub(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR *vubvar, SCIP_Real vubcoef, SCIP_Real vubconstant, SCIP_Bool transitive, SCIP_Bool *infeasible, int *nbdchgs)
Definition: var.c:9902
SCIP_Real SCIPvarGetBdAtIndex(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16088
SCIP_PROP * SCIPbdchginfoGetInferProp(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17875
void SCIPvarMarkNotDeletable(SCIP_VAR *var)
Definition: var.c:16799
void SCIPvarUpdateBestRootSol(SCIP_VAR *var, SCIP_SET *set, SCIP_Real rootsol, SCIP_Real rootredcost, SCIP_Real rootlpobjval)
Definition: var.c:12584
SCIP_RETCODE SCIPvarSetNLPSol(SCIP_VAR *var, SCIP_SET *set, SCIP_Real solval)
Definition: var.c:13311
public methods for branching and inference history structure
SCIP_Bool SCIPlpDiving(SCIP_LP *lp)
Definition: lp.c:16899
int nubchginfos
Definition: struct_var.h:264
SCIP_RETCODE SCIPvarAddObj(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_EVENTQUEUE *eventqueue, SCIP_Real addobj)
Definition: var.c:5876
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoLb(SCIP_VAR *var, int pos)
Definition: var.c:17569
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition: var.c:16961
internal methods for branch and bound tree
SCIP_Longint SCIPgetNLPIterations(SCIP *scip)
Definition: scip.c:41609
SCIP_BDCHGIDX bdchgidx
Definition: struct_var.h:111
void SCIPhistoryIncCutoffSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition: history.c:600
SCIP_Real SCIPvarGetAvgCutoffsCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15609
SCIP_RETCODE SCIPvaluehistoryCreate(SCIP_VALUEHISTORY **valuehistory, BMS_BLKMEM *blkmem)
Definition: history.c:228
SCIP_Real SCIPsetFeastol(SCIP_SET *set)
Definition: set.c:5421
SCIP_Real SCIPvarGetBranchFactor(SCIP_VAR *var)
Definition: var.c:17329
unsigned int inferboundtype
Definition: struct_var.h:92
SCIP_Real SCIPbdchginfoGetOldbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17771
char * name
Definition: struct_var.h:228
static SCIP_RETCODE domchgCreate(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem)
Definition: var.c:962
unsigned int boundchgtype
Definition: struct_var.h:113
SCIP_BRANCHDIR SCIPvarGetBranchDirection(SCIP_VAR *var)
Definition: var.c:17351
union SCIP_BoundChg::@11 data
SCIP_RETCODE SCIPcliqueAddVar(SCIP_CLIQUE *clique, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_VAR *var, SCIP_Bool value, SCIP_Bool *doubleentry, SCIP_Bool *oppositeentry)
Definition: implics.c:1127
SCIP_HOLE hole
Definition: struct_var.h:50
SCIP_Real bestrootsol
Definition: struct_var.h:206
char * name
Definition: struct_lp.h:217
SCIP_Real SCIPvarGetUbLazy(SCIP_VAR *var)
Definition: var.c:17317
SCIP_Real SCIPsetFloor(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5704
static SCIP_RETCODE varProcessChgLbGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Real newbound)
Definition: var.c:6370
SCIP_Bool SCIPsetIsFeasEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5915
int SCIPvarGetNVlbs(SCIP_VAR *var)
Definition: var.c:17361
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17791
#define SCIPsetDuplicateBufferArray(set, ptr, source, num)
Definition: set.h:1836
SCIP_Real SCIPvarGetWorstBoundGlobal(SCIP_VAR *var)
Definition: var.c:17212
#define SCIP_DECL_VARTRANS(x)
Definition: type_var.h:129
SCIP_RETCODE SCIPvarChgLbGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Real newbound)
Definition: var.c:6720
enum SCIP_BaseStat SCIP_BASESTAT
Definition: type_lpi.h:86
SCIP_Bool SCIPvarDoNotMultaggr(SCIP_VAR *var)
Definition: var.c:5492
SCIP_RETCODE SCIPvarCreateTransformed(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
Definition: var.c:2036
SCIP_Real SCIPvarGetPseudocostCountCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:13921
methods for implications, variable bounds, and cliques
SCIP_RETCODE SCIPvarAggregate(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR *aggvar, SCIP_Real scalar, SCIP_Real constant, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition: var.c:4422
int SCIPvarGetLastBdchgDepth(SCIP_VAR *var)
Definition: var.c:16168
SCIP_RETCODE SCIPeventqueueAdd(SCIP_EVENTQUEUE *eventqueue, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENT **event)
Definition: event.c:2112
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17169
SCIP_Real SCIPvarGetAvgBranchdepth(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15092
SCIP_RETCODE SCIPvarGetProbvarBinary(SCIP_VAR **var, SCIP_Bool *negated)
Definition: var.c:11616
SCIP_RETCODE SCIPdomchgAddHolechg(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HOLELIST **ptr, SCIP_HOLELIST *newlist, SCIP_HOLELIST *oldlist)
Definition: var.c:1442
SCIP_Bool SCIPvarIsPscostRelerrorReliable(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real threshold, SCIP_CONFIDENCELEVEL clevel)
Definition: var.c:14088
#define SCIP_MAXSTRLEN
Definition: def.h:225
SCIP_DOM origdom
Definition: struct_var.h:168
SCIP_BASESTAT SCIPcolGetBasisStatus(SCIP_COL *col)
Definition: lp.c:16150
SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition: var.c:16756
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:3255
SCIP_RETCODE SCIPvarChgLbOriginal(SCIP_VAR *var, SCIP_SET *set, SCIP_Real newbound)
Definition: var.c:6102
SCIP_BOUNDCHG * boundchgs
Definition: struct_var.h:124
void SCIPhistoryIncInferenceSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition: history.c:584
SCIP_Bool SCIPsetIsPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5640
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:16949
static long bound
#define SCIPdebugCheckImplic(set, var, varfixing, implvar, impltype, implbound)
Definition: debug.h:259
#define MAXABSVBCOEF
Definition: var.c:66
#define SCIPsetAllocCleanBufferArray(set, ptr, num)
Definition: set.h:1845
static SCIP_Real getImplVarRedcost(SCIP_VAR *var, SCIP_SET *set, SCIP_Bool varfixing, SCIP_STAT *stat, SCIP_LP *lp)
Definition: var.c:12718
SCIP_RETCODE SCIPbdchginfoCreate(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_Real oldbound, SCIP_Real newbound)
Definition: var.c:15663
SCIP_RETCODE SCIPeventfilterDel(SCIP_EVENTFILTER *eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: event.c:1851
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17225
SCIP_RETCODE SCIPvarChgLbLazy(SCIP_VAR *var, SCIP_SET *set, SCIP_Real lazylb)
Definition: var.c:7004
SCIP_Real constant
Definition: struct_var.h:183
SCIP_RETCODE SCIPvarAddLocks(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, int addnlocksdown, int addnlocksup)
Definition: var.c:3047
SCIP_CLIQUE ** SCIPvarGetCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17532
SCIP_RETCODE SCIPprobVarChangedStatus(SCIP_PROB *prob, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_BRANCHCAND *branchcand, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var)
Definition: prob.c:1171
SCIP_Real bestrootredcost
Definition: struct_var.h:207
SCIP_Real SCIPvarGetMultaggrLbGlobal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8095
SCIP_HISTORY * historycrun
Definition: struct_var.h:244
SCIP_BRANCHDIR lastbranchdir
Definition: struct_stat.h:166
SCIP_VALUEHISTORY * SCIPvarGetValuehistory(SCIP_VAR *var)
Definition: var.c:17611
int SCIPcliquelistGetNCliques(SCIP_CLIQUELIST *cliquelist, SCIP_Bool value)
Definition: implics.c:3356
SCIP_NODE * SCIPnodeGetParent(SCIP_NODE *node)
Definition: tree.c:7452
void SCIPprobAddObjoffset(SCIP_PROB *prob, SCIP_Real addval)
Definition: prob.c:1420
void SCIPvarSetTransData(SCIP_VAR *var, SCIP_DECL_VARTRANS((*vartrans)))
Definition: var.c:16608
SCIP_RETCODE SCIPvarChgUbOriginal(SCIP_VAR *var, SCIP_SET *set, SCIP_Real newbound)
Definition: var.c:6161
SCIP_Longint closestvblpcount
Definition: struct_var.h:246
SCIP_RETCODE SCIPvarAddHoleGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_Real left, SCIP_Real right, SCIP_Bool *added)
Definition: var.c:8403
SCIP_RETCODE SCIPvarParseOriginal(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, const char *str, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARCOPY((*varcopy)), SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_VARDATA *vardata, char **endptr, SCIP_Bool *success)
Definition: var.c:2404
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:16735
static SCIP_RETCODE varEventGholeAdded(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_Real left, SCIP_Real right)
Definition: var.c:6297
SCIP_VAR ** SCIPvboundsGetVars(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3222
SCIP_Real SCIPsetInfinity(SCIP_SET *set)
Definition: set.c:5379
SCIP_DOMCHGBOTH domchgboth
Definition: struct_var.h:153
SCIP_RETCODE SCIPcolChgObj(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newobj)
Definition: lp.c:3567
SCIP_Real SCIPvarGetSol(SCIP_VAR *var, SCIP_Bool getlpval)
Definition: var.c:12561
int SCIPprobGetNVars(SCIP_PROB *prob)
Definition: prob.c:2247
SCIP_BDCHGINFO * ubchginfos
Definition: struct_var.h:242
SCIP_Bool SCIPbdchgidxIsEarlier(SCIP_BDCHGIDX *bdchgidx1, SCIP_BDCHGIDX *bdchgidx2)
Definition: var.c:17751
SCIP_Bool SCIPvarWasFixedAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16108
SCIP_Real SCIPvarGetBestBoundLocal(SCIP_VAR *var)
Definition: var.c:17255
SCIP_Real SCIPvarGetRootSol(SCIP_VAR *var)
Definition: var.c:12654
static SCIP_RETCODE boundchgApplyGlobal(SCIP_BOUNDCHG *boundchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool *cutoff)
Definition: var.c:832
SCIP_RETCODE SCIPvarMarkDoNotMultaggr(SCIP_VAR *var)
Definition: var.c:5715
SCIP_RETCODE SCIPvarScaleVSIDS(SCIP_VAR *var, SCIP_Real scalar)
Definition: var.c:14442
SCIP_Real SCIPvarGetLbLP(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:12238
static SCIP_RETCODE holelistDuplicate(SCIP_HOLELIST **target, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HOLELIST *source)
Definition: var.c:124
SCIP_BOUNDTYPE SCIPboundchgGetBoundtype(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16482
unsigned int nboundchgs
Definition: struct_var.h:122
SCIP_RETCODE SCIPvarCatchEvent(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: var.c:17669
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:3148
SCIP_HOLELIST * newlist
Definition: struct_var.h:58
SCIP_Real right
Definition: struct_var.h:44
void SCIPvaluehistoryScaleVSIDS(SCIP_VALUEHISTORY *valuehistory, SCIP_Real scalar)
Definition: history.c:314
void SCIPvarSetProbindex(SCIP_VAR *var, int probindex)
Definition: var.c:5635
SCIP_RETCODE SCIPhistoryCreate(SCIP_HISTORY **history, BMS_BLKMEM *blkmem)
Definition: history.c:40
static SCIP_RETCODE varUpdateAggregationBounds(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *aggvar, SCIP_Real scalar, SCIP_Real constant, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: var.c:4232
SCIP_HOLELIST * SCIPholelistGetNext(SCIP_HOLELIST *holelist)
Definition: var.c:16542
#define FALSE
Definition: def.h:64
int lppos
Definition: struct_lp.h:163
#define EPSEQ(x, y, eps)
Definition: def.h:170
#define EPSISINT(x, eps)
Definition: def.h:182
SCIP_Bool SCIPlpIsSolBasic(SCIP_LP *lp)
Definition: lp.c:16889
SCIP_Bool SCIPsetIsFeasIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6058
int SCIPvarGetNBdchgInfosLb(SCIP_VAR *var)
Definition: var.c:17581
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:16092
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:16072
static SCIP_RETCODE varEventVarUnlocked(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:3026
SCIP_Real constant
Definition: struct_var.h:193
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:9340
SCIP_Bool SCIPsetIsZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5629
SCIP_RETCODE SCIPvboundsDel(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem, SCIP_VAR *vbdvar, SCIP_Bool negativecoef)
Definition: implics.c:281
static SCIP_Bool useValuehistory(SCIP_VAR *var, SCIP_Real value, SCIP_SET *set)
Definition: var.c:14328
#define TRUE
Definition: def.h:63
SCIP_Bool SCIPvarHasImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition: var.c:10456
static void varSetProbindex(SCIP_VAR *var, int probindex)
Definition: var.c:5616
SCIP_Real SCIPvarGetAvgConflictlength(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14665
SCIP_INFERENCEDATA inferencedata
Definition: struct_var.h:110
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_HOLELIST * oldlist
Definition: struct_var.h:59
SCIP_Real SCIPvarGetNegationConstant(SCIP_VAR *var)
Definition: var.c:17006
#define MAXIMPLSCLOSURE
Definition: var.c:63
int SCIPvarGetNVubs(SCIP_VAR *var)
Definition: var.c:17403
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:17886
int nlbchginfos
Definition: struct_var.h:262
static SCIP_BDCHGIDX presolvebdchgidx
Definition: var.c:16128
static void printHolelist(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, FILE *file, SCIP_HOLELIST *holelist, const char *name)
Definition: var.c:2851
enum SCIP_Varstatus SCIP_VARSTATUS
Definition: type_var.h:48
#define SCIPsetAllocBufferArray(set, ptr, num)
Definition: set.h:1834
SCIP_RETCODE SCIPvarCreateOriginal(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
Definition: var.c:1993
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:16862
SCIP_RETCODE SCIPvarAddImplic(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool transitive, SCIP_Bool *infeasible, int *nbdchgs)
Definition: var.c:10257
#define SCIP_DECL_VARCOPY(x)
Definition: type_var.h:172
SCIP_RETCODE SCIPvarChgLbDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newbound)
Definition: var.c:7778
void SCIPvarSetNamePointer(SCIP_VAR *var, const char *name)
Definition: var.c:5650
int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
Definition: set.c:5091
#define SCIP_EVENTTYPE_GLBCHANGED
Definition: type_event.h:61
SCIP_RETCODE SCIPvarChgBdLocal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype)
Definition: var.c:7752
SCIP_Real SCIPvarGetAggrScalar(SCIP_VAR *var)
Definition: var.c:16915
void SCIPvarInitSolve(SCIP_VAR *var)
Definition: var.c:2810
SCIP_RETCODE SCIPvarChgUbGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Real newbound)
Definition: var.c:6863
static GRAPHNODE ** active
SCIP_Real SCIPvarGetInferenceSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15276
void SCIPvarMarkDeletable(SCIP_VAR *var)
Definition: var.c:16788
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:829
SCIP_Real SCIPvarGetAvgInferences(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15364
SCIP_Real SCIPhistoryGetVSIDS(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:513
#define SCIPdebugMessage
Definition: pub_message.h:77
SCIP_RETCODE SCIPvarAddClique(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool value, SCIP_CLIQUE *clique, SCIP_Bool *infeasible, int *nbdchgs)
Definition: var.c:10580
SCIP_VAR ** SCIPvarGetVlbVars(SCIP_VAR *var)
Definition: var.c:17373
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:11313
int SCIPbdchgidxGetPos(SCIP_BDCHGIDX *bdchgidx)
Definition: var.c:17721
SCIP_CLIQUE ** SCIPcliquelistGetCliques(SCIP_CLIQUELIST *cliquelist, SCIP_Bool value)
Definition: implics.c:3365
int index
Definition: struct_var.h:249
SCIP_Real constant
Definition: struct_var.h:176
unsigned int domchgtype
Definition: struct_var.h:141
SCIP_Bool SCIPsetIsNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5651
SCIP_RETCODE SCIPcliquelistAdd(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: implics.c:1458
SCIP_Bool SCIPvarIsDeletable(SCIP_VAR *var)
Definition: var.c:16832
int SCIPvarGetConflictingBdchgDepth(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real bound)
Definition: var.c:16183
SCIP_RETCODE SCIPvarUpdatePseudocost(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition: var.c:13682
#define SCIPsetFreeBufferArray(set, ptr)
Definition: set.h:1841
SCIP_Longint SCIPvarGetNBranchingsCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15049
SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
Definition: var.c:16766
void SCIPvarAdjustLb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *lb)
Definition: var.c:6052
static SCIP_RETCODE domchgEnsureBoundchgsSize(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: var.c:1173
#define SCIPdebugCheckVbound(set, var, vbtype, vbvar, vbcoef, vbconstant)
Definition: debug.h:258
SCIP_RETCODE SCIPvarChgBranchDirection(SCIP_VAR *var, SCIP_BRANCHDIR branchdirection)
Definition: var.c:11126
SCIP_Real SCIPhistoryGetAvgCutoffs(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:668
SCIP_HOLECHG * holechgs
Definition: struct_var.h:133
SCIP_Real obj
Definition: struct_var.h:202
SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition: var.c:16995
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:5358
SCIP_Real relaxsol
Definition: struct_var.h:209
SCIP_RETCODE SCIPvarRemoveCliquesImplicsVbs(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_CLIQUETABLE *cliquetable, SCIP_SET *set, SCIP_Bool irrelevantvar, SCIP_Bool onlyredundant, SCIP_Bool removefromvar)
Definition: var.c:1532
static SCIP_RETCODE boundchgCaptureData(SCIP_BOUNDCHG *boundchg)
Definition: var.c:892
SCIP_Real SCIPsetCeil(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5715
int conflictlbcount
Definition: struct_var.h:265
SCIP_Real SCIPvarGetRelaxSolTransVar(SCIP_VAR *var)
Definition: var.c:13300
#define SCIPstatIncrement(stat, set, field)
Definition: stat.h:251
internal methods for LP management
SCIP_BDCHGIDX * SCIPvarGetLastBdchgIndex(SCIP_VAR *var)
Definition: var.c:16131
int SCIPvarGetNCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17521
SCIP_Real SCIPvarGetLPSol_rec(SCIP_VAR *var)
Definition: var.c:12375
SCIP_Real SCIPhistoryGetPseudocost(SCIP_HISTORY *history, SCIP_Real solvaldelta)
Definition: history.c:423
SCIP_VAR ** vars
Definition: struct_var.h:185
static void domMerge(SCIP_DOM *dom, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real *newlb, SCIP_Real *newub)
Definition: var.c:190
internal methods for branching and inference history
int nrootintfixings
Definition: struct_stat.h:201
int branchpriority
Definition: struct_var.h:260
SCIP_Real SCIPvarGetCutoffSumCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15519
int * SCIPvarGetImplIds(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17509
SCIP_HOLELIST * SCIPvarGetHolelistOriginal(SCIP_VAR *var)
Definition: var.c:17155
SCIP_RETCODE SCIPeventCreateObjChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldobj, SCIP_Real newobj)
Definition: event.c:557
internal methods for collecting primal CIP solutions and primal informations
SCIP_Real SCIPsolGetVal(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var)
Definition: sol.c:1286
static SCIP_RETCODE varParse(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, const char *str, char *name, SCIP_Real *lb, SCIP_Real *ub, SCIP_Real *obj, SCIP_VARTYPE *vartype, SCIP_Real *lazylb, SCIP_Real *lazyub, SCIP_Bool local, char **endptr, SCIP_Bool *success)
Definition: var.c:2262
SCIP_RETCODE SCIPvboundsAdd(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_BOUNDTYPE vboundtype, SCIP_VAR *var, SCIP_Real coef, SCIP_Real constant, SCIP_Bool *added)
Definition: implics.c:199
SCIP_DECL_HASHKEYVAL(SCIPvarGetHashkeyVal)
Definition: var.c:11306
SCIP_VAR * var
Definition: struct_var.h:177
#define SCIP_EVENTTYPE_LBCHANGED
Definition: type_event.h:104
SCIP_Real SCIPvarGetUbLP(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:12308
int nrootboundchgs
Definition: struct_stat.h:199
#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:5611
static SCIP_RETCODE varEventLbChanged(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real oldbound, SCIP_Real newbound)
Definition: var.c:7081
SCIP_HISTORY * glbhistorycrun
Definition: struct_stat.h:161
internal methods for propagators
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:16985
const char * SCIPgetProbName(SCIP *scip)
Definition: scip.c:10759
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2996
SCIP_Real SCIPvarGetVSIDSCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15231
void SCIPhistoryScaleVSIDS(SCIP_HISTORY *history, SCIP_Real scalar)
Definition: history.c:501
enum SCIP_BranchDir SCIP_BRANCHDIR
Definition: type_history.h:39
SCIP_Bool SCIPrealToRational(SCIP_Real val, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Longint *nominator, SCIP_Longint *denominator)
Definition: misc.c:8077
SCIP_Real SCIPvarGetNLPSol_rec(SCIP_VAR *var)
Definition: var.c:12447
int SCIPvarGetNBdchgInfosUb(SCIP_VAR *var)
Definition: var.c:17601
void SCIPcliquelistFree(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem)
Definition: implics.c:1417
SCIP_Real conflictrelaxedub
Definition: struct_var.h:215
SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
Definition: tree.c:7172
void SCIPvarSetCliqueComponentIdx(SCIP_VAR *var, int idx)
Definition: var.c:17658
SCIP_Bool SCIPbdchginfoIsTighter(SCIP_BDCHGINFO *bdchginfo1, SCIP_BDCHGINFO *bdchginfo2)
Definition: var.c:17944
unsigned int inferboundtype
Definition: struct_var.h:115
SCIP_RETCODE SCIPeventCreateVarFixed(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition: event.c:514
SCIP_RETCODE SCIPvarChgLbLocal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real newbound)
Definition: var.c:7501
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17179
union SCIP_Var::@12 data
SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5557
SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
Definition: var.c:11524
SCIP_Real SCIPvarGetObjLP(SCIP_VAR *var)
Definition: var.c:12192
SCIP_RETCODE SCIPvaluehistoryFind(SCIP_VALUEHISTORY *valuehistory, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real value, SCIP_HISTORY **history)
Definition: history.c:269
SCIP_RETCODE SCIPvarChgType(SCIP_VAR *var, SCIP_VARTYPE vartype)
Definition: var.c:5750
SCIP_Real SCIPvarGetBestRootLPObjval(SCIP_VAR *var)
Definition: var.c:13121
void SCIPvarSetHistory(SCIP_VAR *var, SCIP_HISTORY *history, SCIP_STAT *stat)
Definition: var.c:4217
static SCIP_RETCODE varProcessChgBranchFactor(SCIP_VAR *var, SCIP_SET *set, SCIP_Real branchfactor)
Definition: var.c:10806
SCIP_Real SCIPhistoryGetPseudocostVariance(SCIP_HISTORY *history, SCIP_BRANCHDIR direction)
Definition: history.c:437
SCIP_Real SCIPvarGetImplRedcost(SCIP_VAR *var, SCIP_SET *set, SCIP_Bool varfixing, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_LP *lp)
Definition: var.c:12771
SCIP_RETCODE SCIPstatUpdateVarRootLPBestEstimate(SCIP_STAT *stat, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldrootpscostscore)
Definition: stat.c:696
void SCIPvaluehistoryFree(SCIP_VALUEHISTORY **valuehistory, BMS_BLKMEM *blkmem)
Definition: history.c:247
SCIP_Real conflictrelaxedlb
Definition: struct_var.h:214
void SCIPvarSetDelorigData(SCIP_VAR *var, SCIP_DECL_VARDELORIG((*vardelorig)))
Definition: var.c:16596
enum SCIP_Confidencelevel SCIP_CONFIDENCELEVEL
Definition: type_misc.h:44
SCIP_RETCODE SCIPvarChgBranchPriority(SCIP_VAR *var, int branchpriority)
Definition: var.c:10996
SCIP_Real SCIPvarGetPseudocost(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition: var.c:13780
SCIP_AGGREGATE aggregate
Definition: struct_var.h:224
SCIP_Real lazylb
Definition: struct_var.h:216
#define BMSduplicateBlockMemoryArray(mem, ptr, source, num)
Definition: memory.h:420
SCIP_Real SCIPcolGetPrimsol(SCIP_COL *col)
Definition: lp.c:16115
static SCIP_RETCODE varEventUbChanged(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real oldbound, SCIP_Real newbound)
Definition: var.c:7119
SCIP_RETCODE SCIPdomchgApplyGlobal(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool *cutoff)
Definition: var.c:1306
SCIP_RETCODE SCIPeventfilterAdd(SCIP_EVENTFILTER *eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: event.c:1758
void SCIPvarSetDeltransData(SCIP_VAR *var, SCIP_DECL_VARDELTRANS((*vardeltrans)))
Definition: var.c:16620
SCIP_RETCODE SCIPvarChgUbLazy(SCIP_VAR *var, SCIP_SET *set, SCIP_Real lazyub)
Definition: var.c:7027
SCIP_Real SCIPvarGetBestBoundGlobal(SCIP_VAR *var)
Definition: var.c:17199
static SCIP_RETCODE varProcessChgUbLocal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real newbound)
Definition: var.c:7337
void SCIPvarMergeHistories(SCIP_VAR *targetvar, SCIP_VAR *othervar, SCIP_STAT *stat)
Definition: var.c:4201
void SCIPhistoryIncNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real length)
Definition: history.c:526
SCIP_BOUNDTYPE * SCIPimplicsGetTypes(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3264
internal methods for storing and manipulating the main problem
#define MAX_CLIQUELENGTH
Definition: var.c:12767
#define SCIPerrorMessage
Definition: pub_message.h:45
SCIP_Bool SCIPboundchgIsRedundant(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16492
void SCIPlpDecNLoosevars(SCIP_LP *lp)
Definition: lp.c:13750
SCIP_Real SCIPvarGetLbOriginal(SCIP_VAR *var)
Definition: var.c:17115
void SCIPcliqueDelVar(SCIP_CLIQUE *clique, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Bool value)
Definition: implics.c:1261
SCIP_RETCODE SCIPdomchgMakeStatic(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:1084
SCIP_VBOUNDS * vlbs
Definition: struct_var.h:236
SCIP_Bool SCIPlpIsDualReliable(SCIP_LP *lp)
Definition: lp.c:16879
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:16125
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:14232
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:909
SCIP_Longint lpcount
Definition: struct_stat.h:169
SCIP_Bool SCIPbdchgidxIsEarlierNonNull(SCIP_BDCHGIDX *bdchgidx1, SCIP_BDCHGIDX *bdchgidx2)
Definition: var.c:17731
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:626
SCIP_RETCODE SCIPvarChgObj(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PROB *prob, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_EVENTQUEUE *eventqueue, SCIP_Real newobj)
Definition: var.c:5801
int SCIPvarCompareActiveAndNegated(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11211
int lbchginfossize
Definition: struct_var.h:261
SCIP_Real SCIPvarGetAvgBranchdepthCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15137
unsigned int varstatus
Definition: struct_var.h:275
SCIP_RETCODE SCIPvarRelease(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:2765
SCIP_Real SCIPvarGetUbOriginal(SCIP_VAR *var)
Definition: var.c:17135
SCIP_Bool SCIPvarIsTransformedOrigvar(SCIP_VAR *var)
Definition: var.c:12167
SCIP_Real SCIPhistoryGetAvgBranchdepth(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:681
SCIP_Real bestrootlpobjval
Definition: struct_var.h:208
SCIP_VARDATA * vardata
Definition: struct_var.h:233
SCIPInterval sqrt(const SCIPInterval &x)
SCIP_RETCODE SCIPvarChgObjDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newobj)
Definition: var.c:5989
SCIP_EVENTTYPE eventmask
Definition: struct_event.h:180
SCIP_DECL_SORTPTRCOMP(SCIPvarCompActiveAndNegated)
Definition: var.c:11241
SCIP_Real SCIPvarGetPseudocostCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition: var.c:13829
SCIP_Real SCIPvarGetUbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15964
SCIP_Bool SCIPsortedvecFindPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), void *val, int len, int *pos)
SCIP_Real primsolavg
Definition: struct_var.h:211
void SCIPstrCopySection(const char *str, char startchar, char endchar, char *token, int size, char **endptr)
Definition: misc.c:9441
SCIP_Bool SCIPvarHasBinaryImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_Bool implvarfixing)
Definition: var.c:10476
SCIP_RETCODE SCIPvarGetTransformed(SCIP_VAR *origvar, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **transvar)
Definition: var.c:3371
SCIP_HOLECHG * holechgs
Definition: struct_var.h:143
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:7881
SCIP_Real * SCIPvarGetVubConstants(SCIP_VAR *var)
Definition: var.c:17435
static SCIP_RETCODE varProcessChgUbGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Real newbound)
Definition: var.c:6546
SCIP_OBJSENSE objsense
Definition: struct_prob.h:77
unsigned int pos
Definition: struct_var.h:112
static SCIP_RETCODE varSetName(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_STAT *stat, const char *name)
Definition: var.c:1823
SCIP_Real SCIPvarGetAggrConstant(SCIP_VAR *var)
Definition: var.c:16926
SCIP_Real SCIPcolGetLb(SCIP_COL *col)
Definition: lp.c:16082
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:155
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16555
static SCIP_RETCODE tryAggregateIntVars(SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_Real scalarx, SCIP_Real scalary, SCIP_Real rhs, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition: var.c:4714
SCIP_VAR * transvar
Definition: struct_var.h:169
SCIP_DOMCHGDYN domchgdyn
Definition: struct_var.h:154
#define MAXDNOM
SCIP_Real SCIPsetFeasCeil(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6093
void SCIPhistoryUnite(SCIP_HISTORY *history, SCIP_HISTORY *addhistory, SCIP_Bool switcheddirs)
Definition: history.c:96
void SCIPmessagePrintWarning(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
Definition: message.c:417
#define SCIPsetReallocBufferArray(set, ptr, num)
Definition: set.h:1838
SCIP_Longint SCIPhistoryGetNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:542
SCIP_RETCODE SCIPeventCreateLbChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition: event.c:626
SCIP_DECL_HASHGETKEY(SCIPvarGetHashkey)
Definition: var.c:11292
unsigned int initial
Definition: struct_var.h:269
#define NULL
Definition: lpi_spx1.cpp:137
void SCIPvarGetClosestVub(SCIP_VAR *var, SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *closestvub, int *closestvubidx)
Definition: var.c:13502
SCIP_NEGATE negate
Definition: struct_var.h:226
SCIP_RETCODE SCIPvarFlattenAggregationGraph(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: var.c:4143
static SCIP_RETCODE holelistCreate(SCIP_HOLELIST **holelist, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real left, SCIP_Real right)
Definition: var.c:74
static SCIP_RETCODE varProcessChgLbLocal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real newbound)
Definition: var.c:7172
SCIP_RETCODE SCIPvarSetRelaxSol(SCIP_VAR *var, SCIP_SET *set, SCIP_RELAXATION *relaxation, SCIP_Real solval, SCIP_Bool updateobj)
Definition: var.c:13167
SCIP_HISTORY * glbhistory
Definition: struct_stat.h:160
SCIP_Real SCIPboundchgGetNewbound(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16452
SCIP_Real * SCIPvboundsGetCoefs(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3230
#define REALABS(x)
Definition: def.h:169
int nparentvars
Definition: struct_var.h:256
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition: var.c:17543
SCIP_Real unchangedobj
Definition: struct_var.h:203
SCIP_RETCODE SCIPvarFix(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: var.c:3572
SCIP_HOLELIST * SCIPvarGetHolelistGlobal(SCIP_VAR *var)
Definition: var.c:17189
SCIP_RETCODE SCIPvarAddVlb(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR *vlbvar, SCIP_Real vlbcoef, SCIP_Real vlbconstant, SCIP_Bool transitive, SCIP_Bool *infeasible, int *nbdchgs)
Definition: var.c:9530
SCIP_Longint SCIPvarGetNActiveConflicts(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:14573
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:17039
SCIP_Real SCIPvarCalcPscostConfidenceBound(SCIP_VAR *var, SCIP_SET *set, SCIP_BRANCHDIR dir, SCIP_Bool onlycurrentrun, SCIP_CONFIDENCELEVEL clevel)
Definition: var.c:14050
#define SCIP_CALL(x)
Definition: def.h:316
SCIP_Bool SCIPbdchginfoHasInferenceReason(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17930
SCIP_VBOUNDS * vubs
Definition: struct_var.h:237
SCIP_Real SCIPvarGetLbLazy(SCIP_VAR *var)
Definition: var.c:17307
SCIP_Bool SCIPsetIsFeasGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6003
SCIP_Real * SCIPvarGetVlbConstants(SCIP_VAR *var)
Definition: var.c:17393
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:14752
SCIP_Real SCIPvarGetMultaggrConstant(SCIP_VAR *var)
Definition: var.c:16973
int SCIPprobGetNContVars(SCIP_PROB *prob)
Definition: prob.c:2283
SCIP_Real SCIPvarGetPseudocostCount(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:13876
static SCIP_RETCODE varAddTransitiveBinaryClosureImplic(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_Bool implvarfixing, SCIP_Bool *infeasible, int *nbdchgs)
Definition: var.c:9249
static SCIP_VAR * varGetActiveVar(SCIP_VAR *var)
Definition: var.c:5443
SCIP_Real * SCIPvboundsGetConstants(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3238
SCIP_Real SCIPvarGetCutoffSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15476
SCIP_Real * SCIPvarGetVubCoefs(SCIP_VAR *var)
Definition: var.c:17425
SCIP_Bool SCIPbdchginfoIsRedundant(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17919
int closestvubidx
Definition: struct_var.h:268
internal methods for relaxators
SCIP_Real SCIPvarGetMinPseudocostScore(SCIP_VAR *var, SCIP_STAT *stat, SCIP_SET *set, SCIP_Real solval)
Definition: var.c:13964
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:5539
static SCIP_RETCODE varProcessChgBranchPriority(SCIP_VAR *var, int branchpriority)
Definition: var.c:10940
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:7627
#define SCIPdebugCheckLbGlobal(scip, var, lb)
Definition: debug.h:254
unsigned int nboundchgs
Definition: struct_var.h:140
SCIP_BDCHGIDX * SCIPbdchginfoGetIdx(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17841
SCIP_Longint SCIPvarGetNActiveConflictsCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:14620
SCIP_RETCODE SCIPvarPrint(SCIP_VAR *var, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: var.c:2886
unsigned int branchdirection
Definition: struct_var.h:277
int ubchginfossize
Definition: struct_var.h:263
SCIP_Bool SCIPcliquelistsHaveCommonClique(SCIP_CLIQUELIST *cliquelist1, SCIP_Bool value1, SCIP_CLIQUELIST *cliquelist2, SCIP_Bool value2)
Definition: implics.c:1581
SCIP_Bool SCIPsetIsFeasLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5959
#define SCIPdebugCheckUbGlobal(scip, var, ub)
Definition: debug.h:255
#define SCIP_EVENTTYPE_UBCHANGED
Definition: type_event.h:105
void SCIPvboundsShrink(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem, int newnvbds)
Definition: implics.c:326
void SCIPvarSetBestRootSol(SCIP_VAR *var, SCIP_Real rootsol, SCIP_Real rootredcost, SCIP_Real rootlpobjval)
Definition: var.c:13152
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:6086
#define BMSfreeBlockMemory(mem, ptr)
Definition: memory.h:423
data structures and methods for collecting reoptimization information
internal methods for problem variables
SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
Definition: var.c:16684
static SCIP_RETCODE varEventObjChanged(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_EVENTQUEUE *eventqueue, SCIP_Real oldobj, SCIP_Real newobj)
Definition: var.c:5774
SCIP_RETCODE SCIPvarChgBranchFactor(SCIP_VAR *var, SCIP_SET *set, SCIP_Real branchfactor)
Definition: var.c:10870
SCIP_RETCODE SCIPvarTryAggregateVars(SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_Real scalarx, SCIP_Real scalary, SCIP_Real rhs, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition: var.c:4937
#define SCIP_UNKNOWN
Definition: def.h:166
SCIP_Bool SCIPsetIsIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5662
unsigned int vartype
Definition: struct_var.h:274
SCIP_BOUNDTYPE * SCIPvarGetImplTypes(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17479
int clqcomponentidx
Definition: struct_var.h:247
unsigned int boundchgtype
Definition: struct_var.h:90
#define BMSfreeBlockMemorySize(mem, ptr, size)
Definition: memory.h:427
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:14920
static SCIP_RETCODE varEventGlbChanged(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real oldbound, SCIP_Real newbound)
Definition: var.c:6221
SCIP_VAR * var
Definition: struct_var.h:89
SCIP_INFERENCEDATA inferencedata
Definition: struct_var.h:87
SCIP_Real SCIPholelistGetRight(SCIP_HOLELIST *holelist)
Definition: var.c:16532
static SCIP_RETCODE varProcessAddHoleLocal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_Real left, SCIP_Real right, SCIP_Bool *added)
Definition: var.c:8522
#define SCIP_Bool
Definition: def.h:61
void SCIPvarCapture(SCIP_VAR *var)
Definition: var.c:2753
int SCIPvarGetCliqueComponentIdx(SCIP_VAR *var)
Definition: var.c:17649
#define BMSreallocBlockMemorySize(mem, ptr, oldsize, newsize)
Definition: memory.h:414
SCIP_BOUNDCHGTYPE SCIPboundchgGetBoundchgtype(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16472
SCIP_Real ub
Definition: struct_var.h:161
unsigned int boundtype
Definition: struct_var.h:91
int SCIPbdchginfoGetPos(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17831
unsigned int deletable
Definition: struct_var.h:271
enum SCIP_Objsense SCIP_OBJSENSE
Definition: type_prob.h:41
SCIP_Bool SCIPvarWasFixedEarlier(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:16256
SCIP_Real SCIPvarGetInferenceSumCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15321
SCIP_Bool SCIPvarIsInLP(SCIP_VAR *var)
Definition: var.c:16894
SCIP_RETCODE SCIPvarRemove(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_CLIQUETABLE *cliquetable, SCIP_SET *set, SCIP_Bool final)
Definition: var.c:5668
SCIP_RETCODE SCIPconsRelease(SCIP_CONS **cons, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: cons.c:6112
void SCIPvarStoreRootSol(SCIP_VAR *var, SCIP_Bool roothaslp)
Definition: var.c:12573
SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
Definition: var.c:17556
int SCIPvarGetBranchPriority(SCIP_VAR *var)
Definition: var.c:17341
int SCIPgetDepth(SCIP *scip)
Definition: scip.c:42321
SCIP_Real SCIPvarGetLbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15840
SCIP_Bool divingobjchg
Definition: struct_lp.h:359
int SCIPvarGetNImpls(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17447
SCIP_MULTAGGR multaggr
Definition: struct_var.h:225
SCIP_RETCODE SCIPvarChgUbDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newbound)
Definition: var.c:7868
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition: memory.h:425
SCIP_RETCODE SCIPeventCreateGlbChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition: event.c:580
unsigned int deleted
Definition: struct_var.h:272
int * SCIPimplicsGetIds(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3285
SCIP_VARDATA * SCIPvarGetData(SCIP_VAR *var)
Definition: var.c:16575
SCIP_RETCODE SCIPcolChgLb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newlb)
Definition: lp.c:3626
int SCIPvarGetNLocksUp(SCIP_VAR *var)
Definition: var.c:3217
#define MAX(x, y)
Definition: tclique_def.h:75
SCIP_Bool SCIPstrToRealValue(const char *str, SCIP_Real *value, char **endptr)
Definition: misc.c:9411
int SCIPimplicsGetNImpls(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3246
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:16462
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11249
methods for debugging
SCIP_Bool * SCIPcliqueGetValues(SCIP_CLIQUE *clique)
Definition: implics.c:3316
SCIP_BOUNDCHG * SCIPdomchgGetBoundchg(SCIP_DOMCHG *domchg, int pos)
Definition: var.c:16510
SCIP_Real SCIPvarGetUnchangedObj(SCIP_VAR *var)
Definition: var.c:17027
unsigned int removable
Definition: struct_var.h:270
#define SCIPsetDebugMsg
Definition: set.h:1870
static SCIP_RETCODE varAddParent(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_VAR *parentvar)
Definition: var.c:2551
SCIP_Real SCIPvarGetMultaggrUbGlobal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8161
unsigned int redundant
Definition: struct_var.h:94
SCIP_Real oldbound
Definition: struct_var.h:107
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17017
SCIP_RETCODE SCIPvarAddCliqueToList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:10703
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17781
SCIP_Real SCIPvarGetBestRootRedcost(SCIP_VAR *var)
Definition: var.c:13087
SCIP_VAR * SCIPvarGetAggrVar(SCIP_VAR *var)
Definition: var.c:16904
int closestvlbidx
Definition: struct_var.h:267
#define EPSLE(x, y, eps)
Definition: def.h:172
int nuses
Definition: struct_var.h:257
SCIP_Real SCIPvarGetAvgInferencesCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15421
SCIP_RETCODE SCIPvarFixBinary(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool value, SCIP_Bool *infeasible, int *nbdchgs)
Definition: var.c:10489
SCIP_Real SCIPcomputeTwoSampleTTestValue(SCIP_Real meanx, SCIP_Real meany, SCIP_Real variancex, SCIP_Real variancey, SCIP_Real countx, SCIP_Real county)
Definition: misc.c:111
SCIP_RETCODE SCIPvarDelClique(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:10742
#define SCIP_EVENTTYPE_GHOLEADDED
Definition: type_event.h:67
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:93
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:16883
int probindex
Definition: struct_var.h:250
static SCIP_RETCODE varProcessAddHoleGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_Real left, SCIP_Real right, SCIP_Bool *added)
Definition: var.c:8274
SCIP_RETCODE SCIPvarCopy(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP *sourcescip, SCIP_VAR *sourcevar, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global)
Definition: var.c:2078
SCIP_Real SCIPvarGetRelaxSol(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:13228
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:16937
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:17493
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12080
SCIP_Bool SCIPsetIsFeasLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5937
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:2260
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:14492
static SCIP_RETCODE varAddImplic(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool isshortcut, SCIP_Bool *infeasible, int *nbdchgs, SCIP_Bool *added)
Definition: var.c:9041
SCIP_NODE * SCIPgetFocusNode(SCIP *scip)
Definition: scip.c:40661
SCIP_RETCODE SCIPcolChgUb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newub)
Definition: lp.c:3671
SCIP_RETCODE SCIPcolFree(SCIP_COL **col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: lp.c:3246
SCIP * scip
Definition: struct_var.h:200
SCIP_EVENTFILTER * eventfilter
Definition: struct_var.h:240
static SCIP_Real SCIPvarGetPseudoSol_rec(SCIP_VAR *var)
Definition: var.c:12495
int nlocksup
Definition: struct_var.h:259
SCIP_BDCHGINFO * SCIPvarGetLbchgInfo(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15707
SCIP_Bool SCIPprobIsTransformed(SCIP_PROB *prob)
Definition: prob.c:2182
SCIP_BOUNDTYPE SCIPbdchginfoGetInferBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17898
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:15763
int conflictubcount
Definition: struct_var.h:266
int SCIPvboundsGetNVbds(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3214
SCIP_RETCODE SCIPvarGetProbvarBound(SCIP_VAR **var, SCIP_Real *bound, SCIP_BOUNDTYPE *boundtype)
Definition: var.c:11775
static SCIP_RETCODE parseValue(SCIP_SET *set, const char *str, SCIP_Real *value, char **endptr)
Definition: var.c:2190
SCIP_DOM locdom
Definition: struct_var.h:219
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoUb(SCIP_VAR *var, int pos)
Definition: var.c:17589
static SCIP_RETCODE varAddTransitiveImplic(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool transitive, SCIP_Bool *infeasible, int *nbdchgs)
Definition: var.c:9322
SCIP_BDCHGINFO * SCIPvarGetBdchgInfo(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15819
#define SCIP_REAL_MAX
Definition: def.h:146
SCIP_Bool SCIPsetIsDualfeasPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6247
SCIP_VALUEHISTORY * valuehistory
Definition: struct_var.h:245
static void printBounds(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, FILE *file, SCIP_Real lb, SCIP_Real ub, const char *name)
Definition: var.c:2823
static SCIP_RETCODE varAddLbchginfo(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real oldbound, SCIP_Real newbound, int depth, int pos, SCIP_VAR *infervar, SCIP_CONS *infercons, SCIP_PROP *inferprop, int inferinfo, SCIP_BOUNDTYPE inferboundtype, SCIP_BOUNDCHGTYPE boundchgtype)
Definition: var.c:401
#define SCIP_DECL_VARDELORIG(x)
Definition: type_var.h:109
SCIP_Real SCIPhistoryGetCutoffSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:655
SCIP_RETCODE SCIPvarAddToRow(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *prob, SCIP_LP *lp, SCIP_ROW *row, SCIP_Real val)
Definition: var.c:13574
SCIP_RETCODE SCIPvarLoose(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *prob, SCIP_LP *lp)
Definition: var.c:3436
SCIP_Real newbound
Definition: struct_var.h:83
#define SCIP_REAL_MIN
Definition: def.h:147
static SCIP_RETCODE varEventVarFixed(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, int fixeventtype)
Definition: var.c:3477
SCIP_VAR ** parentvars
Definition: struct_var.h:234
SCIP_BRANCHDIR SCIPbranchdirOpposite(SCIP_BRANCHDIR dir)
Definition: history.c:414
SCIP_VAR ** SCIPvarGetImplVars(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17464
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:6082
SCIP_DOMCHGBOUND domchgbound
Definition: struct_var.h:152
SCIP_RETCODE SCIPvarChgBdGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype)
Definition: var.c:7053
#define SCIP_DEFAULT_INFINITY
Definition: def.h:150
static SCIP_RETCODE domchgEnsureHolechgsSize(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: var.c:1198
int SCIPvarGetNLocksDown(SCIP_VAR *var)
Definition: var.c:3162
SCIP_Real SCIPstudentTGetCriticalValue(SCIP_CONFIDENCELEVEL clevel, int df)
Definition: misc.c:94
SCIP_HOLELIST * next
Definition: struct_var.h:51
void SCIPconsCapture(SCIP_CONS *cons)
Definition: cons.c:6100
SCIP_Real SCIPhistoryGetInferenceSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:629
#define BMSallocBlockMemorySize(mem, ptr, size)
Definition: memory.h:411
unsigned int boundtype
Definition: struct_var.h:114
#define SCIPsetFreeCleanBufferArray(set, ptr)
Definition: set.h:1848
void SCIPrelaxationSolObjAdd(SCIP_RELAXATION *relaxation, SCIP_Real val)
Definition: relax.c:706
static const SCIP_Real scalars[]
Definition: lp.c:5573
SCIP_RETCODE SCIPvarMultiaggregate(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, int naggvars, SCIP_VAR **aggvars, SCIP_Real *scalars, SCIP_Real constant, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition: var.c:5100
int lpipos
Definition: struct_lp.h:164
SCIP_NODE * SCIPtreeGetRootNode(SCIP_TREE *tree)
Definition: tree.c:8182
int SCIPdomchgGetNBoundchgs(SCIP_DOMCHG *domchg)
Definition: var.c:16502
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:2001
SCIP_Real lazyub
Definition: struct_var.h:217
int SCIPbdchginfoGetDepth(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17821
SCIP_RETCODE SCIPeventfilterFree(SCIP_EVENTFILTER **eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: event.c:1718
#define SCIP_EVENTTYPE_FORMAT
Definition: type_event.h:135
unsigned int redundant
Definition: struct_var.h:116
SCIP_MESSAGEHDLR * messagehdlr
Definition: struct_visual.h:44
SCIP_RETCODE SCIPvarGetActiveRepresentatives(SCIP_SET *set, SCIP_VAR **vars, SCIP_Real *scalars, int *nvars, int varssize, SCIP_Real *constant, int *requiredsize, SCIP_Bool mergemultiples)
Definition: var.c:3741
SCIP_Real SCIPnormalCDF(SCIP_Real mean, SCIP_Real variance, SCIP_Real value)
Definition: misc.c:184
SCIP_Bool SCIPvarSignificantPscostDifference(SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *varx, SCIP_Real fracx, SCIP_VAR *vary, SCIP_Real fracy, SCIP_BRANCHDIR dir, SCIP_CONFIDENCELEVEL clevel, SCIP_Bool onesided)
Definition: var.c:14165
SCIP_DECL_HASHKEYEQ(SCIPvarIsHashkeyEq)
Definition: var.c:11298
SCIP_Real SCIPvarGetBestRootSol(SCIP_VAR *var)
Definition: var.c:13021
SCIP_VAR * var
Definition: struct_var.h:109
public methods for message output
int nrootboundchgsrun
Definition: struct_stat.h:200
void SCIPcliquelistCheck(SCIP_CLIQUELIST *cliquelist, SCIP_VAR *var)
Definition: implics.c:3374
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:16631
static SCIP_RETCODE varAddVbound(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_BOUNDTYPE vbtype, SCIP_VAR *vbvar, SCIP_Real vbcoef, SCIP_Real vbconstant)
Definition: var.c:8813
SCIP_Real * scalars
Definition: struct_var.h:184
SCIP_IMPLICS * implics
Definition: struct_var.h:238
SCIP_Real SCIPholelistGetLeft(SCIP_HOLELIST *holelist)
Definition: var.c:16522
SCIP_Bool SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5593
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:16674
SCIP_RETCODE SCIPvarResetBounds(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat)
Definition: var.c:8760
static SCIP_RETCODE domAddHole(SCIP_DOM *dom, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real left, SCIP_Real right, SCIP_Bool *added)
Definition: var.c:146
static SCIP_RETCODE applyImplic(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool *infeasible, int *nbdchgs)
Definition: var.c:8942
#define SCIP_Real
Definition: def.h:145
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:15004
SCIP_RETCODE SCIPvarsGetProbvarBinary(SCIP_VAR ***vars, SCIP_Bool **negatedarr, int nvars)
Definition: var.c:11584
SCIP_VAR * SCIPbdchginfoGetInferVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17851
#define MIN(x, y)
Definition: memory.c:75
SCIP_Bool SCIPsetIsFeasPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6036
int parentvarssize
Definition: struct_var.h:255
SCIP_CLIQUELIST * cliquelist
Definition: struct_var.h:239
SCIP_RETCODE SCIPvarSetInitial(SCIP_VAR *var, SCIP_Bool initial)
Definition: var.c:16642
SCIP_VAR ** SCIPprobGetVars(SCIP_PROB *prob)
Definition: prob.c:2292
SCIP_RETCODE SCIPvarGetProbvarHole(SCIP_VAR **var, SCIP_Real *left, SCIP_Real *right)
Definition: var.c:11868
SCIP_RETCODE SCIPlpUpdateVarLoose(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:13729
SCIP_Real SCIPvarGetVSIDS(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:17634
#define SCIP_INVALID
Definition: def.h:165
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:16565
void SCIPvarsGetProbvar(SCIP_VAR **vars, int nvars)
Definition: var.c:11504
SCIP_RETCODE SCIPvarParseTransformed(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, const char *str, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARCOPY((*varcopy)), SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_VARDATA *vardata, char **endptr, SCIP_Bool *success)
Definition: var.c:2468
static SCIP_RETCODE parseBounds(SCIP_SET *set, const char *str, char *type, SCIP_Real *lb, SCIP_Real *ub, char **endptr)
Definition: var.c:2219
SCIP_VAR ** SCIPvarGetVubVars(SCIP_VAR *var)
Definition: var.c:17415
SCIP_RETCODE SCIPeventCreateVarUnlocked(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition: event.c:536
SCIP_RETCODE SCIPprimalUpdateObjoffset(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp)
Definition: primal.c:441
SCIP_Real branchfactor
Definition: struct_var.h:204
unsigned int donotmultaggr
Definition: struct_var.h:273
#define SCIP_Longint
Definition: def.h:130
SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
Definition: var.c:17281
SCIP_CONS * SCIPbdchginfoGetInferCons(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17863
SCIP_Bool SCIPsetIsDualfeasZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6236
SCIP_Real SCIPvarGetAvgSol(SCIP_VAR *var)
Definition: var.c:13367
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:16852
SCIP_Real nlpsol
Definition: struct_var.h:210
SCIP_VAR * lastbranchvar
Definition: struct_stat.h:162
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:15562
SCIP_Real lb
Definition: struct_var.h:160
SCIP_VAR * var
Definition: struct_lp.h:151
SCIP_Bool SCIPsetIsFeasGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5981
SCIP_RETCODE SCIPvarAddHoleLocal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_Real left, SCIP_Real right, SCIP_Bool *added)
Definition: var.c:8651
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16720
SCIP_Real SCIPvarGetMultaggrUbLocal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8029
SCIP_RETCODE SCIPvarChgName(SCIP_VAR *var, BMS_BLKMEM *blkmem, const char *name)
Definition: var.c:2792
SCIP_DOM glbdom
Definition: struct_var.h:218
SCIP_Real SCIPsetEpsilon(SCIP_SET *set)
Definition: set.c:5401
SCIP_Real SCIPhistoryGetAvgInferences(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:642
SCIP_STAGE SCIPsetGetStage(SCIP_SET *set)
Definition: set.c:2664
enum SCIP_Vartype SCIP_VARTYPE
Definition: type_var.h:60
static SCIP_RETCODE varEventGubChanged(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real oldbound, SCIP_Real newbound)
Definition: var.c:6259
SCIP_Bool collectvarhistory
Definition: struct_stat.h:257
SCIP_VAR * negatedvar
Definition: struct_var.h:235
SCIP_Bool SCIPvarIsMarkedDeleteGlobalStructures(SCIP_VAR *var)
Definition: var.c:16822
SCIP_Bool SCIPcliqueIsCleanedUp(SCIP_CLIQUE *clique)
Definition: implics.c:3336
SCIP_Real newbound
Definition: struct_var.h:108
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17235
int nlocksdown
Definition: struct_var.h:258
int SCIPcliqueGetNVars(SCIP_CLIQUE *clique)
Definition: implics.c:3294
SCIP_RETCODE SCIPvarAddHoleOriginal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real left, SCIP_Real right)
Definition: var.c:8222
void SCIPbdchginfoFree(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem)
Definition: var.c:15693
void SCIPvarAdjustUb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *ub)
Definition: var.c:6069
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:16697
static void varIncRootboundchgs(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat)
Definition: var.c:6329
#define BMSallocBlockMemory(mem, ptr)
Definition: memory.h:410
SCIP_HOLELIST * SCIPvarGetHolelistLocal(SCIP_VAR *var)
Definition: var.c:17245
unsigned int delglobalstructs
Definition: struct_var.h:279
SCIP_Bool SCIPsetIsDualfeasNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6258
SCIP_BOUNDTYPE SCIPbdchginfoGetBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17811
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:17696
SCIP_Real rootsol
Definition: struct_var.h:205
SCIP_Bool SCIPeventqueueIsDelayed(SCIP_EVENTQUEUE *eventqueue)
Definition: event.c:2435
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:2845
SCIP_RETCODE SCIPlpUpdateVarColumn(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:13605
SCIP_HISTORY * history
Definition: struct_var.h:243
common defines and data types used in all packages of SCIP
SCIP_RETCODE SCIPvarSetRemovable(SCIP_VAR *var, SCIP_Bool removable)
Definition: var.c:16658
SCIP_Real SCIPvarGetVSIDS_rec(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15182
int nrootintfixingsrun
Definition: struct_stat.h:202
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:396
SCIP_RETCODE SCIPvarGetProbvarSum(SCIP_VAR **var, SCIP_SET *set, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:11953
#define SCIP_EVENTTYPE_GUBCHANGED
Definition: type_event.h:62
#define SCIP_CALL_ABORT(x)
Definition: def.h:295
SCIP_Real SCIPvarGetPseudoSol(SCIP_VAR *var)
Definition: var.c:17621
enum SCIP_BoundchgType SCIP_BOUNDCHGTYPE
Definition: type_var.h:78
SCIP_Real * SCIPimplicsGetBounds(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3273
SCIP_ORIGINAL original
Definition: struct_var.h:222
SCIP_Real SCIPcolGetRedcost(SCIP_COL *col, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:3821
SCIP_VAR * SCIPvarGetTransVar(SCIP_VAR *var)
Definition: var.c:16872
#define SCIP_ALLOC(x)
Definition: def.h:327
#define SCIPABORT()
Definition: def.h:288
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:16746
SCIP_RETCODE SCIPeventCreateGubChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition: event.c:603
void SCIPhistoryFree(SCIP_HISTORY **history, BMS_BLKMEM *blkmem)
Definition: history.c:55
SCIP_Real SCIPvarGetMultaggrLbLocal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:7963
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:7945
unsigned int applied
Definition: struct_var.h:93
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition: var.c:16776
void SCIPvboundsFree(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem)
Definition: implics.c:66
SCIP_RETCODE SCIPvarsAddClique(SCIP_VAR **vars, SCIP_Bool *values, int nvars, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_CLIQUE *clique)
Definition: var.c:10665
SCIP_HOLELIST ** ptr
Definition: struct_var.h:57
#define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
Definition: memory.h:416
SCIP_BOUNDCHG * boundchgs
Definition: struct_var.h:142
void SCIPvarMarkDeleted(SCIP_VAR *var)
Definition: var.c:5704
void SCIPvarSetData(SCIP_VAR *var, SCIP_VARDATA *vardata)
Definition: var.c:16585
SCIP_Bool SCIPcolIsInLP(SCIP_COL *col)
Definition: lp.c:16224
SCIP_COL * col
Definition: struct_var.h:223
SCIP_RETCODE SCIPvarNegate(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **negvar)
Definition: var.c:5527
SCIP_Real left
Definition: struct_var.h:43
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:8056
SCIP_RETCODE SCIPdomchgAddBoundchg(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_VAR *var, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype, SCIP_BOUNDCHGTYPE boundchgtype, SCIP_Real lpsolval, SCIP_VAR *infervar, SCIP_CONS *infercons, SCIP_PROP *inferprop, int inferinfo, SCIP_BOUNDTYPE inferboundtype)
Definition: var.c:1345
SCIP_Bool SCIPvarMayRoundUp(SCIP_VAR *var)
Definition: var.c:3280
#define EPSZ(x, eps)
Definition: def.h:175
void SCIPimplicsFree(SCIP_IMPLICS **implics, BMS_BLKMEM *blkmem)
Definition: implics.c:444
static SCIP_RETCODE varProcessChgBranchDirection(SCIP_VAR *var, SCIP_BRANCHDIR branchdirection)
Definition: var.c:11059
SCIP_Bool SCIPvarMayRoundDown(SCIP_VAR *var)
Definition: var.c:3272
SCIP_RETCODE SCIPprobAddVar(SCIP_PROB *prob, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR *var)
Definition: prob.c:914
SCIP callable library.
SCIP_Bool SCIPsetIsFeasNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6047
SCIP_Real SCIPvarGetPseudocostVariance(SCIP_VAR *var, SCIP_BRANCHDIR dir, SCIP_Bool onlycurrentrun)
Definition: var.c:13996
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:16842
SCIP_Real objscale
Definition: struct_prob.h:42
SCIP_BDCHGINFO * lbchginfos
Definition: struct_var.h:241
static SCIP_RETCODE findValuehistoryEntry(SCIP_VAR *var, SCIP_Real value, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HISTORY **history)
Definition: var.c:14301
SCIP_RETCODE SCIPcliquelistDel(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: implics.c:1503
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:16710
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:5470
SCIP_Real scalar
Definition: struct_var.h:175
uint64_t SCIP_EVENTTYPE
Definition: type_event.h:134
void SCIPvarMarkDeleteGlobalStructures(SCIP_VAR *var)
Definition: var.c:16812
SCIP_BOUNDCHGTYPE SCIPbdchginfoGetChgtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17801
SCIP_RETCODE SCIPvarDelCliqueFromList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:10725