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-2022 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not visit scipopt.org. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file var.c
17  * @ingroup OTHER_CFILES
18  * @brief methods for problem variables
19  * @author Tobias Achterberg
20  * @author Timo Berthold
21  * @author Gerald Gamrath
22  * @author Stefan Heinz
23  * @author Marc Pfetsch
24  * @author Michael Winkler
25  * @author Kati Wolter
26  * @author Stefan Vigerske
27  *
28  * @todo Possibly implement the access of bounds of multi-aggregated variables by accessing the
29  * corresponding linear constraint if it exists. This seems to require some work, since the linear
30  * constraint has to be stored. Moreover, it has even to be created in case the original constraint
31  * was deleted after multi-aggregation, but the bounds of the multi-aggregated variable should be
32  * changed. This has to be done with care in order to not loose the performance gains of
33  * multi-aggregation.
34  */
35 
36 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
37 
38 #include "scip/cons.h"
39 #include "scip/event.h"
40 #include "scip/history.h"
41 #include "scip/implics.h"
42 #include "scip/lp.h"
43 #include "scip/primal.h"
44 #include "scip/prob.h"
45 #include "scip/pub_cons.h"
46 #include "scip/pub_history.h"
47 #include "scip/pub_implics.h"
48 #include "scip/pub_lp.h"
49 #include "scip/pub_message.h"
50 #include "scip/pub_misc.h"
51 #include "scip/pub_misc_sort.h"
52 #include "scip/pub_prop.h"
53 #include "scip/pub_var.h"
54 #include "scip/relax.h"
55 #include "scip/set.h"
56 #include "scip/sol.h"
57 #include "scip/stat.h"
58 #include "scip/struct_event.h"
59 #include "scip/struct_lp.h"
60 #include "scip/struct_prob.h"
61 #include "scip/struct_set.h"
62 #include "scip/struct_stat.h"
63 #include "scip/struct_var.h"
64 #include "scip/tree.h"
65 #include "scip/var.h"
66 #include <string.h>
67 
68 #define MAXIMPLSCLOSURE 100 /**< maximal number of descendants of implied variable for building closure
69  * in implication graph */
70 #define MAXABSVBCOEF 1e+5 /**< maximal absolute coefficient in variable bounds added due to implications */
71 
72 
73 /*
74  * Debugging variable release and capture
75  *
76  * Define DEBUGUSES_VARNAME to the name of the variable for which to print
77  * a backtrace when it is captured and released.
78  * Optionally define DEBUGUSES_PROBNAME to the name of a SCIP problem to consider.
79  * Have DEBUGUSES_NOADDR2LINE defined if you do not have addr2line installed on your system.
80  */
81 /* #define DEBUGUSES_VARNAME "t_t_b7" */
82 /* #define DEBUGUSES_PROBNAME "t_st_e35_rens" */
83 /* #define DEBUGUSES_NOADDR2LINE */
84 
85 #ifdef DEBUGUSES_VARNAME
86 #include <execinfo.h>
87 #include <stdio.h>
88 #include <stdlib.h>
89 #include "scip/struct_scip.h"
90 
91 /** obtains a backtrace and prints it to stdout. */
92 static
93 void print_backtrace(void)
94 {
95  void* array[10];
96  char** strings;
97  int size;
98  int i;
99 
100  size = backtrace(array, 10);
101  strings = backtrace_symbols(array, size);
102  if( strings == NULL )
103  return;
104 
105  /* skip first entry, which is the print_backtrace function */
106  for( i = 1; i < size; ++i )
107  {
108  /* if string is something like
109  * /path/to/scip/bin/../lib/shared/libscip-7.0.1.3.linux.x86_64.gnu.dbg.so(+0x2675dd3)
110  * (that is, no function name because it is a inlined function), then call
111  * addr2line -e <libname> <addr> to get func and code line
112  * dladdr() may be an alternative
113  */
114  char* openpar;
115  char* closepar = NULL;
116 #ifndef DEBUGUSES_NOADDR2LINE
117  openpar = strchr(strings[i], '(');
118  if( openpar != NULL && openpar[1] == '+' )
119  closepar = strchr(openpar+2, ')');
120 #endif
121  if( closepar != NULL )
122  {
123  char cmd[SCIP_MAXSTRLEN];
124  (void) SCIPsnprintf(cmd, SCIP_MAXSTRLEN, "addr2line -f -p -e \"%.*s\" %.*s", openpar - strings[i], strings[i], closepar-openpar-1, openpar+1);
125  printf(" ");
126  fflush(stdout);
127  system(cmd);
128  }
129  else
130  printf(" %s\n", strings[i]);
131  }
132 
133  free(strings);
134 }
135 #endif
136 
137 /*
138  * hole, holelist, and domain methods
139  */
140 
141 /** creates a new holelist element */
142 static
144  SCIP_HOLELIST** holelist, /**< pointer to holelist to create */
145  BMS_BLKMEM* blkmem, /**< block memory for target holelist */
146  SCIP_SET* set, /**< global SCIP settings */
147  SCIP_Real left, /**< left bound of open interval in new hole */
148  SCIP_Real right /**< right bound of open interval in new hole */
149  )
150 {
151  assert(holelist != NULL);
152  assert(blkmem != NULL);
153  assert(SCIPsetIsLT(set, left, right));
154 
155  SCIPsetDebugMsg(set, "create hole list element (%.15g,%.15g) in blkmem %p\n", left, right, (void*)blkmem);
156 
157  SCIP_ALLOC( BMSallocBlockMemory(blkmem, holelist) );
158  (*holelist)->hole.left = left;
159  (*holelist)->hole.right = right;
160  (*holelist)->next = NULL;
161 
162  return SCIP_OKAY;
163 }
164 
165 /** frees all elements in the holelist */
166 static
167 void holelistFree(
168  SCIP_HOLELIST** holelist, /**< pointer to holelist to free */
169  BMS_BLKMEM* blkmem /**< block memory for target holelist */
170  )
171 {
172  assert(holelist != NULL);
173  assert(blkmem != NULL);
174 
175  while( *holelist != NULL )
176  {
177  SCIP_HOLELIST* next;
178 
179  SCIPdebugMessage("free hole list element (%.15g,%.15g) in blkmem %p\n",
180  (*holelist)->hole.left, (*holelist)->hole.right, (void*)blkmem);
181 
182  next = (*holelist)->next;
183  BMSfreeBlockMemory(blkmem, holelist);
184  assert(*holelist == NULL);
185 
186  *holelist = next;
187  }
188  assert(*holelist == NULL);
189 }
190 
191 /** duplicates a list of holes */
192 static
194  SCIP_HOLELIST** target, /**< pointer to target holelist */
195  BMS_BLKMEM* blkmem, /**< block memory for target holelist */
196  SCIP_SET* set, /**< global SCIP settings */
197  SCIP_HOLELIST* source /**< holelist to duplicate */
198  )
199 {
200  assert(target != NULL);
201 
202  while( source != NULL )
203  {
204  assert(source->next == NULL || SCIPsetIsGE(set, source->next->hole.left, source->hole.right));
205  SCIP_CALL( holelistCreate(target, blkmem, set, source->hole.left, source->hole.right) );
206  source = source->next;
207  target = &(*target)->next;
208  }
209 
210  return SCIP_OKAY;
211 }
212 
213 /** adds a hole to the domain */
214 static
216  SCIP_DOM* dom, /**< domain to add hole to */
217  BMS_BLKMEM* blkmem, /**< block memory */
218  SCIP_SET* set, /**< global SCIP settings */
219  SCIP_Real left, /**< left bound of open interval in new hole */
220  SCIP_Real right, /**< right bound of open interval in new hole */
221  SCIP_Bool* added /**< pointer to store whether the hole was added (variable didn't had that hole before), or NULL */
222  )
223 {
224  SCIP_HOLELIST** insertpos;
225  SCIP_HOLELIST* next;
226 
227  assert(dom != NULL);
228  assert(added != NULL);
229 
230  /* search for the position of the new hole */
231  insertpos = &dom->holelist;
232  while( *insertpos != NULL && (*insertpos)->hole.left < left )
233  insertpos = &(*insertpos)->next;
234 
235  /* check if new hole already exists in the hole list or is a sub hole of an existing one */
236  if( *insertpos != NULL && (*insertpos)->hole.left == left && (*insertpos)->hole.right >= right ) /*lint !e777 */
237  {
238  SCIPsetDebugMsg(set, "new hole (%.15g,%.15g) is redundant through known hole (%.15g,%.15g)\n",
239  left, right, (*insertpos)->hole.left, (*insertpos)->hole.right);
240  *added = FALSE;
241  return SCIP_OKAY;
242  }
243 
244  /* add hole */
245  *added = TRUE;
246 
247  next = *insertpos;
248  SCIP_CALL( holelistCreate(insertpos, blkmem, set, left, right) );
249  (*insertpos)->next = next;
250 
251  return SCIP_OKAY;
252 }
253 
254 /** merges overlapping holes into single holes, computes and moves lower and upper bound, respectively */
255 /**@todo the domMerge() method is currently called if a lower or an upper bound locally or globally changed; this could
256  * be more efficient if performed with the knowledge if it was a lower or an upper bound which triggered this
257  * merge */
258 static
259 void domMerge(
260  SCIP_DOM* dom, /**< domain to merge */
261  BMS_BLKMEM* blkmem, /**< block memory */
262  SCIP_SET* set, /**< global SCIP settings */
263  SCIP_Real* newlb, /**< pointer to store new lower bound */
264  SCIP_Real* newub /**< pointer to store new upper bound */
265  )
266 {
267  SCIP_HOLELIST** holelistptr;
268  SCIP_HOLELIST** lastnextptr;
269  SCIP_Real* lastrightptr;
270 
271  assert(dom != NULL);
272  assert(SCIPsetIsLE(set, dom->lb, dom->ub));
273 
274 #ifndef NDEBUG
275  {
276  /* check if the holelist is sorted w.r.t. to the left interval bounds */
277  SCIP_Real lastleft;
278 
279  holelistptr = &dom->holelist;
280 
281  lastleft = -SCIPsetInfinity(set);
282 
283  while( *holelistptr != NULL )
284  {
285  if( (*holelistptr)->next != NULL )
286  {
287  assert( SCIPsetIsLE(set, lastleft, (*holelistptr)->hole.left) );
288  lastleft = (*holelistptr)->hole.left;
289  }
290 
291  holelistptr = &(*holelistptr)->next;
292  }
293  }
294 #endif
295 
296  SCIPsetDebugMsg(set, "merge hole list\n");
297 
298  holelistptr = &dom->holelist;
299  lastrightptr = &dom->lb; /* lower bound is the right bound of the hole (-infinity,lb) */
300  lastnextptr = holelistptr;
301 
302  while( *holelistptr != NULL )
303  {
304  SCIPsetDebugMsg(set, "check hole (%.15g,%.15g) last right interval was <%.15g>\n", (*holelistptr)->hole.left, (*holelistptr)->hole.right, *lastrightptr);
305 
306  /* check that the hole is not empty */
307  assert(SCIPsetIsLT(set, (*holelistptr)->hole.left, (*holelistptr)->hole.right));
308 
309  if( SCIPsetIsGE(set, (*holelistptr)->hole.left, dom->ub) )
310  {
311  /* the remaining holes start behind the upper bound: remove them */
312  SCIPsetDebugMsg(set, "remove remaining hole since upper bound <%.15g> is less then the left hand side of the current hole\n", dom->ub);
313  holelistFree(holelistptr, blkmem);
314  assert(*holelistptr == NULL);
315 
316  /* unlink this hole from the previous hole */
317  *lastnextptr = NULL;
318  }
319  else if( SCIPsetIsGT(set, (*holelistptr)->hole.right, dom->ub) )
320  {
321  /* the hole overlaps the upper bound: decrease upper bound, remove this hole and all remaining holes */
322  SCIPsetDebugMsg(set, "upper bound <%.15g> lays in current hole; store new upper bound and remove this and all remaining holes\n", dom->ub);
323 
324  assert(SCIPsetIsLT(set, (*holelistptr)->hole.left, dom->ub));
325 
326  /* adjust upper bound */
327  dom->ub = (*holelistptr)->hole.left;
328 
329  if(newub != NULL )
330  *newub = (*holelistptr)->hole.left;
331 
332  /* remove remaining hole list */
333  holelistFree(holelistptr, blkmem);
334  assert(*holelistptr == NULL);
335 
336  /* unlink this hole from the previous hole */
337  *lastnextptr = NULL;
338  }
339  else if( SCIPsetIsGT(set, *lastrightptr, (*holelistptr)->hole.left) )
340  {
341  /* the right bound of the last hole is greater than the left bound of this hole: increase the right bound of
342  * the last hole, delete this hole */
343  SCIP_HOLELIST* nextholelist;
344 
345  if( SCIPsetIsEQ(set, *lastrightptr, dom->lb ) )
346  {
347  /* the reason for the overlap results from the lower bound hole (-infinity,lb); therefore, we can increase
348  * the lower bound */
349  SCIPsetDebugMsg(set, "lower bound <%.15g> lays in current hole; store new lower bound and remove hole\n", dom->lb);
350  *lastrightptr = MAX(*lastrightptr, (*holelistptr)->hole.right);
351 
352  /* adjust lower bound */
353  dom->lb = *lastrightptr;
354 
355  if(newlb != NULL )
356  *newlb = *lastrightptr;
357  }
358  else
359  {
360  SCIPsetDebugMsg(set, "current hole overlaps with the previous one (...,%.15g); merge to (...,%.15g)\n",
361  *lastrightptr, MAX(*lastrightptr, (*holelistptr)->hole.right) );
362  *lastrightptr = MAX(*lastrightptr, (*holelistptr)->hole.right);
363  }
364  nextholelist = (*holelistptr)->next;
365  (*holelistptr)->next = NULL;
366  holelistFree(holelistptr, blkmem);
367 
368  /* connect the linked list after removing the hole */
369  *lastnextptr = nextholelist;
370 
371  /* get next hole */
372  *holelistptr = nextholelist;
373  }
374  else
375  {
376  /* the holes do not overlap: update lastholelist and lastrightptr */
377  lastrightptr = &(*holelistptr)->hole.right;
378  lastnextptr = &(*holelistptr)->next;
379 
380  /* get next hole */
381  holelistptr = &(*holelistptr)->next;
382  }
383  }
384 
385 #ifndef NDEBUG
386  {
387  /* check that holes are merged */
388  SCIP_Real lastright;
389 
390  lastright = dom->lb; /* lower bound is the right bound of the hole (-infinity,lb) */
391  holelistptr = &dom->holelist;
392 
393  while( *holelistptr != NULL )
394  {
395  /* check the the last right interval is smaller or equal to the current left interval (none overlapping) */
396  assert( SCIPsetIsLE(set, lastright, (*holelistptr)->hole.left) );
397 
398  /* check the hole property (check that the hole is not empty) */
399  assert( SCIPsetIsLT(set, (*holelistptr)->hole.left, (*holelistptr)->hole.right) );
400  lastright = (*holelistptr)->hole.right;
401 
402  /* get next hole */
403  holelistptr = &(*holelistptr)->next;
404  }
405 
406  /* check the the last right interval is smaller or equal to the upper bound (none overlapping) */
407  assert( SCIPsetIsLE(set, lastright, dom->ub) );
408  }
409 #endif
410 }
411 
412 /*
413  * domain change methods
414  */
415 
416 /** ensures, that bound change info array for lower bound changes can store at least num entries */
417 static
419  SCIP_VAR* var, /**< problem variable */
420  BMS_BLKMEM* blkmem, /**< block memory */
421  SCIP_SET* set, /**< global SCIP settings */
422  int num /**< minimum number of entries to store */
423  )
424 {
425  assert(var != NULL);
426  assert(var->nlbchginfos <= var->lbchginfossize);
427  assert(SCIPvarIsTransformed(var));
428 
429  if( num > var->lbchginfossize )
430  {
431  int newsize;
432 
433  newsize = SCIPsetCalcMemGrowSize(set, num);
434  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->lbchginfos, var->lbchginfossize, newsize) );
435  var->lbchginfossize = newsize;
436  }
437  assert(num <= var->lbchginfossize);
438 
439  return SCIP_OKAY;
440 }
441 
442 /** ensures, that bound change info array for upper bound changes can store at least num entries */
443 static
445  SCIP_VAR* var, /**< problem variable */
446  BMS_BLKMEM* blkmem, /**< block memory */
447  SCIP_SET* set, /**< global SCIP settings */
448  int num /**< minimum number of entries to store */
449  )
450 {
451  assert(var != NULL);
452  assert(var->nubchginfos <= var->ubchginfossize);
453  assert(SCIPvarIsTransformed(var));
454 
455  if( num > var->ubchginfossize )
456  {
457  int newsize;
458 
459  newsize = SCIPsetCalcMemGrowSize(set, num);
460  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->ubchginfos, var->ubchginfossize, newsize) );
461  var->ubchginfossize = newsize;
462  }
463  assert(num <= var->ubchginfossize);
464 
465  return SCIP_OKAY;
466 }
467 
468 /** adds domain change info to the variable's lower bound change info array */
469 static
471  SCIP_VAR* var, /**< problem variable */
472  BMS_BLKMEM* blkmem, /**< block memory */
473  SCIP_SET* set, /**< global SCIP settings */
474  SCIP_Real oldbound, /**< old value for bound */
475  SCIP_Real newbound, /**< new value for bound */
476  int depth, /**< depth in the tree, where the bound change takes place */
477  int pos, /**< position of the bound change in its bound change array */
478  SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself) */
479  SCIP_CONS* infercons, /**< constraint that infered this bound change, or NULL */
480  SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
481  int inferinfo, /**< user information for inference to help resolving the conflict */
482  SCIP_BOUNDTYPE inferboundtype, /**< type of bound for inference var: lower or upper bound */
483  SCIP_BOUNDCHGTYPE boundchgtype /**< bound change type: branching decision or infered bound change */
484  )
485 {
486  assert(var != NULL);
487  assert(SCIPsetIsLT(set, oldbound, newbound));
488  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, oldbound));
489  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
490  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, oldbound, 0.0));
491  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, 1.0));
492  assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
493  assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
494  assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
495 
496  SCIPsetDebugMsg(set, "adding lower bound change info to var <%s>[%g,%g]: depth=%d, pos=%d, infer%s=<%s>, inferinfo=%d, %g -> %g\n",
497  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, depth, pos, infercons != NULL ? "cons" : "prop",
498  infercons != NULL ? SCIPconsGetName(infercons) : (inferprop != NULL ? SCIPpropGetName(inferprop) : "-"), inferinfo,
499  oldbound, newbound);
500 
501  SCIP_CALL( varEnsureLbchginfosSize(var, blkmem, set, var->nlbchginfos+1) );
502  var->lbchginfos[var->nlbchginfos].oldbound = oldbound;
503  var->lbchginfos[var->nlbchginfos].newbound = newbound;
504  var->lbchginfos[var->nlbchginfos].var = var;
505  var->lbchginfos[var->nlbchginfos].bdchgidx.depth = depth;
506  var->lbchginfos[var->nlbchginfos].bdchgidx.pos = pos;
507  var->lbchginfos[var->nlbchginfos].pos = var->nlbchginfos; /*lint !e732*/
508  var->lbchginfos[var->nlbchginfos].boundchgtype = boundchgtype; /*lint !e641*/
509  var->lbchginfos[var->nlbchginfos].boundtype = SCIP_BOUNDTYPE_LOWER; /*lint !e641*/
510  var->lbchginfos[var->nlbchginfos].redundant = FALSE;
511  var->lbchginfos[var->nlbchginfos].inferboundtype = inferboundtype; /*lint !e641*/
512  var->lbchginfos[var->nlbchginfos].inferencedata.var = infervar;
513  var->lbchginfos[var->nlbchginfos].inferencedata.info = inferinfo;
514 
515  /**@note The "pos" data member of the bound change info has a size of 27 bits */
516  assert(var->nlbchginfos < 1 << 27);
517 
518  switch( boundchgtype )
519  {
521  break;
523  assert(infercons != NULL);
524  var->lbchginfos[var->nlbchginfos].inferencedata.reason.cons = infercons;
525  break;
527  var->lbchginfos[var->nlbchginfos].inferencedata.reason.prop = inferprop;
528  break;
529  default:
530  SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
531  return SCIP_INVALIDDATA;
532  }
533 
534  var->nlbchginfos++;
535 
536  assert(var->nlbchginfos < 2
538  &var->lbchginfos[var->nlbchginfos-1].bdchgidx));
539 
540  return SCIP_OKAY;
541 }
542 
543 /** adds domain change info to the variable's upper bound change info array */
544 static
546  SCIP_VAR* var, /**< problem variable */
547  BMS_BLKMEM* blkmem, /**< block memory */
548  SCIP_SET* set, /**< global SCIP settings */
549  SCIP_Real oldbound, /**< old value for bound */
550  SCIP_Real newbound, /**< new value for bound */
551  int depth, /**< depth in the tree, where the bound change takes place */
552  int pos, /**< position of the bound change in its bound change array */
553  SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself) */
554  SCIP_CONS* infercons, /**< constraint that infered this bound change, or NULL */
555  SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
556  int inferinfo, /**< user information for inference to help resolving the conflict */
557  SCIP_BOUNDTYPE inferboundtype, /**< type of bound for inference var: lower or upper bound */
558  SCIP_BOUNDCHGTYPE boundchgtype /**< bound change type: branching decision or infered bound change */
559  )
560 {
561  assert(var != NULL);
562  assert(SCIPsetIsGT(set, oldbound, newbound));
563  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, oldbound));
564  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
565  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, oldbound, 1.0));
566  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, 0.0));
567  assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
568  assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
569  assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
570 
571  SCIPsetDebugMsg(set, "adding upper bound change info to var <%s>[%g,%g]: depth=%d, pos=%d, infer%s=<%s>, inferinfo=%d, %g -> %g\n",
572  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, depth, pos, infercons != NULL ? "cons" : "prop",
573  infercons != NULL ? SCIPconsGetName(infercons) : (inferprop != NULL ? SCIPpropGetName(inferprop) : "-"), inferinfo,
574  oldbound, newbound);
575 
576  SCIP_CALL( varEnsureUbchginfosSize(var, blkmem, set, var->nubchginfos+1) );
577  var->ubchginfos[var->nubchginfos].oldbound = oldbound;
578  var->ubchginfos[var->nubchginfos].newbound = newbound;
579  var->ubchginfos[var->nubchginfos].var = var;
580  var->ubchginfos[var->nubchginfos].bdchgidx.depth = depth;
581  var->ubchginfos[var->nubchginfos].bdchgidx.pos = pos;
582  var->ubchginfos[var->nubchginfos].pos = var->nubchginfos; /*lint !e732*/
583  var->ubchginfos[var->nubchginfos].boundchgtype = boundchgtype; /*lint !e641*/
584  var->ubchginfos[var->nubchginfos].boundtype = SCIP_BOUNDTYPE_UPPER; /*lint !e641*/
585  var->ubchginfos[var->nubchginfos].redundant = FALSE;
586  var->ubchginfos[var->nubchginfos].inferboundtype = inferboundtype; /*lint !e641*/
587  var->ubchginfos[var->nubchginfos].inferencedata.var = infervar;
588  var->ubchginfos[var->nubchginfos].inferencedata.info = inferinfo;
589 
590  /**@note The "pos" data member of the bound change info has a size of 27 bits */
591  assert(var->nubchginfos < 1 << 27);
592 
593  switch( boundchgtype )
594  {
596  break;
598  assert(infercons != NULL);
599  var->ubchginfos[var->nubchginfos].inferencedata.reason.cons = infercons;
600  break;
602  var->ubchginfos[var->nubchginfos].inferencedata.reason.prop = inferprop;
603  break;
604  default:
605  SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
606  return SCIP_INVALIDDATA;
607  }
608 
609  var->nubchginfos++;
610 
611  assert(var->nubchginfos < 2
613  &var->ubchginfos[var->nubchginfos-1].bdchgidx));
614 
615  return SCIP_OKAY;
616 }
617 
618 /** applies single bound change */
620  SCIP_BOUNDCHG* boundchg, /**< bound change to apply */
621  BMS_BLKMEM* blkmem, /**< block memory */
622  SCIP_SET* set, /**< global SCIP settings */
623  SCIP_STAT* stat, /**< problem statistics */
624  SCIP_LP* lp, /**< current LP data */
625  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
626  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
627  int depth, /**< depth in the tree, where the bound change takes place */
628  int pos, /**< position of the bound change in its bound change array */
629  SCIP_Bool* cutoff /**< pointer to store whether an infeasible bound change was detected */
630  )
631 {
632  SCIP_VAR* var;
633 
634  assert(boundchg != NULL);
635  assert(stat != NULL);
636  assert(depth > 0);
637  assert(pos >= 0);
638  assert(cutoff != NULL);
639 
640  *cutoff = FALSE;
641 
642  /* ignore redundant bound changes */
643  if( boundchg->redundant )
644  return SCIP_OKAY;
645 
646  var = boundchg->var;
647  assert(var != NULL);
649  assert(!SCIPvarIsIntegral(var) || SCIPsetIsFeasIntegral(set, boundchg->newbound));
650 
651  /* apply bound change */
652  switch( boundchg->boundtype )
653  {
655  /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
656  if( SCIPsetIsGT(set, boundchg->newbound, var->locdom.lb) )
657  {
658  if( SCIPsetIsLE(set, boundchg->newbound, var->locdom.ub) )
659  {
660  /* add the bound change info to the variable's bound change info array */
661  switch( boundchg->boundchgtype )
662  {
664  SCIPsetDebugMsg(set, " -> branching: new lower bound of <%s>[%g,%g]: %g\n",
665  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
666  SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
668  stat->lastbranchvar = var;
670  stat->lastbranchvalue = boundchg->newbound;
671  break;
672 
674  assert(boundchg->data.inferencedata.reason.cons != NULL);
675  SCIPsetDebugMsg(set, " -> constraint <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
676  SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
677  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
678  SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
679  boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
680  boundchg->data.inferencedata.info,
682  break;
683 
685  SCIPsetDebugMsg(set, " -> propagator <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
686  boundchg->data.inferencedata.reason.prop != NULL
687  ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
688  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
689  SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
690  boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
691  boundchg->data.inferencedata.info,
693  break;
694 
695  default:
696  SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
697  return SCIP_INVALIDDATA;
698  }
699 
700  /* change local bound of variable */
701  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, boundchg->newbound) );
702  }
703  else
704  {
705  SCIPsetDebugMsg(set, " -> cutoff: new lower bound of <%s>[%g,%g]: %g\n",
706  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
707  *cutoff = TRUE;
708  boundchg->redundant = TRUE; /* bound change has not entered the lbchginfos array of the variable! */
709  }
710  }
711  else
712  {
713  /* mark bound change to be inactive */
714  SCIPsetDebugMsg(set, " -> inactive %s: new lower bound of <%s>[%g,%g]: %g\n",
715  (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
716  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
717  boundchg->redundant = TRUE;
718  }
719  break;
720 
722  /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
723  if( SCIPsetIsLT(set, boundchg->newbound, var->locdom.ub) )
724  {
725  if( SCIPsetIsGE(set, boundchg->newbound, var->locdom.lb) )
726  {
727  /* add the bound change info to the variable's bound change info array */
728  switch( boundchg->boundchgtype )
729  {
731  SCIPsetDebugMsg(set, " -> branching: new upper bound of <%s>[%g,%g]: %g\n",
732  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
733  SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
735  stat->lastbranchvar = var;
737  stat->lastbranchvalue = boundchg->newbound;
738  break;
739 
741  assert(boundchg->data.inferencedata.reason.cons != NULL);
742  SCIPsetDebugMsg(set, " -> constraint <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
743  SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
744  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
745  SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
746  boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
747  boundchg->data.inferencedata.info,
749  break;
750 
752  SCIPsetDebugMsg(set, " -> propagator <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
753  boundchg->data.inferencedata.reason.prop != NULL
754  ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
755  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
756  SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
757  boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
758  boundchg->data.inferencedata.info,
760  break;
761 
762  default:
763  SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
764  return SCIP_INVALIDDATA;
765  }
766 
767  /* change local bound of variable */
768  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, boundchg->newbound) );
769  }
770  else
771  {
772  SCIPsetDebugMsg(set, " -> cutoff: new upper bound of <%s>[%g,%g]: %g\n",
773  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
774  *cutoff = TRUE;
775  boundchg->redundant = TRUE; /* bound change has not entered the ubchginfos array of the variable! */
776  }
777  }
778  else
779  {
780  /* mark bound change to be inactive */
781  SCIPsetDebugMsg(set, " -> inactive %s: new upper bound of <%s>[%g,%g]: %g\n",
782  (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
783  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
784  boundchg->redundant = TRUE;
785  }
786  break;
787 
788  default:
789  SCIPerrorMessage("unknown bound type\n");
790  return SCIP_INVALIDDATA;
791  }
792 
793  /* update the branching and inference history */
794  if( !boundchg->applied && !boundchg->redundant )
795  {
796  assert(var == boundchg->var);
797 
799  {
800  SCIP_CALL( SCIPvarIncNBranchings(var, blkmem, set, stat,
803  }
804  else if( stat->lastbranchvar != NULL )
805  {
806  /**@todo if last branching variable is unknown, retrieve it from the nodes' boundchg arrays */
807  SCIP_CALL( SCIPvarIncInferenceSum(stat->lastbranchvar, blkmem, set, stat, stat->lastbranchdir, stat->lastbranchvalue, 1.0) );
808  }
809  boundchg->applied = TRUE;
810  }
811 
812  return SCIP_OKAY;
813 }
814 
815 /** undoes single bound change */
817  SCIP_BOUNDCHG* boundchg, /**< bound change to remove */
818  BMS_BLKMEM* blkmem, /**< block memory */
819  SCIP_SET* set, /**< global SCIP settings */
820  SCIP_STAT* stat, /**< problem statistics */
821  SCIP_LP* lp, /**< current LP data */
822  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
823  SCIP_EVENTQUEUE* eventqueue /**< event queue */
824  )
825 {
826  SCIP_VAR* var;
827 
828  assert(boundchg != NULL);
829  assert(stat != NULL);
830 
831  /* ignore redundant bound changes */
832  if( boundchg->redundant )
833  return SCIP_OKAY;
834 
835  var = boundchg->var;
836  assert(var != NULL);
838 
839  /* undo bound change: apply the previous bound change of variable */
840  switch( boundchg->boundtype )
841  {
843  var->nlbchginfos--;
844  assert(var->nlbchginfos >= 0);
845  assert(var->lbchginfos != NULL);
846  assert( SCIPsetIsFeasEQ(set, var->lbchginfos[var->nlbchginfos].newbound, var->locdom.lb) ); /*lint !e777*/
847  assert( SCIPsetIsFeasLE(set, boundchg->newbound, var->locdom.lb) ); /* current lb might be larger to intermediate global bound change */
848 
849  SCIPsetDebugMsg(set, "removed lower bound change info of var <%s>[%g,%g]: depth=%d, pos=%d, %g -> %g\n",
850  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub,
853 
854  /* reinstall the previous local bound */
855  SCIP_CALL( SCIPvarChgLbLocal(boundchg->var, blkmem, set, stat, lp, branchcand, eventqueue,
856  var->lbchginfos[var->nlbchginfos].oldbound) );
857 
858  /* in case all bound changes are removed the local bound should match the global bound */
859  assert(var->nlbchginfos > 0 || SCIPsetIsFeasEQ(set, var->locdom.lb, var->glbdom.lb));
860 
861  break;
862 
864  var->nubchginfos--;
865  assert(var->nubchginfos >= 0);
866  assert(var->ubchginfos != NULL);
867  assert( SCIPsetIsFeasEQ(set, var->ubchginfos[var->nubchginfos].newbound, var->locdom.ub) ); /*lint !e777*/
868  assert( SCIPsetIsFeasGE(set, boundchg->newbound, var->locdom.ub) ); /* current ub might be smaller to intermediate global bound change */
869 
870  SCIPsetDebugMsg(set, "removed upper bound change info of var <%s>[%g,%g]: depth=%d, pos=%d, %g -> %g\n",
871  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub,
874 
875  /* reinstall the previous local bound */
876  SCIP_CALL( SCIPvarChgUbLocal(boundchg->var, blkmem, set, stat, lp, branchcand, eventqueue,
877  var->ubchginfos[var->nubchginfos].oldbound) );
878 
879  /* in case all bound changes are removed the local bound should match the global bound */
880  assert(var->nubchginfos > 0 || SCIPsetIsFeasEQ(set, var->locdom.ub, var->glbdom.ub));
881 
882  break;
883 
884  default:
885  SCIPerrorMessage("unknown bound type\n");
886  return SCIP_INVALIDDATA;
887  }
888 
889  /* update last branching variable */
891  {
892  stat->lastbranchvar = NULL;
894  }
895 
896  return SCIP_OKAY;
897 }
898 
899 /** applies single bound change to the global problem by changing the global bound of the corresponding variable */
900 static
902  SCIP_BOUNDCHG* boundchg, /**< bound change to apply */
903  BMS_BLKMEM* blkmem, /**< block memory */
904  SCIP_SET* set, /**< global SCIP settings */
905  SCIP_STAT* stat, /**< problem statistics */
906  SCIP_LP* lp, /**< current LP data */
907  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
908  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
909  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
910  SCIP_Bool* cutoff /**< pointer to store whether an infeasible bound change was detected */
911  )
912 {
913  SCIP_VAR* var;
914  SCIP_Real newbound;
915  SCIP_BOUNDTYPE boundtype;
916 
917  assert(boundchg != NULL);
918  assert(cutoff != NULL);
919 
920  *cutoff = FALSE;
921 
922  /* ignore redundant bound changes */
923  if( boundchg->redundant )
924  return SCIP_OKAY;
925 
926  var = SCIPboundchgGetVar(boundchg);
927  newbound = SCIPboundchgGetNewbound(boundchg);
928  boundtype = SCIPboundchgGetBoundtype(boundchg);
929 
930  /* check if the bound change is redundant which can happen due to a (better) global bound change which was performed
931  * after that bound change was applied
932  *
933  * @note a global bound change is not captured by the redundant member of the bound change data structure
934  */
935  if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasLE(set, newbound, SCIPvarGetLbGlobal(var)))
936  || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasGE(set, newbound, SCIPvarGetUbGlobal(var))) )
937  {
938  return SCIP_OKAY;
939  }
940 
941  SCIPsetDebugMsg(set, "applying global bound change: <%s>[%g,%g] %s %g\n",
943  boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", newbound);
944 
945  /* check for cutoff */
946  if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGT(set, newbound, SCIPvarGetUbGlobal(var)))
947  || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLT(set, newbound, SCIPvarGetLbGlobal(var))) )
948  {
949  *cutoff = TRUE;
950  return SCIP_OKAY;
951  }
952 
953  /* apply bound change */
954  SCIP_CALL( SCIPvarChgBdGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound, boundtype) );
955 
956  return SCIP_OKAY;
957 }
958 
959 /** captures branching and inference data of bound change */
960 static
962  SCIP_BOUNDCHG* boundchg /**< bound change to remove */
963  )
964 {
965  assert(boundchg != NULL);
966 
967  /* capture variable associated with the bound change */
968  assert(boundchg->var != NULL);
969  SCIPvarCapture(boundchg->var);
970 
971  switch( boundchg->boundchgtype )
972  {
975  break;
976 
978  assert(boundchg->data.inferencedata.var != NULL);
979  assert(boundchg->data.inferencedata.reason.cons != NULL);
980  SCIPconsCapture(boundchg->data.inferencedata.reason.cons);
981  break;
982 
983  default:
984  SCIPerrorMessage("invalid bound change type\n");
985  return SCIP_INVALIDDATA;
986  }
987 
988  return SCIP_OKAY;
989 }
990 
991 /** releases branching and inference data of bound change */
992 static
994  SCIP_BOUNDCHG* boundchg, /**< bound change to remove */
995  BMS_BLKMEM* blkmem, /**< block memory */
996  SCIP_SET* set, /**< global SCIP settings */
997  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
998  SCIP_LP* lp /**< current LP data */
999 
1000  )
1001 {
1002  assert(boundchg != NULL);
1003 
1004  switch( boundchg->boundchgtype )
1005  {
1008  break;
1009 
1011  assert(boundchg->data.inferencedata.var != NULL);
1012  assert(boundchg->data.inferencedata.reason.cons != NULL);
1013  SCIP_CALL( SCIPconsRelease(&boundchg->data.inferencedata.reason.cons, blkmem, set) );
1014  break;
1015 
1016  default:
1017  SCIPerrorMessage("invalid bound change type\n");
1018  return SCIP_INVALIDDATA;
1019  }
1020 
1021  /* release variable */
1022  assert(boundchg->var != NULL);
1023  SCIP_CALL( SCIPvarRelease(&boundchg->var, blkmem, set, eventqueue, lp) );
1024 
1025  return SCIP_OKAY;
1026 }
1027 
1028 /** creates empty domain change data with dynamic arrays */
1029 static
1031  SCIP_DOMCHG** domchg, /**< pointer to domain change data */
1032  BMS_BLKMEM* blkmem /**< block memory */
1033  )
1034 {
1035  assert(domchg != NULL);
1036  assert(blkmem != NULL);
1037 
1038  SCIP_ALLOC( BMSallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN)) );
1039  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1040  (*domchg)->domchgdyn.nboundchgs = 0;
1041  (*domchg)->domchgdyn.boundchgs = NULL;
1042  (*domchg)->domchgdyn.nholechgs = 0;
1043  (*domchg)->domchgdyn.holechgs = NULL;
1044  (*domchg)->domchgdyn.boundchgssize = 0;
1045  (*domchg)->domchgdyn.holechgssize = 0;
1046 
1047  return SCIP_OKAY;
1048 }
1049 
1050 /** frees domain change data */
1052  SCIP_DOMCHG** domchg, /**< pointer to domain change */
1053  BMS_BLKMEM* blkmem, /**< block memory */
1054  SCIP_SET* set, /**< global SCIP settings */
1055  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1056  SCIP_LP* lp /**< current LP data */
1057  )
1058 {
1059  assert(domchg != NULL);
1060  assert(blkmem != NULL);
1061 
1062  if( *domchg != NULL )
1063  {
1064  int i;
1065 
1066  /* release variables, branching and inference data associated with the bound changes */
1067  for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1068  {
1069  SCIP_CALL( boundchgReleaseData(&(*domchg)->domchgbound.boundchgs[i], blkmem, set, eventqueue, lp) );
1070  }
1071 
1072  /* free memory for bound and hole changes */
1073  switch( (*domchg)->domchgdyn.domchgtype )
1074  {
1075  case SCIP_DOMCHGTYPE_BOUND:
1076  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgbound.boundchgs, (*domchg)->domchgbound.nboundchgs);
1077  BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOUND));
1078  break;
1079  case SCIP_DOMCHGTYPE_BOTH:
1080  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgboth.boundchgs, (*domchg)->domchgboth.nboundchgs);
1081  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgboth.holechgs, (*domchg)->domchgboth.nholechgs);
1082  BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH));
1083  break;
1085  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.boundchgs, (*domchg)->domchgdyn.boundchgssize);
1086  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.holechgs, (*domchg)->domchgdyn.holechgssize);
1087  BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN));
1088  break;
1089  default:
1090  SCIPerrorMessage("invalid domain change type\n");
1091  return SCIP_INVALIDDATA;
1092  }
1093  }
1094 
1095  return SCIP_OKAY;
1096 }
1097 
1098 /** converts a static domain change data into a dynamic one */
1099 static
1101  SCIP_DOMCHG** domchg, /**< pointer to domain change data */
1102  BMS_BLKMEM* blkmem /**< block memory */
1103  )
1104 {
1105  assert(domchg != NULL);
1106  assert(blkmem != NULL);
1107 
1108  SCIPdebugMessage("making domain change data %p pointing to %p dynamic\n", (void*)domchg, (void*)*domchg);
1109 
1110  if( *domchg == NULL )
1111  {
1112  SCIP_CALL( domchgCreate(domchg, blkmem) );
1113  }
1114  else
1115  {
1116  switch( (*domchg)->domchgdyn.domchgtype )
1117  {
1118  case SCIP_DOMCHGTYPE_BOUND:
1119  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOUND), sizeof(SCIP_DOMCHGDYN)) );
1120  (*domchg)->domchgdyn.nholechgs = 0;
1121  (*domchg)->domchgdyn.holechgs = NULL;
1122  (*domchg)->domchgdyn.boundchgssize = (int) (*domchg)->domchgdyn.nboundchgs;
1123  (*domchg)->domchgdyn.holechgssize = 0;
1124  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1125  break;
1126  case SCIP_DOMCHGTYPE_BOTH:
1127  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH), sizeof(SCIP_DOMCHGDYN)) );
1128  (*domchg)->domchgdyn.boundchgssize = (int) (*domchg)->domchgdyn.nboundchgs;
1129  (*domchg)->domchgdyn.holechgssize = (*domchg)->domchgdyn.nholechgs;
1130  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1131  break;
1133  break;
1134  default:
1135  SCIPerrorMessage("invalid domain change type\n");
1136  return SCIP_INVALIDDATA;
1137  }
1138  }
1139 #ifndef NDEBUG
1140  {
1141  int i;
1142  for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1143  assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1144  || EPSISINT((*domchg)->domchgbound.boundchgs[i].newbound, 1e-06));
1145  }
1146 #endif
1147 
1148  return SCIP_OKAY;
1149 }
1150 
1151 /** converts a dynamic domain change data into a static one, using less memory than for a dynamic one */
1153  SCIP_DOMCHG** domchg, /**< pointer to domain change data */
1154  BMS_BLKMEM* blkmem, /**< block memory */
1155  SCIP_SET* set, /**< global SCIP settings */
1156  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1157  SCIP_LP* lp /**< current LP data */
1158  )
1159 {
1160  assert(domchg != NULL);
1161  assert(blkmem != NULL);
1162 
1163  SCIPsetDebugMsg(set, "making domain change data %p pointing to %p static\n", (void*)domchg, (void*)*domchg);
1164 
1165  if( *domchg != NULL )
1166  {
1167  switch( (*domchg)->domchgdyn.domchgtype )
1168  {
1169  case SCIP_DOMCHGTYPE_BOUND:
1170  if( (*domchg)->domchgbound.nboundchgs == 0 )
1171  {
1172  SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1173  }
1174  break;
1175  case SCIP_DOMCHGTYPE_BOTH:
1176  if( (*domchg)->domchgboth.nholechgs == 0 )
1177  {
1178  if( (*domchg)->domchgbound.nboundchgs == 0 )
1179  {
1180  SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1181  }
1182  else
1183  {
1184  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH), sizeof(SCIP_DOMCHGBOUND)) );
1185  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOUND; /*lint !e641*/
1186  }
1187  }
1188  break;
1190  if( (*domchg)->domchgboth.nholechgs == 0 )
1191  {
1192  if( (*domchg)->domchgbound.nboundchgs == 0 )
1193  {
1194  SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1195  }
1196  else
1197  {
1198  /* shrink dynamic size arrays to their minimal sizes */
1199  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.boundchgs, \
1200  (*domchg)->domchgdyn.boundchgssize, (*domchg)->domchgdyn.nboundchgs) ); /*lint !e571*/
1201  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.holechgs, (*domchg)->domchgdyn.holechgssize);
1202 
1203  /* convert into static domain change */
1204  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN), sizeof(SCIP_DOMCHGBOUND)) );
1205  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOUND; /*lint !e641*/
1206  }
1207  }
1208  else
1209  {
1210  /* shrink dynamic size arrays to their minimal sizes */
1211  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.boundchgs, \
1212  (*domchg)->domchgdyn.boundchgssize, (*domchg)->domchgdyn.nboundchgs) ); /*lint !e571*/
1213  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.holechgs, \
1214  (*domchg)->domchgdyn.holechgssize, (*domchg)->domchgdyn.nholechgs) );
1215 
1216  /* convert into static domain change */
1217  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN), sizeof(SCIP_DOMCHGBOTH)) );
1218  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOTH; /*lint !e641*/
1219  }
1220  break;
1221  default:
1222  SCIPerrorMessage("invalid domain change type\n");
1223  return SCIP_INVALIDDATA;
1224  }
1225 #ifndef NDEBUG
1226  if( *domchg != NULL )
1227  {
1228  int i;
1229  for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1230  assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1231  || SCIPsetIsFeasIntegral(set, (*domchg)->domchgbound.boundchgs[i].newbound));
1232  }
1233 #endif
1234  }
1235 
1236  return SCIP_OKAY;
1237 }
1238 
1239 /** ensures, that boundchgs array can store at least num entries */
1240 static
1242  SCIP_DOMCHG* domchg, /**< domain change data structure */
1243  BMS_BLKMEM* blkmem, /**< block memory */
1244  SCIP_SET* set, /**< global SCIP settings */
1245  int num /**< minimum number of entries to store */
1246  )
1247 {
1248  assert(domchg != NULL);
1249  assert(domchg->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1250 
1251  if( num > domchg->domchgdyn.boundchgssize )
1252  {
1253  int newsize;
1254 
1255  newsize = SCIPsetCalcMemGrowSize(set, num);
1256  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &domchg->domchgdyn.boundchgs, domchg->domchgdyn.boundchgssize, newsize) );
1257  domchg->domchgdyn.boundchgssize = newsize;
1258  }
1259  assert(num <= domchg->domchgdyn.boundchgssize);
1260 
1261  return SCIP_OKAY;
1262 }
1263 
1264 /** ensures, that holechgs array can store at least num additional entries */
1265 static
1267  SCIP_DOMCHG* domchg, /**< domain change data structure */
1268  BMS_BLKMEM* blkmem, /**< block memory */
1269  SCIP_SET* set, /**< global SCIP settings */
1270  int num /**< minimum number of additional entries to store */
1271  )
1272 {
1273  assert(domchg != NULL);
1274  assert(domchg->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1275 
1276  if( num > domchg->domchgdyn.holechgssize )
1277  {
1278  int newsize;
1279 
1280  newsize = SCIPsetCalcMemGrowSize(set, num);
1281  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &domchg->domchgdyn.holechgs, domchg->domchgdyn.holechgssize, newsize) );
1282  domchg->domchgdyn.holechgssize = newsize;
1283  }
1284  assert(num <= domchg->domchgdyn.holechgssize);
1285 
1286  return SCIP_OKAY;
1287 }
1288 
1289 /** applies domain change */
1291  SCIP_DOMCHG* domchg, /**< domain change to apply */
1292  BMS_BLKMEM* blkmem, /**< block memory */
1293  SCIP_SET* set, /**< global SCIP settings */
1294  SCIP_STAT* stat, /**< problem statistics */
1295  SCIP_LP* lp, /**< current LP data */
1296  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1297  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1298  int depth, /**< depth in the tree, where the domain change takes place */
1299  SCIP_Bool* cutoff /**< pointer to store whether an infeasible domain change was detected */
1300  )
1301 {
1302  int i;
1303 
1304  assert(cutoff != NULL);
1305 
1306  *cutoff = FALSE;
1307 
1308  SCIPsetDebugMsg(set, "applying domain changes at %p in depth %d\n", (void*)domchg, depth);
1309 
1310  if( domchg == NULL )
1311  return SCIP_OKAY;
1312 
1313  /* apply bound changes */
1314  for( i = 0; i < (int)domchg->domchgbound.nboundchgs; ++i )
1315  {
1316  SCIP_CALL( SCIPboundchgApply(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp,
1317  branchcand, eventqueue, depth, i, cutoff) );
1318  if( *cutoff )
1319  break;
1320  }
1321  SCIPsetDebugMsg(set, " -> %u bound changes (cutoff %u)\n", domchg->domchgbound.nboundchgs, *cutoff);
1322 
1323  /* mark all bound changes after a cutoff redundant */
1324  for( ; i < (int)domchg->domchgbound.nboundchgs; ++i )
1325  domchg->domchgbound.boundchgs[i].redundant = TRUE;
1326 
1327  /* apply holelist changes */
1328  if( domchg->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_BOUND ) /*lint !e641*/
1329  {
1330  for( i = 0; i < domchg->domchgboth.nholechgs; ++i )
1331  *(domchg->domchgboth.holechgs[i].ptr) = domchg->domchgboth.holechgs[i].newlist;
1332  SCIPsetDebugMsg(set, " -> %d hole changes\n", domchg->domchgboth.nholechgs);
1333  }
1334 
1335  return SCIP_OKAY;
1336 }
1337 
1338 /** undoes domain change */
1340  SCIP_DOMCHG* domchg, /**< domain change to remove */
1341  BMS_BLKMEM* blkmem, /**< block memory */
1342  SCIP_SET* set, /**< global SCIP settings */
1343  SCIP_STAT* stat, /**< problem statistics */
1344  SCIP_LP* lp, /**< current LP data */
1345  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1346  SCIP_EVENTQUEUE* eventqueue /**< event queue */
1347  )
1348 {
1349  int i;
1350 
1351  SCIPsetDebugMsg(set, "undoing domain changes at %p\n", (void*)domchg);
1352  if( domchg == NULL )
1353  return SCIP_OKAY;
1354 
1355  /* undo holelist changes */
1356  if( domchg->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_BOUND ) /*lint !e641*/
1357  {
1358  for( i = domchg->domchgboth.nholechgs-1; i >= 0; --i )
1359  *(domchg->domchgboth.holechgs[i].ptr) = domchg->domchgboth.holechgs[i].oldlist;
1360  SCIPsetDebugMsg(set, " -> %d hole changes\n", domchg->domchgboth.nholechgs);
1361  }
1362 
1363  /* undo bound changes */
1364  for( i = domchg->domchgbound.nboundchgs-1; i >= 0; --i )
1365  {
1366  SCIP_CALL( SCIPboundchgUndo(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp, branchcand, eventqueue) );
1367  }
1368  SCIPsetDebugMsg(set, " -> %u bound changes\n", domchg->domchgbound.nboundchgs);
1369 
1370  return SCIP_OKAY;
1371 }
1372 
1373 /** applies domain change to the global problem */
1375  SCIP_DOMCHG* domchg, /**< domain change to apply */
1376  BMS_BLKMEM* blkmem, /**< block memory */
1377  SCIP_SET* set, /**< global SCIP settings */
1378  SCIP_STAT* stat, /**< problem statistics */
1379  SCIP_LP* lp, /**< current LP data */
1380  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1381  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1382  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1383  SCIP_Bool* cutoff /**< pointer to store whether an infeasible domain change was detected */
1384  )
1385 {
1386  int i;
1387 
1388  assert(cutoff != NULL);
1389 
1390  *cutoff = FALSE;
1391 
1392  if( domchg == NULL )
1393  return SCIP_OKAY;
1394 
1395  SCIPsetDebugMsg(set, "applying domain changes at %p to the global problem\n", (void*)domchg);
1396 
1397  /* apply bound changes */
1398  for( i = 0; i < (int)domchg->domchgbound.nboundchgs; ++i )
1399  {
1400  SCIP_CALL( boundchgApplyGlobal(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp,
1401  branchcand, eventqueue, cliquetable, cutoff) );
1402  if( *cutoff )
1403  break;
1404  }
1405  SCIPsetDebugMsg(set, " -> %u global bound changes\n", domchg->domchgbound.nboundchgs);
1406 
1407  /**@todo globally apply holelist changes - how can this be done without confusing pointer updates? */
1408 
1409  return SCIP_OKAY;
1410 }
1411 
1412 /** adds bound change to domain changes */
1414  SCIP_DOMCHG** domchg, /**< pointer to domain change data structure */
1415  BMS_BLKMEM* blkmem, /**< block memory */
1416  SCIP_SET* set, /**< global SCIP settings */
1417  SCIP_VAR* var, /**< variable to change the bounds for */
1418  SCIP_Real newbound, /**< new value for bound */
1419  SCIP_BOUNDTYPE boundtype, /**< type of bound for var: lower or upper bound */
1420  SCIP_BOUNDCHGTYPE boundchgtype, /**< type of bound change: branching decision or inference */
1421  SCIP_Real lpsolval, /**< solval of variable in last LP on path to node, or SCIP_INVALID if unknown */
1422  SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself), or NULL */
1423  SCIP_CONS* infercons, /**< constraint that deduced the bound change, or NULL */
1424  SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
1425  int inferinfo, /**< user information for inference to help resolving the conflict */
1426  SCIP_BOUNDTYPE inferboundtype /**< type of bound for inference var: lower or upper bound */
1427  )
1428 {
1429  SCIP_BOUNDCHG* boundchg;
1430 
1431  assert(domchg != NULL);
1432  assert(var != NULL);
1434  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
1435  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, boundtype == SCIP_BOUNDTYPE_LOWER ? 1.0 : 0.0));
1436  assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
1437  assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
1438  assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
1439 
1440  SCIPsetDebugMsg(set, "adding %s bound change <%s: %g> of variable <%s> to domain change at %p pointing to %p\n",
1441  boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
1442  newbound, var->name, (void*)domchg, (void*)*domchg);
1443 
1444  /* if domain change data doesn't exist, create it;
1445  * if domain change is static, convert it into dynamic change
1446  */
1447  if( *domchg == NULL )
1448  {
1449  SCIP_CALL( domchgCreate(domchg, blkmem) );
1450  }
1451  else if( (*domchg)->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_DYNAMIC ) /*lint !e641*/
1452  {
1453  SCIP_CALL( domchgMakeDynamic(domchg, blkmem) );
1454  }
1455  assert(*domchg != NULL && (*domchg)->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1456 
1457  /* get memory for additional bound change */
1458  SCIP_CALL( domchgEnsureBoundchgsSize(*domchg, blkmem, set, (*domchg)->domchgdyn.nboundchgs+1) );
1459 
1460  /* fill in the bound change data */
1461  boundchg = &(*domchg)->domchgdyn.boundchgs[(*domchg)->domchgdyn.nboundchgs];
1462  boundchg->var = var;
1463  switch( boundchgtype )
1464  {
1466  boundchg->data.branchingdata.lpsolval = lpsolval;
1467  break;
1469  assert(infercons != NULL);
1470  boundchg->data.inferencedata.var = infervar;
1471  boundchg->data.inferencedata.reason.cons = infercons;
1472  boundchg->data.inferencedata.info = inferinfo;
1473  break;
1475  boundchg->data.inferencedata.var = infervar;
1476  boundchg->data.inferencedata.reason.prop = inferprop;
1477  boundchg->data.inferencedata.info = inferinfo;
1478  break;
1479  default:
1480  SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
1481  return SCIP_INVALIDDATA;
1482  }
1483 
1484  boundchg->newbound = newbound;
1485  boundchg->boundchgtype = boundchgtype; /*lint !e641*/
1486  boundchg->boundtype = boundtype; /*lint !e641*/
1487  boundchg->inferboundtype = inferboundtype; /*lint !e641*/
1488  boundchg->applied = FALSE;
1489  boundchg->redundant = FALSE;
1490  (*domchg)->domchgdyn.nboundchgs++;
1491 
1492  /* capture branching and inference data associated with the bound changes */
1493  SCIP_CALL( boundchgCaptureData(boundchg) );
1494 
1495 #ifdef SCIP_DISABLED_CODE /* expensive debug check */
1496 #ifdef SCIP_MORE_DEBUG
1497  {
1498  int i;
1499  for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1500  assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1501  || SCIPsetIsFeasIntegral(set, (*domchg)->domchgbound.boundchgs[i].newbound));
1502  }
1503 #endif
1504 #endif
1505 
1506  return SCIP_OKAY;
1507 }
1508 
1509 /** adds hole change to domain changes */
1511  SCIP_DOMCHG** domchg, /**< pointer to domain change data structure */
1512  BMS_BLKMEM* blkmem, /**< block memory */
1513  SCIP_SET* set, /**< global SCIP settings */
1514  SCIP_HOLELIST** ptr, /**< changed list pointer */
1515  SCIP_HOLELIST* newlist, /**< new value of list pointer */
1516  SCIP_HOLELIST* oldlist /**< old value of list pointer */
1517  )
1518 {
1519  SCIP_HOLECHG* holechg;
1520 
1521  assert(domchg != NULL);
1522  assert(ptr != NULL);
1523 
1524  /* if domain change data doesn't exist, create it;
1525  * if domain change is static, convert it into dynamic change
1526  */
1527  if( *domchg == NULL )
1528  {
1529  SCIP_CALL( domchgCreate(domchg, blkmem) );
1530  }
1531  else if( (*domchg)->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_DYNAMIC ) /*lint !e641*/
1532  {
1533  SCIP_CALL( domchgMakeDynamic(domchg, blkmem) );
1534  }
1535  assert(*domchg != NULL && (*domchg)->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1536 
1537  /* get memory for additional hole change */
1538  SCIP_CALL( domchgEnsureHolechgsSize(*domchg, blkmem, set, (*domchg)->domchgdyn.nholechgs+1) );
1539 
1540  /* fill in the hole change data */
1541  holechg = &(*domchg)->domchgdyn.holechgs[(*domchg)->domchgdyn.nholechgs];
1542  holechg->ptr = ptr;
1543  holechg->newlist = newlist;
1544  holechg->oldlist = oldlist;
1545  (*domchg)->domchgdyn.nholechgs++;
1546 
1547  return SCIP_OKAY;
1548 }
1549 
1550 
1551 
1552 
1553 /*
1554  * methods for variables
1555  */
1556 
1557 /** returns adjusted lower bound value, which is rounded for integral variable types */
1558 static
1560  SCIP_SET* set, /**< global SCIP settings */
1561  SCIP_VARTYPE vartype, /**< type of variable */
1562  SCIP_Real lb /**< lower bound to adjust */
1563  )
1564 {
1565  if( lb < 0.0 && SCIPsetIsInfinity(set, -lb) )
1566  return -SCIPsetInfinity(set);
1567  else if( lb > 0.0 && SCIPsetIsInfinity(set, lb) )
1568  return SCIPsetInfinity(set);
1569  else if( vartype != SCIP_VARTYPE_CONTINUOUS )
1570  return SCIPsetFeasCeil(set, lb);
1571  else if( lb > 0.0 && lb < SCIPsetEpsilon(set) )
1572  return 0.0;
1573  else
1574  return lb;
1575 }
1576 
1577 /** returns adjusted upper bound value, which is rounded for integral variable types */
1578 static
1580  SCIP_SET* set, /**< global SCIP settings */
1581  SCIP_VARTYPE vartype, /**< type of variable */
1582  SCIP_Real ub /**< upper bound to adjust */
1583  )
1584 {
1585  if( ub > 0.0 && SCIPsetIsInfinity(set, ub) )
1586  return SCIPsetInfinity(set);
1587  else if( ub < 0.0 && SCIPsetIsInfinity(set, -ub) )
1588  return -SCIPsetInfinity(set);
1589  else if( vartype != SCIP_VARTYPE_CONTINUOUS )
1590  return SCIPsetFeasFloor(set, ub);
1591  else if( ub < 0.0 && ub > -SCIPsetEpsilon(set) )
1592  return 0.0;
1593  else
1594  return ub;
1595 }
1596 
1597 /** removes (redundant) cliques, implications and variable bounds of variable from all other variables' implications and variable
1598  * bounds arrays, and optionally removes them also from the variable itself
1599  */
1601  SCIP_VAR* var, /**< problem variable */
1602  BMS_BLKMEM* blkmem, /**< block memory */
1603  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1604  SCIP_SET* set, /**< global SCIP settings */
1605  SCIP_Bool irrelevantvar, /**< has the variable become irrelevant? */
1606  SCIP_Bool onlyredundant, /**< should only the redundant implications and variable bounds be removed? */
1607  SCIP_Bool removefromvar /**< should the implications and variable bounds be removed from the var itself? */
1608  )
1609 {
1610  SCIP_Real lb;
1611  SCIP_Real ub;
1612 
1613  assert(var != NULL);
1615  assert(SCIPvarIsActive(var) || SCIPvarGetType(var) != SCIP_VARTYPE_BINARY);
1616 
1617  lb = SCIPvarGetLbGlobal(var);
1618  ub = SCIPvarGetUbGlobal(var);
1619 
1620  SCIPsetDebugMsg(set, "removing %s implications and vbounds of %s<%s>[%g,%g]\n",
1621  onlyredundant ? "redundant" : "all", irrelevantvar ? "irrelevant " : "", SCIPvarGetName(var), lb, ub);
1622 
1623  /* remove implications of (fixed) binary variable */
1624  if( var->implics != NULL && (!onlyredundant || lb > 0.5 || ub < 0.5) )
1625  {
1626  SCIP_Bool varfixing;
1627 
1628  assert(SCIPvarIsBinary(var));
1629 
1630  varfixing = FALSE;
1631  do
1632  {
1633  SCIP_VAR** implvars;
1634  SCIP_BOUNDTYPE* impltypes;
1635  int nimpls;
1636  int i;
1637 
1638  nimpls = SCIPimplicsGetNImpls(var->implics, varfixing);
1639  implvars = SCIPimplicsGetVars(var->implics, varfixing);
1640  impltypes = SCIPimplicsGetTypes(var->implics, varfixing);
1641 
1642  for( i = 0; i < nimpls; i++ )
1643  {
1644  SCIP_VAR* implvar;
1645  SCIP_BOUNDTYPE impltype;
1646 
1647  implvar = implvars[i];
1648  impltype = impltypes[i];
1649  assert(implvar != var);
1650 
1651  /* remove for all implications z == 0 / 1 ==> x <= p / x >= p (x not binary)
1652  * the following variable bound from x's variable bounds
1653  * x <= b*z+d (z in vubs of x) , for z == 0 / 1 ==> x <= p
1654  * x >= b*z+d (z in vlbs of x) , for z == 0 / 1 ==> x >= p
1655  */
1656  if( impltype == SCIP_BOUNDTYPE_UPPER )
1657  {
1658  if( implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1659  {
1660  SCIPsetDebugMsg(set, "deleting variable bound: <%s> == %u ==> <%s> <= %g\n",
1661  SCIPvarGetName(var), varfixing, SCIPvarGetName(implvar),
1662  SCIPimplicsGetBounds(var->implics, varfixing)[i]);
1663  SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, varfixing) );
1664  implvar->closestvblpcount = -1;
1665  var->closestvblpcount = -1;
1666  }
1667  }
1668  else
1669  {
1670  if( implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1671  {
1672  SCIPsetDebugMsg(set, "deleting variable bound: <%s> == %u ==> <%s> >= %g\n",
1673  SCIPvarGetName(var), varfixing, SCIPvarGetName(implvar),
1674  SCIPimplicsGetBounds(var->implics, varfixing)[i]);
1675  SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, !varfixing) );
1676  implvar->closestvblpcount = -1;
1677  var->closestvblpcount = -1;
1678  }
1679  }
1680  }
1681  varfixing = !varfixing;
1682  }
1683  while( varfixing == TRUE );
1684 
1685  if( removefromvar )
1686  {
1687  /* free the implications data structures */
1688  SCIPimplicsFree(&var->implics, blkmem);
1689  }
1690  }
1691 
1692  /* remove the (redundant) variable lower bounds */
1693  if( var->vlbs != NULL )
1694  {
1695  SCIP_VAR** vars;
1696  SCIP_Real* coefs;
1697  SCIP_Real* constants;
1698  int nvbds;
1699  int newnvbds;
1700  int i;
1701 
1702  nvbds = SCIPvboundsGetNVbds(var->vlbs);
1703  vars = SCIPvboundsGetVars(var->vlbs);
1704  coefs = SCIPvboundsGetCoefs(var->vlbs);
1705  constants = SCIPvboundsGetConstants(var->vlbs);
1706 
1707  /* remove for all variable bounds x >= b*z+d the following implication from z's implications
1708  * z == ub ==> x >= b*ub + d , if b > 0
1709  * z == lb ==> x >= b*lb + d , if b < 0
1710  */
1711  newnvbds = 0;
1712  for( i = 0; i < nvbds; i++ )
1713  {
1714  SCIP_VAR* implvar;
1715  SCIP_Real coef;
1716 
1717  assert(newnvbds <= i);
1718 
1719  implvar = vars[i];
1720  assert(implvar != NULL);
1721 
1722  coef = coefs[i];
1723  assert(!SCIPsetIsZero(set, coef));
1724 
1725  /* check, if we want to remove the variable bound */
1726  if( onlyredundant )
1727  {
1728  SCIP_Real vbound;
1729 
1730  vbound = MAX(coef * SCIPvarGetUbGlobal(implvar), coef * SCIPvarGetLbGlobal(implvar)) + constants[i]; /*lint !e666*/
1731  if( SCIPsetIsFeasGT(set, vbound, lb) )
1732  {
1733  /* the variable bound is not redundant: keep it */
1734  if( removefromvar )
1735  {
1736  if( newnvbds < i )
1737  {
1738  vars[newnvbds] = implvar;
1739  coefs[newnvbds] = coef;
1740  constants[newnvbds] = constants[i];
1741  }
1742  newnvbds++;
1743  }
1744  continue;
1745  }
1746  }
1747 
1748  /* remove the corresponding implication */
1749  if( implvar->implics != NULL ) /* variable may have been aggregated in the mean time */
1750  {
1751  SCIPsetDebugMsg(set, "deleting implication: <%s> == %d ==> <%s> >= %g\n",
1752  SCIPvarGetName(implvar), (coef > 0.0), SCIPvarGetName(var), MAX(coef, 0.0) + constants[i]);
1753  SCIP_CALL( SCIPimplicsDel(&implvar->implics, blkmem, set, (coef > 0.0), var, SCIP_BOUNDTYPE_LOWER) );
1754  }
1755  if( coef > 0.0 && implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1756  {
1757  SCIPsetDebugMsg(set, "deleting variable upper bound from <%s> involving variable %s\n",
1758  SCIPvarGetName(implvar), SCIPvarGetName(var));
1759  SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, FALSE) );
1760  implvar->closestvblpcount = -1;
1761  var->closestvblpcount = -1;
1762  }
1763  else if( coef < 0.0 && implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1764  {
1765  SCIPsetDebugMsg(set, "deleting variable lower bound from <%s> involving variable %s\n",
1766  SCIPvarGetName(implvar), SCIPvarGetName(var));
1767  SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, TRUE) );
1768  implvar->closestvblpcount = -1;
1769  var->closestvblpcount = -1;
1770  }
1771  }
1772 
1773  if( removefromvar )
1774  {
1775  /* update the number of variable bounds */
1776  SCIPvboundsShrink(&var->vlbs, blkmem, newnvbds);
1777  var->closestvblpcount = -1;
1778  }
1779  }
1780 
1781  /**@todo in general, variable bounds like x >= b*z + d corresponding to an implication like z = ub ==> x >= b*ub + d
1782  * might be missing because we only add variable bounds with reasonably small value of b. thus, we currently
1783  * cannot remove such variables x from z's implications.
1784  */
1785 
1786  /* remove the (redundant) variable upper bounds */
1787  if( var->vubs != NULL )
1788  {
1789  SCIP_VAR** vars;
1790  SCIP_Real* coefs;
1791  SCIP_Real* constants;
1792  int nvbds;
1793  int newnvbds;
1794  int i;
1795 
1796  nvbds = SCIPvboundsGetNVbds(var->vubs);
1797  vars = SCIPvboundsGetVars(var->vubs);
1798  coefs = SCIPvboundsGetCoefs(var->vubs);
1799  constants = SCIPvboundsGetConstants(var->vubs);
1800 
1801  /* remove for all variable bounds x <= b*z+d the following implication from z's implications
1802  * z == lb ==> x <= b*lb + d , if b > 0
1803  * z == ub ==> x <= b*ub + d , if b < 0
1804  */
1805  newnvbds = 0;
1806  for( i = 0; i < nvbds; i++ )
1807  {
1808  SCIP_VAR* implvar;
1809  SCIP_Real coef;
1810 
1811  assert(newnvbds <= i);
1812 
1813  implvar = vars[i];
1814  assert(implvar != NULL);
1815 
1816  coef = coefs[i];
1817  assert(!SCIPsetIsZero(set, coef));
1818 
1819  /* check, if we want to remove the variable bound */
1820  if( onlyredundant )
1821  {
1822  SCIP_Real vbound;
1823 
1824  vbound = MIN(coef * SCIPvarGetUbGlobal(implvar), coef * SCIPvarGetLbGlobal(implvar)) + constants[i]; /*lint !e666*/
1825  if( SCIPsetIsFeasLT(set, vbound, ub) )
1826  {
1827  /* the variable bound is not redundant: keep it */
1828  if( removefromvar )
1829  {
1830  if( newnvbds < i )
1831  {
1832  vars[newnvbds] = implvar;
1833  coefs[newnvbds] = coefs[i];
1834  constants[newnvbds] = constants[i];
1835  }
1836  newnvbds++;
1837  }
1838  continue;
1839  }
1840  }
1841 
1842  /* remove the corresponding implication */
1843  if( implvar->implics != NULL ) /* variable may have been aggregated in the mean time */
1844  {
1845  SCIPsetDebugMsg(set, "deleting implication: <%s> == %d ==> <%s> <= %g\n",
1846  SCIPvarGetName(implvar), (coef < 0.0), SCIPvarGetName(var), MIN(coef, 0.0) + constants[i]);
1847  SCIP_CALL( SCIPimplicsDel(&implvar->implics, blkmem, set, (coef < 0.0), var, SCIP_BOUNDTYPE_UPPER) );
1848  }
1849  if( coef < 0.0 && implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1850  {
1851  SCIPsetDebugMsg(set, "deleting variable upper bound from <%s> involving variable %s\n",
1852  SCIPvarGetName(implvar), SCIPvarGetName(var));
1853  SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, TRUE) );
1854  implvar->closestvblpcount = -1;
1855  var->closestvblpcount = -1;
1856  }
1857  else if( coef > 0.0 && implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1858  {
1859  SCIPsetDebugMsg(set, "deleting variable lower bound from <%s> involving variable %s\n",
1860  SCIPvarGetName(implvar), SCIPvarGetName(var));
1861  SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, FALSE) );
1862  implvar->closestvblpcount = -1;
1863  var->closestvblpcount = -1;
1864  }
1865  }
1866 
1867  if( removefromvar )
1868  {
1869  /* update the number of variable bounds */
1870  SCIPvboundsShrink(&var->vubs, blkmem, newnvbds);
1871  var->closestvblpcount = -1;
1872  }
1873  }
1874 
1875  /* remove the variable from all cliques */
1876  if( SCIPvarIsBinary(var) )
1877  {
1878  SCIPcliquelistRemoveFromCliques(var->cliquelist, cliquetable, var, irrelevantvar);
1879  SCIPcliquelistFree(&var->cliquelist, blkmem);
1880  }
1881 
1882  /**@todo variable bounds like x <= b*z + d with z general integer are not removed from x's vbd arrays, because
1883  * z has no link (like in the binary case) to x
1884  */
1885 
1886  return SCIP_OKAY;
1887 }
1888 
1889 /** sets the variable name */
1890 static
1892  SCIP_VAR* var, /**< problem variable */
1893  BMS_BLKMEM* blkmem, /**< block memory */
1894  SCIP_STAT* stat, /**< problem statistics, or NULL */
1895  const char* name /**< name of variable, or NULL for automatic name creation */
1896  )
1897 {
1898  assert(blkmem != NULL);
1899  assert(var != NULL);
1900 
1901  if( name == NULL )
1902  {
1903  char s[SCIP_MAXSTRLEN];
1904 
1905  assert(stat != NULL);
1906 
1907  (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "_var%d_", stat->nvaridx);
1908  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->name, s, strlen(s)+1) );
1909  }
1910  else
1911  {
1912  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->name, name, strlen(name)+1) );
1913  }
1914 
1915  return SCIP_OKAY;
1916 }
1917 
1918 
1919 /** creates variable; if variable is of integral type, fractional bounds are automatically rounded; an integer variable
1920  * with bounds zero and one is automatically converted into a binary variable
1921  */
1922 static
1924  SCIP_VAR** var, /**< pointer to variable data */
1925  BMS_BLKMEM* blkmem, /**< block memory */
1926  SCIP_SET* set, /**< global SCIP settings */
1927  SCIP_STAT* stat, /**< problem statistics */
1928  const char* name, /**< name of variable, or NULL for automatic name creation */
1929  SCIP_Real lb, /**< lower bound of variable */
1930  SCIP_Real ub, /**< upper bound of variable */
1931  SCIP_Real obj, /**< objective function value */
1932  SCIP_VARTYPE vartype, /**< type of variable */
1933  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
1934  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
1935  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
1936  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
1937  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
1938  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
1939  SCIP_VARDATA* vardata /**< user data for this specific variable */
1940  )
1941 {
1942  int i;
1943 
1944  assert(var != NULL);
1945  assert(blkmem != NULL);
1946  assert(stat != NULL);
1947 
1948  /* adjust bounds of variable */
1949  lb = adjustedLb(set, vartype, lb);
1950  ub = adjustedUb(set, vartype, ub);
1951 
1952  /* convert [0,1]-integers into binary variables and check that binary variables have correct bounds */
1953  if( (SCIPsetIsEQ(set, lb, 0.0) || SCIPsetIsEQ(set, lb, 1.0))
1954  && (SCIPsetIsEQ(set, ub, 0.0) || SCIPsetIsEQ(set, ub, 1.0)) )
1955  {
1956  if( vartype == SCIP_VARTYPE_INTEGER )
1957  vartype = SCIP_VARTYPE_BINARY;
1958  }
1959  else
1960  {
1961  if( vartype == SCIP_VARTYPE_BINARY )
1962  {
1963  SCIPerrorMessage("invalid bounds [%.2g,%.2g] for binary variable <%s>\n", lb, ub, name);
1964  return SCIP_INVALIDDATA;
1965  }
1966  }
1967 
1968  assert(vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, lb, 0.0) || SCIPsetIsEQ(set, lb, 1.0));
1969  assert(vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, ub, 0.0) || SCIPsetIsEQ(set, ub, 1.0));
1970 
1971  SCIP_ALLOC( BMSallocBlockMemory(blkmem, var) );
1972 
1973  /* set variable's name */
1974  SCIP_CALL( varSetName(*var, blkmem, stat, name) );
1975 
1976 #ifndef NDEBUG
1977  (*var)->scip = set->scip;
1978 #endif
1979  (*var)->obj = obj;
1980  (*var)->unchangedobj = obj;
1981  (*var)->branchfactor = 1.0;
1982  (*var)->rootsol = 0.0;
1983  (*var)->bestrootsol = 0.0;
1984  (*var)->bestrootredcost = 0.0;
1985  (*var)->bestrootlpobjval = SCIP_INVALID;
1986  (*var)->relaxsol = 0.0;
1987  (*var)->nlpsol = 0.0;
1988  (*var)->primsolavg = 0.5 * (lb + ub);
1989  (*var)->conflictlb = SCIP_REAL_MIN;
1990  (*var)->conflictub = SCIP_REAL_MAX;
1991  (*var)->conflictrelaxedlb = (*var)->conflictlb;
1992  (*var)->conflictrelaxedub = (*var)->conflictub;
1993  (*var)->lazylb = -SCIPsetInfinity(set);
1994  (*var)->lazyub = SCIPsetInfinity(set);
1995  (*var)->glbdom.holelist = NULL;
1996  (*var)->glbdom.lb = lb;
1997  (*var)->glbdom.ub = ub;
1998  (*var)->locdom.holelist = NULL;
1999  (*var)->locdom.lb = lb;
2000  (*var)->locdom.ub = ub;
2001  (*var)->varcopy = varcopy;
2002  (*var)->vardelorig = vardelorig;
2003  (*var)->vartrans = vartrans;
2004  (*var)->vardeltrans = vardeltrans;
2005  (*var)->vardata = vardata;
2006  (*var)->parentvars = NULL;
2007  (*var)->negatedvar = NULL;
2008  (*var)->vlbs = NULL;
2009  (*var)->vubs = NULL;
2010  (*var)->implics = NULL;
2011  (*var)->cliquelist = NULL;
2012  (*var)->eventfilter = NULL;
2013  (*var)->lbchginfos = NULL;
2014  (*var)->ubchginfos = NULL;
2015  (*var)->index = stat->nvaridx;
2016  (*var)->probindex = -1;
2017  (*var)->pseudocandindex = -1;
2018  (*var)->eventqueueindexobj = -1;
2019  (*var)->eventqueueindexlb = -1;
2020  (*var)->eventqueueindexub = -1;
2021  (*var)->parentvarssize = 0;
2022  (*var)->nparentvars = 0;
2023  (*var)->nuses = 0;
2024  (*var)->branchpriority = 0;
2025  (*var)->branchdirection = SCIP_BRANCHDIR_AUTO; /*lint !e641*/
2026  (*var)->lbchginfossize = 0;
2027  (*var)->nlbchginfos = 0;
2028  (*var)->ubchginfossize = 0;
2029  (*var)->nubchginfos = 0;
2030  (*var)->conflictlbcount = 0;
2031  (*var)->conflictubcount = 0;
2032  (*var)->closestvlbidx = -1;
2033  (*var)->closestvubidx = -1;
2034  (*var)->closestvblpcount = -1;
2035  (*var)->initial = initial;
2036  (*var)->removable = removable;
2037  (*var)->deleted = FALSE;
2038  (*var)->donotaggr = FALSE;
2039  (*var)->donotmultaggr = FALSE;
2040  (*var)->vartype = vartype; /*lint !e641*/
2041  (*var)->pseudocostflag = FALSE;
2042  (*var)->eventqueueimpl = FALSE;
2043  (*var)->deletable = FALSE;
2044  (*var)->delglobalstructs = FALSE;
2045  (*var)->relaxationonly = FALSE;
2046 
2047  for( i = 0; i < NLOCKTYPES; i++ )
2048  {
2049  (*var)->nlocksdown[i] = 0;
2050  (*var)->nlocksup[i] = 0;
2051  }
2052 
2053  stat->nvaridx++;
2054 
2055  /* create branching and inference history entries */
2056  SCIP_CALL( SCIPhistoryCreate(&(*var)->history, blkmem) );
2057  SCIP_CALL( SCIPhistoryCreate(&(*var)->historycrun, blkmem) );
2058 
2059  /* the value based history is only created on demand */
2060  (*var)->valuehistory = NULL;
2061 
2062  return SCIP_OKAY;
2063 }
2064 
2065 /** creates and captures an original problem variable; an integer variable with bounds
2066  * zero and one is automatically converted into a binary variable
2067  */
2069  SCIP_VAR** var, /**< pointer to variable data */
2070  BMS_BLKMEM* blkmem, /**< block memory */
2071  SCIP_SET* set, /**< global SCIP settings */
2072  SCIP_STAT* stat, /**< problem statistics */
2073  const char* name, /**< name of variable, or NULL for automatic name creation */
2074  SCIP_Real lb, /**< lower bound of variable */
2075  SCIP_Real ub, /**< upper bound of variable */
2076  SCIP_Real obj, /**< objective function value */
2077  SCIP_VARTYPE vartype, /**< type of variable */
2078  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2079  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2080  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2081  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2082  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2083  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2084  SCIP_VARDATA* vardata /**< user data for this specific variable */
2085  )
2086 {
2087  assert(var != NULL);
2088  assert(blkmem != NULL);
2089  assert(stat != NULL);
2090 
2091  /* create variable */
2092  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2093  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2094 
2095  /* set variable status and data */
2096  (*var)->varstatus = SCIP_VARSTATUS_ORIGINAL; /*lint !e641*/
2097  (*var)->data.original.origdom.holelist = NULL;
2098  (*var)->data.original.origdom.lb = lb;
2099  (*var)->data.original.origdom.ub = ub;
2100  (*var)->data.original.transvar = NULL;
2101 
2102  /* capture variable */
2103  SCIPvarCapture(*var);
2104 
2105  return SCIP_OKAY;
2106 }
2107 
2108 /** creates and captures a loose variable belonging to the transformed problem; an integer variable with bounds
2109  * zero and one is automatically converted into a binary variable
2110  */
2112  SCIP_VAR** var, /**< pointer to variable data */
2113  BMS_BLKMEM* blkmem, /**< block memory */
2114  SCIP_SET* set, /**< global SCIP settings */
2115  SCIP_STAT* stat, /**< problem statistics */
2116  const char* name, /**< name of variable, or NULL for automatic name creation */
2117  SCIP_Real lb, /**< lower bound of variable */
2118  SCIP_Real ub, /**< upper bound of variable */
2119  SCIP_Real obj, /**< objective function value */
2120  SCIP_VARTYPE vartype, /**< type of variable */
2121  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2122  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2123  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2124  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2125  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2126  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2127  SCIP_VARDATA* vardata /**< user data for this specific variable */
2128  )
2129 {
2130  assert(var != NULL);
2131  assert(blkmem != NULL);
2132 
2133  /* create variable */
2134  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2135  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2136 
2137  /* create event filter for transformed variable */
2138  SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
2139 
2140  /* set variable status and data */
2141  (*var)->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
2142 
2143  /* capture variable */
2144  SCIPvarCapture(*var);
2145 
2146  return SCIP_OKAY;
2147 }
2148 
2149 /** copies and captures a variable from source to target SCIP; an integer variable with bounds zero and one is
2150  * automatically converted into a binary variable; in case the variable data cannot be copied the variable is not
2151  * copied at all
2152  */
2154  SCIP_VAR** var, /**< pointer to store the target variable */
2155  BMS_BLKMEM* blkmem, /**< block memory */
2156  SCIP_SET* set, /**< global SCIP settings */
2157  SCIP_STAT* stat, /**< problem statistics */
2158  SCIP* sourcescip, /**< source SCIP data structure */
2159  SCIP_VAR* sourcevar, /**< source variable */
2160  SCIP_HASHMAP* varmap, /**< a hashmap to store the mapping of source variables corresponding
2161  * target variables */
2162  SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
2163  * target constraints */
2164  SCIP_Bool global /**< should global or local bounds be used? */
2165  )
2166 {
2167  SCIP_VARDATA* targetdata;
2168  SCIP_RESULT result;
2169  SCIP_Real lb;
2170  SCIP_Real ub;
2171 
2172  assert(set != NULL);
2173  assert(blkmem != NULL);
2174  assert(stat != NULL);
2175  assert(sourcescip != NULL);
2176  assert(sourcevar != NULL);
2177  assert(var != NULL);
2178  assert(set->stage == SCIP_STAGE_PROBLEM);
2179  assert(varmap != NULL);
2180  assert(consmap != NULL);
2181 
2182  /** @todo copy hole lists */
2183  assert(global || SCIPvarGetHolelistLocal(sourcevar) == NULL);
2184  assert(!global || SCIPvarGetHolelistGlobal(sourcevar) == NULL);
2185 
2186  result = SCIP_DIDNOTRUN;
2187  targetdata = NULL;
2188 
2189  if( SCIPvarGetStatus(sourcevar) == SCIP_VARSTATUS_ORIGINAL )
2190  {
2191  lb = SCIPvarGetLbOriginal(sourcevar);
2192  ub = SCIPvarGetUbOriginal(sourcevar);
2193  }
2194  else
2195  {
2196  lb = global ? SCIPvarGetLbGlobal(sourcevar) : SCIPvarGetLbLocal(sourcevar);
2197  ub = global ? SCIPvarGetUbGlobal(sourcevar) : SCIPvarGetUbLocal(sourcevar);
2198  }
2199 
2200  /* creates and captures the variable in the target SCIP and initialize callback methods and variable data to NULL */
2201  SCIP_CALL( SCIPvarCreateOriginal(var, blkmem, set, stat, SCIPvarGetName(sourcevar),
2202  lb, ub, SCIPvarGetObj(sourcevar), SCIPvarGetType(sourcevar),
2203  SCIPvarIsInitial(sourcevar), SCIPvarIsRemovable(sourcevar),
2204  NULL, NULL, NULL, NULL, NULL) );
2205  assert(*var != NULL);
2206 
2207  /* directly copy donot(mult)aggr flag */
2208  (*var)->donotaggr = sourcevar->donotaggr;
2209  (*var)->donotmultaggr = sourcevar->donotmultaggr;
2210 
2211  /* insert variable into mapping between source SCIP and the target SCIP */
2212  assert(!SCIPhashmapExists(varmap, sourcevar));
2213  SCIP_CALL( SCIPhashmapInsert(varmap, sourcevar, *var) );
2214 
2215  /* in case there exists variable data and the variable data copy callback, try to copy variable data */
2216  if( sourcevar->vardata != NULL && sourcevar->varcopy != NULL )
2217  {
2218  SCIP_CALL( sourcevar->varcopy(set->scip, sourcescip, sourcevar, sourcevar->vardata,
2219  varmap, consmap, (*var), &targetdata, &result) );
2220 
2221  /* evaluate result */
2222  if( result != SCIP_DIDNOTRUN && result != SCIP_SUCCESS )
2223  {
2224  SCIPerrorMessage("variable data copying method returned invalid result <%d>\n", result);
2225  return SCIP_INVALIDRESULT;
2226  }
2227 
2228  assert(targetdata == NULL || result == SCIP_SUCCESS);
2229 
2230  /* if copying was successful, add the created variable data to the variable as well as all callback methods */
2231  if( result == SCIP_SUCCESS )
2232  {
2233  (*var)->varcopy = sourcevar->varcopy;
2234  (*var)->vardelorig = sourcevar->vardelorig;
2235  (*var)->vartrans = sourcevar->vartrans;
2236  (*var)->vardeltrans = sourcevar->vardeltrans;
2237  (*var)->vardata = targetdata;
2238  }
2239  }
2240 
2241  /* we initialize histories of the variables by copying the source variable-information */
2242  if( set->history_allowtransfer )
2243  {
2244  SCIPvarMergeHistories((*var), sourcevar, stat);
2245  }
2246 
2247  /* in case the copying was successfully, add the created variable data to the variable as well as all callback
2248  * methods
2249  */
2250  if( result == SCIP_SUCCESS )
2251  {
2252  (*var)->varcopy = sourcevar->varcopy;
2253  (*var)->vardelorig = sourcevar->vardelorig;
2254  (*var)->vartrans = sourcevar->vartrans;
2255  (*var)->vardeltrans = sourcevar->vardeltrans;
2256  (*var)->vardata = targetdata;
2257  }
2258 
2259  SCIPsetDebugMsg(set, "created copy <%s> of variable <%s>\n", SCIPvarGetName(*var), SCIPvarGetName(sourcevar));
2260 
2261  return SCIP_OKAY;
2262 }
2263 
2264 /** parse given string for a SCIP_Real bound */
2265 static
2267  SCIP_SET* set, /**< global SCIP settings */
2268  const char* str, /**< string to parse */
2269  SCIP_Real* value, /**< pointer to store the parsed value */
2270  char** endptr /**< pointer to store the final string position if successfully parsed */
2271  )
2272 {
2273  /* first check for infinity value */
2274  if( strncmp(str, "+inf", 4) == 0 )
2275  {
2276  *value = SCIPsetInfinity(set);
2277  (*endptr) = (char*)str + 4;
2278  }
2279  else if( strncmp(str, "-inf", 4) == 0 )
2280  {
2281  *value = -SCIPsetInfinity(set);
2282  (*endptr) = (char*)str + 4;
2283  }
2284  else
2285  {
2286  if( !SCIPstrToRealValue(str, value, endptr) )
2287  {
2288  SCIPerrorMessage("expected value: %s.\n", str);
2289  return SCIP_READERROR;
2290  }
2291  }
2292 
2293  return SCIP_OKAY;
2294 }
2295 
2296 /** parse the characters as bounds */
2297 static
2299  SCIP_SET* set, /**< global SCIP settings */
2300  const char* str, /**< string to parse */
2301  char* type, /**< bound type (global, local, or lazy) */
2302  SCIP_Real* lb, /**< pointer to store the lower bound */
2303  SCIP_Real* ub, /**< pointer to store the upper bound */
2304  char** endptr /**< pointer to store the final string position if successfully parsed (or NULL if an error occured) */
2305  )
2306 {
2307  char token[SCIP_MAXSTRLEN];
2308  char* tmpend;
2309 
2310  SCIPsetDebugMsg(set, "parsing bounds: '%s'\n", str);
2311 
2312  /* get bound type */
2313  SCIPstrCopySection(str, ' ', ' ', type, SCIP_MAXSTRLEN, endptr);
2314  if ( strncmp(type, "original", 8) != 0 && strncmp(type, "global", 6) != 0 && strncmp(type, "local", 5) != 0 && strncmp(type, "lazy", 4) != 0 )
2315  {
2316  SCIPsetDebugMsg(set, "unkown bound type <%s>\n", type);
2317  *endptr = NULL;
2318  return SCIP_OKAY;
2319  }
2320 
2321  SCIPsetDebugMsg(set, "parsed bound type <%s>\n", type);
2322 
2323  /* get lower bound */
2324  SCIPstrCopySection(str, '[', ',', token, SCIP_MAXSTRLEN, endptr);
2325  str = *endptr;
2326  SCIP_CALL( parseValue(set, token, lb, &tmpend) );
2327 
2328  /* get upper bound */
2329  SCIP_CALL( parseValue(set, str, ub, endptr) );
2330 
2331  SCIPsetDebugMsg(set, "parsed bounds: [%g,%g]\n", *lb, *ub);
2332 
2333  /* skip end of bounds */
2334  while ( **endptr != '\0' && (**endptr == ']' || **endptr == ',') )
2335  ++(*endptr);
2336 
2337  return SCIP_OKAY;
2338 }
2339 
2340 /** parses a given string for a variable informations */
2341 static
2343  SCIP_SET* set, /**< global SCIP settings */
2344  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2345  const char* str, /**< string to parse */
2346  char* name, /**< pointer to store the variable name */
2347  SCIP_Real* lb, /**< pointer to store the lower bound */
2348  SCIP_Real* ub, /**< pointer to store the upper bound */
2349  SCIP_Real* obj, /**< pointer to store the objective coefficient */
2350  SCIP_VARTYPE* vartype, /**< pointer to store the variable type */
2351  SCIP_Real* lazylb, /**< pointer to store if the lower bound is lazy */
2352  SCIP_Real* lazyub, /**< pointer to store if the upper bound is lazy */
2353  SCIP_Bool local, /**< should the local bound be applied */
2354  char** endptr, /**< pointer to store the final string position if successfully */
2355  SCIP_Bool* success /**< pointer store if the paring process was successful */
2356  )
2357 {
2358  SCIP_Real parsedlb;
2359  SCIP_Real parsedub;
2360  char token[SCIP_MAXSTRLEN];
2361  char* strptr;
2362  int i;
2363 
2364  assert(lb != NULL);
2365  assert(ub != NULL);
2366  assert(obj != NULL);
2367  assert(vartype != NULL);
2368  assert(lazylb != NULL);
2369  assert(lazyub != NULL);
2370  assert(success != NULL);
2371 
2372  (*success) = TRUE;
2373 
2374  /* copy variable type */
2375  SCIPstrCopySection(str, '[', ']', token, SCIP_MAXSTRLEN, endptr);
2376  assert(str != *endptr);
2377  SCIPsetDebugMsg(set, "parsed variable type <%s>\n", token);
2378 
2379  /* get variable type */
2380  if( strncmp(token, "binary", 3) == 0 )
2381  (*vartype) = SCIP_VARTYPE_BINARY;
2382  else if( strncmp(token, "integer", 3) == 0 )
2383  (*vartype) = SCIP_VARTYPE_INTEGER;
2384  else if( strncmp(token, "implicit", 3) == 0 )
2385  (*vartype) = SCIP_VARTYPE_IMPLINT;
2386  else if( strncmp(token, "continuous", 3) == 0 )
2387  (*vartype) = SCIP_VARTYPE_CONTINUOUS;
2388  else
2389  {
2390  SCIPmessagePrintWarning(messagehdlr, "unknown variable type\n");
2391  (*success) = FALSE;
2392  return SCIP_OKAY;
2393  }
2394 
2395  /* move string pointer behind variable type */
2396  str = *endptr;
2397 
2398  /* get variable name */
2399  SCIPstrCopySection(str, '<', '>', name, SCIP_MAXSTRLEN, endptr);
2400  assert(endptr != NULL);
2401  SCIPsetDebugMsg(set, "parsed variable name <%s>\n", name);
2402 
2403  /* move string pointer behind variable name */
2404  str = *endptr;
2405 
2406  /* cut out objective coefficient */
2407  SCIPstrCopySection(str, '=', ',', token, SCIP_MAXSTRLEN, endptr);
2408 
2409  /* move string pointer behind objective coefficient */
2410  str = *endptr;
2411 
2412  /* get objective coefficient */
2413  if( !SCIPstrToRealValue(token, obj, endptr) )
2414  {
2415  *endptr = NULL;
2416  return SCIP_READERROR;
2417  }
2418 
2419  SCIPsetDebugMsg(set, "parsed objective coefficient <%g>\n", *obj);
2420 
2421  /* parse global/original bounds */
2422  SCIP_CALL( parseBounds(set, str, token, lb, ub, endptr) );
2423  if ( *endptr == NULL )
2424  {
2425  SCIPerrorMessage("Expected bound type: %s.\n", token);
2426  return SCIP_READERROR;
2427  }
2428  assert(strncmp(token, "global", 6) == 0 || strncmp(token, "original", 8) == 0);
2429 
2430  /* initialize the lazy bound */
2431  *lazylb = -SCIPsetInfinity(set);
2432  *lazyub = SCIPsetInfinity(set);
2433 
2434  /* store pointer */
2435  strptr = *endptr;
2436 
2437  /* possibly parse optional local and lazy bounds */
2438  for( i = 0; i < 2 && *endptr != NULL && **endptr != '\0'; ++i )
2439  {
2440  /* start after previous bounds */
2441  strptr = *endptr;
2442 
2443  /* parse global bounds */
2444  SCIP_CALL( parseBounds(set, strptr, token, &parsedlb, &parsedub, endptr) );
2445 
2446  /* stop if parsing of bounds failed */
2447  if( *endptr == NULL )
2448  break;
2449 
2450  if( strncmp(token, "local", 5) == 0 && local )
2451  {
2452  *lb = parsedlb;
2453  *ub = parsedub;
2454  }
2455  else if( strncmp(token, "lazy", 4) == 0 )
2456  {
2457  *lazylb = parsedlb;
2458  *lazyub = parsedub;
2459  }
2460  }
2461 
2462  /* restore pointer */
2463  if ( *endptr == NULL )
2464  *endptr = strptr;
2465 
2466  /* check bounds for binary variables */
2467  if ( (*vartype) == SCIP_VARTYPE_BINARY )
2468  {
2469  if ( SCIPsetIsLT(set, *lb, 0.0) || SCIPsetIsGT(set, *ub, 1.0) )
2470  {
2471  SCIPerrorMessage("Parsed invalid bounds for binary variable <%s>: [%f, %f].\n", name, *lb, *ub);
2472  return SCIP_READERROR;
2473  }
2474  if ( !SCIPsetIsInfinity(set, -(*lazylb)) && !SCIPsetIsInfinity(set, *lazyub) &&
2475  ( SCIPsetIsLT(set, *lazylb, 0.0) || SCIPsetIsGT(set, *lazyub, 1.0) ) )
2476  {
2477  SCIPerrorMessage("Parsed invalid lazy bounds for binary variable <%s>: [%f, %f].\n", name, *lazylb, *lazyub);
2478  return SCIP_READERROR;
2479  }
2480  }
2481 
2482  return SCIP_OKAY;
2483 }
2484 
2485 /** parses variable information (in cip format) out of a string; if the parsing process was successful an original
2486  * variable is created and captured; if variable is of integral type, fractional bounds are automatically rounded; an
2487  * integer variable with bounds zero and one is automatically converted into a binary variable
2488  */
2490  SCIP_VAR** var, /**< pointer to variable data */
2491  BMS_BLKMEM* blkmem, /**< block memory */
2492  SCIP_SET* set, /**< global SCIP settings */
2493  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2494  SCIP_STAT* stat, /**< problem statistics */
2495  const char* str, /**< string to parse */
2496  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2497  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2498  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2499  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable */
2500  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data */
2501  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable */
2502  SCIP_VARDATA* vardata, /**< user data for this specific variable */
2503  char** endptr, /**< pointer to store the final string position if successfully */
2504  SCIP_Bool* success /**< pointer store if the paring process was successful */
2505  )
2506 {
2507  char name[SCIP_MAXSTRLEN];
2508  SCIP_Real lb;
2509  SCIP_Real ub;
2510  SCIP_Real obj;
2511  SCIP_VARTYPE vartype;
2512  SCIP_Real lazylb;
2513  SCIP_Real lazyub;
2514 
2515  assert(var != NULL);
2516  assert(blkmem != NULL);
2517  assert(stat != NULL);
2518  assert(endptr != NULL);
2519  assert(success != NULL);
2520 
2521  /* parse string in cip format for variable information */
2522  SCIP_CALL( varParse(set, messagehdlr, str, name, &lb, &ub, &obj, &vartype, &lazylb, &lazyub, FALSE, endptr, success) );
2523 
2524  if( *success ) /*lint !e774*/
2525  {
2526  /* create variable */
2527  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2528  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2529 
2530  /* set variable status and data */
2531  (*var)->varstatus = SCIP_VARSTATUS_ORIGINAL; /*lint !e641*/
2532  (*var)->data.original.origdom.holelist = NULL;
2533  (*var)->data.original.origdom.lb = lb;
2534  (*var)->data.original.origdom.ub = ub;
2535  (*var)->data.original.transvar = NULL;
2536 
2537  /* set lazy status of variable bounds */
2538  (*var)->lazylb = lazylb;
2539  (*var)->lazyub = lazyub;
2540 
2541  /* capture variable */
2542  SCIPvarCapture(*var);
2543  }
2544 
2545  return SCIP_OKAY;
2546 }
2547 
2548 /** parses variable information (in cip format) out of a string; if the parsing process was successful a loose variable
2549  * belonging to the transformed problem is created and captured; if variable is of integral type, fractional bounds are
2550  * automatically rounded; an integer variable with bounds zero and one is automatically converted into a binary
2551  * variable
2552  */
2554  SCIP_VAR** var, /**< pointer to variable data */
2555  BMS_BLKMEM* blkmem, /**< block memory */
2556  SCIP_SET* set, /**< global SCIP settings */
2557  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2558  SCIP_STAT* stat, /**< problem statistics */
2559  const char* str, /**< string to parse */
2560  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2561  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2562  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2563  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable */
2564  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data */
2565  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable */
2566  SCIP_VARDATA* vardata, /**< user data for this specific variable */
2567  char** endptr, /**< pointer to store the final string position if successfully */
2568  SCIP_Bool* success /**< pointer store if the paring process was successful */
2569  )
2570 {
2571  char name[SCIP_MAXSTRLEN];
2572  SCIP_Real lb;
2573  SCIP_Real ub;
2574  SCIP_Real obj;
2575  SCIP_VARTYPE vartype;
2576  SCIP_Real lazylb;
2577  SCIP_Real lazyub;
2578 
2579  assert(var != NULL);
2580  assert(blkmem != NULL);
2581  assert(endptr != NULL);
2582  assert(success != NULL);
2583 
2584  /* parse string in cip format for variable information */
2585  SCIP_CALL( varParse(set, messagehdlr, str, name, &lb, &ub, &obj, &vartype, &lazylb, &lazyub, TRUE, endptr, success) );
2586 
2587  if( *success ) /*lint !e774*/
2588  {
2589  /* create variable */
2590  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2591  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2592 
2593  /* create event filter for transformed variable */
2594  SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
2595 
2596  /* set variable status and data */
2597  (*var)->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
2598 
2599  /* set lazy status of variable bounds */
2600  (*var)->lazylb = lazylb;
2601  (*var)->lazyub = lazyub;
2602 
2603  /* capture variable */
2604  SCIPvarCapture(*var);
2605  }
2606 
2607  return SCIP_OKAY;
2608 }
2609 
2610 /** ensures, that parentvars array of var can store at least num entries */
2611 static
2613  SCIP_VAR* var, /**< problem variable */
2614  BMS_BLKMEM* blkmem, /**< block memory */
2615  SCIP_SET* set, /**< global SCIP settings */
2616  int num /**< minimum number of entries to store */
2617  )
2618 {
2619  assert(var->nparentvars <= var->parentvarssize);
2620 
2621  if( num > var->parentvarssize )
2622  {
2623  int newsize;
2624 
2625  newsize = SCIPsetCalcMemGrowSize(set, num);
2626  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->parentvars, var->parentvarssize, newsize) );
2627  var->parentvarssize = newsize;
2628  }
2629  assert(num <= var->parentvarssize);
2630 
2631  return SCIP_OKAY;
2632 }
2633 
2634 /** adds variable to parent list of a variable and captures parent variable */
2635 static
2637  SCIP_VAR* var, /**< variable to add parent to */
2638  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
2639  SCIP_SET* set, /**< global SCIP settings */
2640  SCIP_VAR* parentvar /**< parent variable to add */
2641  )
2642 {
2643  assert(var != NULL);
2644  assert(parentvar != NULL);
2645 
2646  /* the direct original counterpart must be stored as first parent */
2647  assert(var->nparentvars == 0 || SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL);
2648 
2649  SCIPsetDebugMsg(set, "adding parent <%s>[%p] to variable <%s>[%p] in slot %d\n",
2650  parentvar->name, (void*)parentvar, var->name, (void*)var, var->nparentvars);
2651 
2652  SCIP_CALL( varEnsureParentvarsSize(var, blkmem, set, var->nparentvars+1) );
2653 
2654  var->parentvars[var->nparentvars] = parentvar;
2655  var->nparentvars++;
2656 
2657  SCIPvarCapture(parentvar);
2658 
2659  return SCIP_OKAY;
2660 }
2661 
2662 /** deletes and releases all variables from the parent list of a variable, frees the memory of parents array */
2663 static
2665  SCIP_VAR** var, /**< pointer to variable */
2666  BMS_BLKMEM* blkmem, /**< block memory */
2667  SCIP_SET* set, /**< global SCIP settings */
2668  SCIP_EVENTQUEUE* eventqueue, /**< event queue (or NULL, if it's an original variable) */
2669  SCIP_LP* lp /**< current LP data (or NULL, if it's an original variable) */
2670  )
2671 {
2672  SCIP_VAR* parentvar;
2673  int i;
2674 
2675  SCIPsetDebugMsg(set, "free parents of <%s>\n", (*var)->name);
2676 
2677  /* release the parent variables and remove the link from the parent variable to the child */
2678  for( i = 0; i < (*var)->nparentvars; ++i )
2679  {
2680  assert((*var)->parentvars != NULL);
2681  parentvar = (*var)->parentvars[i];
2682  assert(parentvar != NULL);
2683 
2684  switch( SCIPvarGetStatus(parentvar) )
2685  {
2687  assert(parentvar->data.original.transvar == *var);
2688  assert(&parentvar->data.original.transvar != var);
2689  parentvar->data.original.transvar = NULL;
2690  break;
2691 
2693  assert(parentvar->data.aggregate.var == *var);
2694  assert(&parentvar->data.aggregate.var != var);
2695  parentvar->data.aggregate.var = NULL;
2696  break;
2697 
2698 #if 0
2699  /* The following code is unclear: should the current variable be removed from its parents? */
2701  assert(parentvar->data.multaggr.vars != NULL);
2702  for( v = 0; v < parentvar->data.multaggr.nvars && parentvar->data.multaggr.vars[v] != *var; ++v )
2703  {}
2704  assert(v < parentvar->data.multaggr.nvars && parentvar->data.multaggr.vars[v] == *var);
2705  if( v < parentvar->data.multaggr.nvars-1 )
2706  {
2707  parentvar->data.multaggr.vars[v] = parentvar->data.multaggr.vars[parentvar->data.multaggr.nvars-1];
2708  parentvar->data.multaggr.scalars[v] = parentvar->data.multaggr.scalars[parentvar->data.multaggr.nvars-1];
2709  }
2710  parentvar->data.multaggr.nvars--;
2711  break;
2712 #endif
2713 
2715  assert(parentvar->negatedvar == *var);
2716  assert((*var)->negatedvar == parentvar);
2717  parentvar->negatedvar = NULL;
2718  (*var)->negatedvar = NULL;
2719  break;
2720 
2721  default:
2722  SCIPerrorMessage("parent variable is neither ORIGINAL, AGGREGATED nor NEGATED\n");
2723  return SCIP_INVALIDDATA;
2724  } /*lint !e788*/
2725 
2726  SCIP_CALL( SCIPvarRelease(&(*var)->parentvars[i], blkmem, set, eventqueue, lp) );
2727  }
2728 
2729  /* free parentvars array */
2730  BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->parentvars, (*var)->parentvarssize);
2731 
2732  return SCIP_OKAY;
2733 }
2734 
2735 /** frees a variable */
2736 static
2738  SCIP_VAR** var, /**< pointer to variable */
2739  BMS_BLKMEM* blkmem, /**< block memory */
2740  SCIP_SET* set, /**< global SCIP settings */
2741  SCIP_EVENTQUEUE* eventqueue, /**< event queue (may be NULL, if it's not a column variable) */
2742  SCIP_LP* lp /**< current LP data (may be NULL, if it's not a column variable) */
2743  )
2744 {
2745  assert(var != NULL);
2746  assert(*var != NULL);
2747  assert(SCIPvarGetStatus(*var) != SCIP_VARSTATUS_COLUMN || &(*var)->data.col->var != var);
2748  assert((*var)->nuses == 0);
2749  assert((*var)->probindex == -1);
2750  assert((*var)->nlocksup[SCIP_LOCKTYPE_MODEL] == 0);
2751  assert((*var)->nlocksdown[SCIP_LOCKTYPE_MODEL] == 0);
2752 
2753  SCIPsetDebugMsg(set, "free variable <%s> with status=%d\n", (*var)->name, SCIPvarGetStatus(*var));
2754 
2755  switch( SCIPvarGetStatus(*var) )
2756  {
2758  assert((*var)->data.original.transvar == NULL); /* cannot free variable, if transformed variable is still existing */
2759  holelistFree(&(*var)->data.original.origdom.holelist, blkmem);
2760  assert((*var)->data.original.origdom.holelist == NULL);
2761  break;
2762  case SCIP_VARSTATUS_LOOSE:
2763  break;
2764  case SCIP_VARSTATUS_COLUMN:
2765  SCIP_CALL( SCIPcolFree(&(*var)->data.col, blkmem, set, eventqueue, lp) ); /* free corresponding LP column */
2766  break;
2767  case SCIP_VARSTATUS_FIXED:
2769  break;
2771  BMSfreeBlockMemoryArray(blkmem, &(*var)->data.multaggr.vars, (*var)->data.multaggr.varssize);
2772  BMSfreeBlockMemoryArray(blkmem, &(*var)->data.multaggr.scalars, (*var)->data.multaggr.varssize);
2773  break;
2775  break;
2776  default:
2777  SCIPerrorMessage("unknown variable status\n");
2778  return SCIP_INVALIDDATA;
2779  }
2780 
2781  /* release all parent variables and free the parentvars array */
2782  SCIP_CALL( varFreeParents(var, blkmem, set, eventqueue, lp) );
2783 
2784  /* free user data */
2786  {
2787  if( (*var)->vardelorig != NULL )
2788  {
2789  SCIP_CALL( (*var)->vardelorig(set->scip, *var, &(*var)->vardata) );
2790  }
2791  }
2792  else
2793  {
2794  if( (*var)->vardeltrans != NULL )
2795  {
2796  SCIP_CALL( (*var)->vardeltrans(set->scip, *var, &(*var)->vardata) );
2797  }
2798  }
2799 
2800  /* free event filter */
2801  if( (*var)->eventfilter != NULL )
2802  {
2803  SCIP_CALL( SCIPeventfilterFree(&(*var)->eventfilter, blkmem, set) );
2804  }
2805  assert((*var)->eventfilter == NULL);
2806 
2807  /* free hole lists */
2808  holelistFree(&(*var)->glbdom.holelist, blkmem);
2809  holelistFree(&(*var)->locdom.holelist, blkmem);
2810  assert((*var)->glbdom.holelist == NULL);
2811  assert((*var)->locdom.holelist == NULL);
2812 
2813  /* free variable bounds data structures */
2814  SCIPvboundsFree(&(*var)->vlbs, blkmem);
2815  SCIPvboundsFree(&(*var)->vubs, blkmem);
2816 
2817  /* free implications data structures */
2818  SCIPimplicsFree(&(*var)->implics, blkmem);
2819 
2820  /* free clique list data structures */
2821  SCIPcliquelistFree(&(*var)->cliquelist, blkmem);
2822 
2823  /* free bound change information arrays */
2824  BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->lbchginfos, (*var)->lbchginfossize);
2825  BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->ubchginfos, (*var)->ubchginfossize);
2826 
2827  /* free branching and inference history entries */
2828  SCIPhistoryFree(&(*var)->history, blkmem);
2829  SCIPhistoryFree(&(*var)->historycrun, blkmem);
2830  SCIPvaluehistoryFree(&(*var)->valuehistory, blkmem);
2831 
2832  /* free variable data structure */
2833  BMSfreeBlockMemoryArray(blkmem, &(*var)->name, strlen((*var)->name)+1);
2834  BMSfreeBlockMemory(blkmem, var);
2835 
2836  return SCIP_OKAY;
2837 }
2838 
2839 /** increases usage counter of variable */
2840 void SCIPvarCapture(
2841  SCIP_VAR* var /**< variable */
2842  )
2843 {
2844  assert(var != NULL);
2845  assert(var->nuses >= 0);
2846 
2847  SCIPdebugMessage("capture variable <%s> with nuses=%d\n", var->name, var->nuses);
2848  var->nuses++;
2849 
2850 #ifdef DEBUGUSES_VARNAME
2851  if( strcmp(var->name, DEBUGUSES_VARNAME) == 0
2852 #ifdef DEBUGUSES_PROBNAME
2853  && ((var->scip->transprob != NULL && strcmp(SCIPprobGetName(var->scip->transprob), DEBUGUSES_PROBNAME) == 0) ||
2854  strcmp(SCIPprobGetName(var->scip->origprob), DEBUGUSES_PROBNAME) == 0)
2855 #endif
2856  )
2857  {
2858  printf("Captured variable " DEBUGUSES_VARNAME " in SCIP %p, now %d uses; captured at\n", (void*)var->scip, var->nuses);
2859  print_backtrace();
2860  }
2861 #endif
2862 }
2863 
2864 /** decreases usage counter of variable, and frees memory if necessary */
2866  SCIP_VAR** var, /**< pointer to variable */
2867  BMS_BLKMEM* blkmem, /**< block memory */
2868  SCIP_SET* set, /**< global SCIP settings */
2869  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2870  SCIP_LP* lp /**< current LP data (or NULL, if it's an original variable) */
2871  )
2872 {
2873  assert(var != NULL);
2874  assert(*var != NULL);
2875  assert((*var)->nuses >= 1);
2876  assert(blkmem != NULL);
2877  assert((*var)->scip == set->scip);
2878 
2879  SCIPsetDebugMsg(set, "release variable <%s> with nuses=%d\n", (*var)->name, (*var)->nuses);
2880  (*var)->nuses--;
2881 
2882 #ifdef DEBUGUSES_VARNAME
2883  if( strcmp((*var)->name, DEBUGUSES_VARNAME) == 0
2884 #ifdef DEBUGUSES_PROBNAME
2885  && (((*var)->scip->transprob != NULL && strcmp(SCIPprobGetName((*var)->scip->transprob), DEBUGUSES_PROBNAME) == 0) ||
2886  strcmp(SCIPprobGetName((*var)->scip->origprob), DEBUGUSES_PROBNAME) == 0)
2887 #endif
2888  )
2889  {
2890  printf("Released variable " DEBUGUSES_VARNAME " in SCIP %p, now %d uses; released at\n", (void*)(*var)->scip, (*var)->nuses);
2891  print_backtrace();
2892  }
2893 #endif
2894 
2895  if( (*var)->nuses == 0 )
2896  {
2897  SCIP_CALL( varFree(var, blkmem, set, eventqueue, lp) );
2898  }
2899 
2900  *var = NULL;
2901 
2902  return SCIP_OKAY;
2903 }
2904 
2905 /** change variable name */
2907  SCIP_VAR* var, /**< problem variable */
2908  BMS_BLKMEM* blkmem, /**< block memory */
2909  const char* name /**< name of variable */
2910  )
2911 {
2912  assert(name != NULL);
2913 
2914  /* remove old variable name */
2915  BMSfreeBlockMemoryArray(blkmem, &var->name, strlen(var->name)+1);
2916 
2917  /* set new variable name */
2918  SCIP_CALL( varSetName(var, blkmem, NULL, name) );
2919 
2920  return SCIP_OKAY;
2921 }
2922 
2923 /** initializes variable data structure for solving */
2924 void SCIPvarInitSolve(
2925  SCIP_VAR* var /**< problem variable */
2926  )
2927 {
2928  assert(var != NULL);
2929 
2931  var->conflictlbcount = 0;
2932  var->conflictubcount = 0;
2933 }
2934 
2935 /** outputs the given bounds into the file stream */
2936 static
2937 void printBounds(
2938  SCIP_SET* set, /**< global SCIP settings */
2939  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2940  FILE* file, /**< output file (or NULL for standard output) */
2941  SCIP_Real lb, /**< lower bound */
2942  SCIP_Real ub, /**< upper bound */
2943  const char* name /**< bound type name */
2944  )
2945 {
2946  assert(set != NULL);
2947 
2948  SCIPmessageFPrintInfo(messagehdlr, file, ", %s=", name);
2949  if( SCIPsetIsInfinity(set, lb) )
2950  SCIPmessageFPrintInfo(messagehdlr, file, "[+inf,");
2951  else if( SCIPsetIsInfinity(set, -lb) )
2952  SCIPmessageFPrintInfo(messagehdlr, file, "[-inf,");
2953  else
2954  SCIPmessageFPrintInfo(messagehdlr, file, "[%.15g,", lb);
2955  if( SCIPsetIsInfinity(set, ub) )
2956  SCIPmessageFPrintInfo(messagehdlr, file, "+inf]");
2957  else if( SCIPsetIsInfinity(set, -ub) )
2958  SCIPmessageFPrintInfo(messagehdlr, file, "-inf]");
2959  else
2960  SCIPmessageFPrintInfo(messagehdlr, file, "%.15g]", ub);
2961 }
2962 
2963 /** prints hole list to file stream */
2964 static
2965 void printHolelist(
2966  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2967  FILE* file, /**< output file (or NULL for standard output) */
2968  SCIP_HOLELIST* holelist, /**< hole list pointer to hole of interest */
2969  const char* name /**< hole type name */
2970  )
2971 { /*lint --e{715}*/
2972  SCIP_Real left;
2973  SCIP_Real right;
2974 
2975  if( holelist == NULL )
2976  return;
2977 
2978  left = SCIPholelistGetLeft(holelist);
2979  right = SCIPholelistGetRight(holelist);
2980 
2981  /* display first hole */
2982  SCIPmessageFPrintInfo(messagehdlr, file, ", %s=(%g,%g)", name, left, right);
2983  holelist = SCIPholelistGetNext(holelist);
2984 
2985  while(holelist != NULL )
2986  {
2987  left = SCIPholelistGetLeft(holelist);
2988  right = SCIPholelistGetRight(holelist);
2989 
2990  /* display hole */
2991  SCIPmessageFPrintInfo(messagehdlr, file, "(%g,%g)", left, right);
2992 
2993  /* get next hole */
2994  holelist = SCIPholelistGetNext(holelist);
2995  }
2996 }
2997 
2998 /** outputs variable information into file stream */
3000  SCIP_VAR* var, /**< problem variable */
3001  SCIP_SET* set, /**< global SCIP settings */
3002  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3003  FILE* file /**< output file (or NULL for standard output) */
3004  )
3005 {
3006  SCIP_HOLELIST* holelist;
3007  SCIP_Real lb;
3008  SCIP_Real ub;
3009  int i;
3010 
3011  assert(var != NULL);
3012  assert(var->scip == set->scip);
3013 
3014  /* type of variable */
3015  switch( SCIPvarGetType(var) )
3016  {
3017  case SCIP_VARTYPE_BINARY:
3018  SCIPmessageFPrintInfo(messagehdlr, file, " [binary]");
3019  break;
3020  case SCIP_VARTYPE_INTEGER:
3021  SCIPmessageFPrintInfo(messagehdlr, file, " [integer]");
3022  break;
3023  case SCIP_VARTYPE_IMPLINT:
3024  SCIPmessageFPrintInfo(messagehdlr, file, " [implicit]");
3025  break;
3027  SCIPmessageFPrintInfo(messagehdlr, file, " [continuous]");
3028  break;
3029  default:
3030  SCIPerrorMessage("unknown variable type\n");
3031  SCIPABORT();
3032  return SCIP_ERROR; /*lint !e527*/
3033  }
3034 
3035  /* name */
3036  SCIPmessageFPrintInfo(messagehdlr, file, " <%s>:", var->name);
3037 
3038  /* objective value */
3039  SCIPmessageFPrintInfo(messagehdlr, file, " obj=%.15g", var->obj);
3040 
3041  /* bounds (global bounds for transformed variables, original bounds for original variables) */
3042  if( !SCIPvarIsTransformed(var) )
3043  {
3044  /* output original bound */
3045  lb = SCIPvarGetLbOriginal(var);
3046  ub = SCIPvarGetUbOriginal(var);
3047  printBounds(set, messagehdlr, file, lb, ub, "original bounds");
3048 
3049  /* output lazy bound */
3050  lb = SCIPvarGetLbLazy(var);
3051  ub = SCIPvarGetUbLazy(var);
3052 
3053  /* only display the lazy bounds if they are different from [-infinity,infinity] */
3054  if( !SCIPsetIsInfinity(set, -lb) || !SCIPsetIsInfinity(set, ub) )
3055  printBounds(set, messagehdlr, file, lb, ub, "lazy bounds");
3056 
3057  holelist = SCIPvarGetHolelistOriginal(var);
3058  printHolelist(messagehdlr, file, holelist, "original holes");
3059  }
3060  else
3061  {
3062  /* output global bound */
3063  lb = SCIPvarGetLbGlobal(var);
3064  ub = SCIPvarGetUbGlobal(var);
3065  printBounds(set, messagehdlr, file, lb, ub, "global bounds");
3066 
3067  /* output local bound */
3068  lb = SCIPvarGetLbLocal(var);
3069  ub = SCIPvarGetUbLocal(var);
3070  printBounds(set, messagehdlr, file, lb, ub, "local bounds");
3071 
3072  /* output lazy bound */
3073  lb = SCIPvarGetLbLazy(var);
3074  ub = SCIPvarGetUbLazy(var);
3075 
3076  /* only display the lazy bounds if they are different from [-infinity,infinity] */
3077  if( !SCIPsetIsInfinity(set, -lb) || !SCIPsetIsInfinity(set, ub) )
3078  printBounds(set, messagehdlr, file, lb, ub, "lazy bounds");
3079 
3080  /* global hole list */
3081  holelist = SCIPvarGetHolelistGlobal(var);
3082  printHolelist(messagehdlr, file, holelist, "global holes");
3083 
3084  /* local hole list */
3085  holelist = SCIPvarGetHolelistLocal(var);
3086  printHolelist(messagehdlr, file, holelist, "local holes");
3087  }
3088 
3089  /* fixings and aggregations */
3090  switch( SCIPvarGetStatus(var) )
3091  {
3093  case SCIP_VARSTATUS_LOOSE:
3094  case SCIP_VARSTATUS_COLUMN:
3095  break;
3096 
3097  case SCIP_VARSTATUS_FIXED:
3098  SCIPmessageFPrintInfo(messagehdlr, file, ", fixed:");
3099  if( SCIPsetIsInfinity(set, var->glbdom.lb) )
3100  SCIPmessageFPrintInfo(messagehdlr, file, "+inf");
3101  else if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
3102  SCIPmessageFPrintInfo(messagehdlr, file, "-inf");
3103  else
3104  SCIPmessageFPrintInfo(messagehdlr, file, "%.15g", var->glbdom.lb);
3105  break;
3106 
3108  SCIPmessageFPrintInfo(messagehdlr, file, ", aggregated:");
3109  if( !SCIPsetIsZero(set, var->data.aggregate.constant) )
3110  SCIPmessageFPrintInfo(messagehdlr, file, " %.15g", var->data.aggregate.constant);
3111  SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g<%s>", var->data.aggregate.scalar, SCIPvarGetName(var->data.aggregate.var));
3112  break;
3113 
3115  SCIPmessageFPrintInfo(messagehdlr, file, ", aggregated:");
3116  if( var->data.multaggr.nvars == 0 || !SCIPsetIsZero(set, var->data.multaggr.constant) )
3117  SCIPmessageFPrintInfo(messagehdlr, file, " %.15g", var->data.multaggr.constant);
3118  for( i = 0; i < var->data.multaggr.nvars; ++i )
3119  SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g<%s>", var->data.multaggr.scalars[i], SCIPvarGetName(var->data.multaggr.vars[i]));
3120  break;
3121 
3123  SCIPmessageFPrintInfo(messagehdlr, file, ", negated: %.15g - <%s>", var->data.negate.constant, SCIPvarGetName(var->negatedvar));
3124  break;
3125 
3126  default:
3127  SCIPerrorMessage("unknown variable status\n");
3128  SCIPABORT();
3129  return SCIP_ERROR; /*lint !e527*/
3130  }
3131 
3132  SCIPmessageFPrintInfo(messagehdlr, file, "\n");
3133 
3134  return SCIP_OKAY;
3135 }
3136 
3137 /** issues a VARUNLOCKED event on the given variable */
3138 static
3140  SCIP_VAR* var, /**< problem variable to change */
3141  BMS_BLKMEM* blkmem, /**< block memory */
3142  SCIP_SET* set, /**< global SCIP settings */
3143  SCIP_EVENTQUEUE* eventqueue /**< event queue */
3144  )
3145 {
3146  SCIP_EVENT* event;
3147 
3148  assert(var != NULL);
3149  assert(var->nlocksdown[SCIP_LOCKTYPE_MODEL] <= 1 && var->nlocksup[SCIP_LOCKTYPE_MODEL] <= 1);
3150  assert(var->scip == set->scip);
3151 
3152  /* issue VARUNLOCKED event on variable */
3153  SCIP_CALL( SCIPeventCreateVarUnlocked(&event, blkmem, var) );
3154  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
3155 
3156  return SCIP_OKAY;
3157 }
3158 
3159 /** modifies lock numbers for rounding */
3161  SCIP_VAR* var, /**< problem variable */
3162  BMS_BLKMEM* blkmem, /**< block memory */
3163  SCIP_SET* set, /**< global SCIP settings */
3164  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3165  SCIP_LOCKTYPE locktype, /**< type of the variable locks */
3166  int addnlocksdown, /**< increase in number of rounding down locks */
3167  int addnlocksup /**< increase in number of rounding up locks */
3168  )
3169 {
3170  SCIP_VAR* lockvar;
3171 
3172  assert(var != NULL);
3173  assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
3174  assert(var->nlocksup[locktype] >= 0);
3175  assert(var->nlocksdown[locktype] >= 0);
3176  assert(var->scip == set->scip);
3177 
3178  if( addnlocksdown == 0 && addnlocksup == 0 )
3179  return SCIP_OKAY;
3180 
3181 #ifdef SCIP_DEBUG
3182  SCIPsetDebugMsg(set, "add rounding locks %d/%d to variable <%s> (locks=%d/%d, type=%u)\n",
3183  addnlocksdown, addnlocksup, var->name, var->nlocksdown[locktype], var->nlocksup[locktype], locktype);
3184 #endif
3185 
3186  lockvar = var;
3187 
3188  while( TRUE ) /*lint !e716 */
3189  {
3190  assert(lockvar != NULL);
3191 
3192  switch( SCIPvarGetStatus(lockvar) )
3193  {
3195  if( lockvar->data.original.transvar != NULL )
3196  {
3197  lockvar = lockvar->data.original.transvar;
3198  break;
3199  }
3200  else
3201  {
3202  lockvar->nlocksdown[locktype] += addnlocksdown;
3203  lockvar->nlocksup[locktype] += addnlocksup;
3204 
3205  assert(lockvar->nlocksdown[locktype] >= 0);
3206  assert(lockvar->nlocksup[locktype] >= 0);
3207 
3208  return SCIP_OKAY;
3209  }
3210  case SCIP_VARSTATUS_LOOSE:
3211  case SCIP_VARSTATUS_COLUMN:
3212  case SCIP_VARSTATUS_FIXED:
3213  lockvar->nlocksdown[locktype] += addnlocksdown;
3214  lockvar->nlocksup[locktype] += addnlocksup;
3215 
3216  assert(lockvar->nlocksdown[locktype] >= 0);
3217  assert(lockvar->nlocksup[locktype] >= 0);
3218 
3219  if( locktype == SCIP_LOCKTYPE_MODEL && lockvar->nlocksdown[locktype] <= 1
3220  && lockvar->nlocksup[locktype] <= 1 )
3221  {
3222  SCIP_CALL( varEventVarUnlocked(lockvar, blkmem, set, eventqueue) );
3223  }
3224 
3225  return SCIP_OKAY;
3227  assert(!lockvar->donotaggr);
3228 
3229  if( lockvar->data.aggregate.scalar < 0.0 )
3230  {
3231  int tmp = addnlocksup;
3232 
3233  addnlocksup = addnlocksdown;
3234  addnlocksdown = tmp;
3235  }
3236 
3237  lockvar = lockvar->data.aggregate.var;
3238  break;
3240  {
3241  int v;
3242 
3243  assert(!lockvar->donotmultaggr);
3244 
3245  lockvar->nlocksdown[locktype] += addnlocksdown;
3246  lockvar->nlocksup[locktype] += addnlocksup;
3247 
3248  assert(lockvar->nlocksdown[locktype] >= 0);
3249  assert(lockvar->nlocksup[locktype] >= 0);
3250 
3251  for( v = lockvar->data.multaggr.nvars - 1; v >= 0; --v )
3252  {
3253  if( lockvar->data.multaggr.scalars[v] > 0.0 )
3254  {
3255  SCIP_CALL( SCIPvarAddLocks(lockvar->data.multaggr.vars[v], blkmem, set, eventqueue, locktype, addnlocksdown,
3256  addnlocksup) );
3257  }
3258  else
3259  {
3260  SCIP_CALL( SCIPvarAddLocks(lockvar->data.multaggr.vars[v], blkmem, set, eventqueue, locktype, addnlocksup,
3261  addnlocksdown) );
3262  }
3263  }
3264  return SCIP_OKAY;
3265  }
3267  {
3268  int tmp = addnlocksup;
3269 
3270  assert(lockvar->negatedvar != NULL);
3271  assert(SCIPvarGetStatus(lockvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
3272  assert(lockvar->negatedvar->negatedvar == lockvar);
3273 
3274  addnlocksup = addnlocksdown;
3275  addnlocksdown = tmp;
3276 
3277  lockvar = lockvar->negatedvar;
3278  break;
3279  }
3280  default:
3281  SCIPerrorMessage("unknown variable status\n");
3282  return SCIP_INVALIDDATA;
3283  }
3284  }
3285 }
3286 
3287 /** gets number of locks for rounding down of a special type */
3289  SCIP_VAR* var, /**< problem variable */
3290  SCIP_LOCKTYPE locktype /**< type of variable locks */
3291  )
3292 {
3293  int nlocks;
3294  int i;
3295 
3296  assert(var != NULL);
3297  assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
3298  assert(var->nlocksdown[locktype] >= 0);
3299 
3300  switch( SCIPvarGetStatus(var) )
3301  {
3303  if( var->data.original.transvar != NULL )
3304  return SCIPvarGetNLocksDownType(var->data.original.transvar, locktype);
3305  else
3306  return var->nlocksdown[locktype];
3307 
3308  case SCIP_VARSTATUS_LOOSE:
3309  case SCIP_VARSTATUS_COLUMN:
3310  case SCIP_VARSTATUS_FIXED:
3311  return var->nlocksdown[locktype];
3312 
3314  assert(!var->donotaggr);
3315  if( var->data.aggregate.scalar > 0.0 )
3316  return SCIPvarGetNLocksDownType(var->data.aggregate.var, locktype);
3317  else
3318  return SCIPvarGetNLocksUpType(var->data.aggregate.var, locktype);
3319 
3321  assert(!var->donotmultaggr);
3322  nlocks = 0;
3323  for( i = 0; i < var->data.multaggr.nvars; ++i )
3324  {
3325  if( var->data.multaggr.scalars[i] > 0.0 )
3326  nlocks += SCIPvarGetNLocksDownType(var->data.multaggr.vars[i], locktype);
3327  else
3328  nlocks += SCIPvarGetNLocksUpType(var->data.multaggr.vars[i], locktype);
3329  }
3330  return nlocks;
3331 
3333  assert(var->negatedvar != NULL);
3335  assert(var->negatedvar->negatedvar == var);
3336  return SCIPvarGetNLocksUpType(var->negatedvar, locktype);
3337 
3338  default:
3339  SCIPerrorMessage("unknown variable status\n");
3340  SCIPABORT();
3341  return INT_MAX; /*lint !e527*/
3342  }
3343 }
3344 
3345 /** gets number of locks for rounding up of a special type */
3347  SCIP_VAR* var, /**< problem variable */
3348  SCIP_LOCKTYPE locktype /**< type of variable locks */
3349  )
3350 {
3351  int nlocks;
3352  int i;
3353 
3354  assert(var != NULL);
3355  assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
3356  assert(var->nlocksup[locktype] >= 0);
3357 
3358  switch( SCIPvarGetStatus(var) )
3359  {
3361  if( var->data.original.transvar != NULL )
3362  return SCIPvarGetNLocksUpType(var->data.original.transvar, locktype);
3363  else
3364  return var->nlocksup[locktype];
3365 
3366  case SCIP_VARSTATUS_LOOSE:
3367  case SCIP_VARSTATUS_COLUMN:
3368  case SCIP_VARSTATUS_FIXED:
3369  return var->nlocksup[locktype];
3370 
3372  assert(!var->donotaggr);
3373  if( var->data.aggregate.scalar > 0.0 )
3374  return SCIPvarGetNLocksUpType(var->data.aggregate.var, locktype);
3375  else
3376  return SCIPvarGetNLocksDownType(var->data.aggregate.var, locktype);
3377 
3379  assert(!var->donotmultaggr);
3380  nlocks = 0;
3381  for( i = 0; i < var->data.multaggr.nvars; ++i )
3382  {
3383  if( var->data.multaggr.scalars[i] > 0.0 )
3384  nlocks += SCIPvarGetNLocksUpType(var->data.multaggr.vars[i], locktype);
3385  else
3386  nlocks += SCIPvarGetNLocksDownType(var->data.multaggr.vars[i], locktype);
3387  }
3388  return nlocks;
3389 
3391  assert(var->negatedvar != NULL);
3393  assert(var->negatedvar->negatedvar == var);
3394  return SCIPvarGetNLocksDownType(var->negatedvar, locktype);
3395 
3396  default:
3397  SCIPerrorMessage("unknown variable status\n");
3398  SCIPABORT();
3399  return INT_MAX; /*lint !e527*/
3400  }
3401 }
3402 
3403 /** gets number of locks for rounding down
3404  *
3405  * @note This method will always return variable locks of type model
3406  *
3407  * @note It is recommented to use SCIPvarGetNLocksDownType()
3408  */
3410  SCIP_VAR* var /**< problem variable */
3411  )
3412 {
3414 }
3415 
3416 /** gets number of locks for rounding up
3417  *
3418  * @note This method will always return variable locks of type model
3419  *
3420  * @note It is recommented to use SCIPvarGetNLocksUpType()
3421  */
3422 int SCIPvarGetNLocksUp(
3423  SCIP_VAR* var /**< problem variable */
3424  )
3425 {
3427 }
3428 
3429 /** is it possible, to round variable down and stay feasible?
3430  *
3431  * @note This method will always check w.r.t variable locks of type model
3432  */
3434  SCIP_VAR* var /**< problem variable */
3435  )
3436 {
3437  return (SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 0);
3438 }
3439 
3440 /** is it possible, to round variable up and stay feasible?
3441  *
3442  * @note This method will always check w.r.t. variable locks of type model
3443  */
3445  SCIP_VAR* var /**< problem variable */
3446  )
3447 {
3448  return (SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 0);
3449 }
3450 
3451 /** gets and captures transformed variable of a given variable; if the variable is not yet transformed,
3452  * a new transformed variable for this variable is created
3453  */
3455  SCIP_VAR* origvar, /**< original problem variable */
3456  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3457  SCIP_SET* set, /**< global SCIP settings */
3458  SCIP_STAT* stat, /**< problem statistics */
3459  SCIP_OBJSENSE objsense, /**< objective sense of original problem; transformed is always MINIMIZE */
3460  SCIP_VAR** transvar /**< pointer to store the transformed variable */
3461  )
3462 {
3463  char name[SCIP_MAXSTRLEN];
3464 
3465  assert(origvar != NULL);
3466  assert(origvar->scip == set->scip);
3467  assert(SCIPvarGetStatus(origvar) == SCIP_VARSTATUS_ORIGINAL);
3468  assert(SCIPsetIsEQ(set, origvar->glbdom.lb, origvar->locdom.lb));
3469  assert(SCIPsetIsEQ(set, origvar->glbdom.ub, origvar->locdom.ub));
3470  assert(origvar->vlbs == NULL);
3471  assert(origvar->vubs == NULL);
3472  assert(transvar != NULL);
3473 
3474  /* check if variable is already transformed */
3475  if( origvar->data.original.transvar != NULL )
3476  {
3477  *transvar = origvar->data.original.transvar;
3478  SCIPvarCapture(*transvar);
3479  }
3480  else
3481  {
3482  int i;
3483 
3484  /* create transformed variable */
3485  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "t_%s", origvar->name);
3486  SCIP_CALL( SCIPvarCreateTransformed(transvar, blkmem, set, stat, name,
3487  origvar->glbdom.lb, origvar->glbdom.ub, (SCIP_Real)objsense * origvar->obj,
3488  SCIPvarGetType(origvar), origvar->initial, origvar->removable,
3489  origvar->vardelorig, origvar->vartrans, origvar->vardeltrans, origvar->varcopy, NULL) );
3490 
3491  /* copy the branch factor and priority */
3492  (*transvar)->branchfactor = origvar->branchfactor;
3493  (*transvar)->branchpriority = origvar->branchpriority;
3494  (*transvar)->branchdirection = origvar->branchdirection; /*lint !e732*/
3495 
3496  /* duplicate hole lists */
3497  SCIP_CALL( holelistDuplicate(&(*transvar)->glbdom.holelist, blkmem, set, origvar->glbdom.holelist) );
3498  SCIP_CALL( holelistDuplicate(&(*transvar)->locdom.holelist, blkmem, set, origvar->locdom.holelist) );
3499 
3500  /* link original and transformed variable */
3501  origvar->data.original.transvar = *transvar;
3502  SCIP_CALL( varAddParent(*transvar, blkmem, set, origvar) );
3503 
3504  /* copy rounding locks */
3505  for( i = 0; i < NLOCKTYPES; i++ )
3506  {
3507  (*transvar)->nlocksdown[i] = origvar->nlocksdown[i];
3508  (*transvar)->nlocksup[i] = origvar->nlocksup[i];
3509  assert((*transvar)->nlocksdown[i] >= 0);
3510  assert((*transvar)->nlocksup[i] >= 0);
3511  }
3512 
3513  /* copy donot(mult)aggr status */
3514  (*transvar)->donotaggr = origvar->donotaggr;
3515  (*transvar)->donotmultaggr = origvar->donotmultaggr;
3516 
3517  /* copy lazy bounds */
3518  (*transvar)->lazylb = origvar->lazylb;
3519  (*transvar)->lazyub = origvar->lazyub;
3520 
3521  /* transfer eventual variable statistics; do not update global statistics, because this has been done
3522  * when original variable was created
3523  */
3524  SCIPhistoryUnite((*transvar)->history, origvar->history, FALSE);
3525 
3526  /* transform user data */
3527  if( origvar->vartrans != NULL )
3528  {
3529  SCIP_CALL( origvar->vartrans(set->scip, origvar, origvar->vardata, *transvar, &(*transvar)->vardata) );
3530  }
3531  else
3532  (*transvar)->vardata = origvar->vardata;
3533  }
3534 
3535  SCIPsetDebugMsg(set, "transformed variable: <%s>[%p] -> <%s>[%p]\n", origvar->name, (void*)origvar, (*transvar)->name, (void*)*transvar);
3536 
3537  return SCIP_OKAY;
3538 }
3539 
3540 /** gets corresponding transformed variable of an original or negated original variable */
3542  SCIP_VAR* origvar, /**< original problem variable */
3543  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3544  SCIP_SET* set, /**< global SCIP settings */
3545  SCIP_STAT* stat, /**< problem statistics */
3546  SCIP_VAR** transvar /**< pointer to store the transformed variable, or NULL if not existing yet */
3547  )
3548 {
3549  assert(origvar != NULL);
3551  assert(origvar->scip == set->scip);
3552 
3553  if( SCIPvarGetStatus(origvar) == SCIP_VARSTATUS_NEGATED )
3554  {
3555  assert(origvar->negatedvar != NULL);
3557 
3558  if( origvar->negatedvar->data.original.transvar == NULL )
3559  *transvar = NULL;
3560  else
3561  {
3562  SCIP_CALL( SCIPvarNegate(origvar->negatedvar->data.original.transvar, blkmem, set, stat, transvar) );
3563  }
3564  }
3565  else
3566  *transvar = origvar->data.original.transvar;
3567 
3568  return SCIP_OKAY;
3569 }
3570 
3571 /** converts loose transformed variable into column variable, creates LP column */
3573  SCIP_VAR* var, /**< problem variable */
3574  BMS_BLKMEM* blkmem, /**< block memory */
3575  SCIP_SET* set, /**< global SCIP settings */
3576  SCIP_STAT* stat, /**< problem statistics */
3577  SCIP_PROB* prob, /**< problem data */
3578  SCIP_LP* lp /**< current LP data */
3579  )
3580 {
3581  assert(var != NULL);
3582  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
3583  assert(var->scip == set->scip);
3584 
3585  SCIPsetDebugMsg(set, "creating column for variable <%s>\n", var->name);
3586 
3587  /* switch variable status */
3588  var->varstatus = SCIP_VARSTATUS_COLUMN; /*lint !e641*/
3589 
3590  /* create column of variable */
3591  SCIP_CALL( SCIPcolCreate(&var->data.col, blkmem, set, stat, var, 0, NULL, NULL, var->removable) );
3592 
3593  if( var->probindex != -1 )
3594  {
3595  /* inform problem about the variable's status change */
3596  SCIP_CALL( SCIPprobVarChangedStatus(prob, blkmem, set, NULL, NULL, var) );
3597 
3598  /* inform LP, that problem variable is now a column variable and no longer loose */
3599  SCIP_CALL( SCIPlpUpdateVarColumn(lp, set, var) );
3600  }
3601 
3602  return SCIP_OKAY;
3603 }
3604 
3605 /** converts column transformed variable back into loose variable, frees LP column */
3607  SCIP_VAR* var, /**< problem variable */
3608  BMS_BLKMEM* blkmem, /**< block memory */
3609  SCIP_SET* set, /**< global SCIP settings */
3610  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3611  SCIP_PROB* prob, /**< problem data */
3612  SCIP_LP* lp /**< current LP data */
3613  )
3614 {
3615  assert(var != NULL);
3616  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
3617  assert(var->scip == set->scip);
3618  assert(var->data.col != NULL);
3619  assert(var->data.col->lppos == -1);
3620  assert(var->data.col->lpipos == -1);
3621 
3622  SCIPsetDebugMsg(set, "deleting column for variable <%s>\n", var->name);
3623 
3624  /* free column of variable */
3625  SCIP_CALL( SCIPcolFree(&var->data.col, blkmem, set, eventqueue, lp) );
3626 
3627  /* switch variable status */
3628  var->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
3629 
3630  if( var->probindex != -1 )
3631  {
3632  /* inform problem about the variable's status change */
3633  SCIP_CALL( SCIPprobVarChangedStatus(prob, blkmem, set, NULL, NULL, var) );
3634 
3635  /* inform LP, that problem variable is now a loose variable and no longer a column */
3636  SCIP_CALL( SCIPlpUpdateVarLoose(lp, set, var) );
3637  }
3638 
3639  return SCIP_OKAY;
3640 }
3641 
3642 /** issues a VARFIXED event on the given variable and all its parents (except ORIGINAL parents);
3643  * the event issuing on the parents is necessary, because unlike with bound changes, the parent variables
3644  * are not informed about a fixing of an active variable they are pointing to
3645  */
3646 static
3648  SCIP_VAR* var, /**< problem variable to change */
3649  BMS_BLKMEM* blkmem, /**< block memory */
3650  SCIP_SET* set, /**< global SCIP settings */
3651  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3652  int fixeventtype /**< is this event a fixation(0), an aggregation(1), or a
3653  * multi-aggregation(2)
3654  */
3655  )
3656 {
3657  SCIP_EVENT* event;
3658  SCIP_VARSTATUS varstatus;
3659  int i;
3660 
3661  assert(var != NULL);
3662  assert(var->scip == set->scip);
3663  assert(0 <= fixeventtype && fixeventtype <= 2);
3664 
3665  /* issue VARFIXED event on variable */
3666  SCIP_CALL( SCIPeventCreateVarFixed(&event, blkmem, var) );
3667  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
3668 
3669 #ifndef NDEBUG
3670  for( i = var->nparentvars -1; i >= 0; --i )
3671  {
3673  }
3674 #endif
3675 
3676  switch( fixeventtype )
3677  {
3678  case 0:
3679  /* process all parents of a fixed variable */
3680  for( i = var->nparentvars - 1; i >= 0; --i )
3681  {
3682  varstatus = SCIPvarGetStatus(var->parentvars[i]);
3683 
3684  assert(varstatus != SCIP_VARSTATUS_FIXED);
3685 
3686  /* issue event on all not yet fixed parent variables, (that should already issued this event) except the original
3687  * one
3688  */
3689  if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3690  {
3691  SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3692  }
3693  }
3694  break;
3695  case 1:
3696  /* process all parents of a aggregated variable */
3697  for( i = var->nparentvars - 1; i >= 0; --i )
3698  {
3699  varstatus = SCIPvarGetStatus(var->parentvars[i]);
3700 
3701  assert(varstatus != SCIP_VARSTATUS_FIXED);
3702 
3703  /* issue event for not aggregated parent variable, because for these and its parents the var event was already
3704  * issued(, except the original one)
3705  *
3706  * @note that even before an aggregated parent variable, there might be variables, for which the vent was not
3707  * yet issued
3708  */
3709  if( varstatus == SCIP_VARSTATUS_AGGREGATED )
3710  continue;
3711 
3712  if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3713  {
3714  SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3715  }
3716  }
3717  break;
3718  case 2:
3719  /* process all parents of a aggregated variable */
3720  for( i = var->nparentvars - 1; i >= 0; --i )
3721  {
3722  varstatus = SCIPvarGetStatus(var->parentvars[i]);
3723 
3724  assert(varstatus != SCIP_VARSTATUS_FIXED);
3725 
3726  /* issue event on all parent variables except the original one */
3727  if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3728  {
3729  SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3730  }
3731  }
3732  break;
3733  default:
3734  SCIPerrorMessage("unknown variable fixation event origin\n");
3735  return SCIP_INVALIDDATA;
3736  }
3737 
3738  return SCIP_OKAY;
3739 }
3740 
3741 /** converts variable into fixed variable */
3743  SCIP_VAR* var, /**< problem variable */
3744  BMS_BLKMEM* blkmem, /**< block memory */
3745  SCIP_SET* set, /**< global SCIP settings */
3746  SCIP_STAT* stat, /**< problem statistics */
3747  SCIP_PROB* transprob, /**< tranformed problem data */
3748  SCIP_PROB* origprob, /**< original problem data */
3749  SCIP_PRIMAL* primal, /**< primal data */
3750  SCIP_TREE* tree, /**< branch and bound tree */
3751  SCIP_REOPT* reopt, /**< reoptimization data structure */
3752  SCIP_LP* lp, /**< current LP data */
3753  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3754  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
3755  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3756  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
3757  SCIP_Real fixedval, /**< value to fix variable at */
3758  SCIP_Bool* infeasible, /**< pointer to store whether the fixing is infeasible */
3759  SCIP_Bool* fixed /**< pointer to store whether the fixing was performed (variable was unfixed) */
3760  )
3761 {
3762  SCIP_Real obj;
3763  SCIP_Real childfixedval;
3764 
3765  assert(var != NULL);
3766  assert(var->scip == set->scip);
3767  assert(SCIPsetIsEQ(set, var->glbdom.lb, var->locdom.lb));
3768  assert(SCIPsetIsEQ(set, var->glbdom.ub, var->locdom.ub));
3769  assert(infeasible != NULL);
3770  assert(fixed != NULL);
3771 
3772  SCIPsetDebugMsg(set, "fix variable <%s>[%g,%g] to %g\n", var->name, var->glbdom.lb, var->glbdom.ub, fixedval);
3773 
3774  *infeasible = FALSE;
3775  *fixed = FALSE;
3776 
3778  {
3779  *infeasible = !SCIPsetIsFeasEQ(set, fixedval, var->locdom.lb);
3780  SCIPsetDebugMsg(set, " -> variable already fixed to %g (fixedval=%g): infeasible=%u\n", var->locdom.lb, fixedval, *infeasible);
3781  return SCIP_OKAY;
3782  }
3783  else if( (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPsetIsFeasIntegral(set, fixedval))
3784  || SCIPsetIsFeasLT(set, fixedval, var->locdom.lb)
3785  || SCIPsetIsFeasGT(set, fixedval, var->locdom.ub) )
3786  {
3787  SCIPsetDebugMsg(set, " -> fixing infeasible: locdom=[%g,%g], fixedval=%g\n", var->locdom.lb, var->locdom.ub, fixedval);
3788  *infeasible = TRUE;
3789  return SCIP_OKAY;
3790  }
3791 
3792  switch( SCIPvarGetStatus(var) )
3793  {
3795  if( var->data.original.transvar == NULL )
3796  {
3797  SCIPerrorMessage("cannot fix an untransformed original variable\n");
3798  return SCIP_INVALIDDATA;
3799  }
3800  SCIP_CALL( SCIPvarFix(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
3801  lp, branchcand, eventfilter, eventqueue, cliquetable, fixedval, infeasible, fixed) );
3802  break;
3803 
3804  case SCIP_VARSTATUS_LOOSE:
3805  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
3806 
3807  /* set the fixed variable's objective value to 0.0 */
3808  obj = var->obj;
3809  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
3810 
3811  /* since we change the variable type form loose to fixed, we have to adjust the number of loose
3812  * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
3813  * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
3814  * objective of this variable is set to zero
3815  */
3816  SCIPlpDecNLoosevars(lp);
3817 
3818  /* change variable's bounds to fixed value (thereby removing redundant implications and variable bounds) */
3819  holelistFree(&var->glbdom.holelist, blkmem);
3820  holelistFree(&var->locdom.holelist, blkmem);
3821  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, fixedval) );
3822  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, fixedval) );
3823 
3824  /* explicitly set variable's bounds, even if the fixed value is in epsilon range of the old bound */
3825  var->glbdom.lb = fixedval;
3826  var->glbdom.ub = fixedval;
3827  var->locdom.lb = fixedval;
3828  var->locdom.ub = fixedval;
3829 
3830  /* delete implications and variable bounds information */
3831  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
3832  assert(var->vlbs == NULL);
3833  assert(var->vubs == NULL);
3834  assert(var->implics == NULL);
3835  assert(var->cliquelist == NULL);
3836 
3837  /* clear the history of the variable */
3838  SCIPhistoryReset(var->history);
3840 
3841  /* convert variable into fixed variable */
3842  var->varstatus = SCIP_VARSTATUS_FIXED; /*lint !e641*/
3843 
3844  /* inform problem about the variable's status change */
3845  if( var->probindex != -1 )
3846  {
3847  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
3848  }
3849 
3850  /* reset the objective value of the fixed variable, thus adjusting the problem's objective offset */
3851  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventfilter, eventqueue, obj) );
3852 
3853  /* issue VARFIXED event */
3854  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 0) );
3855 
3856  *fixed = TRUE;
3857  break;
3858 
3859  case SCIP_VARSTATUS_COLUMN:
3860  SCIPerrorMessage("cannot fix a column variable\n");
3861  return SCIP_INVALIDDATA;
3862 
3863  case SCIP_VARSTATUS_FIXED:
3864  SCIPerrorMessage("cannot fix a fixed variable again\n"); /*lint !e527*/
3865  SCIPABORT(); /* case is already handled in earlier if condition */
3866  return SCIP_INVALIDDATA; /*lint !e527*/
3867 
3869  /* fix aggregation variable y in x = a*y + c, instead of fixing x directly */
3870  assert(SCIPsetIsZero(set, var->obj));
3871  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
3872  if( SCIPsetIsInfinity(set, fixedval) || SCIPsetIsInfinity(set, -fixedval) )
3873  childfixedval = (var->data.aggregate.scalar < 0.0 ? -fixedval : fixedval);
3874  else
3875  childfixedval = (fixedval - var->data.aggregate.constant)/var->data.aggregate.scalar;
3876  SCIP_CALL( SCIPvarFix(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
3877  branchcand, eventfilter, eventqueue, cliquetable, childfixedval, infeasible, fixed) );
3878  break;
3879 
3881  SCIPerrorMessage("cannot fix a multiple aggregated variable\n");
3882  SCIPABORT();
3883  return SCIP_INVALIDDATA; /*lint !e527*/
3884 
3886  /* fix negation variable x in x' = offset - x, instead of fixing x' directly */
3887  assert(SCIPsetIsZero(set, var->obj));
3888  assert(var->negatedvar != NULL);
3890  assert(var->negatedvar->negatedvar == var);
3891  SCIP_CALL( SCIPvarFix(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
3892  branchcand, eventfilter, eventqueue, cliquetable, var->data.negate.constant - fixedval, infeasible, fixed) );
3893  break;
3894 
3895  default:
3896  SCIPerrorMessage("unknown variable status\n");
3897  return SCIP_INVALIDDATA;
3898  }
3899 
3900  return SCIP_OKAY;
3901 }
3902 
3903 /** transforms given variables, scalars and constant to the corresponding active variables, scalars and constant
3904  *
3905  * If the number of needed active variables is greater than the available slots in the variable array, nothing happens except
3906  * that the required size is stored in the corresponding variable; hence, if afterwards the required size is greater than the
3907  * available slots (varssize), nothing happens; otherwise, the active variable representation is stored in the arrays.
3908  *
3909  * The reason for this approach is that we cannot reallocate memory, since we do not know how the
3910  * memory has been allocated (e.g., by a C++ 'new' or SCIP functions).
3911  */
3913  SCIP_SET* set, /**< global SCIP settings */
3914  SCIP_VAR** vars, /**< variable array to get active variables */
3915  SCIP_Real* scalars, /**< scalars a_1, ..., a_n in linear sum a_1*x_1 + ... + a_n*x_n + c */
3916  int* nvars, /**< pointer to number of variables and values in vars and scalars array */
3917  int varssize, /**< available slots in vars and scalars array */
3918  SCIP_Real* constant, /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c */
3919  int* requiredsize, /**< pointer to store the required array size for the active variables */
3920  SCIP_Bool mergemultiples /**< should multiple occurrences of a var be replaced by a single coeff? */
3921  )
3922 {
3923  SCIP_VAR** activevars;
3924  SCIP_Real* activescalars;
3925  int nactivevars;
3926  SCIP_Real activeconstant;
3927  SCIP_Bool activeconstantinf;
3928  int activevarssize;
3929 
3930  SCIP_VAR* var;
3931  SCIP_Real scalar;
3932  int v;
3933  int k;
3934 
3935  SCIP_VAR** tmpvars;
3936  SCIP_VAR** multvars;
3937  SCIP_Real* tmpscalars;
3938  SCIP_Real* multscalars;
3939  int tmpvarssize;
3940  int ntmpvars;
3941  int nmultvars;
3942 
3943  SCIP_VAR* multvar;
3944  SCIP_Real multscalar;
3945  SCIP_Real multconstant;
3946  int pos;
3947 
3948  int noldtmpvars;
3949 
3950  SCIP_VAR** tmpvars2;
3951  SCIP_Real* tmpscalars2;
3952  int tmpvarssize2;
3953  int ntmpvars2;
3954 
3955  SCIP_Bool sortagain = FALSE;
3956 
3957  assert(set != NULL);
3958  assert(nvars != NULL);
3959  assert(scalars != NULL || *nvars == 0);
3960  assert(constant != NULL);
3961  assert(requiredsize != NULL);
3962  assert(*nvars <= varssize);
3963 
3964  *requiredsize = 0;
3965 
3966  if( *nvars == 0 )
3967  return SCIP_OKAY;
3968 
3969  assert(vars != NULL);
3970 
3971  /* handle the "easy" case of just one variable and avoid memory allocation if the variable is already active */
3972  if( *nvars == 1 && (vars[0]->varstatus == ((int) SCIP_VARSTATUS_COLUMN) || vars[0]->varstatus == ((int) SCIP_VARSTATUS_LOOSE)) )
3973  {
3974  *requiredsize = 1;
3975 
3976  return SCIP_OKAY;
3977  }
3978 
3979  nactivevars = 0;
3980  activeconstant = 0.0;
3981  activeconstantinf = FALSE;
3982  activevarssize = (*nvars) * 2;
3983  ntmpvars = *nvars;
3984  tmpvarssize = *nvars;
3985 
3986  tmpvarssize2 = 1;
3987 
3988  /* allocate temporary memory */
3989  SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpvars2, tmpvarssize2) );
3990  SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpscalars2, tmpvarssize2) );
3991  SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
3992  SCIP_CALL( SCIPsetAllocBufferArray(set, &activescalars, activevarssize) );
3993  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
3994  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpscalars, scalars, ntmpvars) );
3995 
3996  /* to avoid unnecessary expanding of variable arrays while disaggregating several variables multiple times combine same variables
3997  * first, first get all corresponding variables with status loose, column, multaggr or fixed
3998  */
3999  for( v = ntmpvars - 1; v >= 0; --v )
4000  {
4001  var = tmpvars[v];
4002  scalar = tmpscalars[v];
4003 
4004  assert(var != NULL);
4005  /* transforms given variable, scalar and constant to the corresponding active, fixed, or
4006  * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed
4007  * variable, "scalar" will be 0.0 and the value of the sum will be stored in "constant".
4008  */
4009  SCIP_CALL( SCIPvarGetProbvarSum(&var, set, &scalar, &activeconstant) );
4010  assert(var != NULL);
4011 
4012  assert(SCIPsetIsInfinity(set, activeconstant) == (activeconstant == SCIPsetInfinity(set))); /*lint !e777*/
4013  assert(SCIPsetIsInfinity(set, -activeconstant) == (activeconstant == -SCIPsetInfinity(set))); /*lint !e777*/
4014 
4015  activeconstantinf = SCIPsetIsInfinity(set, activeconstant) || SCIPsetIsInfinity(set, -activeconstant);
4016 
4017  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
4018  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
4021 
4022  tmpvars[v] = var;
4023  tmpscalars[v] = scalar;
4024  }
4025  noldtmpvars = ntmpvars;
4026 
4027  /* sort all variables to combine equal variables easily */
4028  SCIPsortPtrReal((void**)tmpvars, tmpscalars, SCIPvarComp, noldtmpvars);
4029  ntmpvars = 0;
4030  for( v = 1; v < noldtmpvars; ++v )
4031  {
4032  /* combine same variables */
4033  if( SCIPvarCompare(tmpvars[v], tmpvars[ntmpvars]) == 0 )
4034  {
4035  tmpscalars[ntmpvars] += tmpscalars[v];
4036  }
4037  else
4038  {
4039  ++ntmpvars;
4040  if( v > ntmpvars )
4041  {
4042  tmpscalars[ntmpvars] = tmpscalars[v];
4043  tmpvars[ntmpvars] = tmpvars[v];
4044  }
4045  }
4046  }
4047  ++ntmpvars;
4048 
4049 #ifdef SCIP_MORE_DEBUG
4050  for( v = 1; v < ntmpvars; ++v )
4051  assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
4052 #endif
4053 
4054  /* collect for each variable the representation in active variables */
4055  while( ntmpvars >= 1 )
4056  {
4057  --ntmpvars;
4058  ntmpvars2 = 0;
4059  var = tmpvars[ntmpvars];
4060  scalar = tmpscalars[ntmpvars];
4061 
4062  assert(var != NULL);
4063 
4064  /* TODO: maybe we should test here on SCIPsetIsZero() instead of 0.0 */
4065  if( scalar == 0.0 )
4066  continue;
4067 
4068  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
4069  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
4072 
4073  switch( SCIPvarGetStatus(var) )
4074  {
4075  case SCIP_VARSTATUS_LOOSE:
4076  case SCIP_VARSTATUS_COLUMN:
4077  /* x = a*y + c */
4078  if( nactivevars >= activevarssize )
4079  {
4080  activevarssize *= 2;
4081  SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
4082  SCIP_CALL( SCIPsetReallocBufferArray(set, &activescalars, activevarssize) );
4083  assert(nactivevars < activevarssize);
4084  }
4085  activevars[nactivevars] = var;
4086  activescalars[nactivevars] = scalar;
4087  nactivevars++;
4088  break;
4089 
4091  /* x = a_1*y_1 + ... + a_n*y_n + c */
4092  nmultvars = var->data.multaggr.nvars;
4093  multvars = var->data.multaggr.vars;
4094  multscalars = var->data.multaggr.scalars;
4095  sortagain = TRUE;
4096 
4097  if( nmultvars + ntmpvars > tmpvarssize )
4098  {
4099  while( nmultvars + ntmpvars > tmpvarssize )
4100  tmpvarssize *= 2;
4101  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
4102  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpscalars, tmpvarssize) );
4103  assert(nmultvars + ntmpvars <= tmpvarssize);
4104  }
4105 
4106  if( nmultvars > tmpvarssize2 )
4107  {
4108  while( nmultvars > tmpvarssize2 )
4109  tmpvarssize2 *= 2;
4110  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars2, tmpvarssize2) );
4111  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpscalars2, tmpvarssize2) );
4112  assert(nmultvars <= tmpvarssize2);
4113  }
4114 
4115  --nmultvars;
4116 
4117  for( ; nmultvars >= 0; --nmultvars )
4118  {
4119  multvar = multvars[nmultvars];
4120  multscalar = multscalars[nmultvars];
4121  multconstant = 0;
4122 
4123  assert(multvar != NULL);
4124  SCIP_CALL( SCIPvarGetProbvarSum(&multvar, set, &multscalar, &multconstant) );
4125  assert(multvar != NULL);
4126 
4127  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
4128  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
4131 
4132  if( !activeconstantinf )
4133  {
4134  assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
4135 
4136  if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) )
4137  {
4138  assert(scalar != 0.0);
4139  if( scalar * multconstant > 0.0 )
4140  {
4141  activeconstant = SCIPsetInfinity(set);
4142  activeconstantinf = TRUE;
4143  }
4144  else
4145  {
4146  activeconstant = -SCIPsetInfinity(set);
4147  activeconstantinf = TRUE;
4148  }
4149  }
4150  else
4151  activeconstant += scalar * multconstant;
4152  }
4153 #ifndef NDEBUG
4154  else
4155  {
4156  assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
4157  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4158  assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
4159  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4160  }
4161 #endif
4162 
4163  if( SCIPsortedvecFindPtr((void**)tmpvars, SCIPvarComp, multvar, ntmpvars, &pos) )
4164  {
4165  assert(SCIPvarCompare(tmpvars[pos], multvar) == 0);
4166  tmpscalars[pos] += scalar * multscalar;
4167  }
4168  else
4169  {
4170  tmpvars2[ntmpvars2] = multvar;
4171  tmpscalars2[ntmpvars2] = scalar * multscalar;
4172  ++(ntmpvars2);
4173  assert(ntmpvars2 <= tmpvarssize2);
4174  }
4175  }
4176 
4177  if( ntmpvars2 > 0 )
4178  {
4179  /* sort all variables to combine equal variables easily */
4180  SCIPsortPtrReal((void**)tmpvars2, tmpscalars2, SCIPvarComp, ntmpvars2);
4181  pos = 0;
4182  for( v = 1; v < ntmpvars2; ++v )
4183  {
4184  /* combine same variables */
4185  if( SCIPvarCompare(tmpvars2[v], tmpvars2[pos]) == 0 )
4186  {
4187  tmpscalars2[pos] += tmpscalars2[v];
4188  }
4189  else
4190  {
4191  ++pos;
4192  if( v > pos )
4193  {
4194  tmpscalars2[pos] = tmpscalars2[v];
4195  tmpvars2[pos] = tmpvars2[v];
4196  }
4197  }
4198  }
4199  ntmpvars2 = pos + 1;
4200 #ifdef SCIP_MORE_DEBUG
4201  for( v = 1; v < ntmpvars2; ++v )
4202  {
4203  assert(SCIPvarCompare(tmpvars2[v], tmpvars2[v-1]) > 0);
4204  }
4205  for( v = 1; v < ntmpvars; ++v )
4206  {
4207  assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
4208  }
4209 #endif
4210  v = ntmpvars - 1;
4211  k = ntmpvars2 - 1;
4212  pos = ntmpvars + ntmpvars2 - 1;
4213  ntmpvars += ntmpvars2;
4214 
4215  while( v >= 0 && k >= 0 )
4216  {
4217  assert(pos >= 0);
4218  assert(SCIPvarCompare(tmpvars[v], tmpvars2[k]) != 0);
4219  if( SCIPvarCompare(tmpvars[v], tmpvars2[k]) >= 0 )
4220  {
4221  tmpvars[pos] = tmpvars[v];
4222  tmpscalars[pos] = tmpscalars[v];
4223  --v;
4224  }
4225  else
4226  {
4227  tmpvars[pos] = tmpvars2[k];
4228  tmpscalars[pos] = tmpscalars2[k];
4229  --k;
4230  }
4231  --pos;
4232  assert(pos >= 0);
4233  }
4234  while( v >= 0 )
4235  {
4236  assert(pos >= 0);
4237  tmpvars[pos] = tmpvars[v];
4238  tmpscalars[pos] = tmpscalars[v];
4239  --v;
4240  --pos;
4241  }
4242  while( k >= 0 )
4243  {
4244  assert(pos >= 0);
4245  tmpvars[pos] = tmpvars2[k];
4246  tmpscalars[pos] = tmpscalars2[k];
4247  --k;
4248  --pos;
4249  }
4250  }
4251 #ifdef SCIP_MORE_DEBUG
4252  for( v = 1; v < ntmpvars; ++v )
4253  {
4254  assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
4255  }
4256 #endif
4257 
4258  if( !activeconstantinf )
4259  {
4260  assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
4261 
4262  multconstant = SCIPvarGetMultaggrConstant(var);
4263 
4264  if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) )
4265  {
4266  assert(scalar != 0.0);
4267  if( scalar * multconstant > 0.0 )
4268  {
4269  activeconstant = SCIPsetInfinity(set);
4270  activeconstantinf = TRUE;
4271  }
4272  else
4273  {
4274  activeconstant = -SCIPsetInfinity(set);
4275  activeconstantinf = TRUE;
4276  }
4277  }
4278  else
4279  activeconstant += scalar * multconstant;
4280  }
4281 #ifndef NDEBUG
4282  else
4283  {
4284  multconstant = SCIPvarGetMultaggrConstant(var);
4285  assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
4286  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4287  assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
4288  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4289  }
4290 #endif
4291  break;
4292 
4293  case SCIP_VARSTATUS_FIXED:
4297  default:
4298  /* case x = c, but actually we should not be here, since SCIPvarGetProbvarSum() returns a scalar of 0.0 for
4299  * fixed variables and is handled already
4300  */
4301  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED);
4302  assert(SCIPsetIsZero(set, var->glbdom.lb) && SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub));
4303  }
4304  }
4305 
4306  if( mergemultiples )
4307  {
4308  if( sortagain )
4309  {
4310  /* sort variable and scalar array by variable index */
4311  SCIPsortPtrReal((void**)activevars, activescalars, SCIPvarComp, nactivevars);
4312 
4313  /* eliminate duplicates and count required size */
4314  v = nactivevars - 1;
4315  while( v > 0 )
4316  {
4317  /* combine both variable since they are the same */
4318  if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
4319  {
4320  if( activescalars[v - 1] + activescalars[v] != 0.0 )
4321  {
4322  activescalars[v - 1] += activescalars[v];
4323  --nactivevars;
4324  activevars[v] = activevars[nactivevars];
4325  activescalars[v] = activescalars[nactivevars];
4326  }
4327  else
4328  {
4329  --nactivevars;
4330  activevars[v] = activevars[nactivevars];
4331  activescalars[v] = activescalars[nactivevars];
4332  --nactivevars;
4333  --v;
4334  activevars[v] = activevars[nactivevars];
4335  activescalars[v] = activescalars[nactivevars];
4336  }
4337  }
4338  --v;
4339  }
4340  }
4341  /* the variables were added in reverse order, we revert the order now;
4342  * this should not be necessary, but not doing this changes the behavior sometimes
4343  */
4344  else
4345  {
4346  SCIP_VAR* tmpvar;
4347  SCIP_Real tmpscalar;
4348 
4349  for( v = 0; v < nactivevars / 2; ++v )
4350  {
4351  tmpvar = activevars[v];
4352  tmpscalar = activescalars[v];
4353  activevars[v] = activevars[nactivevars - 1 - v];
4354  activescalars[v] = activescalars[nactivevars - 1 - v];
4355  activevars[nactivevars - 1 - v] = tmpvar;
4356  activescalars[nactivevars - 1 - v] = tmpscalar;
4357  }
4358  }
4359  }
4360  *requiredsize = nactivevars;
4361 
4362  if( varssize >= *requiredsize )
4363  {
4364  assert(vars != NULL);
4365 
4366  *nvars = *requiredsize;
4367 
4368  if( !SCIPsetIsInfinity(set, *constant) && !SCIPsetIsInfinity(set, -(*constant)) )
4369  {
4370  /* if the activeconstant is infinite, the constant pointer gets the same value, otherwise add the value */
4371  if( activeconstantinf )
4372  (*constant) = activeconstant;
4373  else
4374  (*constant) += activeconstant;
4375  }
4376 #ifndef NDEBUG
4377  else
4378  {
4379  assert(!SCIPsetIsInfinity(set, (*constant)) || !SCIPsetIsInfinity(set, -activeconstant));
4380  assert(!SCIPsetIsInfinity(set, -(*constant)) || !SCIPsetIsInfinity(set, activeconstant));
4381  }
4382 #endif
4383 
4384  /* copy active variable and scalar array to the given arrays */
4385  for( v = 0; v < *nvars; ++v )
4386  {
4387  vars[v] = activevars[v];
4388  scalars[v] = activescalars[v]; /*lint !e613*/
4389  }
4390  }
4391 
4392  assert(SCIPsetIsInfinity(set, *constant) == ((*constant) == SCIPsetInfinity(set))); /*lint !e777*/
4393  assert(SCIPsetIsInfinity(set, -(*constant)) == ((*constant) == -SCIPsetInfinity(set))); /*lint !e777*/
4394 
4395  SCIPsetFreeBufferArray(set, &tmpscalars);
4396  SCIPsetFreeBufferArray(set, &tmpvars);
4397  SCIPsetFreeBufferArray(set, &activescalars);
4398  SCIPsetFreeBufferArray(set, &activevars);
4399  SCIPsetFreeBufferArray(set, &tmpscalars2);
4400  SCIPsetFreeBufferArray(set, &tmpvars2);
4401 
4402  return SCIP_OKAY;
4403 }
4404 
4405 
4406 /** flattens aggregation graph of multi-aggregated variable in order to avoid exponential recursion later on */
4408  SCIP_VAR* var, /**< problem variable */
4409  BMS_BLKMEM* blkmem, /**< block memory */
4410  SCIP_SET* set, /**< global SCIP settings */
4411  SCIP_EVENTQUEUE* eventqueue /**< event queue */
4412  )
4413 {
4414  int nlocksup[NLOCKTYPES];
4415  int nlocksdown[NLOCKTYPES];
4416  SCIP_Real multconstant;
4417  int multvarssize;
4418  int nmultvars;
4419  int multrequiredsize;
4420  int i;
4421 
4422  assert( var != NULL );
4423  assert( SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR );
4424  assert(var->scip == set->scip);
4425 
4426  /* in order to update the locks on the active representation of the multi-aggregated variable, we remove all locks
4427  * on the current representation now and re-add the locks once the variable graph has been flattened, which
4428  * may lead to duplicate occurences of the same variable being merged
4429  *
4430  * Here is an example. Assume we have the multi-aggregation z = x + y.
4431  * z occures with positive coefficient in a <= constraint c1, so it has an uplock from there.
4432  * When the multi-aggregation is performed, all locks are added to the active representation,
4433  * so x and y both get an uplock from c1. However, z was not yet replaced by x + y in c1.
4434  * Next, a negation y = 1 - x is identified. Again, locks are moved, so that the uplock of y originating
4435  * from c1 is added to x as a downlock. Thus, x has both an up- and downlock from c1.
4436  * The multi-aggregation changes to z = x + 1 - x, which corresponds to the locks.
4437  * However, before z is replaced by that sum, SCIPvarFlattenAggregationGraph() is called
4438  * which changes z = x + y = x + 1 - x = 1, since it merges multiple occurences of the same variable.
4439  * The up- and downlock of x, however, is not removed when replacing z in c1 by its active representation,
4440  * because it is just 1 now. Therefore, we need to update locks when flattening the aggregation graph.
4441  * For this, the multi-aggregated variable knows its locks in addition to adding them to the active
4442  * representation, which corresponds to the locks from constraints where the variable was not replaced yet.
4443  * By removing the locks here, based on the old representation and adding them again after flattening,
4444  * we ensure that the locks are correct afterwards if coefficients were merged.
4445  */
4446  for( i = 0; i < NLOCKTYPES; ++i )
4447  {
4448  nlocksup[i] = var->nlocksup[i];
4449  nlocksdown[i] = var->nlocksdown[i];
4450 
4451  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, -nlocksdown[i], -nlocksup[i]) );
4452  }
4453 
4454  multconstant = var->data.multaggr.constant;
4455  nmultvars = var->data.multaggr.nvars;
4456  multvarssize = var->data.multaggr.varssize;
4457 
4458  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize, TRUE) );
4459 
4460  if( multrequiredsize > multvarssize )
4461  {
4462  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.vars), multvarssize, multrequiredsize) );
4463  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.scalars), multvarssize, multrequiredsize) );
4464  multvarssize = multrequiredsize;
4465  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize, TRUE) );
4466  assert( multrequiredsize <= multvarssize );
4467  }
4468  /**@note After the flattening the multi aggregation might resolve to be in fact an aggregation (or even a fixing?).
4469  * This issue is not resolved right now, since var->data.multaggr.nvars < 2 should not cause troubles. However, one
4470  * may loose performance hereby, since aggregated variables are easier to handle.
4471  *
4472  * Note, that there are two cases where SCIPvarFlattenAggregationGraph() is called: The easier one is that it is
4473  * called while installing the multi-aggregation. in principle, the described issue could be handled straightforward
4474  * in this case by aggregating or fixing the variable instead. The more complicated case is the one, when the
4475  * multi-aggregation is used, e.g., in linear presolving (and the variable is already declared to be multi-aggregated).
4476  *
4477  * By now, it is not allowed to fix or aggregate multi-aggregated variables which would be necessary in this case.
4478  *
4479  * The same issue appears in the SCIPvarGetProbvar...() methods.
4480  */
4481 
4482  var->data.multaggr.constant = multconstant;
4483  var->data.multaggr.nvars = nmultvars;
4484  var->data.multaggr.varssize = multvarssize;
4485 
4486  for( i = 0; i < NLOCKTYPES; ++i )
4487  {
4488  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
4489  }
4490 
4491  return SCIP_OKAY;
4492 }
4493 
4494 /** merge two variable histories together; a typical use case is that \p othervar is an image of the target variable
4495  * in a SCIP copy. Method should be applied with care, especially because no internal checks are performed whether
4496  * the history merge is reasonable
4497  *
4498  * @note Do not use this method if the two variables originate from two SCIP's with different objective functions, since
4499  * this corrupts the variable pseudo costs
4500  * @note Apply with care; no internal checks are performed if the two variables should be merged
4501  */
4503  SCIP_VAR* targetvar, /**< the variable that should contain both histories afterwards */
4504  SCIP_VAR* othervar, /**< the variable whose history is to be merged with that of the target variable */
4505  SCIP_STAT* stat /**< problem statistics */
4506  )
4507 {
4508  /* merge only the history of the current run into the target history */
4509  SCIPhistoryUnite(targetvar->history, othervar->historycrun, FALSE);
4510 
4511  /* apply the changes also to the global history */
4512  SCIPhistoryUnite(stat->glbhistory, othervar->historycrun, FALSE);
4513 }
4514 
4515 /** sets the history of a variable; this method is typically used within reoptimization to keep and update the variable
4516  * history over several iterations
4517  */
4518 void SCIPvarSetHistory(
4519  SCIP_VAR* var, /**< variable */
4520  SCIP_HISTORY* history, /**< the history which is to set */
4521  SCIP_STAT* stat /**< problem statistics */
4522  )
4523 {
4524  /* merge only the history of the current run into the target history */
4525  SCIPhistoryUnite(var->history, history, FALSE);
4526 
4527  /* apply the changes also to the global history */
4528  SCIPhistoryUnite(stat->glbhistory, history, FALSE);
4529 }
4530 
4531 /** tightens the bounds of both variables in aggregation x = a*y + c */
4532 static
4534  SCIP_VAR* var, /**< problem variable */
4535  BMS_BLKMEM* blkmem, /**< block memory */
4536  SCIP_SET* set, /**< global SCIP settings */
4537  SCIP_STAT* stat, /**< problem statistics */
4538  SCIP_PROB* transprob, /**< tranformed problem data */
4539  SCIP_PROB* origprob, /**< original problem data */
4540  SCIP_PRIMAL* primal, /**< primal data */
4541  SCIP_TREE* tree, /**< branch and bound tree */
4542  SCIP_REOPT* reopt, /**< reoptimization data structure */
4543  SCIP_LP* lp, /**< current LP data */
4544  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4545  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4546  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4547  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4548  SCIP_VAR* aggvar, /**< variable y in aggregation x = a*y + c */
4549  SCIP_Real scalar, /**< multiplier a in aggregation x = a*y + c */
4550  SCIP_Real constant, /**< constant shift c in aggregation x = a*y + c */
4551  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4552  SCIP_Bool* fixed /**< pointer to store whether the variables were fixed */
4553  )
4554 {
4555  SCIP_Real varlb;
4556  SCIP_Real varub;
4557  SCIP_Real aggvarlb;
4558  SCIP_Real aggvarub;
4559  SCIP_Bool aggvarbdschanged;
4560 
4561  assert(var != NULL);
4562  assert(var->scip == set->scip);
4563  assert(aggvar != NULL);
4564  assert(!SCIPsetIsZero(set, scalar));
4565  assert(infeasible != NULL);
4566  assert(fixed != NULL);
4567 
4568  *infeasible = FALSE;
4569  *fixed = FALSE;
4570 
4571  SCIPsetDebugMsg(set, "updating bounds of variables in aggregation <%s> == %g*<%s> %+g\n", var->name, scalar, aggvar->name, constant);
4572  SCIPsetDebugMsg(set, " old bounds: <%s> [%g,%g] <%s> [%g,%g]\n",
4573  var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
4574 
4575  /* loop as long additional changes may be found */
4576  do
4577  {
4578  aggvarbdschanged = FALSE;
4579 
4580  /* update the bounds of the aggregated variable x in x = a*y + c */
4581  if( scalar > 0.0 )
4582  {
4583  if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
4584  varlb = -SCIPsetInfinity(set);
4585  else
4586  varlb = aggvar->glbdom.lb * scalar + constant;
4587  if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
4588  varub = SCIPsetInfinity(set);
4589  else
4590  varub = aggvar->glbdom.ub * scalar + constant;
4591  }
4592  else
4593  {
4594  if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
4595  varub = SCIPsetInfinity(set);
4596  else
4597  varub = aggvar->glbdom.lb * scalar + constant;
4598  if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
4599  varlb = -SCIPsetInfinity(set);
4600  else
4601  varlb = aggvar->glbdom.ub * scalar + constant;
4602  }
4603  varlb = MAX(varlb, var->glbdom.lb);
4604  varub = MIN(varub, var->glbdom.ub);
4605  SCIPvarAdjustLb(var, set, &varlb);
4606  SCIPvarAdjustUb(var, set, &varub);
4607 
4608  /* check the new bounds */
4609  if( SCIPsetIsGT(set, varlb, varub) )
4610  {
4611  /* the aggregation is infeasible */
4612  *infeasible = TRUE;
4613  return SCIP_OKAY;
4614  }
4615  else if( SCIPsetIsEQ(set, varlb, varub) )
4616  {
4617  /* the aggregated variable is fixed -> fix both variables */
4618  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4619  eventfilter, eventqueue, cliquetable, varlb, infeasible, fixed) );
4620  if( !(*infeasible) )
4621  {
4622  SCIP_Bool aggfixed;
4623 
4624  SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4625  eventfilter, eventqueue, cliquetable, (varlb-constant)/scalar, infeasible, &aggfixed) );
4626  assert(*fixed == aggfixed);
4627  }
4628  return SCIP_OKAY;
4629  }
4630  else
4631  {
4632  if( SCIPsetIsGT(set, varlb, var->glbdom.lb) )
4633  {
4634  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, varlb) );
4635  }
4636  if( SCIPsetIsLT(set, varub, var->glbdom.ub) )
4637  {
4638  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, varub) );
4639  }
4640 
4641  /* update the hole list of the aggregation variable */
4642  /**@todo update hole list of aggregation variable */
4643  }
4644 
4645  /* update the bounds of the aggregation variable y in x = a*y + c -> y = (x-c)/a */
4646  if( scalar > 0.0 )
4647  {
4648  if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
4649  aggvarlb = -SCIPsetInfinity(set);
4650  else
4651  aggvarlb = (var->glbdom.lb - constant) / scalar;
4652  if( SCIPsetIsInfinity(set, var->glbdom.ub) )
4653  aggvarub = SCIPsetInfinity(set);
4654  else
4655  aggvarub = (var->glbdom.ub - constant) / scalar;
4656  }
4657  else
4658  {
4659  if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
4660  aggvarub = SCIPsetInfinity(set);
4661  else
4662  aggvarub = (var->glbdom.lb - constant) / scalar;
4663  if( SCIPsetIsInfinity(set, var->glbdom.ub) )
4664  aggvarlb = -SCIPsetInfinity(set);
4665  else
4666  aggvarlb = (var->glbdom.ub - constant) / scalar;
4667  }
4668  aggvarlb = MAX(aggvarlb, aggvar->glbdom.lb);
4669  aggvarub = MIN(aggvarub, aggvar->glbdom.ub);
4670  SCIPvarAdjustLb(aggvar, set, &aggvarlb);
4671  SCIPvarAdjustUb(aggvar, set, &aggvarub);
4672 
4673  /* check the new bounds */
4674  if( SCIPsetIsGT(set, aggvarlb, aggvarub) )
4675  {
4676  /* the aggregation is infeasible */
4677  *infeasible = TRUE;
4678  return SCIP_OKAY;
4679  }
4680  else if( SCIPsetIsEQ(set, aggvarlb, aggvarub) )
4681  {
4682  /* the aggregation variable is fixed -> fix both variables */
4683  SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4684  eventfilter, eventqueue, cliquetable, aggvarlb, infeasible, fixed) );
4685  if( !(*infeasible) )
4686  {
4687  SCIP_Bool varfixed;
4688 
4689  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4690  eventfilter, eventqueue, cliquetable, aggvarlb * scalar + constant, infeasible, &varfixed) );
4691  assert(*fixed == varfixed);
4692  }
4693  return SCIP_OKAY;
4694  }
4695  else
4696  {
4697  SCIP_Real oldbd;
4698  if( SCIPsetIsGT(set, aggvarlb, aggvar->glbdom.lb) )
4699  {
4700  oldbd = aggvar->glbdom.lb;
4701  SCIP_CALL( SCIPvarChgLbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, aggvarlb) );
4702  aggvarbdschanged = !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.lb);
4703  }
4704  if( SCIPsetIsLT(set, aggvarub, aggvar->glbdom.ub) )
4705  {
4706  oldbd = aggvar->glbdom.ub;
4707  SCIP_CALL( SCIPvarChgUbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, aggvarub) );
4708  aggvarbdschanged = aggvarbdschanged || !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.ub);
4709  }
4710 
4711  /* update the hole list of the aggregation variable */
4712  /**@todo update hole list of aggregation variable */
4713  }
4714  }
4715  while( aggvarbdschanged );
4716 
4717  SCIPsetDebugMsg(set, " new bounds: <%s> [%g,%g] <%s> [%g,%g]\n",
4718  var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
4719 
4720  return SCIP_OKAY;
4721 }
4722 
4723 /** converts loose variable into aggregated variable */
4725  SCIP_VAR* var, /**< loose problem variable */
4726  BMS_BLKMEM* blkmem, /**< block memory */
4727  SCIP_SET* set, /**< global SCIP settings */
4728  SCIP_STAT* stat, /**< problem statistics */
4729  SCIP_PROB* transprob, /**< tranformed problem data */
4730  SCIP_PROB* origprob, /**< original problem data */
4731  SCIP_PRIMAL* primal, /**< primal data */
4732  SCIP_TREE* tree, /**< branch and bound tree */
4733  SCIP_REOPT* reopt, /**< reoptimization data structure */
4734  SCIP_LP* lp, /**< current LP data */
4735  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4736  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4737  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4738  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4739  SCIP_VAR* aggvar, /**< loose variable y in aggregation x = a*y + c */
4740  SCIP_Real scalar, /**< multiplier a in aggregation x = a*y + c */
4741  SCIP_Real constant, /**< constant shift c in aggregation x = a*y + c */
4742  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4743  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
4744  )
4745 {
4746  SCIP_VAR** vars;
4747  SCIP_Real* coefs;
4748  SCIP_Real* constants;
4749  SCIP_Real obj;
4750  SCIP_Real branchfactor;
4751  SCIP_Bool fixed;
4752  int branchpriority;
4753  int nlocksdown[NLOCKTYPES];
4754  int nlocksup[NLOCKTYPES];
4755  int nvbds;
4756  int i;
4757  int j;
4758 
4759  assert(var != NULL);
4760  assert(aggvar != NULL);
4761  assert(var->scip == set->scip);
4762  assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
4763  assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
4764  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
4765  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
4766  assert(infeasible != NULL);
4767  assert(aggregated != NULL);
4768 
4769  /* check aggregation on debugging solution */
4770  SCIP_CALL( SCIPdebugCheckAggregation(set, var, &aggvar, &scalar, constant, 1) ); /*lint !e506 !e774*/
4771 
4772  *infeasible = FALSE;
4773  *aggregated = FALSE;
4774 
4775  /* get active problem variable of aggregation variable */
4776  SCIP_CALL( SCIPvarGetProbvarSum(&aggvar, set, &scalar, &constant) );
4777 
4778  /* aggregation is a fixing, if the scalar is zero */
4779  if( SCIPsetIsZero(set, scalar) )
4780  {
4781  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventfilter,
4782  eventqueue, cliquetable, constant, infeasible, aggregated) );
4783  return SCIP_OKAY;
4784  }
4785 
4786  /* don't perform the aggregation if the aggregation variable is multi-aggregated itself */
4787  if( SCIPvarGetStatus(aggvar) == SCIP_VARSTATUS_MULTAGGR )
4788  return SCIP_OKAY;
4789 
4790  /**@todo currently we don't perform the aggregation if the aggregation variable has a non-empty hole list; this
4791  * should be changed in the future
4792  */
4793  if( SCIPvarGetHolelistGlobal(var) != NULL )
4794  return SCIP_OKAY;
4795 
4796  /* if the variable is not allowed to be aggregated */
4797  if( SCIPvarDoNotAggr(var) )
4798  {
4799  SCIPsetDebugMsg(set, "variable is not allowed to be aggregated.\n");
4800  return SCIP_OKAY;
4801  }
4802 
4803  assert(aggvar->glbdom.lb == aggvar->locdom.lb); /*lint !e777*/
4804  assert(aggvar->glbdom.ub == aggvar->locdom.ub); /*lint !e777*/
4805  assert(SCIPvarGetStatus(aggvar) == SCIP_VARSTATUS_LOOSE);
4806 
4807  SCIPsetDebugMsg(set, "aggregate variable <%s>[%g,%g] == %g*<%s>[%g,%g] %+g\n", var->name, var->glbdom.lb, var->glbdom.ub,
4808  scalar, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub, constant);
4809 
4810  /* if variable and aggregation variable are equal, the variable can be fixed: x == a*x + c => x == c/(1-a) */
4811  if( var == aggvar )
4812  {
4813  if( SCIPsetIsEQ(set, scalar, 1.0) )
4814  *infeasible = !SCIPsetIsZero(set, constant);
4815  else
4816  {
4817  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4818  eventfilter, eventqueue, cliquetable, constant/(1.0-scalar), infeasible, aggregated) );
4819  }
4820  return SCIP_OKAY;
4821  }
4822 
4823  /* tighten the bounds of aggregated and aggregation variable */
4824  SCIP_CALL( varUpdateAggregationBounds(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
4825  branchcand, eventfilter, eventqueue, cliquetable, aggvar, scalar, constant, infeasible, &fixed) );
4826  if( *infeasible || fixed )
4827  {
4828  *aggregated = fixed;
4829  return SCIP_OKAY;
4830  }
4831 
4832  /* delete implications and variable bounds of the aggregated variable from other variables, but keep them in the
4833  * aggregated variable
4834  */
4835  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, FALSE) );
4836  assert(var->cliquelist == NULL);
4837 
4838  /* set the aggregated variable's objective value to 0.0 */
4839  obj = var->obj;
4840  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
4841 
4842  /* unlock all locks */
4843  for( i = 0; i < NLOCKTYPES; i++ )
4844  {
4845  nlocksdown[i] = var->nlocksdown[i];
4846  nlocksup[i] = var->nlocksup[i];
4847 
4848  var->nlocksdown[i] = 0;
4849  var->nlocksup[i] = 0;
4850  }
4851 
4852  /* check, if variable should be used as NEGATED variable of the aggregation variable */
4853  if( SCIPvarIsBinary(var) && SCIPvarIsBinary(aggvar)
4854  && var->negatedvar == NULL && aggvar->negatedvar == NULL
4855  && SCIPsetIsEQ(set, scalar, -1.0) && SCIPsetIsEQ(set, constant, 1.0) )
4856  {
4857  /* link both variables as negation pair */
4858  var->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
4859  var->data.negate.constant = 1.0;
4860  var->negatedvar = aggvar;
4861  aggvar->negatedvar = var;
4862 
4863  /* copy donot(mult)aggr status */
4864  aggvar->donotaggr |= var->donotaggr;
4865  aggvar->donotmultaggr |= var->donotmultaggr;
4866 
4867  /* mark both variables to be non-deletable */
4869  SCIPvarMarkNotDeletable(aggvar);
4870  }
4871  else
4872  {
4873  /* convert variable into aggregated variable */
4874  var->varstatus = SCIP_VARSTATUS_AGGREGATED; /*lint !e641*/
4875  var->data.aggregate.var = aggvar;
4876  var->data.aggregate.scalar = scalar;
4877  var->data.aggregate.constant = constant;
4878 
4879  /* copy donot(mult)aggr status */
4880  aggvar->donotaggr |= var->donotaggr;
4881  aggvar->donotmultaggr |= var->donotmultaggr;
4882 
4883  /* mark both variables to be non-deletable */
4885  SCIPvarMarkNotDeletable(aggvar);
4886  }
4887 
4888  /* make aggregated variable a parent of the aggregation variable */
4889  SCIP_CALL( varAddParent(aggvar, blkmem, set, var) );
4890 
4891  /* relock the variable, thus increasing the locks of the aggregation variable */
4892  for( i = 0; i < NLOCKTYPES; i++ )
4893  {
4894  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
4895  }
4896 
4897  /* move the variable bounds to the aggregation variable:
4898  * - add all variable bounds again to the variable, thus adding it to the aggregation variable
4899  * - free the variable bounds data structures
4900  */
4901  if( var->vlbs != NULL )
4902  {
4903  nvbds = SCIPvboundsGetNVbds(var->vlbs);
4904  vars = SCIPvboundsGetVars(var->vlbs);
4905  coefs = SCIPvboundsGetCoefs(var->vlbs);
4906  constants = SCIPvboundsGetConstants(var->vlbs);
4907  for( i = 0; i < nvbds && !(*infeasible); ++i )
4908  {
4909  SCIP_CALL( SCIPvarAddVlb(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
4910  eventqueue, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
4911  }
4912  }
4913  if( var->vubs != NULL )
4914  {
4915  nvbds = SCIPvboundsGetNVbds(var->vubs);
4916  vars = SCIPvboundsGetVars(var->vubs);
4917  coefs = SCIPvboundsGetCoefs(var->vubs);
4918  constants = SCIPvboundsGetConstants(var->vubs);
4919  for( i = 0; i < nvbds && !(*infeasible); ++i )
4920  {
4921  SCIP_CALL( SCIPvarAddVub(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
4922  eventqueue, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
4923  }
4924  }
4925  SCIPvboundsFree(&var->vlbs, blkmem);
4926  SCIPvboundsFree(&var->vubs, blkmem);
4927 
4928  /* move the implications to the aggregation variable:
4929  * - add all implications again to the variable, thus adding it to the aggregation variable
4930  * - free the implications data structures
4931  */
4932  if( var->implics != NULL && SCIPvarGetType(aggvar) == SCIP_VARTYPE_BINARY )
4933  {
4934  assert(SCIPvarIsBinary(var));
4935  for( i = 0; i < 2; ++i )
4936  {
4937  SCIP_VAR** implvars;
4938  SCIP_BOUNDTYPE* impltypes;
4939  SCIP_Real* implbounds;
4940  int nimpls;
4941 
4942  nimpls = SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i);
4943  implvars = SCIPimplicsGetVars(var->implics, (SCIP_Bool)i);
4944  impltypes = SCIPimplicsGetTypes(var->implics, (SCIP_Bool)i);
4945  implbounds = SCIPimplicsGetBounds(var->implics, (SCIP_Bool)i);
4946 
4947  for( j = 0; j < nimpls && !(*infeasible); ++j )
4948  {
4949  /* @todo can't we omit transitive closure, because it should already have been done when adding the
4950  * implication to the aggregated variable?
4951  */
4952  SCIP_CALL( SCIPvarAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
4953  branchcand, eventqueue, (SCIP_Bool)i, implvars[j], impltypes[j], implbounds[j], FALSE, infeasible,
4954  NULL) );
4955  assert(nimpls == SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i));
4956  }
4957  }
4958  }
4959  SCIPimplicsFree(&var->implics, blkmem);
4960 
4961  /* add the history entries to the aggregation variable and clear the history of the aggregated variable */
4962  SCIPhistoryUnite(aggvar->history, var->history, scalar < 0.0);
4963  SCIPhistoryUnite(aggvar->historycrun, var->historycrun, scalar < 0.0);
4964  SCIPhistoryReset(var->history);
4966 
4967  /* update flags of aggregation variable */
4968  aggvar->removable &= var->removable;
4969 
4970  /* update branching factors and priorities of both variables to be the maximum of both variables */
4971  branchfactor = MAX(aggvar->branchfactor, var->branchfactor);
4972  branchpriority = MAX(aggvar->branchpriority, var->branchpriority);
4973  SCIP_CALL( SCIPvarChgBranchFactor(aggvar, set, branchfactor) );
4974  SCIP_CALL( SCIPvarChgBranchPriority(aggvar, branchpriority) );
4975  SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
4976  SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
4977 
4978  /* update branching direction of both variables to agree to a single direction */
4979  if( scalar >= 0.0 )
4980  {
4982  {
4984  }
4985  else if( (SCIP_BRANCHDIR)aggvar->branchdirection == SCIP_BRANCHDIR_AUTO )
4986  {
4988  }
4989  else if( var->branchdirection != aggvar->branchdirection )
4990  {
4992  }
4993  }
4994  else
4995  {
4997  {
4999  }
5000  else if( (SCIP_BRANCHDIR)aggvar->branchdirection == SCIP_BRANCHDIR_AUTO )
5001  {
5003  }
5004  else if( var->branchdirection != aggvar->branchdirection )
5005  {
5007  }
5008  }
5009 
5010  if( var->probindex != -1 )
5011  {
5012  /* inform problem about the variable's status change */
5013  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
5014  }
5015 
5016  /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
5017  * variable and the problem's objective offset
5018  */
5019  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventfilter, eventqueue, obj) );
5020 
5021  /* issue VARFIXED event */
5022  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 1) );
5023 
5024  *aggregated = TRUE;
5025 
5026  return SCIP_OKAY;
5027 }
5028 
5029 /** Tries to aggregate an equality a*x + b*y == c consisting of two (implicit) integral active problem variables x and
5030  * y. An integer aggregation (i.e. integral coefficients a' and b', such that a'*x + b'*y == c') is searched.
5031  *
5032  * This can lead to the detection of infeasibility (e.g. if c' is fractional), or to a rejection of the aggregation
5033  * (denoted by aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
5034  */
5035 static
5037  SCIP_SET* set, /**< global SCIP settings */
5038  BMS_BLKMEM* blkmem, /**< block memory */
5039  SCIP_STAT* stat, /**< problem statistics */
5040  SCIP_PROB* transprob, /**< tranformed problem data */
5041  SCIP_PROB* origprob, /**< original problem data */
5042  SCIP_PRIMAL* primal, /**< primal data */
5043  SCIP_TREE* tree, /**< branch and bound tree */
5044  SCIP_REOPT* reopt, /**< reoptimization data structure */
5045  SCIP_LP* lp, /**< current LP data */
5046  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5047  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5048  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
5049  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5050  SCIP_VAR* varx, /**< integral variable x in equality a*x + b*y == c */
5051  SCIP_VAR* vary, /**< integral variable y in equality a*x + b*y == c */
5052  SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
5053  SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
5054  SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
5055  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
5056  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
5057  )
5058 {
5059  SCIP_VAR* aggvar;
5060  char aggvarname[SCIP_MAXSTRLEN];
5061  SCIP_Longint scalarxn = 0;
5062  SCIP_Longint scalarxd = 0;
5063  SCIP_Longint scalaryn = 0;
5064  SCIP_Longint scalaryd = 0;
5065  SCIP_Longint a;
5066  SCIP_Longint b;
5067  SCIP_Longint c;
5068  SCIP_Longint scm;
5069  SCIP_Longint gcd;
5070  SCIP_Longint currentclass;
5071  SCIP_Longint classstep;
5072  SCIP_Longint xsol;
5073  SCIP_Longint ysol;
5074  SCIP_Bool success;
5075  SCIP_VARTYPE vartype;
5076 
5077 #define MAXDNOM 1000000LL
5078 
5079  assert(set != NULL);
5080  assert(blkmem != NULL);
5081  assert(stat != NULL);
5082  assert(transprob != NULL);
5083  assert(origprob != NULL);
5084  assert(tree != NULL);
5085  assert(lp != NULL);
5086  assert(cliquetable != NULL);
5087  assert(branchcand != NULL);
5088  assert(eventqueue != NULL);
5089  assert(varx != NULL);
5090  assert(vary != NULL);
5091  assert(varx != vary);
5092  assert(infeasible != NULL);
5093  assert(aggregated != NULL);
5094  assert(SCIPsetGetStage(set) == SCIP_STAGE_PRESOLVING);
5095  assert(SCIPvarGetStatus(varx) == SCIP_VARSTATUS_LOOSE);
5097  assert(SCIPvarGetStatus(vary) == SCIP_VARSTATUS_LOOSE);
5099  assert(!SCIPsetIsZero(set, scalarx));
5100  assert(!SCIPsetIsZero(set, scalary));
5101 
5102  *infeasible = FALSE;
5103  *aggregated = FALSE;
5104 
5105  /* if the variable is not allowed to be aggregated */
5106  if( SCIPvarDoNotAggr(varx) )
5107  {
5108  SCIPsetDebugMsg(set, "variable is not allowed to be aggregated.\n");
5109  return SCIP_OKAY;
5110  }
5111 
5112  /* get rational representation of coefficients */
5113  success = SCIPrealToRational(scalarx, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalarxn, &scalarxd);
5114  if( success )
5115  success = SCIPrealToRational(scalary, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalaryn, &scalaryd);
5116  if( !success )
5117  return SCIP_OKAY;
5118  assert(scalarxd >= 1);
5119  assert(scalaryd >= 1);
5120 
5121  /* multiply equality with smallest common denominator */
5122  scm = SCIPcalcSmaComMul(scalarxd, scalaryd);
5123  a = (scm/scalarxd)*scalarxn;
5124  b = (scm/scalaryd)*scalaryn;
5125  rhs *= scm;
5126 
5127  /* divide equality by the greatest common divisor of a and b */
5128  gcd = SCIPcalcGreComDiv(ABS(a), ABS(b));
5129  a /= gcd;
5130  b /= gcd;
5131  rhs /= gcd;
5132  assert(a != 0);
5133  assert(b != 0);
5134 
5135  /* check, if right hand side is integral */
5136  if( !SCIPsetIsFeasIntegral(set, rhs) )
5137  {
5138  *infeasible = TRUE;
5139  return SCIP_OKAY;
5140  }
5141  c = (SCIP_Longint)(SCIPsetFeasFloor(set, rhs));
5142 
5143  /* check that the scalar and constant in the aggregation are not too large to avoid numerical problems */
5144  if( REALABS((SCIP_Real)(c/a)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) /*lint !e653*/
5145  || REALABS((SCIP_Real)(b)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) /*lint !e653*/
5146  || REALABS((SCIP_Real)(a)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
5147  {
5148  return SCIP_OKAY;
5149  }
5150 
5151  /* check, if we are in an easy case with either |a| = 1 or |b| = 1 */
5152  if( (a == 1 || a == -1) && SCIPvarGetType(vary) == SCIP_VARTYPE_INTEGER )
5153  {
5154  /* aggregate x = - b/a*y + c/a */
5155  /*lint --e{653}*/
5156  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5157  branchcand, eventfilter, eventqueue, vary, (SCIP_Real)(-b/a), (SCIP_Real)(c/a), infeasible, aggregated) );
5158  assert(*aggregated);
5159  return SCIP_OKAY;
5160  }
5161  if( (b == 1 || b == -1) && SCIPvarGetType(varx) == SCIP_VARTYPE_INTEGER )
5162  {
5163  /* aggregate y = - a/b*x + c/b */
5164  /*lint --e{653}*/
5165  SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5166  branchcand, eventfilter, eventqueue, varx, (SCIP_Real)(-a/b), (SCIP_Real)(c/b), infeasible, aggregated) );
5167  assert(*aggregated);
5168  return SCIP_OKAY;
5169  }
5170 
5171  /* Both variables are integers, their coefficients are not multiples of each other, and they don't have any
5172  * common divisor. Let (x',y') be a solution of the equality
5173  * a*x + b*y == c -> a*x == c - b*y
5174  * Then x = -b*z + x', y = a*z + y' with z integral gives all solutions to the equality.
5175  */
5176 
5177  /* find initial solution (x',y'):
5178  * - find y' such that c - b*y' is a multiple of a
5179  * - start in equivalence class c%a
5180  * - step through classes, where each step increases class number by (-b)%a, until class 0 is visited
5181  * - if equivalence class 0 is visited, we are done: y' equals the number of steps taken
5182  * - 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
5183  * - calculate x' with x' = (c - b*y')/a (which must be integral)
5184  *
5185  * Algorithm works for a > 0 only.
5186  */
5187  if( a < 0 )
5188  {
5189  a = -a;
5190  b = -b;
5191  c = -c;
5192  }
5193  assert(a > 0);
5194 
5195  /* search upwards from ysol = 0 */
5196  ysol = 0;
5197  currentclass = c % a;
5198  if( currentclass < 0 )
5199  currentclass += a;
5200  assert(0 <= currentclass && currentclass < a);
5201 
5202  classstep = (-b) % a;
5203 
5204  if( classstep < 0 )
5205  classstep += a;
5206  assert(0 <= classstep && classstep < a);
5207 
5208  while( currentclass != 0 )
5209  {
5210  assert(0 <= currentclass && currentclass < a);
5211  currentclass += classstep;
5212  if( currentclass >= a )
5213  currentclass -= a;
5214  ysol++;
5215  }
5216  assert(ysol < a);
5217  assert(((c - b*ysol) % a) == 0);
5218 
5219  xsol = (c - b*ysol)/a;
5220 
5221  /* determine variable type for new artificial variable:
5222  *
5223  * if both variables are implicit integer the new variable can be implicit too, because the integer implication on
5224  * these both variables should be enforced by some other variables, otherwise the new variable needs to be of
5225  * integral type
5226  */
5229 
5230  /* feasible solutions are (x,y) = (x',y') + z*(-b,a)
5231  * - create new integer variable z with infinite bounds
5232  * - aggregate variable x = -b*z + x'
5233  * - aggregate variable y = a*z + y'
5234  * - the bounds of z are calculated automatically during aggregation
5235  */
5236  (void) SCIPsnprintf(aggvarname, SCIP_MAXSTRLEN, "agg%d", stat->nvaridx);
5237  SCIP_CALL( SCIPvarCreateTransformed(&aggvar, blkmem, set, stat,
5238  aggvarname, -SCIPsetInfinity(set), SCIPsetInfinity(set), 0.0, vartype,
5240  NULL, NULL, NULL, NULL, NULL) );
5241 
5242  SCIP_CALL( SCIPprobAddVar(transprob, blkmem, set, lp, branchcand, eventfilter, eventqueue, aggvar) );
5243 
5244  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5245  branchcand, eventfilter, eventqueue, aggvar, (SCIP_Real)(-b), (SCIP_Real)xsol, infeasible, aggregated) );
5246  assert(*aggregated || *infeasible);
5247 
5248  if( !(*infeasible) )
5249  {
5250  SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5251  branchcand, eventfilter, eventqueue, aggvar, (SCIP_Real)a, (SCIP_Real)ysol, infeasible, aggregated) );
5252  assert(*aggregated || *infeasible);
5253  }
5254 
5255  /* release z */
5256  SCIP_CALL( SCIPvarRelease(&aggvar, blkmem, set, eventqueue, lp) );
5257 
5258  return SCIP_OKAY; /*lint !e438*/
5259 }
5260 
5261 /** performs second step of SCIPaggregateVars():
5262  * the variable to be aggregated is chosen among active problem variables x' and y', preferring a less strict variable
5263  * type as aggregation variable (i.e. continuous variables are preferred over implicit integers, implicit integers
5264  * or integers over binaries). If none of the variables is continuous, it is tried to find an integer
5265  * aggregation (i.e. integral coefficients a'' and b'', such that a''*x' + b''*y' == c''). This can lead to
5266  * the detection of infeasibility (e.g. if c'' is fractional), or to a rejection of the aggregation (denoted by
5267  * aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
5268  *
5269  * @todo check for fixings, infeasibility, bound changes, or domain holes:
5270  * a) if there is no easy aggregation and we have one binary variable and another integer/implicit/binary variable
5271  * b) for implicit integer variables with fractional aggregation scalar (we cannot (for technical reasons) and do
5272  * not want to aggregate implicit integer variables, since we loose the corresponding divisibility property)
5273  */
5275  SCIP_SET* set, /**< global SCIP settings */
5276  BMS_BLKMEM* blkmem, /**< block memory */
5277  SCIP_STAT* stat, /**< problem statistics */
5278  SCIP_PROB* transprob, /**< tranformed problem data */
5279  SCIP_PROB* origprob, /**< original problem data */
5280  SCIP_PRIMAL* primal, /**< primal data */
5281  SCIP_TREE* tree, /**< branch and bound tree */
5282  SCIP_REOPT* reopt, /**< reoptimization data structure */
5283  SCIP_LP* lp, /**< current LP data */
5284  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5285  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5286  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
5287  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5288  SCIP_VAR* varx, /**< variable x in equality a*x + b*y == c */
5289  SCIP_VAR* vary, /**< variable y in equality a*x + b*y == c */
5290  SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
5291  SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
5292  SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
5293  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
5294  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
5295  )
5296 {
5297  SCIP_Bool easyaggr;
5298  SCIP_Real maxscalar;
5299  SCIP_Real absquot;
5300 
5301  assert(set != NULL);
5302  assert(blkmem != NULL);
5303  assert(stat != NULL);
5304  assert(transprob != NULL);
5305  assert(origprob != NULL);
5306  assert(tree != NULL);
5307  assert(lp != NULL);
5308  assert(cliquetable != NULL);
5309  assert(branchcand != NULL);
5310  assert(eventqueue != NULL);
5311  assert(varx != NULL);
5312  assert(vary != NULL);
5313  assert(varx != vary);
5314  assert(infeasible != NULL);
5315  assert(aggregated != NULL);
5316  assert(SCIPsetGetStage(set) == SCIP_STAGE_PRESOLVING);
5317  assert(SCIPvarGetStatus(varx) == SCIP_VARSTATUS_LOOSE);
5318  assert(SCIPvarGetStatus(vary) == SCIP_VARSTATUS_LOOSE);
5319  assert(!SCIPsetIsZero(set, scalarx));
5320  assert(!SCIPsetIsZero(set, scalary));
5321 
5322  *infeasible = FALSE;
5323  *aggregated = FALSE;
5324 
5325  absquot = REALABS(scalarx / scalary);
5326  maxscalar = SCIPsetFeastol(set) / SCIPsetEpsilon(set);
5327  maxscalar = MAX(maxscalar, 1.0);
5328 
5329  if( absquot > maxscalar || absquot < 1 / maxscalar )
5330  return SCIP_OKAY;
5331 
5332  /* prefer aggregating the variable of more general type (preferred aggregation variable is varx) */
5333  if( SCIPvarGetType(vary) > SCIPvarGetType(varx) ||
5334  (SCIPvarGetType(vary) == SCIPvarGetType(varx) && !SCIPvarIsBinary(vary) && SCIPvarIsBinary(varx)) )
5335  {
5336  SCIP_VAR* var;
5337  SCIP_Real scalar;
5338 
5339  /* switch the variables, such that varx is the variable of more general type (cont > implint > int > bin) */
5340  var = vary;
5341  vary = varx;
5342  varx = var;
5343  scalar = scalary;
5344  scalary = scalarx;
5345  scalarx = scalar;
5346  }
5347 
5348  /* don't aggregate if the aggregation would lead to a binary variable aggregated to a non-binary variable */
5349  if( SCIPvarIsBinary(varx) && !SCIPvarIsBinary(vary) )
5350  return SCIP_OKAY;
5351 
5352  assert(SCIPvarGetType(varx) >= SCIPvarGetType(vary));
5353 
5354  /* figure out, which variable should be aggregated */
5355  easyaggr = FALSE;
5356 
5357  /* check if it is an easy aggregation that means:
5358  *
5359  * a*x + b*y == c -> x == -b/a * y + c/a iff |b/a| > feastol and |a/b| > feastol
5360  */
5361  if( !SCIPsetIsFeasZero(set, scalary/scalarx) && !SCIPsetIsFeasZero(set, scalarx/scalary) )
5362  {
5364  {
5365  easyaggr = TRUE;
5366  }
5367  else if( SCIPsetIsFeasIntegral(set, scalary/scalarx) )
5368  {
5369  easyaggr = TRUE;
5370  }
5371  else if( SCIPsetIsFeasIntegral(set, scalarx/scalary) && SCIPvarGetType(vary) == SCIPvarGetType(varx) )
5372  {
5373  /* we have an easy aggregation if we flip the variables x and y */
5374  SCIP_VAR* var;
5375  SCIP_Real scalar;
5376 
5377  /* switch the variables, such that varx is the aggregated variable */
5378  var = vary;
5379  vary = varx;
5380  varx = var;
5381  scalar = scalary;
5382  scalary = scalarx;
5383  scalarx = scalar;
5384  easyaggr = TRUE;
5385  }
5386  else if( SCIPvarGetType(varx) == SCIP_VARTYPE_CONTINUOUS )
5387  {
5388  /* the aggregation is still easy if both variables are continuous */
5389  assert(SCIPvarGetType(vary) == SCIP_VARTYPE_CONTINUOUS); /* otherwise we are in the first case */
5390  easyaggr = TRUE;
5391  }
5392  }
5393 
5394  /* did we find an "easy" aggregation? */
5395  if( easyaggr )
5396  {
5397  SCIP_Real scalar;
5398  SCIP_Real constant;
5399 
5400  assert(SCIPvarGetType(varx) >= SCIPvarGetType(vary));
5401 
5402  /* calculate aggregation scalar and constant: a*x + b*y == c => x == -b/a * y + c/a */
5403  scalar = -scalary/scalarx;
5404  constant = rhs/scalarx;
5405 
5406  if( REALABS(constant) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
5407  return SCIP_OKAY;
5408 
5409  /* check aggregation for integer feasibility */
5412  && SCIPsetIsFeasIntegral(set, scalar) && !SCIPsetIsFeasIntegral(set, constant) )
5413  {
5414  *infeasible = TRUE;
5415  return SCIP_OKAY;
5416  }
5417 
5418  /* if the aggregation scalar is fractional, we cannot (for technical reasons) and do not want to aggregate implicit integer variables,
5419  * since then we would loose the corresponding divisibility property
5420  */
5421  assert(SCIPvarGetType(varx) != SCIP_VARTYPE_IMPLINT || SCIPsetIsFeasIntegral(set, scalar));
5422 
5423  /* aggregate the variable */
5424  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5425  branchcand, eventfilter, eventqueue, vary, scalar, constant, infeasible, aggregated) );
5426  assert(*aggregated || *infeasible);
5427  }
5430  {
5431  /* the variables are both integral: we have to try to find an integer aggregation */
5432  SCIP_CALL( tryAggregateIntVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5433  branchcand, eventfilter, eventqueue, varx, vary, scalarx, scalary, rhs, infeasible, aggregated) );
5434  }
5435 
5436  return SCIP_OKAY;
5437 }
5438 
5439 /** converts variable into multi-aggregated variable */
5441  SCIP_VAR* var, /**< problem variable */
5442  BMS_BLKMEM* blkmem, /**< block memory */
5443  SCIP_SET* set, /**< global SCIP settings */
5444  SCIP_STAT* stat, /**< problem statistics */
5445  SCIP_PROB* transprob, /**< tranformed problem data */
5446  SCIP_PROB* origprob, /**< original problem data */
5447  SCIP_PRIMAL* primal, /**< primal data */
5448  SCIP_TREE* tree, /**< branch and bound tree */
5449  SCIP_REOPT* reopt, /**< reoptimization data structure */
5450  SCIP_LP* lp, /**< current LP data */
5451  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5452  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5453  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
5454  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5455  int naggvars, /**< number n of variables in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5456  SCIP_VAR** aggvars, /**< variables y_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5457  SCIP_Real* scalars, /**< multipliers a_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5458  SCIP_Real constant, /**< constant shift c in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5459  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
5460  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
5461  )
5462 {
5463  SCIP_VAR** tmpvars;
5464  SCIP_Real* tmpscalars;
5465  SCIP_Real obj;
5466  SCIP_Real branchfactor;
5467  int branchpriority;
5468  SCIP_BRANCHDIR branchdirection;
5469  int nlocksdown[NLOCKTYPES];
5470  int nlocksup[NLOCKTYPES];
5471  int v;
5472  SCIP_Real tmpconstant;
5473  SCIP_Real tmpscalar;
5474  int ntmpvars;
5475  int tmpvarssize;
5476  int tmprequiredsize;
5477  int i;
5478 
5479  assert(var != NULL);
5480  assert(var->scip == set->scip);
5481  assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
5482  assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
5483  assert(naggvars == 0 || aggvars != NULL);
5484  assert(naggvars == 0 || scalars != NULL);
5485  assert(infeasible != NULL);
5486  assert(aggregated != NULL);
5487 
5488  SCIPsetDebugMsg(set, "trying multi-aggregating variable <%s> == ...%d vars... %+g\n", var->name, naggvars, constant);
5489 
5490  /* check multi-aggregation on debugging solution */
5491  SCIP_CALL( SCIPdebugCheckAggregation(set, var, aggvars, scalars, constant, naggvars) ); /*lint !e506 !e774*/
5492 
5493  *infeasible = FALSE;
5494  *aggregated = FALSE;
5495 
5496  switch( SCIPvarGetStatus(var) )
5497  {
5499  if( var->data.original.transvar == NULL )
5500  {
5501  SCIPerrorMessage("cannot multi-aggregate an untransformed original variable\n");
5502  return SCIP_INVALIDDATA;
5503  }
5504  SCIP_CALL( SCIPvarMultiaggregate(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
5505  reopt, lp, cliquetable, branchcand, eventfilter, eventqueue, naggvars, aggvars, scalars, constant, infeasible, aggregated) );
5506  break;
5507 
5508  case SCIP_VARSTATUS_LOOSE:
5509  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
5510 
5511  /* check if we would create a self-reference */
5512  ntmpvars = naggvars;
5513  tmpvarssize = naggvars;
5514  tmpconstant = constant;
5515  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpvars, aggvars, ntmpvars) );
5516  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpscalars, scalars, ntmpvars) );
5517 
5518  /* get all active variables for multi-aggregation */
5519  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize, FALSE) );
5520  if( tmprequiredsize > tmpvarssize )
5521  {
5522  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpvars, tmpvarssize, tmprequiredsize) );
5523  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize, tmprequiredsize) );
5524  tmpvarssize = tmprequiredsize;
5525  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize, FALSE) );
5526  assert( tmprequiredsize <= tmpvarssize );
5527  }
5528 
5529  tmpscalar = 0.0;
5530 
5531  /* iterate over all active variables of the multi-aggregation and filter all variables which are equal to the
5532  * possible multi-aggregated variable
5533  */
5534  for( v = ntmpvars - 1; v >= 0; --v )
5535  {
5536  assert(tmpvars[v] != NULL);
5537  assert(SCIPvarGetStatus(tmpvars[v]) == SCIP_VARSTATUS_LOOSE);
5538 
5539  if( tmpvars[v]->index == var->index )
5540  {
5541  tmpscalar += tmpscalars[v];
5542  tmpvars[v] = tmpvars[ntmpvars - 1];
5543  tmpscalars[v] = tmpscalars[ntmpvars - 1];
5544  --ntmpvars;
5545  }
5546  }
5547 
5548  /* this means that x = x + a_1*y_1 + ... + a_n*y_n + c */
5549  if( SCIPsetIsEQ(set, tmpscalar, 1.0) )
5550  {
5551  if( ntmpvars == 0 )
5552  {
5553  if( SCIPsetIsZero(set, tmpconstant) ) /* x = x */
5554  {
5555  SCIPsetDebugMsg(set, "Possible multi-aggregation was completely resolved and detected to be redundant.\n");
5556  goto TERMINATE;
5557  }
5558  else /* 0 = c and c != 0 */
5559  {
5560  SCIPsetDebugMsg(set, "Multi-aggregation was completely resolved and led to infeasibility.\n");
5561  *infeasible = TRUE;
5562  goto TERMINATE;
5563  }
5564  }
5565  else if( ntmpvars == 1 ) /* 0 = a*y + c => y = -c/a */
5566  {
5567  assert(tmpscalars[0] != 0.0);
5568  assert(tmpvars[0] != NULL);
5569 
5570  SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(tmpvars[0]), -constant/tmpscalars[0]);
5571  SCIP_CALL( SCIPvarFix(tmpvars[0], blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5572  branchcand, eventfilter, eventqueue, cliquetable, -constant/tmpscalars[0], infeasible, aggregated) );
5573  goto TERMINATE;
5574  }
5575  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 */
5576  {
5577  /* both variables are different active problem variables, and both scalars are non-zero: try to aggregate them */
5578  SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
5579  SCIPvarGetName(tmpvars[0]), SCIPvarGetName(tmpvars[1]), tmpscalars[0], tmpscalars[1], -tmpconstant);
5580 
5581  SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
5582  cliquetable, branchcand, eventfilter, eventqueue, tmpvars[0], tmpvars[1], tmpscalars[0],
5583  tmpscalars[1], -tmpconstant, infeasible, aggregated) );
5584 
5585  goto TERMINATE;
5586  }
5587  else
5588  /* @todo: it is possible to multi-aggregate another variable, does it make sense?,
5589  * rest looks like 0 = a_1*y_1 + ... + a_n*y_n + c and has at least three variables
5590  */
5591  goto TERMINATE;
5592  }
5593  /* this means that x = b*x + a_1*y_1 + ... + a_n*y_n + c */
5594  else if( !SCIPsetIsZero(set, tmpscalar) )
5595  {
5596  tmpscalar = 1 - tmpscalar;
5597  tmpconstant /= tmpscalar;
5598  for( v = ntmpvars - 1; v >= 0; --v )
5599  tmpscalars[v] /= tmpscalar;
5600  }
5601 
5602  /* check, if we are in one of the simple cases */
5603  if( ntmpvars == 0 )
5604  {
5605  SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(var), tmpconstant);
5606  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
5607  eventfilter, eventqueue, cliquetable, tmpconstant, infeasible, aggregated) );
5608  goto TERMINATE;
5609  }
5610 
5611  /* if only one aggregation variable is left, we perform a normal aggregation instead of a multi-aggregation */
5612  if( ntmpvars == 1 )
5613  {
5614  SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
5615  SCIPvarGetName(var), SCIPvarGetName(tmpvars[0]), 1.0, -tmpscalars[0], tmpconstant);
5616 
5617  SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
5618  cliquetable, branchcand, eventfilter, eventqueue, var, tmpvars[0], 1.0, -tmpscalars[0], tmpconstant,
5619  infeasible, aggregated) );
5620 
5621  goto TERMINATE;
5622  }
5623 
5624  /**@todo currently we don't perform the multi aggregation if the multi aggregation variable has a non
5625  * empty hole list; this should be changed in the future */
5626  if( SCIPvarGetHolelistGlobal(var) != NULL )
5627  goto TERMINATE;
5628 
5629  /* if the variable is not allowed to be multi-aggregated */
5630  if( SCIPvarDoNotMultaggr(var) )
5631  {
5632  SCIPsetDebugMsg(set, "variable is not allowed to be multi-aggregated.\n");
5633  goto TERMINATE;
5634  }
5635 
5636  /* if the variable to be multi-aggregated has implications or variable bounds (i.e. is the implied variable or
5637  * variable bound variable of another variable), we have to remove it from the other variables implications or
5638  * variable bounds
5639  */
5640  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
5641  assert(var->vlbs == NULL);
5642  assert(var->vubs == NULL);
5643  assert(var->implics == NULL);
5644  assert(var->cliquelist == NULL);
5645 
5646  /* set the aggregated variable's objective value to 0.0 */
5647  obj = var->obj;
5648  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
5649 
5650  /* since we change the variable type form loose to multi aggregated, we have to adjust the number of loose
5651  * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
5652  * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
5653  * objective of this variable is set to zero
5654  */
5655  SCIPlpDecNLoosevars(lp);
5656 
5657  /* unlock all rounding locks */
5658  for( i = 0; i < NLOCKTYPES; i++ )
5659  {
5660  nlocksdown[i] = var->nlocksdown[i];
5661  nlocksup[i] = var->nlocksup[i];
5662 
5663  var->nlocksdown[i] = 0;
5664  var->nlocksup[i] = 0;
5665  }
5666 
5667  /* convert variable into multi-aggregated variable */
5668  var->varstatus = SCIP_VARSTATUS_MULTAGGR; /*lint !e641*/
5669  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.vars, tmpvars, ntmpvars) );
5670  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.scalars, tmpscalars, ntmpvars) );
5671  var->data.multaggr.constant = tmpconstant;
5672  var->data.multaggr.nvars = ntmpvars;
5673  var->data.multaggr.varssize = ntmpvars;
5674 
5675  /* mark variable to be non-deletable */
5677 
5678  /* relock the variable, thus increasing the locks of the aggregation variables */
5679  for( i = 0; i < NLOCKTYPES; i++ )
5680  {
5681  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
5682  }
5683 
5684  /* update flags and branching factors and priorities of aggregation variables;
5685  * update preferred branching direction of all aggregation variables that don't have a preferred direction yet
5686  */
5687  branchfactor = var->branchfactor;
5688  branchpriority = var->branchpriority;
5689  branchdirection = (SCIP_BRANCHDIR)var->branchdirection;
5690 
5691  for( v = 0; v < ntmpvars; ++v )
5692  {
5693  assert(tmpvars[v] != NULL);
5694  tmpvars[v]->removable &= var->removable;
5695  branchfactor = MAX(tmpvars[v]->branchfactor, branchfactor);
5696  branchpriority = MAX(tmpvars[v]->branchpriority, branchpriority);
5697 
5698  /* mark variable to be non-deletable */
5699  SCIPvarMarkNotDeletable(tmpvars[v]);
5700  }
5701  for( v = 0; v < ntmpvars; ++v )
5702  {
5703  SCIP_CALL( SCIPvarChgBranchFactor(tmpvars[v], set, branchfactor) );
5704  SCIP_CALL( SCIPvarChgBranchPriority(tmpvars[v], branchpriority) );
5705  if( (SCIP_BRANCHDIR)tmpvars[v]->branchdirection == SCIP_BRANCHDIR_AUTO )
5706  {
5707  if( tmpscalars[v] >= 0.0 )
5708  {
5709  SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], branchdirection) );
5710  }
5711  else
5712  {
5713  SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], SCIPbranchdirOpposite(branchdirection)) );
5714  }
5715  }
5716  }
5717  SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
5718  SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
5719 
5720  if( var->probindex != -1 )
5721  {
5722  /* inform problem about the variable's status change */
5723  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
5724  }
5725 
5726  /* issue VARFIXED event */
5727  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 2) );
5728 
5729  /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
5730  * variables and the problem's objective offset
5731  */
5732  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventfilter, eventqueue, obj) );
5733 
5734  *aggregated = TRUE;
5735 
5736  TERMINATE:
5737  BMSfreeBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize);
5738  BMSfreeBlockMemoryArray(blkmem, &tmpvars, tmpvarssize);
5739 
5740  break;
5741 
5742  case SCIP_VARSTATUS_COLUMN:
5743  SCIPerrorMessage("cannot multi-aggregate a column variable\n");
5744  return SCIP_INVALIDDATA;
5745 
5746  case SCIP_VARSTATUS_FIXED:
5747  SCIPerrorMessage("cannot multi-aggregate a fixed variable\n");
5748  return SCIP_INVALIDDATA;
5749 
5751  SCIPerrorMessage("cannot multi-aggregate an aggregated variable\n");
5752  return SCIP_INVALIDDATA;
5753 
5755  SCIPerrorMessage("cannot multi-aggregate a multiple aggregated variable again\n");
5756  return SCIP_INVALIDDATA;
5757 
5759  /* aggregate negation variable x in x' = offset - x, instead of aggregating x' directly:
5760  * x' = a_1*y_1 + ... + a_n*y_n + c -> x = offset - x' = offset - a_1*y_1 - ... - a_n*y_n - c
5761  */
5762  assert(SCIPsetIsZero(set, var->obj));
5763  assert(var->negatedvar != NULL);
5765  assert(var->negatedvar->negatedvar == var);
5766 
5767  /* switch the signs of the aggregation scalars */
5768  for( v = 0; v < naggvars; ++v )
5769  scalars[v] *= -1.0;
5770 
5771  /* perform the multi aggregation on the negation variable */
5772  SCIP_CALL( SCIPvarMultiaggregate(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5773  cliquetable, branchcand, eventfilter, eventqueue, naggvars, aggvars, scalars,
5774  var->data.negate.constant - constant, infeasible, aggregated) );
5775 
5776  /* switch the signs of the aggregation scalars again, to reset them to their original values */
5777  for( v = 0; v < naggvars; ++v )
5778  scalars[v] *= -1.0;
5779  break;
5780 
5781  default:
5782  SCIPerrorMessage("unknown variable status\n");
5783  return SCIP_INVALIDDATA;
5784  }
5785 
5786  return SCIP_OKAY;
5787 }
5788 
5789 /** transformed variables are resolved to their active, fixed, or multi-aggregated problem variable of a variable,
5790  * or for original variables the same variable is returned
5791  */
5792 static
5794  SCIP_VAR* var /**< problem variable */
5795  )
5796 {
5797  SCIP_VAR* retvar;
5798 
5799  assert(var != NULL);
5800 
5801  retvar = var;
5802 
5803  SCIPdebugMessage("get active variable of <%s>\n", var->name);
5804 
5805  while( TRUE ) /*lint !e716 */
5806  {
5807  assert(retvar != NULL);
5808 
5809  switch( SCIPvarGetStatus(retvar) )
5810  {
5812  case SCIP_VARSTATUS_LOOSE:
5813  case SCIP_VARSTATUS_COLUMN:
5814  case SCIP_VARSTATUS_FIXED:
5815  return retvar;
5816 
5818  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
5819  if ( retvar->data.multaggr.nvars == 1 )
5820  retvar = retvar->data.multaggr.vars[0];
5821  else
5822  return retvar;
5823  break;
5824 
5826  retvar = retvar->data.aggregate.var;
5827  break;
5828 
5830  retvar = retvar->negatedvar;
5831  break;
5832 
5833  default:
5834  SCIPerrorMessage("unknown variable status\n");
5835  SCIPABORT();
5836  return NULL; /*lint !e527*/
5837  }
5838  }
5839 }
5840 
5841 /** returns whether variable is not allowed to be aggregated */
5843  SCIP_VAR* var /**< problem variable */
5844  )
5845 {
5846  SCIP_VAR* retvar;
5847 
5848  assert(var != NULL);
5849 
5850  retvar = varGetActiveVar(var);
5851  assert(retvar != NULL);
5852 
5853  switch( SCIPvarGetStatus(retvar) )
5854  {
5856  case SCIP_VARSTATUS_LOOSE:
5857  case SCIP_VARSTATUS_COLUMN:
5858  case SCIP_VARSTATUS_FIXED:
5859  return retvar->donotaggr;
5860 
5862  return FALSE;
5863 
5866  default:
5867  /* aggregated and negated variables should be resolved by varGetActiveVar() */
5868  SCIPerrorMessage("wrong variable status\n");
5869  SCIPABORT();
5870  return FALSE; /*lint !e527 */
5871  }
5872 }
5873 
5874 /** returns whether variable is not allowed to be multi-aggregated */
5876  SCIP_VAR* var /**< problem variable */
5877  )
5878 {
5879  SCIP_VAR* retvar;
5880 
5881  assert(var != NULL);
5882 
5883  retvar = varGetActiveVar(var);
5884  assert(retvar != NULL);
5885 
5886  switch( SCIPvarGetStatus(retvar) )
5887  {
5889  case SCIP_VARSTATUS_LOOSE:
5890  case SCIP_VARSTATUS_COLUMN:
5891  case SCIP_VARSTATUS_FIXED:
5892  return retvar->donotmultaggr;
5893 
5895  return FALSE;
5896 
5899  default:
5900  /* aggregated and negated variables should be resolved by varGetActiveVar() */
5901  SCIPerrorMessage("wrong variable status\n");
5902  SCIPABORT();
5903  return FALSE; /*lint !e527 */
5904  }
5905 }
5906 
5907 /** gets negated variable x' = offset - x of problem variable x; the negated variable is created if not yet existing;
5908  * the negation offset of binary variables is always 1, the offset of other variables is fixed to lb + ub when the
5909  * negated variable is created
5910  */
5912  SCIP_VAR* var, /**< problem variable to negate */
5913  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
5914  SCIP_SET* set, /**< global SCIP settings */
5915  SCIP_STAT* stat, /**< problem statistics */
5916  SCIP_VAR** negvar /**< pointer to store the negated variable */
5917  )
5918 {
5919  assert(var != NULL);
5920  assert(var->scip == set->scip);
5921  assert(negvar != NULL);
5922 
5923  /* check, if we already created the negated variable */
5924  if( var->negatedvar == NULL )
5925  {
5926  char negvarname[SCIP_MAXSTRLEN];
5927 
5928  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED);
5929 
5930  SCIPsetDebugMsg(set, "creating negated variable of <%s>\n", var->name);
5931 
5932  /* negation is only possible for bounded variables */
5933  if( SCIPsetIsInfinity(set, -var->glbdom.lb) || SCIPsetIsInfinity(set, var->glbdom.ub) )
5934  {
5935  SCIPerrorMessage("cannot negate unbounded variable\n");
5936  return SCIP_INVALIDDATA;
5937  }
5938 
5939  (void) SCIPsnprintf(negvarname, SCIP_MAXSTRLEN, "%s_neg", var->name);
5940 
5941  /* create negated variable */
5942  SCIP_CALL( varCreate(negvar, blkmem, set, stat, negvarname, var->glbdom.lb, var->glbdom.ub, 0.0,
5943  SCIPvarGetType(var), var->initial, var->removable, NULL, NULL, NULL, NULL, NULL) );
5944  (*negvar)->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
5945  if( SCIPvarIsBinary(var) )
5946  (*negvar)->data.negate.constant = 1.0;
5947  else
5948  (*negvar)->data.negate.constant = var->glbdom.lb + var->glbdom.ub;
5949 
5950  /* create event filter for transformed variable */
5951  if( SCIPvarIsTransformed(var) )
5952  {
5953  SCIP_CALL( SCIPeventfilterCreate(&(*negvar)->eventfilter, blkmem) );
5954  }
5955 
5956  /* set the bounds corresponding to the negation variable */
5957  (*negvar)->glbdom.lb = (*negvar)->data.negate.constant - var->glbdom.ub;
5958  (*negvar)->glbdom.ub = (*negvar)->data.negate.constant - var->glbdom.lb;
5959  (*negvar)->locdom.lb = (*negvar)->data.negate.constant - var->locdom.ub;
5960  (*negvar)->locdom.ub = (*negvar)->data.negate.constant - var->locdom.lb;
5961  /**@todo create holes in the negated variable corresponding to the holes of the negation variable */
5962 
5963  /* link the variables together */
5964  var->negatedvar = *negvar;
5965  (*negvar)->negatedvar = var;
5966 
5967  /* mark both variables to be non-deletable */
5969  SCIPvarMarkNotDeletable(*negvar);
5970 
5971  /* copy the branch factor and priority, and use the negative preferred branching direction */
5972  (*negvar)->branchfactor = var->branchfactor;
5973  (*negvar)->branchpriority = var->branchpriority;
5974  (*negvar)->branchdirection = SCIPbranchdirOpposite((SCIP_BRANCHDIR)var->branchdirection); /*lint !e641*/
5975 
5976  /* copy donot(mult)aggr status */
5977  (*negvar)->donotaggr = var->donotaggr;
5978  (*negvar)->donotmultaggr = var->donotmultaggr;
5979 
5980  /* copy lazy bounds (they have to be flipped) */
5981  (*negvar)->lazylb = (*negvar)->data.negate.constant - var->lazyub;
5982  (*negvar)->lazyub = (*negvar)->data.negate.constant - var->lazylb;
5983 
5984  /* make negated variable a parent of the negation variable (negated variable is captured as a parent) */
5985  SCIP_CALL( varAddParent(var, blkmem, set, *negvar) );
5986  assert((*negvar)->nuses == 1);
5987  }
5988  assert(var->negatedvar != NULL);
5989 
5990  /* return the negated variable */
5991  *negvar = var->negatedvar;
5992 
5993  /* exactly one variable of the negation pair has to be marked as negated variable */
5995 
5996  return SCIP_OKAY;
5997 }
5998 
5999 /** informs variable that its position in problem's vars array changed */
6000 static
6001 void varSetProbindex(
6002  SCIP_VAR* var, /**< problem variable */
6003  int probindex /**< new problem index of variable (-1 for removal) */
6004  )
6005 {
6006  assert(var != NULL);
6007  assert(probindex >= 0 || var->vlbs == NULL);
6008  assert(probindex >= 0 || var->vubs == NULL);
6009  assert(probindex >= 0 || var->implics == NULL);
6010 
6011  var->probindex = probindex;
6013  {
6014  assert(var->data.col != NULL);
6015  var->data.col->var_probindex = probindex;
6016  }
6017 }
6018 
6019 /** informs variable that its position in problem's vars array changed */
6020 void SCIPvarSetProbindex(
6021  SCIP_VAR* var, /**< problem variable */
6022  int probindex /**< new problem index of variable */
6023  )
6024 {
6025  assert(var != NULL);
6026  assert(probindex >= 0);
6027 
6028  varSetProbindex(var, probindex);
6029 }
6030 
6031 /** gives the variable a new name
6032  *
6033  * @note the old pointer is overwritten, which might result in a memory leakage
6034  */
6036  SCIP_VAR* var, /**< problem variable */
6037  const char* name /**< new name of variable */
6038  )
6039 {
6040  assert(var != NULL);
6041  assert(name != NULL);
6042 
6043  var->name = (char*)name;
6044 }
6045 
6046 /** informs variable that it will be removed from the problem; adjusts probindex and removes variable from the
6047  * implication graph;
6048  * If 'final' is TRUE, the thorough implication graph removal is not performed. Instead, only the
6049  * variable bounds and implication data structures of the variable are freed. Since in the final removal
6050  * of all variables from the transformed problem, this deletes the implication graph completely and is faster
6051  * than removing the variables one by one, each time updating all lists of the other variables.
6052  */
6054  SCIP_VAR* var, /**< problem variable */
6055  BMS_BLKMEM* blkmem, /**< block memory buffer */
6056  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6057  SCIP_SET* set, /**< global SCIP settings */
6058  SCIP_Bool final /**< is this the final removal of all problem variables? */
6059  )
6060 {
6061  assert(SCIPvarGetProbindex(var) >= 0);
6062  assert(var->scip == set->scip);
6063 
6064  /* if the variable is active in the transformed problem, remove it from the implication graph */
6065  if( SCIPvarIsTransformed(var)
6067  {
6068  if( final )
6069  {
6070  /* just destroy the data structures */
6071  SCIPvboundsFree(&var->vlbs, blkmem);
6072  SCIPvboundsFree(&var->vubs, blkmem);
6073  SCIPimplicsFree(&var->implics, blkmem);
6074  }
6075  else
6076  {
6077  /* unlink the variable from all other variables' lists and free the data structures */
6078  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
6079  }
6080  }
6081 
6082  /* mark the variable to be no longer a member of the problem */
6083  varSetProbindex(var, -1);
6084 
6085  return SCIP_OKAY;
6086 }
6087 
6088 /** marks the variable to be deleted from the problem */
6089 void SCIPvarMarkDeleted(
6090  SCIP_VAR* var /**< problem variable */
6091  )
6092 {
6093  assert(var != NULL);
6094  assert(var->probindex != -1);
6095 
6096  var->deleted = TRUE;
6097 }
6098 
6099 /** marks the variable to not to be aggregated */
6101  SCIP_VAR* var /**< problem variable */
6102  )
6103 {
6104  SCIP_VAR* retvar;
6105 
6106  assert(var != NULL);
6107 
6108  retvar = varGetActiveVar(var);
6109  assert(retvar != NULL);
6110 
6111  switch( SCIPvarGetStatus(retvar) )
6112  {
6114  case SCIP_VARSTATUS_LOOSE:
6115  case SCIP_VARSTATUS_COLUMN:
6116  case SCIP_VARSTATUS_FIXED:
6117  retvar->donotaggr = TRUE;
6118  break;
6119 
6121  SCIPerrorMessage("cannot mark a multi-aggregated variable to not be aggregated.\n");
6122  return SCIP_INVALIDDATA;
6123 
6126  default:
6127  /* aggregated and negated variables should be resolved by varGetActiveVar() */
6128  SCIPerrorMessage("wrong variable status\n");
6129  return SCIP_INVALIDDATA;
6130  }
6131 
6132  return SCIP_OKAY;
6133 }
6134 
6135 /** marks the variable to not to be multi-aggregated */
6137  SCIP_VAR* var /**< problem variable */
6138  )
6139 {
6140  SCIP_VAR* retvar;
6141 
6142  assert(var != NULL);
6143 
6144  retvar = varGetActiveVar(var);
6145  assert(retvar != NULL);
6146 
6147  switch( SCIPvarGetStatus(retvar) )
6148  {
6150  case SCIP_VARSTATUS_LOOSE:
6151  case SCIP_VARSTATUS_COLUMN:
6152  case SCIP_VARSTATUS_FIXED:
6153  retvar->donotmultaggr = TRUE;
6154  break;
6155 
6157  SCIPerrorMessage("cannot mark a multi-aggregated variable to not be multi-aggregated.\n");
6158  return SCIP_INVALIDDATA;
6159 
6162  default:
6163  /* aggregated and negated variables should be resolved by varGetActiveVar() */
6164  SCIPerrorMessage("wrong variable status\n");
6165  return SCIP_INVALIDDATA;
6166  }
6167 
6168  return SCIP_OKAY;
6169 }
6170 
6171 /** changes type of variable; cannot be called, if var belongs to a problem */
6173  SCIP_VAR* var, /**< problem variable to change */
6174  BMS_BLKMEM* blkmem, /**< block memory */
6175  SCIP_SET* set, /**< global SCIP settings */
6176  SCIP_PRIMAL* primal, /**< primal data */
6177  SCIP_LP* lp, /**< current LP data */
6178  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6179  SCIP_VARTYPE vartype /**< new type of variable */
6180  )
6181 {
6182  SCIP_EVENT* event;
6183  SCIP_VARTYPE oldtype;
6184 
6185  assert(var != NULL);
6186 
6187  SCIPdebugMessage("change type of <%s> from %d to %d\n", var->name, SCIPvarGetType(var), vartype);
6188 
6189  if( var->probindex >= 0 )
6190  {
6191  SCIPerrorMessage("cannot change type of variable already in the problem\n");
6192  return SCIP_INVALIDDATA;
6193  }
6194 
6195  oldtype = (SCIP_VARTYPE)var->vartype;
6196  var->vartype = vartype; /*lint !e641*/
6197 
6199  {
6200  SCIP_CALL( SCIPeventCreateTypeChanged(&event, blkmem, var, oldtype, vartype) );
6201  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
6202  }
6203 
6204  if( var->negatedvar != NULL )
6205  {
6206  assert(oldtype == (SCIP_VARTYPE)var->negatedvar->vartype
6207  || SCIPvarIsBinary(var) == SCIPvarIsBinary(var->negatedvar));
6208 
6209 
6210  var->negatedvar->vartype = vartype; /*lint !e641*/
6211 
6213  {
6214  SCIP_CALL( SCIPeventCreateTypeChanged(&event, blkmem, var->negatedvar, oldtype, vartype) );
6215  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
6216  }
6217  }
6218 
6219  return SCIP_OKAY;
6220 }
6221 
6222 /** appends OBJCHANGED event to the event queue */
6223 static
6225  SCIP_VAR* var, /**< problem variable to change */
6226  BMS_BLKMEM* blkmem, /**< block memory */
6227  SCIP_SET* set, /**< global SCIP settings */
6228  SCIP_PRIMAL* primal, /**< primal data */
6229  SCIP_LP* lp, /**< current LP data */
6230  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6231  SCIP_Real oldobj, /**< old objective value for variable */
6232  SCIP_Real newobj /**< new objective value for variable */
6233  )
6234 {
6235  SCIP_EVENT* event;
6236 
6237  assert(var != NULL);
6238  assert(var->scip == set->scip);
6239  assert(var->eventfilter != NULL);
6241  assert(SCIPvarIsTransformed(var));
6242 
6243  /* In the case where the objcetive value of a variable is very close to epsilon, and it is aggregated
6244  * into a variable with a big objective value, round-off errors might make the assert oldobj != newobj fail.
6245  * Hence, we relax it by letting it pass if the variables are percieved the same and we use very large values
6246  * that make comparison with values close to epsilon inaccurate.
6247  */
6248  assert(!SCIPsetIsEQ(set, oldobj, newobj) ||
6249  (SCIPsetIsEQ(set, oldobj, newobj) && REALABS(newobj) > 1e+15 * SCIPsetEpsilon(set))
6250  );
6251 
6252  SCIP_CALL( SCIPeventCreateObjChanged(&event, blkmem, var, oldobj, newobj) );
6253  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
6254 
6255  return SCIP_OKAY;
6256 }
6257 
6258 /** changes objective value of variable */
6260  SCIP_VAR* var, /**< variable to change */
6261  BMS_BLKMEM* blkmem, /**< block memory */
6262  SCIP_SET* set, /**< global SCIP settings */
6263  SCIP_PROB* prob, /**< problem data */
6264  SCIP_PRIMAL* primal, /**< primal data */
6265  SCIP_LP* lp, /**< current LP data */
6266  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6267  SCIP_Real newobj /**< new objective value for variable */
6268  )
6269 {
6270  SCIP_Real oldobj;
6271 
6272  assert(var != NULL);
6273  assert(set != NULL);
6274  assert(var->scip == set->scip);
6275 
6276  SCIPsetDebugMsg(set, "changing objective value of <%s> from %g to %g\n", var->name, var->obj, newobj);
6277 
6278  if( !SCIPsetIsEQ(set, var->obj, newobj) )
6279  {
6280  switch( SCIPvarGetStatus(var) )
6281  {
6283  if( var->data.original.transvar != NULL )
6284  {
6285  assert(SCIPprobIsTransformed(prob));
6286 
6287  SCIP_CALL( SCIPvarChgObj(var->data.original.transvar, blkmem, set, prob, primal, lp, eventqueue,
6288  (SCIP_Real) prob->objsense * newobj/prob->objscale) );
6289  }
6290  else
6291  assert(set->stage == SCIP_STAGE_PROBLEM);
6292 
6293  var->obj = newobj;
6294  var->unchangedobj = newobj;
6295 
6296  break;
6297 
6298  case SCIP_VARSTATUS_LOOSE:
6299  case SCIP_VARSTATUS_COLUMN:
6300  oldobj = var->obj;
6301  var->obj = newobj;
6302 
6303  /* update unchanged objective value of variable */
6304  if( !lp->divingobjchg )
6305  var->unchangedobj = newobj;
6306 
6307  /* update the number of variables with non-zero objective coefficient;
6308  * we only want to do the update, if the variable is added to the problem;
6309  * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
6310  */
6311  if( SCIPvarIsActive(var) )
6312  SCIPprobUpdateNObjVars(prob, set, oldobj, var->obj);
6313 
6314  SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
6315  break;
6316 
6317  case SCIP_VARSTATUS_FIXED:
6321  SCIPerrorMessage("cannot change objective value of a fixed, aggregated, multi-aggregated, or negated variable\n");
6322  return SCIP_INVALIDDATA;
6323 
6324  default:
6325  SCIPerrorMessage("unknown variable status\n");
6326  return SCIP_INVALIDDATA;
6327  }
6328  }
6329 
6330  return SCIP_OKAY;
6331 }
6332 
6333 /** adds value to objective value of variable */
6335  SCIP_VAR* var, /**< variable to change */
6336  BMS_BLKMEM* blkmem, /**< block memory */
6337  SCIP_SET* set, /**< global SCIP settings */
6338  SCIP_STAT* stat, /**< problem statistics */
6339  SCIP_PROB* transprob, /**< transformed problem data */
6340  SCIP_PROB* origprob, /**< original problem data */
6341  SCIP_PRIMAL* primal, /**< primal data */
6342  SCIP_TREE* tree, /**< branch and bound tree */
6343  SCIP_REOPT* reopt, /**< reoptimization data structure */
6344  SCIP_LP* lp, /**< current LP data */
6345  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
6346  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6347  SCIP_Real addobj /**< additional objective value for variable */
6348  )
6349 {
6350  assert(var != NULL);
6351  assert(set != NULL);
6352  assert(var->scip == set->scip);
6353  assert(set->stage < SCIP_STAGE_INITSOLVE);
6354 
6355  SCIPsetDebugMsg(set, "adding %g to objective value %g of <%s>\n", addobj, var->obj, var->name);
6356 
6357  if( !SCIPsetIsZero(set, addobj) )
6358  {
6359  SCIP_Real oldobj;
6360  int i;
6361 
6362  switch( SCIPvarGetStatus(var) )
6363  {
6365  if( var->data.original.transvar != NULL )
6366  {
6367  SCIP_CALL( SCIPvarAddObj(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
6368  reopt, lp, eventfilter, eventqueue, (SCIP_Real) transprob->objsense * addobj/transprob->objscale) );
6369  }
6370  else
6371  assert(set->stage == SCIP_STAGE_PROBLEM);
6372 
6373  var->obj += addobj;
6374  var->unchangedobj += addobj;
6375  assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
6376 
6377  break;
6378 
6379  case SCIP_VARSTATUS_LOOSE:
6380  case SCIP_VARSTATUS_COLUMN:
6381  oldobj = var->obj;
6382  var->obj += addobj;
6383 
6384  /* update unchanged objective value of variable */
6385  if( !lp->divingobjchg )
6386  {
6387  var->unchangedobj += addobj;
6388  assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
6389  }
6390 
6391  /* update the number of variables with non-zero objective coefficient;
6392  * we only want to do the update, if the variable is added to the problem;
6393  * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
6394  */
6395  if( SCIPvarIsActive(var) )
6396  SCIPprobUpdateNObjVars(transprob, set, oldobj, var->obj);
6397 
6398  SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
6399  break;
6400 
6401  case SCIP_VARSTATUS_FIXED:
6402  assert(SCIPsetIsEQ(set, var->locdom.lb, var->locdom.ub));
6403  SCIPprobAddObjoffset(transprob, var->locdom.lb * addobj);
6404  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6405  break;
6406 
6408  assert(!var->donotaggr);
6409  /* x = a*y + c -> add a*addobj to obj. val. of y, and c*addobj to obj. offset of problem */
6410  SCIPprobAddObjoffset(transprob, var->data.aggregate.constant * addobj);
6411  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6412  SCIP_CALL( SCIPvarAddObj(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
6413  lp, eventfilter, eventqueue, var->data.aggregate.scalar * addobj) );
6414  break;
6415 
6417  assert(!var->donotmultaggr);
6418  /* 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 */
6419  SCIPprobAddObjoffset(transprob, var->data.multaggr.constant * addobj);
6420  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6421  for( i = 0; i < var->data.multaggr.nvars; ++i )
6422  {
6423  SCIP_CALL( SCIPvarAddObj(var->data.multaggr.vars[i], blkmem, set, stat, transprob, origprob, primal, tree,
6424  reopt, lp, eventfilter, eventqueue, var->data.multaggr.scalars[i] * addobj) );
6425  }
6426  break;
6427 
6429  /* x' = offset - x -> add -addobj to obj. val. of x and offset*addobj to obj. offset of problem */
6430  assert(var->negatedvar != NULL);
6432  assert(var->negatedvar->negatedvar == var);
6433  SCIPprobAddObjoffset(transprob, var->data.negate.constant * addobj);
6434  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6435  SCIP_CALL( SCIPvarAddObj(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
6436  eventfilter, eventqueue, -addobj) );
6437  break;
6438 
6439  default:
6440  SCIPerrorMessage("unknown variable status\n");
6441  return SCIP_INVALIDDATA;
6442  }
6443  }
6444 
6445  return SCIP_OKAY;
6446 }
6447 
6448 /** changes objective value of variable in current dive */
6450  SCIP_VAR* var, /**< problem variable to change */
6451  SCIP_SET* set, /**< global SCIP settings */
6452  SCIP_LP* lp, /**< current LP data */
6453  SCIP_Real newobj /**< new objective value for variable */
6454  )
6455 {
6456  assert(var != NULL);
6457  assert(set != NULL);
6458  assert(var->scip == set->scip);
6459  assert(lp != NULL);
6460 
6461  SCIPsetDebugMsg(set, "changing objective of <%s> to %g in current dive\n", var->name, newobj);
6462 
6463  if( SCIPsetIsZero(set, newobj) )
6464  newobj = 0.0;
6465 
6466  /* change objective value of attached variables */
6467  switch( SCIPvarGetStatus(var) )
6468  {
6470  assert(var->data.original.transvar != NULL);
6471  SCIP_CALL( SCIPvarChgObjDive(var->data.original.transvar, set, lp, newobj) );
6472  break;
6473 
6474  case SCIP_VARSTATUS_COLUMN:
6475  assert(var->data.col != NULL);
6476  SCIP_CALL( SCIPcolChgObj(var->data.col, set, lp, newobj) );
6477  break;
6478 
6479  case SCIP_VARSTATUS_LOOSE:
6480  case SCIP_VARSTATUS_FIXED:
6481  /* nothing to do here: only the constant shift in objective function would change */
6482  break;
6483 
6484  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6485  assert(var->data.aggregate.var != NULL);
6486  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
6487  SCIP_CALL( SCIPvarChgObjDive(var->data.aggregate.var, set, lp, newobj / var->data.aggregate.scalar) );
6488  /* the constant can be ignored, because it would only affect the objective shift */
6489  break;
6490 
6492  SCIPerrorMessage("cannot change diving objective value of a multi-aggregated variable\n");
6493  return SCIP_INVALIDDATA;
6494 
6495  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6496  assert(var->negatedvar != NULL);
6498  assert(var->negatedvar->negatedvar == var);
6499  SCIP_CALL( SCIPvarChgObjDive(var->negatedvar, set, lp, -newobj) );
6500  /* the offset can be ignored, because it would only affect the objective shift */
6501  break;
6502 
6503  default:
6504  SCIPerrorMessage("unknown variable status\n");
6505  return SCIP_INVALIDDATA;
6506  }
6507 
6508  return SCIP_OKAY;
6509 }
6510 
6511 /** adjust lower bound to integral value, if variable is integral */
6512 void SCIPvarAdjustLb(
6513  SCIP_VAR* var, /**< problem variable */
6514  SCIP_SET* set, /**< global SCIP settings */
6515  SCIP_Real* lb /**< pointer to lower bound to adjust */
6516  )
6517 {
6518  assert(var != NULL);
6519  assert(set != NULL);
6520  assert(var->scip == set->scip);
6521  assert(lb != NULL);
6522 
6523  SCIPsetDebugMsg(set, "adjust lower bound %g of <%s>\n", *lb, var->name);
6524 
6525  *lb = adjustedLb(set, SCIPvarGetType(var), *lb);
6526 }
6527 
6528 /** adjust upper bound to integral value, if variable is integral */
6529 void SCIPvarAdjustUb(
6530  SCIP_VAR* var, /**< problem variable */
6531  SCIP_SET* set, /**< global SCIP settings */
6532  SCIP_Real* ub /**< pointer to upper bound to adjust */
6533  )
6534 {
6535  assert(var != NULL);
6536  assert(set != NULL);
6537  assert(var->scip == set->scip);
6538  assert(ub != NULL);
6539 
6540  SCIPsetDebugMsg(set, "adjust upper bound %g of <%s>\n", *ub, var->name);
6541 
6542  *ub = adjustedUb(set, SCIPvarGetType(var), *ub);
6543 }
6544 
6545 /** adjust lower or upper bound to integral value, if variable is integral */
6546 void SCIPvarAdjustBd(
6547  SCIP_VAR* var, /**< problem variable */
6548  SCIP_SET* set, /**< global SCIP settings */
6549  SCIP_BOUNDTYPE boundtype, /**< type of bound to adjust */
6550  SCIP_Real* bd /**< pointer to bound to adjust */
6551  )
6552 {
6553  assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
6554 
6555  if( boundtype == SCIP_BOUNDTYPE_LOWER )
6556  SCIPvarAdjustLb(var, set, bd);
6557  else
6558  SCIPvarAdjustUb(var, set, bd);
6559 }
6560 
6561 /** changes lower bound of original variable in original problem */
6563  SCIP_VAR* var, /**< problem variable to change */
6564  SCIP_SET* set, /**< global SCIP settings */
6565  SCIP_Real newbound /**< new bound for variable */
6566  )
6567 {
6568  int i;
6569 
6570  assert(var != NULL);
6571  assert(!SCIPvarIsTransformed(var));
6573  assert(set != NULL);
6574  assert(var->scip == set->scip);
6575  assert(set->stage == SCIP_STAGE_PROBLEM);
6576 
6577  /* check that the bound is feasible */
6578  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsLE(set, newbound, SCIPvarGetUbOriginal(var)));
6579  /* adjust bound to integral value if variable is of integral type */
6580  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6581 
6582  if( SCIPsetIsZero(set, newbound) )
6583  newbound = 0.0;
6584 
6585  /* original domains are only stored for ORIGINAL variables, not for NEGATED */
6587  {
6588  SCIPsetDebugMsg(set, "changing original lower bound of <%s> from %g to %g\n",
6589  var->name, var->data.original.origdom.lb, newbound);
6590 
6591  if( SCIPsetIsEQ(set, var->data.original.origdom.lb, newbound) )
6592  return SCIP_OKAY;
6593 
6594  /* change the bound */
6595  var->data.original.origdom.lb = newbound;
6596  }
6597  else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
6598  {
6599  assert( var->negatedvar != NULL );
6600  SCIP_CALL( SCIPvarChgUbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
6601  }
6602 
6603  /* process parent variables */
6604  for( i = 0; i < var->nparentvars; ++i )
6605  {
6606  SCIP_VAR* parentvar;
6607 
6608  parentvar = var->parentvars[i];
6609  assert(parentvar != NULL);
6610  assert(SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_NEGATED);
6611  assert(parentvar->negatedvar == var);
6612  assert(var->negatedvar == parentvar);
6613 
6614  SCIP_CALL( SCIPvarChgUbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
6615  }
6616 
6617  return SCIP_OKAY;
6618 }
6619 
6620 /** changes upper bound of original variable in original problem */
6622  SCIP_VAR* var, /**< problem variable to change */
6623  SCIP_SET* set, /**< global SCIP settings */
6624  SCIP_Real newbound /**< new bound for variable */
6625  )
6626 {
6627  int i;
6628 
6629  assert(var != NULL);
6630  assert(!SCIPvarIsTransformed(var));
6632  assert(set != NULL);
6633  assert(var->scip == set->scip);
6634  assert(set->stage == SCIP_STAGE_PROBLEM);
6635 
6636  /* check that the bound is feasible */
6637  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsGE(set, newbound, SCIPvarGetLbOriginal(var)));
6638  /* adjust bound to integral value if variable is of integral type */
6639  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
6640 
6641  if( SCIPsetIsZero(set, newbound) )
6642  newbound = 0.0;
6643 
6644  /* original domains are only stored for ORIGINAL variables, not for NEGATED */
6646  {
6647  SCIPsetDebugMsg(set, "changing original upper bound of <%s> from %g to %g\n",
6648  var->name, var->data.original.origdom.ub, newbound);
6649 
6650  if( SCIPsetIsEQ(set, var->data.original.origdom.ub, newbound) )
6651  return SCIP_OKAY;
6652 
6653  /* change the bound */
6654  var->data.original.origdom.ub = newbound;
6655  }
6656  else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
6657  {
6658  assert( var->negatedvar != NULL );
6659  SCIP_CALL( SCIPvarChgLbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
6660  }
6661 
6662  /* process parent variables */
6663  for( i = 0; i < var->nparentvars; ++i )
6664  {
6665  SCIP_VAR* parentvar;
6666 
6667  parentvar = var->parentvars[i];
6668  assert(parentvar != NULL);
6669  assert(SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_NEGATED);
6670  assert(parentvar->negatedvar == var);
6671  assert(var->negatedvar == parentvar);
6672 
6673  SCIP_CALL( SCIPvarChgLbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
6674  }
6675 
6676  return SCIP_OKAY;
6677 }
6678 
6679 /** appends GLBCHANGED event to the event queue */
6680 static
6682  SCIP_VAR* var, /**< problem variable to change */
6683  BMS_BLKMEM* blkmem, /**< block memory */
6684  SCIP_SET* set, /**< global SCIP settings */
6685  SCIP_LP* lp, /**< current LP data */
6686  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6687  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6688  SCIP_Real oldbound, /**< old lower bound for variable */
6689  SCIP_Real newbound /**< new lower bound for variable */
6690  )
6691 {
6692  assert(var != NULL);
6693  assert(var->eventfilter != NULL);
6694  assert(SCIPvarIsTransformed(var));
6695  assert(!SCIPsetIsEQ(set, oldbound, newbound) || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
6696  assert(set != NULL);
6697  assert(var->scip == set->scip);
6698 
6699  /* check, if the variable is being tracked for bound changes
6700  * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
6701  */
6702  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GLBCHANGED) != 0)
6705  {
6706  SCIP_EVENT* event;
6707 
6708  SCIPsetDebugMsg(set, "issue GLBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
6709 
6710  SCIP_CALL( SCIPeventCreateGlbChanged(&event, blkmem, var, oldbound, newbound) );
6711  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
6712  }
6713 
6714  return SCIP_OKAY;
6715 }
6716 
6717 /** appends GUBCHANGED event to the event queue */
6718 static
6720  SCIP_VAR* var, /**< problem variable to change */
6721  BMS_BLKMEM* blkmem, /**< block memory */
6722  SCIP_SET* set, /**< global SCIP settings */
6723  SCIP_LP* lp, /**< current LP data */
6724  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6725  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6726  SCIP_Real oldbound, /**< old lower bound for variable */
6727  SCIP_Real newbound /**< new lower bound for variable */
6728  )
6729 {
6730  assert(var != NULL);
6731  assert(var->eventfilter != NULL);
6732  assert(SCIPvarIsTransformed(var));
6733  assert(!SCIPsetIsEQ(set, oldbound, newbound) || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
6734  assert(set != NULL);
6735  assert(var->scip == set->scip);
6736 
6737  /* check, if the variable is being tracked for bound changes
6738  * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
6739  */
6740  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GUBCHANGED) != 0)
6743  {
6744  SCIP_EVENT* event;
6745 
6746  SCIPsetDebugMsg(set, "issue GUBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
6747 
6748  SCIP_CALL( SCIPeventCreateGubChanged(&event, blkmem, var, oldbound, newbound) );
6749  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
6750  }
6751 
6752  return SCIP_OKAY;
6753 }
6754 
6755 /** appends GHOLEADDED event to the event queue */
6756 static
6758  SCIP_VAR* var, /**< problem variable to change */
6759  BMS_BLKMEM* blkmem, /**< block memory */
6760  SCIP_SET* set, /**< global SCIP settings */
6761  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6762  SCIP_Real left, /**< left bound of open interval in new hole */
6763  SCIP_Real right /**< right bound of open interval in new hole */
6764  )
6765 {
6766  assert(var != NULL);
6767  assert(var->eventfilter != NULL);
6768  assert(SCIPvarIsTransformed(var));
6769  assert(set != NULL);
6770  assert(var->scip == set->scip);
6771  assert(SCIPsetIsLT(set, left, right));
6772 
6773  /* check, if the variable is being tracked for bound changes */
6774  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GHOLEADDED) != 0) )
6775  {
6776  SCIP_EVENT* event;
6777 
6778  SCIPsetDebugMsg(set, "issue GHOLEADDED event for variable <%s>: (%.15g,%.15g)\n", var->name, left, right);
6779 
6780  SCIP_CALL( SCIPeventCreateGholeAdded(&event, blkmem, var, left, right) );
6781  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
6782  }
6783 
6784  return SCIP_OKAY;
6785 }
6786 
6787 /** increases root bound change statistics after a global bound change */
6788 static
6789 void varIncRootboundchgs(
6790  SCIP_VAR* var, /**< problem variable to change */
6791  SCIP_SET* set, /**< global SCIP settings */
6792  SCIP_STAT* stat /**< problem statistics */
6793  )
6794 {
6795  assert(var != NULL);
6796  assert(set != NULL);
6797  assert(var->scip == set->scip);
6798  assert(stat != NULL);
6799 
6800  if( SCIPvarIsActive(var) && SCIPvarIsTransformed(var) && set->stage == SCIP_STAGE_SOLVING )
6801  {
6802  stat->nrootboundchgs++;
6803  stat->nrootboundchgsrun++;
6804  if( SCIPvarIsIntegral(var) && SCIPvarGetLbGlobal(var) + 0.5 > SCIPvarGetUbGlobal(var) )
6805  {
6806  stat->nrootintfixings++;
6807  stat->nrootintfixingsrun++;
6808  }
6809  }
6810 }
6811 
6812 /* forward declaration, because both methods call each other recursively */
6813 
6814 /* performs the current change in upper bound, changes all parents accordingly */
6815 static
6817  SCIP_VAR* var, /**< problem variable to change */
6818  BMS_BLKMEM* blkmem, /**< block memory */
6819  SCIP_SET* set, /**< global SCIP settings */
6820  SCIP_STAT* stat, /**< problem statistics */
6821  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6822  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6823  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6824  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6825  SCIP_Real newbound /**< new bound for variable */
6826  );
6827 
6828 /** performs the current change in lower bound, changes all parents accordingly */
6829 static
6831  SCIP_VAR* var, /**< problem variable to change */
6832  BMS_BLKMEM* blkmem, /**< block memory */
6833  SCIP_SET* set, /**< global SCIP settings */
6834  SCIP_STAT* stat, /**< problem statistics */
6835  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6836  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6837  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6838  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6839  SCIP_Real newbound /**< new bound for variable */
6840  )
6841 {
6842  SCIP_VAR* parentvar;
6843  SCIP_Real oldbound;
6844  int i;
6845 
6846  assert(var != NULL);
6847  /* local domains can violate global bounds but not more than feasibility epsilon */
6848  assert(SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb));
6849  assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
6850  assert(blkmem != NULL);
6851  assert(set != NULL);
6852  assert(var->scip == set->scip);
6853  assert(stat != NULL);
6854 
6855  /* adjust bound to integral value if variable is of integral type */
6856  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6857 
6858  /* check that the bound is feasible */
6859  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound > var->glbdom.ub )
6860  {
6861  /* due to numerics we only want to be feasible in feasibility tolerance */
6862  assert(SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
6863  newbound = var->glbdom.ub;
6864  }
6865  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6866 
6867  assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
6868 
6869  SCIPsetDebugMsg(set, "process changing global lower bound of <%s> from %f to %f\n", var->name, var->glbdom.lb, newbound);
6870 
6871  if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) && !(newbound != var->glbdom.lb && newbound * var->glbdom.lb <= 0.0) ) /*lint !e777*/
6872  return SCIP_OKAY;
6873 
6874  /* check bound on debugging solution */
6875  SCIP_CALL( SCIPdebugCheckLbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
6876 
6877  /* change the bound */
6878  oldbound = var->glbdom.lb;
6879  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
6880  var->glbdom.lb = newbound;
6881  assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
6882  assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
6883 
6884  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6885  {
6886  /* merges overlapping holes into single holes, moves bounds respectively */
6887  domMerge(&var->glbdom, blkmem, set, &newbound, NULL);
6888  }
6889 
6890  /* update the root bound changes counters */
6891  varIncRootboundchgs(var, set, stat);
6892 
6893  /* update the lbchginfos array by replacing worse local bounds with the new global bound and changing the
6894  * redundant bound changes to be branching decisions
6895  */
6896  for( i = 0; i < var->nlbchginfos; ++i )
6897  {
6898  assert(var->lbchginfos[i].var == var);
6899 
6900  if( var->lbchginfos[i].oldbound < var->glbdom.lb )
6901  {
6902  SCIPsetDebugMsg(set, " -> adjust lower bound change <%s>: %g -> %g due to new global lower bound %g\n",
6903  SCIPvarGetName(var), var->lbchginfos[i].oldbound, var->lbchginfos[i].newbound, var->glbdom.lb);
6904  var->lbchginfos[i].oldbound = var->glbdom.lb;
6905  if( SCIPsetIsLE(set, var->lbchginfos[i].newbound, var->glbdom.lb) )
6906  {
6907  /* this bound change is redundant due to the new global bound */
6908  var->lbchginfos[i].newbound = var->glbdom.lb;
6909  var->lbchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
6910  var->lbchginfos[i].redundant = TRUE;
6911  }
6912  else
6913  break; /* from now on, the remaining local bound changes are not redundant */
6914  }
6915  else
6916  break; /* from now on, the remaining local bound changes are not redundant */
6917  }
6918 
6919  /* remove redundant implications and variable bounds */
6921  && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
6922  {
6923  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
6924  }
6925 
6926  /* issue bound change event */
6927  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
6928  if( var->eventfilter != NULL )
6929  {
6930  SCIP_CALL( varEventGlbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
6931  }
6932 
6933  /* process parent variables */
6934  for( i = 0; i < var->nparentvars; ++i )
6935  {
6936  parentvar = var->parentvars[i];
6937  assert(parentvar != NULL);
6938 
6939  switch( SCIPvarGetStatus(parentvar) )
6940  {
6942  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6943  break;
6944 
6945  case SCIP_VARSTATUS_COLUMN:
6946  case SCIP_VARSTATUS_LOOSE:
6947  case SCIP_VARSTATUS_FIXED:
6949  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
6950  return SCIP_INVALIDDATA;
6951 
6952  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6953  assert(parentvar->data.aggregate.var == var);
6954  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
6955  {
6956  SCIP_Real parentnewbound;
6957 
6958  /* a > 0 -> change lower bound of y */
6959  assert(SCIPsetIsInfinity(set, -parentvar->glbdom.lb) || SCIPsetIsInfinity(set, -oldbound)
6960  || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
6961  || (SCIPsetIsZero(set, parentvar->glbdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
6962 
6963  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6964  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6965  else
6966  parentnewbound = newbound;
6967  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6968  }
6969  else
6970  {
6971  SCIP_Real parentnewbound;
6972 
6973  /* a < 0 -> change upper bound of y */
6974  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
6975  assert(SCIPsetIsInfinity(set, parentvar->glbdom.ub) || SCIPsetIsInfinity(set, -oldbound)
6976  || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
6977  || (SCIPsetIsZero(set, parentvar->glbdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
6978 
6979  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6980  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6981  else
6982  parentnewbound = -newbound;
6983  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6984  }
6985  break;
6986 
6987  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6988  assert(parentvar->negatedvar != NULL);
6989  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
6990  assert(parentvar->negatedvar->negatedvar == parentvar);
6991  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6992  parentvar->data.negate.constant - newbound) );
6993  break;
6994 
6995  default:
6996  SCIPerrorMessage("unknown variable status\n");
6997  return SCIP_INVALIDDATA;
6998  }
6999  }
7000 
7001  return SCIP_OKAY;
7002 }
7003 
7004 /** performs the current change in upper bound, changes all parents accordingly */
7005 static
7007  SCIP_VAR* var, /**< problem variable to change */
7008  BMS_BLKMEM* blkmem, /**< block memory */
7009  SCIP_SET* set, /**< global SCIP settings */
7010  SCIP_STAT* stat, /**< problem statistics */
7011  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7012  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7013  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7014  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7015  SCIP_Real newbound /**< new bound for variable */
7016  )
7017 {
7018  SCIP_VAR* parentvar;
7019  SCIP_Real oldbound;
7020  int i;
7021 
7022  assert(var != NULL);
7023  /* local domains can violate global bounds but not more than feasibility epsilon */
7024  assert(SCIPsetIsFeasLE(set, var->glbdom.lb , var->locdom.lb));
7025  assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
7026  assert(blkmem != NULL);
7027  assert(set != NULL);
7028  assert(var->scip == set->scip);
7029  assert(stat != NULL);
7030 
7031  /* adjust bound to integral value if variable is of integral type */
7032  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7033 
7034  /* check that the bound is feasible */
7035  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound < var->glbdom.lb )
7036  {
7037  /* due to numerics we only want to be feasible in feasibility tolerance */
7038  assert(SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
7039  newbound = var->glbdom.lb;
7040  }
7041  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7042 
7043  assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
7044 
7045  SCIPsetDebugMsg(set, "process changing global upper bound of <%s> from %f to %f\n", var->name, var->glbdom.ub, newbound);
7046 
7047  if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) && !(newbound != var->glbdom.ub && newbound * var->glbdom.ub <= 0.0) ) /*lint !e777*/
7048  return SCIP_OKAY;
7049 
7050  /* check bound on debugging solution */
7051  SCIP_CALL( SCIPdebugCheckUbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
7052 
7053  /* change the bound */
7054  oldbound = var->glbdom.ub;
7055  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
7056  var->glbdom.ub = newbound;
7057  assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
7058  assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
7059 
7060  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7061  {
7062  /* merges overlapping holes into single holes, moves bounds respectively */
7063  domMerge(&var->glbdom, blkmem, set, NULL, &newbound);
7064  }
7065 
7066  /* update the root bound changes counters */
7067  varIncRootboundchgs(var, set, stat);
7068 
7069  /* update the ubchginfos array by replacing worse local bounds with the new global bound and changing the
7070  * redundant bound changes to be branching decisions
7071  */
7072  for( i = 0; i < var->nubchginfos; ++i )
7073  {
7074  assert(var->ubchginfos[i].var == var);
7075  if( var->ubchginfos[i].oldbound > var->glbdom.ub )
7076  {
7077  SCIPsetDebugMsg(set, " -> adjust upper bound change <%s>: %g -> %g due to new global upper bound %g\n",
7078  SCIPvarGetName(var), var->ubchginfos[i].oldbound, var->ubchginfos[i].newbound, var->glbdom.ub);
7079  var->ubchginfos[i].oldbound = var->glbdom.ub;
7080  if( SCIPsetIsGE(set, var->ubchginfos[i].newbound, var->glbdom.ub) )
7081  {
7082  /* this bound change is redundant due to the new global bound */
7083  var->ubchginfos[i].newbound = var->glbdom.ub;
7084  var->ubchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
7085  var->ubchginfos[i].redundant = TRUE;
7086  }
7087  else
7088  break; /* from now on, the remaining local bound changes are not redundant */
7089  }
7090  else
7091  break; /* from now on, the remaining local bound changes are not redundant */
7092  }
7093 
7094  /* remove redundant implications and variable bounds */
7096  && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
7097  {
7098  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
7099  }
7100 
7101  /* issue bound change event */
7102  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7103  if( var->eventfilter != NULL )
7104  {
7105  SCIP_CALL( varEventGubChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7106  }
7107 
7108  /* process parent variables */
7109  for( i = 0; i < var->nparentvars; ++i )
7110  {
7111  parentvar = var->parentvars[i];
7112  assert(parentvar != NULL);
7113 
7114  switch( SCIPvarGetStatus(parentvar) )
7115  {
7117  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7118  break;
7119 
7120  case SCIP_VARSTATUS_COLUMN:
7121  case SCIP_VARSTATUS_LOOSE:
7122  case SCIP_VARSTATUS_FIXED:
7124  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7125  return SCIP_INVALIDDATA;
7126 
7127  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7128  assert(parentvar->data.aggregate.var == var);
7129  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7130  {
7131  SCIP_Real parentnewbound;
7132 
7133  /* a > 0 -> change upper bound of y */
7134  assert(SCIPsetIsInfinity(set, parentvar->glbdom.ub) || SCIPsetIsInfinity(set, oldbound)
7135  || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub,
7136  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7137  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7138  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7139  else
7140  parentnewbound = newbound;
7141  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
7142  }
7143  else
7144  {
7145  SCIP_Real parentnewbound;
7146 
7147  /* a < 0 -> change lower bound of y */
7148  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7149  assert(SCIPsetIsInfinity(set, -parentvar->glbdom.lb) || SCIPsetIsInfinity(set, oldbound)
7150  || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb,
7151  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7152  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7153  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7154  else
7155  parentnewbound = -newbound;
7156  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
7157  }
7158  break;
7159 
7160  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7161  assert(parentvar->negatedvar != NULL);
7162  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7163  assert(parentvar->negatedvar->negatedvar == parentvar);
7164  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7165  parentvar->data.negate.constant - newbound) );
7166  break;
7167 
7168  default:
7169  SCIPerrorMessage("unknown variable status\n");
7170  return SCIP_INVALIDDATA;
7171  }
7172  }
7173 
7174  return SCIP_OKAY;
7175 }
7176 
7177 /** changes global lower bound of variable; if possible, adjusts bound to integral value;
7178  * updates local lower bound if the global bound is tighter
7179  */
7181  SCIP_VAR* var, /**< problem variable to change */
7182  BMS_BLKMEM* blkmem, /**< block memory */
7183  SCIP_SET* set, /**< global SCIP settings */
7184  SCIP_STAT* stat, /**< problem statistics */
7185  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7186  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7187  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7188  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7189  SCIP_Real newbound /**< new bound for variable */
7190  )
7191 {
7192  assert(var != NULL);
7193  assert(blkmem != NULL);
7194  assert(set != NULL);
7195  assert(var->scip == set->scip);
7196 
7197  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7198  * of the domain within feastol
7199  */
7200  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
7201 
7202  /* adjust bound to integral value if variable is of integral type */
7203  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7204 
7205  /* check that the adjusted bound is feasible
7206  * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
7207  * here because we reset bounds to their original value!
7208  */
7209  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
7210 
7211  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7212  {
7213  /* we do not want to exceed the upperbound, which could have happened due to numerics */
7214  newbound = MIN(newbound, var->glbdom.ub);
7215  }
7216  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7217 
7218  /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
7219  * SCIPvarFix() allows fixings that are outside of the domain within feastol
7220  */
7221  assert(lp == NULL || SCIPsetIsFeasLE(set, var->glbdom.lb, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
7222 
7223  SCIPsetDebugMsg(set, "changing global lower bound of <%s> from %g to %g\n", var->name, var->glbdom.lb, newbound);
7224 
7225  if( SCIPsetIsEQ(set, var->glbdom.lb, newbound) && !(newbound != var->glbdom.lb && newbound * var->glbdom.lb <= 0.0) ) /*lint !e777*/
7226  return SCIP_OKAY;
7227 
7228  /* change bounds of attached variables */
7229  switch( SCIPvarGetStatus(var) )
7230  {
7232  if( var->data.original.transvar != NULL )
7233  {
7234  SCIP_CALL( SCIPvarChgLbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
7235  cliquetable, newbound) );
7236  }
7237  else
7238  {
7239  assert(set->stage == SCIP_STAGE_PROBLEM);
7240  if( newbound > SCIPvarGetLbLocal(var) )
7241  {
7242  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7243  }
7244  SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7245  }
7246  break;
7247 
7248  case SCIP_VARSTATUS_COLUMN:
7249  case SCIP_VARSTATUS_LOOSE:
7250  if( newbound > SCIPvarGetLbLocal(var) )
7251  {
7252  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7253  }
7254  SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7255  break;
7256 
7257  case SCIP_VARSTATUS_FIXED:
7258  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7259  return SCIP_INVALIDDATA;
7260 
7261  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7262  assert(var->data.aggregate.var != NULL);
7263  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7264  {
7265  SCIP_Real childnewbound;
7266 
7267  /* a > 0 -> change lower bound of y */
7268  assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, -var->data.aggregate.var->glbdom.lb))
7269  || SCIPsetIsFeasEQ(set, var->glbdom.lb,
7271  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7272  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7273  else
7274  childnewbound = newbound;
7275  SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7276  childnewbound) );
7277  }
7278  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7279  {
7280  SCIP_Real childnewbound;
7281 
7282  /* a < 0 -> change upper bound of y */
7283  assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
7284  || SCIPsetIsFeasEQ(set, var->glbdom.lb,
7286  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7287  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7288  else
7289  childnewbound = -newbound;
7290  SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7291  childnewbound) );
7292  }
7293  else
7294  {
7295  SCIPerrorMessage("scalar is zero in aggregation\n");
7296  return SCIP_INVALIDDATA;
7297  }
7298  break;
7299 
7301  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7302  return SCIP_INVALIDDATA;
7303 
7304  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7305  assert(var->negatedvar != NULL);
7307  assert(var->negatedvar->negatedvar == var);
7308  SCIP_CALL( SCIPvarChgUbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7309  var->data.negate.constant - newbound) );
7310  break;
7311 
7312  default:
7313  SCIPerrorMessage("unknown variable status\n");
7314  return SCIP_INVALIDDATA;
7315  }
7316 
7317  return SCIP_OKAY;
7318 }
7319 
7320 /** changes global upper bound of variable; if possible, adjusts bound to integral value;
7321  * updates local upper bound if the global bound is tighter
7322  */
7324  SCIP_VAR* var, /**< problem variable to change */
7325  BMS_BLKMEM* blkmem, /**< block memory */
7326  SCIP_SET* set, /**< global SCIP settings */
7327  SCIP_STAT* stat, /**< problem statistics */
7328  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7329  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7330  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7331  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7332  SCIP_Real newbound /**< new bound for variable */
7333  )
7334 {
7335  assert(var != NULL);
7336  assert(blkmem != NULL);
7337  assert(set != NULL);
7338  assert(var->scip == set->scip);
7339 
7340  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7341  * of the domain within feastol
7342  */
7343  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
7344 
7345  /* adjust bound to integral value if variable is of integral type */
7346  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7347 
7348  /* check that the adjusted bound is feasible
7349  * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
7350  * here because we reset bounds to their original value!
7351  */
7352  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
7353 
7354  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7355  {
7356  /* we do not want to undercut the lowerbound, which could have happened due to numerics */
7357  newbound = MAX(newbound, var->glbdom.lb);
7358  }
7359  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7360 
7361  /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
7362  * SCIPvarFix() allows fixings that are outside of the domain within feastol
7363  */
7364  assert(lp == NULL || SCIPsetIsFeasGE(set, var->glbdom.ub, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
7365 
7366  SCIPsetDebugMsg(set, "changing global upper bound of <%s> from %g to %g\n", var->name, var->glbdom.ub, newbound);
7367 
7368  if( SCIPsetIsEQ(set, var->glbdom.ub, newbound) && !(newbound != var->glbdom.ub && newbound * var->glbdom.ub <= 0.0) ) /*lint !e777*/
7369  return SCIP_OKAY;
7370 
7371  /* change bounds of attached variables */
7372  switch( SCIPvarGetStatus(var) )
7373  {
7375  if( var->data.original.transvar != NULL )
7376  {
7377  SCIP_CALL( SCIPvarChgUbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7378  newbound) );
7379  }
7380  else
7381  {
7382  assert(set->stage == SCIP_STAGE_PROBLEM);
7383  if( newbound < SCIPvarGetUbLocal(var) )
7384  {
7385  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7386  }
7387  SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7388  }
7389  break;
7390 
7391  case SCIP_VARSTATUS_COLUMN:
7392  case SCIP_VARSTATUS_LOOSE:
7393  if( newbound < SCIPvarGetUbLocal(var) )
7394  {
7395  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7396  }
7397  SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7398  break;
7399 
7400  case SCIP_VARSTATUS_FIXED:
7401  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7402  return SCIP_INVALIDDATA;
7403 
7404  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7405  assert(var->data.aggregate.var != NULL);
7406  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7407  {
7408  SCIP_Real childnewbound;
7409 
7410  /* a > 0 -> change lower bound of y */
7411  assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
7412  || SCIPsetIsFeasEQ(set, var->glbdom.ub,
7414  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7415  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7416  else
7417  childnewbound = newbound;
7418  SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7419  childnewbound) );
7420  }
7421  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7422  {
7423  SCIP_Real childnewbound;
7424 
7425  /* a < 0 -> change upper bound of y */
7426  assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, -var->data.aggregate.var->glbdom.lb))
7427  || SCIPsetIsFeasEQ(set, var->glbdom.ub,
7429  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7430  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7431  else
7432  childnewbound = -newbound;
7433  SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7434  childnewbound) );
7435  }
7436  else
7437  {
7438  SCIPerrorMessage("scalar is zero in aggregation\n");
7439  return SCIP_INVALIDDATA;
7440  }
7441  break;
7442 
7444  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7445  return SCIP_INVALIDDATA;
7446 
7447  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7448  assert(var->negatedvar != NULL);
7450  assert(var->negatedvar->negatedvar == var);
7451  SCIP_CALL( SCIPvarChgLbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7452  var->data.negate.constant - newbound) );
7453  break;
7454 
7455  default:
7456  SCIPerrorMessage("unknown variable status\n");
7457  return SCIP_INVALIDDATA;
7458  }
7459 
7460  return SCIP_OKAY;
7461 }
7462 
7463 /** changes lazy lower bound of the variable, this is only possible if the variable is not in the LP yet */
7465  SCIP_VAR* var, /**< problem variable */
7466  SCIP_SET* set, /**< global SCIP settings */
7467  SCIP_Real lazylb /**< the lazy lower bound to be set */
7468  )
7469 {
7470  assert(var != NULL);
7471  assert(var->probindex != -1);
7472  assert(SCIPsetIsFeasGE(set, var->glbdom.ub, lazylb));
7473  assert(SCIPsetIsFeasGE(set, var->lazyub, lazylb));
7474  assert(set != NULL);
7475  assert(var->scip == set->scip);
7476 
7477  /* variable should not be in the LP */
7479  return SCIP_INVALIDCALL;
7480 
7481  var->lazylb = lazylb;
7482 
7483  return SCIP_OKAY;
7484 }
7485 
7486 /** changes lazy upper bound of the variable, this is only possible if the variable is not in the LP yet */
7488  SCIP_VAR* var, /**< problem variable */
7489  SCIP_SET* set, /**< global SCIP settings */
7490  SCIP_Real lazyub /**< the lazy lower bound to be set */
7491  )
7492 {
7493  assert(var != NULL);
7494  assert(var->probindex != -1);
7495  assert(SCIPsetIsFeasGE(set, lazyub, var->glbdom.lb));
7496  assert(SCIPsetIsFeasGE(set, lazyub, var->lazylb));
7497  assert(set != NULL);
7498  assert(var->scip == set->scip);
7499 
7500  /* variable should not be in the LP */
7502  return SCIP_INVALIDCALL;
7503 
7504  var->lazyub = lazyub;
7505 
7506  return SCIP_OKAY;
7507 }
7508 
7509 
7510 /** changes global bound of variable; if possible, adjusts bound to integral value;
7511  * updates local bound if the global bound is tighter
7512  */
7514  SCIP_VAR* var, /**< problem variable to change */
7515  BMS_BLKMEM* blkmem, /**< block memory */
7516  SCIP_SET* set, /**< global SCIP settings */
7517  SCIP_STAT* stat, /**< problem statistics */
7518  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7519  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7520  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7521  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7522  SCIP_Real newbound, /**< new bound for variable */
7523  SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
7524  )
7525 {
7526  /* apply bound change to the LP data */
7527  switch( boundtype )
7528  {
7529  case SCIP_BOUNDTYPE_LOWER:
7530  return SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
7531  case SCIP_BOUNDTYPE_UPPER:
7532  return SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
7533  default:
7534  SCIPerrorMessage("unknown bound type\n");
7535  return SCIP_INVALIDDATA;
7536  }
7537 }
7538 
7539 /** appends LBTIGHTENED or LBRELAXED event to the event queue */
7540 static
7542  SCIP_VAR* var, /**< problem variable to change */
7543  BMS_BLKMEM* blkmem, /**< block memory */
7544  SCIP_SET* set, /**< global SCIP settings */
7545  SCIP_LP* lp, /**< current LP data */
7546  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7547  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7548  SCIP_Real oldbound, /**< old lower bound for variable */
7549  SCIP_Real newbound /**< new lower bound for variable */
7550  )
7551 {
7552  assert(var != NULL);
7553  assert(var->eventfilter != NULL);
7554  assert(SCIPvarIsTransformed(var));
7555  assert(!SCIPsetIsEQ(set, oldbound, newbound) || newbound == var->glbdom.lb || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
7556  assert(set != NULL);
7557  assert(var->scip == set->scip);
7558 
7559  /* check, if the variable is being tracked for bound changes
7560  * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
7561  */
7562  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_LBCHANGED) != 0)
7565  {
7566  SCIP_EVENT* event;
7567 
7568  SCIPsetDebugMsg(set, "issue LBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
7569 
7570  SCIP_CALL( SCIPeventCreateLbChanged(&event, blkmem, var, oldbound, newbound) );
7571  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
7572  }
7573 
7574  return SCIP_OKAY;
7575 }
7576 
7577 /** appends UBTIGHTENED or UBRELAXED event to the event queue */
7578 static
7580  SCIP_VAR* var, /**< problem variable to change */
7581  BMS_BLKMEM* blkmem, /**< block memory */
7582  SCIP_SET* set, /**< global SCIP settings */
7583  SCIP_LP* lp, /**< current LP data */
7584  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7585  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7586  SCIP_Real oldbound, /**< old upper bound for variable */
7587  SCIP_Real newbound /**< new upper bound for variable */
7588  )
7589 {
7590  assert(var != NULL);
7591  assert(var->eventfilter != NULL);
7592  assert(SCIPvarIsTransformed(var));
7593  assert(!SCIPsetIsEQ(set, oldbound, newbound) || newbound == var->glbdom.ub || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
7594  assert(set != NULL);
7595  assert(var->scip == set->scip);
7596 
7597  /* check, if the variable is being tracked for bound changes
7598  * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
7599  */
7600  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_UBCHANGED) != 0)
7603  {
7604  SCIP_EVENT* event;
7605 
7606  SCIPsetDebugMsg(set, "issue UBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
7607 
7608  SCIP_CALL( SCIPeventCreateUbChanged(&event, blkmem, var, oldbound, newbound) );
7609  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
7610  }
7611 
7612  return SCIP_OKAY;
7613 }
7614 
7615 /* forward declaration, because both methods call each other recursively */
7616 
7617 /* performs the current change in upper bound, changes all parents accordingly */
7618 static
7620  SCIP_VAR* var, /**< problem variable to change */
7621  BMS_BLKMEM* blkmem, /**< block memory */
7622  SCIP_SET* set, /**< global SCIP settings */
7623  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7624  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7625  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7626  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7627  SCIP_Real newbound /**< new bound for variable */
7628  );
7629 
7630 /** performs the current change in lower bound, changes all parents accordingly */
7631 static
7633  SCIP_VAR* var, /**< problem variable to change */
7634  BMS_BLKMEM* blkmem, /**< block memory */
7635  SCIP_SET* set, /**< global SCIP settings */
7636  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7637  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7638  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7639  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7640  SCIP_Real newbound /**< new bound for variable */
7641  )
7642 {
7643  SCIP_VAR* parentvar;
7644  SCIP_Real oldbound;
7645  int i;
7646 
7647  assert(var != NULL);
7648  assert(set != NULL);
7649  assert(var->scip == set->scip);
7650  assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)
7651  || SCIPsetIsEQ(set, newbound, var->locdom.ub)))
7652  || (SCIPvarGetType(var) < SCIP_VARTYPE_CONTINUOUS && (SCIPsetIsIntegral(set, newbound)
7653  || SCIPsetIsEQ(set, newbound, var->locdom.ub)))
7655 
7656  /* check that the bound is feasible */
7657  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsLE(set, newbound, var->glbdom.ub));
7658  /* adjust bound to integral value if variable is of integral type */
7659  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7660 
7661  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7662  {
7663  /* we do not want to exceed the upper bound, which could have happened due to numerics */
7664  newbound = MIN(newbound, var->locdom.ub);
7665 
7666  /* we do not want to undercut the global lower bound, which could have happened due to numerics */
7667  newbound = MAX(newbound, var->glbdom.lb);
7668  }
7669  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7670 
7671  SCIPsetDebugMsg(set, "process changing lower bound of <%s> from %g to %g\n", var->name, var->locdom.lb, newbound);
7672 
7673  if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) && var->glbdom.lb != var->locdom.lb ) /*lint !e777*/
7674  newbound = var->glbdom.lb;
7675  else if( SCIPsetIsEQ(set, newbound, var->locdom.lb) && !(newbound != var->locdom.lb && newbound * var->locdom.lb <= 0.0) ) /*lint !e777*/
7676  return SCIP_OKAY;
7677 
7678  /* change the bound */
7679  oldbound = var->locdom.lb;
7680  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->locdom.ub));
7681  var->locdom.lb = newbound;
7682 
7683  /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
7684  * once update the statistic
7685  */
7686  if( stat != NULL )
7687  SCIPstatIncrement(stat, set, domchgcount);
7688 
7689  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7690  {
7691  /* merges overlapping holes into single holes, moves bounds respectively */
7692  domMerge(&var->locdom, blkmem, set, &newbound, NULL);
7693  }
7694 
7695  /* issue bound change event */
7696  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7697  if( var->eventfilter != NULL )
7698  {
7699  SCIP_CALL( varEventLbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7700  }
7701 
7702  /* process parent variables */
7703  for( i = 0; i < var->nparentvars; ++i )
7704  {
7705  parentvar = var->parentvars[i];
7706  assert(parentvar != NULL);
7707 
7708  switch( SCIPvarGetStatus(parentvar) )
7709  {
7711  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
7712  break;
7713 
7714  case SCIP_VARSTATUS_COLUMN:
7715  case SCIP_VARSTATUS_LOOSE:
7716  case SCIP_VARSTATUS_FIXED:
7718  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7719  return SCIP_INVALIDDATA;
7720 
7721  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7722  assert(parentvar->data.aggregate.var == var);
7723  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7724  {
7725  SCIP_Real parentnewbound;
7726 
7727  /* a > 0 -> change lower bound of y */
7728  assert(SCIPsetIsInfinity(set, -parentvar->locdom.lb) || SCIPsetIsInfinity(set, -oldbound)
7729  || SCIPsetIsFeasEQ(set, parentvar->locdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
7730  || (SCIPsetIsZero(set, parentvar->locdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
7731 
7732  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7733  {
7734  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7735  /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
7736  * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
7737  * as a result, the parent's lower bound is set to it's upper bound, and not above
7738  */
7739  if( parentnewbound > parentvar->glbdom.ub )
7740  {
7741  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7742  assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
7743  parentnewbound = parentvar->glbdom.ub;
7744  }
7745  }
7746  else
7747  parentnewbound = newbound;
7748  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7749  }
7750  else
7751  {
7752  SCIP_Real parentnewbound;
7753 
7754  /* a < 0 -> change upper bound of y */
7755  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7756  assert(SCIPsetIsInfinity(set, parentvar->locdom.ub) || SCIPsetIsInfinity(set, -oldbound)
7757  || SCIPsetIsFeasEQ(set, parentvar->locdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
7758  || (SCIPsetIsZero(set, parentvar->locdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
7759 
7760  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7761  {
7762  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7763  /* 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
7764  * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
7765  * as a result, the parent's upper bound is set to it's lower bound, and not below
7766  */
7767  if( parentnewbound < parentvar->glbdom.lb )
7768  {
7769  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7770  assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
7771  parentnewbound = parentvar->glbdom.lb;
7772  }
7773  }
7774  else
7775  parentnewbound = -newbound;
7776  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7777  }
7778  break;
7779 
7780  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
7781  assert(parentvar->negatedvar != NULL);
7782  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7783  assert(parentvar->negatedvar->negatedvar == parentvar);
7784  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
7785  parentvar->data.negate.constant - newbound) );
7786  break;
7787 
7788  default:
7789  SCIPerrorMessage("unknown variable status\n");
7790  return SCIP_INVALIDDATA;
7791  }
7792  }
7793 
7794  return SCIP_OKAY;
7795 }
7796 
7797 /** performs the current change in upper bound, changes all parents accordingly */
7798 static
7800  SCIP_VAR* var, /**< problem variable to change */
7801  BMS_BLKMEM* blkmem, /**< block memory */
7802  SCIP_SET* set, /**< global SCIP settings */
7803  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7804  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7805  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7806  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7807  SCIP_Real newbound /**< new bound for variable */
7808  )
7809 {
7810  SCIP_VAR* parentvar;
7811  SCIP_Real oldbound;
7812  int i;
7813 
7814  assert(var != NULL);
7815  assert(set != NULL);
7816  assert(var->scip == set->scip);
7817  assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)
7818  || SCIPsetIsEQ(set, newbound, var->locdom.lb)))
7819  || (SCIPvarGetType(var) < SCIP_VARTYPE_CONTINUOUS && (SCIPsetIsIntegral(set, newbound)
7820  || SCIPsetIsEQ(set, newbound, var->locdom.lb)))
7822 
7823  /* check that the bound is feasible */
7824  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsGE(set, newbound, var->glbdom.lb));
7825  /* adjust bound to integral value if variable is of integral type */
7826  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7827 
7828  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7829  {
7830  /* we do not want to undercut the lower bound, which could have happened due to numerics */
7831  newbound = MAX(newbound, var->locdom.lb);
7832 
7833  /* we do not want to exceed the global upper bound, which could have happened due to numerics */
7834  newbound = MIN(newbound, var->glbdom.ub);
7835  }
7836  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7837 
7838  SCIPsetDebugMsg(set, "process changing upper bound of <%s> from %g to %g\n", var->name, var->locdom.ub, newbound);
7839 
7840  if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) && var->glbdom.ub != var->locdom.ub ) /*lint !e777*/
7841  newbound = var->glbdom.ub;
7842  else if( SCIPsetIsEQ(set, newbound, var->locdom.ub) && !(newbound != var->locdom.ub && newbound * var->locdom.ub <= 0.0) ) /*lint !e777*/
7843  return SCIP_OKAY;
7844 
7845  /* change the bound */
7846  oldbound = var->locdom.ub;
7847  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->locdom.lb));
7848  var->locdom.ub = newbound;
7849 
7850  /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
7851  * once update the statistic
7852  */
7853  if( stat != NULL )
7854  SCIPstatIncrement(stat, set, domchgcount);
7855 
7856  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7857  {
7858  /* merges overlapping holes into single holes, moves bounds respectively */
7859  domMerge(&var->locdom, blkmem, set, NULL, &newbound);
7860  }
7861 
7862  /* issue bound change event */
7863  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7864  if( var->eventfilter != NULL )
7865  {
7866  SCIP_CALL( varEventUbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7867  }
7868 
7869  /* process parent variables */
7870  for( i = 0; i < var->nparentvars; ++i )
7871  {
7872  parentvar = var->parentvars[i];
7873  assert(parentvar != NULL);
7874 
7875  switch( SCIPvarGetStatus(parentvar) )
7876  {
7878  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
7879  break;
7880 
7881  case SCIP_VARSTATUS_COLUMN:
7882  case SCIP_VARSTATUS_LOOSE:
7883  case SCIP_VARSTATUS_FIXED:
7885  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7886  return SCIP_INVALIDDATA;
7887 
7888  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7889  assert(parentvar->data.aggregate.var == var);
7890  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7891  {
7892  SCIP_Real parentnewbound;
7893 
7894  /* a > 0 -> change upper bound of x */
7895  assert(SCIPsetIsInfinity(set, parentvar->locdom.ub) || SCIPsetIsInfinity(set, oldbound)
7896  || SCIPsetIsFeasEQ(set, parentvar->locdom.ub,
7897  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7898  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7899  {
7900  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7901  /* 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
7902  * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
7903  * as a result, the parent's upper bound is set to it's lower bound, and not below
7904  */
7905  if( parentnewbound < parentvar->glbdom.lb )
7906  {
7907  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7908  assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
7909  parentnewbound = parentvar->glbdom.lb;
7910  }
7911  }
7912  else
7913  parentnewbound = newbound;
7914  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7915  }
7916  else
7917  {
7918  SCIP_Real parentnewbound;
7919 
7920  /* a < 0 -> change lower bound of x */
7921  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7922  assert(SCIPsetIsInfinity(set, -parentvar->locdom.lb) || SCIPsetIsInfinity(set, oldbound)
7923  || SCIPsetIsFeasEQ(set, parentvar->locdom.lb,
7924  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7925  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7926  {
7927  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7928  /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
7929  * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
7930  * as a result, the parent's lower bound is set to it's upper bound, and not above
7931  */
7932  if( parentnewbound > parentvar->glbdom.ub )
7933  {
7934  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7935  assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
7936  parentnewbound = parentvar->glbdom.ub;
7937  }
7938  }
7939  else
7940  parentnewbound = -newbound;
7941  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7942  }
7943  break;
7944 
7945  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
7946  assert(parentvar->negatedvar != NULL);
7947  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7948  assert(parentvar->negatedvar->negatedvar == parentvar);
7949  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
7950  parentvar->data.negate.constant - newbound) );
7951  break;
7952 
7953  default:
7954  SCIPerrorMessage("unknown variable status\n");
7955  return SCIP_INVALIDDATA;
7956  }
7957  }
7958 
7959  return SCIP_OKAY;
7960 }
7961 
7962 /** changes current local lower bound of variable; if possible, adjusts bound to integral value; stores inference
7963  * information in variable
7964  */
7966  SCIP_VAR* var, /**< problem variable to change */
7967  BMS_BLKMEM* blkmem, /**< block memory */
7968  SCIP_SET* set, /**< global SCIP settings */
7969  SCIP_STAT* stat, /**< problem statistics */
7970  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7971  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7972  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7973  SCIP_Real newbound /**< new bound for variable */
7974  )
7975 {
7976  assert(var != NULL);
7977  assert(blkmem != NULL);
7978  assert(set != NULL);
7979  assert(var->scip == set->scip);
7980 
7981  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7982  * of the domain within feastol
7983  */
7984  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
7985 
7986  /* adjust bound to integral value if variable is of integral type */
7987  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7988 
7989  /* check that the adjusted bound is feasible */
7990  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
7991 
7992  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7993  {
7994  /* we do not want to exceed the upperbound, which could have happened due to numerics */
7995  newbound = MIN(newbound, var->locdom.ub);
7996  }
7997  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7998 
7999  SCIPsetDebugMsg(set, "changing lower bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
8000 
8001  if( SCIPsetIsEQ(set, var->locdom.lb, newbound) && (!SCIPsetIsEQ(set, var->glbdom.lb, newbound) || var->locdom.lb == newbound) /*lint !e777*/
8002  && !(newbound != var->locdom.lb && newbound * var->locdom.lb <= 0.0) ) /*lint !e777*/
8003  return SCIP_OKAY;
8004 
8005  /* change bounds of attached variables */
8006  switch( SCIPvarGetStatus(var) )
8007  {
8009  if( var->data.original.transvar != NULL )
8010  {
8011  SCIP_CALL( SCIPvarChgLbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
8012  newbound) );
8013  }
8014  else
8015  {
8016  assert(set->stage == SCIP_STAGE_PROBLEM);
8017  SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8018  }
8019  break;
8020 
8021  case SCIP_VARSTATUS_COLUMN:
8022  case SCIP_VARSTATUS_LOOSE:
8023  SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8024  break;
8025 
8026  case SCIP_VARSTATUS_FIXED:
8027  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8028  return SCIP_INVALIDDATA;
8029 
8030  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8031  assert(var->data.aggregate.var != NULL);
8032  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8033  {
8034  SCIP_Real childnewbound;
8035 
8036  /* a > 0 -> change lower bound of y */
8037  assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, -var->data.aggregate.var->locdom.lb))
8038  || SCIPsetIsFeasEQ(set, var->locdom.lb,
8040  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8041  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8042  else
8043  childnewbound = newbound;
8044  SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
8045  childnewbound) );
8046  }
8047  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8048  {
8049  SCIP_Real childnewbound;
8050 
8051  /* a < 0 -> change upper bound of y */
8052  assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->locdom.ub))
8053  || SCIPsetIsFeasEQ(set, var->locdom.lb,
8055  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8056  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8057  else
8058  childnewbound = -newbound;
8059  SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
8060  childnewbound) );
8061  }
8062  else
8063  {
8064  SCIPerrorMessage("scalar is zero in aggregation\n");
8065  return SCIP_INVALIDDATA;
8066  }
8067  break;
8068 
8070  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8071  return SCIP_INVALIDDATA;
8072 
8073  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8074  assert(var->negatedvar != NULL);
8076  assert(var->negatedvar->negatedvar == var);
8077  SCIP_CALL( SCIPvarChgUbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
8078  var->data.negate.constant - newbound) );
8079  break;
8080 
8081  default:
8082  SCIPerrorMessage("unknown variable status\n");
8083  return SCIP_INVALIDDATA;
8084  }
8085 
8086  return SCIP_OKAY;
8087 }
8088 
8089 /** changes current local upper bound of variable; if possible, adjusts bound to integral value; stores inference
8090  * information in variable
8091  */
8093  SCIP_VAR* var, /**< problem variable to change */
8094  BMS_BLKMEM* blkmem, /**< block memory */
8095  SCIP_SET* set, /**< global SCIP settings */
8096  SCIP_STAT* stat, /**< problem statistics */
8097  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
8098  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
8099  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8100  SCIP_Real newbound /**< new bound for variable */
8101  )
8102 {
8103  assert(var != NULL);
8104  assert(blkmem != NULL);
8105  assert(set != NULL);
8106  assert(var->scip == set->scip);
8107 
8108  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
8109  * of the domain within feastol
8110  */
8111  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
8112 
8113  /* adjust bound to integral value if variable is of integral type */
8114  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
8115 
8116  /* check that the adjusted bound is feasible */
8117  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
8118 
8119  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
8120  {
8121  /* we do not want to undercut the lowerbound, which could have happened due to numerics */
8122  newbound = MAX(newbound, var->locdom.lb);
8123  }
8124  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
8125 
8126  SCIPsetDebugMsg(set, "changing upper bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
8127 
8128  if( SCIPsetIsEQ(set, var->locdom.ub, newbound) && (!SCIPsetIsEQ(set, var->glbdom.ub, newbound) || var->locdom.ub == newbound) /*lint !e777*/
8129  && !(newbound != var->locdom.ub && newbound * var->locdom.ub <= 0.0) ) /*lint !e777*/
8130  return SCIP_OKAY;
8131 
8132  /* change bounds of attached variables */
8133  switch( SCIPvarGetStatus(var) )
8134  {
8136  if( var->data.original.transvar != NULL )
8137  {
8138  SCIP_CALL( SCIPvarChgUbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8139  }
8140  else
8141  {
8142  assert(set->stage == SCIP_STAGE_PROBLEM);
8143  SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8144  }
8145  break;
8146 
8147  case SCIP_VARSTATUS_COLUMN:
8148  case SCIP_VARSTATUS_LOOSE:
8149  SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8150  break;
8151 
8152  case SCIP_VARSTATUS_FIXED:
8153  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8154  return SCIP_INVALIDDATA;
8155 
8156  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8157  assert(var->data.aggregate.var != NULL);
8158  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8159  {
8160  SCIP_Real childnewbound;
8161 
8162  /* a > 0 -> change upper bound of y */
8163  assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, var->data.aggregate.var->locdom.ub))
8164  || SCIPsetIsFeasEQ(set, var->locdom.ub,
8166  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8167  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8168  else
8169  childnewbound = newbound;
8170  SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
8171  childnewbound) );
8172  }
8173  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8174  {
8175  SCIP_Real childnewbound;
8176 
8177  /* a < 0 -> change lower bound of y */
8178  assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, -var->data.aggregate.var->locdom.lb))
8179  || SCIPsetIsFeasEQ(set, var->locdom.ub,
8181  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8182  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8183  else
8184  childnewbound = -newbound;
8185  SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
8186  childnewbound) );
8187  }
8188  else
8189  {
8190  SCIPerrorMessage("scalar is zero in aggregation\n");
8191  return SCIP_INVALIDDATA;
8192  }
8193  break;
8194 
8196  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8197  return SCIP_INVALIDDATA;
8198 
8199  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8200  assert(var->negatedvar != NULL);
8202  assert(var->negatedvar->negatedvar == var);
8203  SCIP_CALL( SCIPvarChgLbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
8204  var->data.negate.constant - newbound) );
8205  break;
8206 
8207  default:
8208  SCIPerrorMessage("unknown variable status\n");
8209  return SCIP_INVALIDDATA;
8210  }
8211 
8212  return SCIP_OKAY;
8213 }
8214 
8215 /** changes current local bound of variable; if possible, adjusts bound to integral value; stores inference
8216  * information in variable
8217  */
8219  SCIP_VAR* var, /**< problem variable to change */
8220  BMS_BLKMEM* blkmem, /**< block memory */
8221  SCIP_SET* set, /**< global SCIP settings */
8222  SCIP_STAT* stat, /**< problem statistics */
8223  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
8224  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
8225  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8226  SCIP_Real newbound, /**< new bound for variable */
8227  SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
8228  )
8229 {
8230  /* apply bound change to the LP data */
8231  switch( boundtype )
8232  {
8233  case SCIP_BOUNDTYPE_LOWER:
8234  return SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
8235  case SCIP_BOUNDTYPE_UPPER:
8236  return SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
8237  default:
8238  SCIPerrorMessage("unknown bound type\n");
8239  return SCIP_INVALIDDATA;
8240  }
8241 }
8242 
8243 /** changes lower bound of variable in current dive; if possible, adjusts bound to integral value */
8245  SCIP_VAR* var, /**< problem variable to change */
8246  SCIP_SET* set, /**< global SCIP settings */
8247  SCIP_LP* lp, /**< current LP data */
8248  SCIP_Real newbound /**< new bound for variable */
8249  )
8250 {
8251  assert(var != NULL);
8252  assert(set != NULL);
8253  assert(var->scip == set->scip);
8254  assert(lp != NULL);
8255  assert(SCIPlpDiving(lp));
8256 
8257  /* adjust bound for integral variables */
8258  SCIPvarAdjustLb(var, set, &newbound);
8259 
8260  SCIPsetDebugMsg(set, "changing lower bound of <%s> to %g in current dive\n", var->name, newbound);
8261 
8262  /* change bounds of attached variables */
8263  switch( SCIPvarGetStatus(var) )
8264  {
8266  assert(var->data.original.transvar != NULL);
8267  SCIP_CALL( SCIPvarChgLbDive(var->data.original.transvar, set, lp, newbound) );
8268  break;
8269 
8270  case SCIP_VARSTATUS_COLUMN:
8271  assert(var->data.col != NULL);
8272  SCIP_CALL( SCIPcolChgLb(var->data.col, set, lp, newbound) );
8273  break;
8274 
8275  case SCIP_VARSTATUS_LOOSE:
8276  SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
8277  return SCIP_INVALIDDATA;
8278 
8279  case SCIP_VARSTATUS_FIXED:
8280  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8281  return SCIP_INVALIDDATA;
8282 
8283  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8284  assert(var->data.aggregate.var != NULL);
8285  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8286  {
8287  SCIP_Real childnewbound;
8288 
8289  /* a > 0 -> change lower bound of y */
8290  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8291  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8292  else
8293  childnewbound = newbound;
8294  SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
8295  }
8296  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8297  {
8298  SCIP_Real childnewbound;
8299 
8300  /* a < 0 -> change upper bound of y */
8301  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8302  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8303  else
8304  childnewbound = -newbound;
8305  SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
8306  }
8307  else
8308  {
8309  SCIPerrorMessage("scalar is zero in aggregation\n");
8310  return SCIP_INVALIDDATA;
8311  }
8312  break;
8313 
8315  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8316  return SCIP_INVALIDDATA;
8317 
8318  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8319  assert(var->negatedvar != NULL);
8321  assert(var->negatedvar->negatedvar == var);
8322  SCIP_CALL( SCIPvarChgUbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
8323  break;
8324 
8325  default:
8326  SCIPerrorMessage("unknown variable status\n");
8327  return SCIP_INVALIDDATA;
8328  }
8329 
8330  return SCIP_OKAY;
8331 }
8332 
8333 /** changes upper bound of variable in current dive; if possible, adjusts bound to integral value */
8335  SCIP_VAR* var, /**< problem variable to change */
8336  SCIP_SET* set, /**< global SCIP settings */
8337  SCIP_LP* lp, /**< current LP data */
8338  SCIP_Real newbound /**< new bound for variable */
8339  )
8340 {
8341  assert(var != NULL);
8342  assert(set != NULL);
8343  assert(var->scip == set->scip);
8344  assert(lp != NULL);
8345  assert(SCIPlpDiving(lp));
8346 
8347  /* adjust bound for integral variables */
8348  SCIPvarAdjustUb(var, set, &newbound);
8349 
8350  SCIPsetDebugMsg(set, "changing upper bound of <%s> to %g in current dive\n", var->name, newbound);
8351 
8352  /* change bounds of attached variables */
8353  switch( SCIPvarGetStatus(var) )
8354  {
8356  assert(var->data.original.transvar != NULL);
8357  SCIP_CALL( SCIPvarChgUbDive(var->data.original.transvar, set, lp, newbound) );
8358  break;
8359 
8360  case SCIP_VARSTATUS_COLUMN:
8361  assert(var->data.col != NULL);
8362  SCIP_CALL( SCIPcolChgUb(var->data.col, set, lp, newbound) );
8363  break;
8364 
8365  case SCIP_VARSTATUS_LOOSE:
8366  SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
8367  return SCIP_INVALIDDATA;
8368 
8369  case SCIP_VARSTATUS_FIXED:
8370  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8371  return SCIP_INVALIDDATA;
8372 
8373  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8374  assert(var->data.aggregate.var != NULL);
8375  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8376  {
8377  SCIP_Real childnewbound;
8378 
8379  /* a > 0 -> change upper bound of y */
8380  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8381  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8382  else
8383  childnewbound = newbound;
8384  SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
8385  }
8386  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8387  {
8388  SCIP_Real childnewbound;
8389 
8390  /* a < 0 -> change lower bound of y */
8391  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8392  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8393  else
8394  childnewbound = -newbound;
8395  SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
8396  }
8397  else
8398  {
8399  SCIPerrorMessage("scalar is zero in aggregation\n");
8400  return SCIP_INVALIDDATA;
8401  }
8402  break;
8403 
8405  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8406  return SCIP_INVALIDDATA;
8407 
8408  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8409  assert(var->negatedvar != NULL);
8411  assert(var->negatedvar->negatedvar == var);
8412  SCIP_CALL( SCIPvarChgLbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
8413  break;
8414 
8415  default:
8416  SCIPerrorMessage("unknown variable status\n");
8417  return SCIP_INVALIDDATA;
8418  }
8419 
8420  return SCIP_OKAY;
8421 }
8422 
8423 /** for a multi-aggregated variable, gives the local lower bound computed by adding the local bounds from all
8424  * aggregation variables, this lower bound may be tighter than the one given by SCIPvarGetLbLocal, since the latter is
8425  * not updated if bounds of aggregation variables are changing
8426  *
8427  * calling this function for a non-multi-aggregated variable is not allowed
8428  */
8430  SCIP_VAR* var, /**< problem variable */
8431  SCIP_SET* set /**< global SCIP settings */
8432  )
8433 {
8434  int i;
8435  SCIP_Real lb;
8436  SCIP_Real bnd;
8437  SCIP_VAR* aggrvar;
8438  SCIP_Bool posinf;
8439  SCIP_Bool neginf;
8440 
8441  assert(var != NULL);
8442  assert(set != NULL);
8443  assert(var->scip == set->scip);
8445 
8446  posinf = FALSE;
8447  neginf = FALSE;
8448  lb = var->data.multaggr.constant;
8449  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8450  {
8451  aggrvar = var->data.multaggr.vars[i];
8452  if( var->data.multaggr.scalars[i] > 0.0 )
8453  {
8454  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbLocal(aggrvar, set) : SCIPvarGetLbLocal(aggrvar);
8455 
8456  if( SCIPsetIsInfinity(set, bnd) )
8457  posinf = TRUE;
8458  else if( SCIPsetIsInfinity(set, -bnd) )
8459  neginf = TRUE;
8460  else
8461  lb += var->data.multaggr.scalars[i] * bnd;
8462  }
8463  else
8464  {
8465  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbLocal(aggrvar, set) : SCIPvarGetUbLocal(aggrvar);
8466 
8467  if( SCIPsetIsInfinity(set, -bnd) )
8468  posinf = TRUE;
8469  else if( SCIPsetIsInfinity(set, bnd) )
8470  neginf = TRUE;
8471  else
8472  lb += var->data.multaggr.scalars[i] * bnd;
8473  }
8474 
8475  /* stop if two diffrent infinities (or a -infinity) were found and return local lower bound of multi aggregated
8476  * variable
8477  */
8478  if( neginf )
8479  return SCIPvarGetLbLocal(var);
8480  }
8481 
8482  /* if positive infinity flag was set to true return infinity */
8483  if( posinf )
8484  return SCIPsetInfinity(set);
8485 
8486  return (MAX(lb, SCIPvarGetLbLocal(var))); /*lint !e666*/
8487 }
8488 
8489 /** for a multi-aggregated variable, gives the local upper bound computed by adding the local bounds from all
8490  * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbLocal, since the latter is
8491  * not updated if bounds of aggregation variables are changing
8492  *
8493  * calling this function for a non-multi-aggregated variable is not allowed
8494  */
8496  SCIP_VAR* var, /**< problem variable */
8497  SCIP_SET* set /**< global SCIP settings */
8498  )
8499 {
8500  int i;
8501  SCIP_Real ub;
8502  SCIP_Real bnd;
8503  SCIP_VAR* aggrvar;
8504  SCIP_Bool posinf;
8505  SCIP_Bool neginf;
8506 
8507  assert(var != NULL);
8508  assert(set != NULL);
8509  assert(var->scip == set->scip);
8511 
8512  posinf = FALSE;
8513  neginf = FALSE;
8514  ub = var->data.multaggr.constant;
8515  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8516  {
8517  aggrvar = var->data.multaggr.vars[i];
8518  if( var->data.multaggr.scalars[i] > 0.0 )
8519  {
8520  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbLocal(aggrvar, set) : SCIPvarGetUbLocal(aggrvar);
8521 
8522  if( SCIPsetIsInfinity(set, bnd) )
8523  posinf = TRUE;
8524  else if( SCIPsetIsInfinity(set, -bnd) )
8525  neginf = TRUE;
8526  else
8527  ub += var->data.multaggr.scalars[i] * bnd;
8528  }
8529  else
8530  {
8531  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbLocal(aggrvar, set) : SCIPvarGetLbLocal(aggrvar);
8532 
8533  if( SCIPsetIsInfinity(set, -bnd) )
8534  posinf = TRUE;
8535  else if( SCIPsetIsInfinity(set, bnd) )
8536  neginf = TRUE;
8537  else
8538  ub += var->data.multaggr.scalars[i] * bnd;
8539  }
8540 
8541  /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
8542  * variable
8543  */
8544  if( posinf )
8545  return SCIPvarGetUbLocal(var);
8546  }
8547 
8548  /* if negative infinity flag was set to true return -infinity */
8549  if( neginf )
8550  return -SCIPsetInfinity(set);
8551 
8552  return (MIN(ub, SCIPvarGetUbLocal(var))); /*lint !e666*/
8553 }
8554 
8555 /** for a multi-aggregated variable, gives the global lower bound computed by adding the global bounds from all
8556  * aggregation variables, this global bound may be tighter than the one given by SCIPvarGetLbGlobal, since the latter is
8557  * not updated if bounds of aggregation variables are changing
8558  *
8559  * calling this function for a non-multi-aggregated variable is not allowed
8560  */
8562  SCIP_VAR* var, /**< problem variable */
8563  SCIP_SET* set /**< global SCIP settings */
8564  )
8565 {
8566  int i;
8567  SCIP_Real lb;
8568  SCIP_Real bnd;
8569  SCIP_VAR* aggrvar;
8570  SCIP_Bool posinf;
8571  SCIP_Bool neginf;
8572 
8573  assert(var != NULL);
8574  assert(set != NULL);
8575  assert(var->scip == set->scip);
8577 
8578  posinf = FALSE;
8579  neginf = FALSE;
8580  lb = var->data.multaggr.constant;
8581  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8582  {
8583  aggrvar = var->data.multaggr.vars[i];
8584  if( var->data.multaggr.scalars[i] > 0.0 )
8585  {
8586  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbGlobal(aggrvar, set) : SCIPvarGetLbGlobal(aggrvar);
8587 
8588  if( SCIPsetIsInfinity(set, bnd) )
8589  posinf = TRUE;
8590  else if( SCIPsetIsInfinity(set, -bnd) )
8591  neginf = TRUE;
8592  else
8593  lb += var->data.multaggr.scalars[i] * bnd;
8594  }
8595  else
8596  {
8597  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbGlobal(aggrvar, set) : SCIPvarGetUbGlobal(aggrvar);
8598 
8599  if( SCIPsetIsInfinity(set, -bnd) )
8600  posinf = TRUE;
8601  else if( SCIPsetIsInfinity(set, bnd) )
8602  neginf = TRUE;
8603  else
8604  lb += var->data.multaggr.scalars[i] * bnd;
8605  }
8606 
8607  /* stop if two diffrent infinities (or a -infinity) were found and return global lower bound of multi aggregated
8608  * variable
8609  */
8610  if( neginf )
8611  return SCIPvarGetLbGlobal(var);
8612  }
8613 
8614  /* if positive infinity flag was set to true return infinity */
8615  if( posinf )
8616  return SCIPsetInfinity(set);
8617 
8618  return (MAX(lb, SCIPvarGetLbGlobal(var))); /*lint !e666*/
8619 }
8620 
8621 /** for a multi-aggregated variable, gives the global upper bound computed by adding the global bounds from all
8622  * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbGlobal, since the latter is
8623  * not updated if bounds of aggregation variables are changing
8624  *
8625  * calling this function for a non-multi-aggregated variable is not allowed
8626  */
8628  SCIP_VAR* var, /**< problem variable */
8629  SCIP_SET* set /**< global SCIP settings */
8630  )
8631 {
8632  int i;
8633  SCIP_Real ub;
8634  SCIP_Real bnd;
8635  SCIP_VAR* aggrvar;
8636  SCIP_Bool posinf;
8637  SCIP_Bool neginf;
8638 
8639  assert(var != NULL);
8640  assert(set != NULL);
8641  assert(var->scip == set->scip);
8643 
8644  posinf = FALSE;
8645  neginf = FALSE;
8646  ub = var->data.multaggr.constant;
8647  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8648  {
8649  aggrvar = var->data.multaggr.vars[i];
8650  if( var->data.multaggr.scalars[i] > 0.0 )
8651  {
8652  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbGlobal(aggrvar, set) : SCIPvarGetUbGlobal(aggrvar);
8653 
8654  if( SCIPsetIsInfinity(set, bnd) )
8655  posinf = TRUE;
8656  else if( SCIPsetIsInfinity(set, -bnd) )
8657  neginf = TRUE;
8658  else
8659  ub += var->data.multaggr.scalars[i] * bnd;
8660  }
8661  else
8662  {
8663  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbGlobal(aggrvar, set) : SCIPvarGetLbGlobal(aggrvar);
8664 
8665  if( SCIPsetIsInfinity(set, -bnd) )
8666  posinf = TRUE;
8667  else if( SCIPsetIsInfinity(set, bnd) )
8668  neginf = TRUE;
8669  else
8670  ub += var->data.multaggr.scalars[i] * bnd;
8671  }
8672 
8673  /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
8674  * variable
8675  */
8676  if( posinf )
8677  return SCIPvarGetUbGlobal(var);
8678  }
8679 
8680  /* if negative infinity flag was set to true return -infinity */
8681  if( neginf )
8682  return -SCIPsetInfinity(set);
8683 
8684  return (MIN(ub, SCIPvarGetUbGlobal(var))); /*lint !e666*/
8685 }
8686 
8687 /** adds a hole to the original domain of the variable */
8689  SCIP_VAR* var, /**< problem variable */
8690  BMS_BLKMEM* blkmem, /**< block memory */
8691  SCIP_SET* set, /**< global SCIP settings */
8692  SCIP_Real left, /**< left bound of open interval in new hole */
8693  SCIP_Real right /**< right bound of open interval in new hole */
8694  )
8695 {
8696  SCIP_Bool added;
8697 
8698  assert(var != NULL);
8699  assert(!SCIPvarIsTransformed(var));
8701  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8702  assert(set != NULL);
8703  assert(var->scip == set->scip);
8704  assert(set->stage == SCIP_STAGE_PROBLEM);
8705 
8706  SCIPsetDebugMsg(set, "adding original hole (%g,%g) to <%s>\n", left, right, var->name);
8707 
8708  if( SCIPsetIsEQ(set, left, right) )
8709  return SCIP_OKAY;
8710 
8711  /* the interval should not be empty */
8712  assert(SCIPsetIsLT(set, left, right));
8713 
8714  /* the the interval bound should already be adjusted */
8715  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8716  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8717 
8718  /* the the interval should lay between the lower and upper bound */
8719  assert(SCIPsetIsGE(set, left, SCIPvarGetLbOriginal(var)));
8720  assert(SCIPsetIsLE(set, right, SCIPvarGetUbOriginal(var)));
8721 
8722  /* add domain hole */
8723  SCIP_CALL( domAddHole(&var->data.original.origdom, blkmem, set, left, right, &added) );
8724 
8725  /* merges overlapping holes into single holes, moves bounds respectively if hole was added */
8726  if( added )
8727  {
8728  domMerge(&var->data.original.origdom, blkmem, set, NULL, NULL);
8729  }
8730 
8731  /**@todo add hole in parent and child variables (just like with bound changes);
8732  * warning! original vars' holes are in original blkmem, transformed vars' holes in transformed blkmem
8733  */
8734 
8735  return SCIP_OKAY;
8736 }
8737 
8738 /** performs the current add of domain, changes all parents accordingly */
8739 static
8741  SCIP_VAR* var, /**< problem variable */
8742  BMS_BLKMEM* blkmem, /**< block memory */
8743  SCIP_SET* set, /**< global SCIP settings */
8744  SCIP_STAT* stat, /**< problem statistics */
8745  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8746  SCIP_Real left, /**< left bound of open interval in new hole */
8747  SCIP_Real right, /**< right bound of open interval in new hole */
8748  SCIP_Bool* added /**< pointer to store whether the hole was added */
8749  )
8750 {
8751  SCIP_VAR* parentvar;
8752  SCIP_Real newlb;
8753  SCIP_Real newub;
8754  int i;
8755 
8756  assert(var != NULL);
8757  assert(added != NULL);
8758  assert(blkmem != NULL);
8759 
8760  /* the interval should not be empty */
8761  assert(SCIPsetIsLT(set, left, right));
8762 
8763  /* the interval bound should already be adjusted */
8764  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8765  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8766 
8767  /* the interval should lay between the lower and upper bound */
8768  assert(SCIPsetIsGE(set, left, SCIPvarGetLbGlobal(var)));
8769  assert(SCIPsetIsLE(set, right, SCIPvarGetUbGlobal(var)));
8770 
8771  /* @todo add debugging mechanism for holes when using a debugging solution */
8772 
8773  /* add hole to hole list */
8774  SCIP_CALL( domAddHole(&var->glbdom, blkmem, set, left, right, added) );
8775 
8776  /* check if the hole is redundant */
8777  if( !(*added) )
8778  return SCIP_OKAY;
8779 
8780  /* current bounds */
8781  newlb = var->glbdom.lb;
8782  newub = var->glbdom.ub;
8783 
8784  /* merge domain holes */
8785  domMerge(&var->glbdom, blkmem, set, &newlb, &newub);
8786 
8787  /* the bound should not be changed */
8788  assert(SCIPsetIsEQ(set, newlb, var->glbdom.lb));
8789  assert(SCIPsetIsEQ(set, newub, var->glbdom.ub));
8790 
8791  /* issue bound change event */
8792  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
8793  if( var->eventfilter != NULL )
8794  {
8795  SCIP_CALL( varEventGholeAdded(var, blkmem, set, eventqueue, left, right) );
8796  }
8797 
8798  /* process parent variables */
8799  for( i = 0; i < var->nparentvars; ++i )
8800  {
8801  SCIP_Real parentnewleft;
8802  SCIP_Real parentnewright;
8803  SCIP_Bool localadded;
8804 
8805  parentvar = var->parentvars[i];
8806  assert(parentvar != NULL);
8807 
8808  switch( SCIPvarGetStatus(parentvar) )
8809  {
8811  parentnewleft = left;
8812  parentnewright = right;
8813  break;
8814 
8815  case SCIP_VARSTATUS_COLUMN:
8816  case SCIP_VARSTATUS_LOOSE:
8817  case SCIP_VARSTATUS_FIXED:
8819  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
8820  return SCIP_INVALIDDATA;
8821 
8822  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8823  assert(parentvar->data.aggregate.var == var);
8824 
8825  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
8826  {
8827  /* a > 0 -> change upper bound of x */
8828  parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8829  parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8830  }
8831  else
8832  {
8833  /* a < 0 -> change lower bound of x */
8834  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
8835 
8836  parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8837  parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8838  }
8839  break;
8840 
8841  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
8842  assert(parentvar->negatedvar != NULL);
8843  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
8844  assert(parentvar->negatedvar->negatedvar == parentvar);
8845 
8846  parentnewright = -left + parentvar->data.negate.constant;
8847  parentnewleft = -right + parentvar->data.negate.constant;
8848  break;
8849 
8850  default:
8851  SCIPerrorMessage("unknown variable status\n");
8852  return SCIP_INVALIDDATA;
8853  }
8854 
8855  SCIPsetDebugMsg(set, "add global hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
8856 
8857  /* perform hole added for parent variable */
8858  assert(blkmem != NULL);
8859  assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
8860  SCIP_CALL( varProcessAddHoleGlobal(parentvar, blkmem, set, stat, eventqueue,
8861  parentnewleft, parentnewright, &localadded) );
8862  assert(localadded);
8863  }
8864 
8865  return SCIP_OKAY;
8866 }
8867 
8868 /** adds a hole to the variable's global and local domain */
8870  SCIP_VAR* var, /**< problem variable */
8871  BMS_BLKMEM* blkmem, /**< block memory */
8872  SCIP_SET* set, /**< global SCIP settings */
8873  SCIP_STAT* stat, /**< problem statistics */
8874  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8875  SCIP_Real left, /**< left bound of open interval in new hole */
8876  SCIP_Real right, /**< right bound of open interval in new hole */
8877  SCIP_Bool* added /**< pointer to store whether the hole was added */
8878  )
8879 {
8880  SCIP_Real childnewleft;
8881  SCIP_Real childnewright;
8882 
8883  assert(var != NULL);
8884  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8885  assert(blkmem != NULL);
8886  assert(added != NULL);
8887 
8888  SCIPsetDebugMsg(set, "adding global hole (%g,%g) to <%s>\n", left, right, var->name);
8889 
8890  /* the interval should not be empty */
8891  assert(SCIPsetIsLT(set, left, right));
8892 
8893  /* the the interval bound should already be adjusted */
8894  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8895  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8896 
8897  /* the the interval should lay between the lower and upper bound */
8898  assert(SCIPsetIsGE(set, left, SCIPvarGetLbGlobal(var)));
8899  assert(SCIPsetIsLE(set, right, SCIPvarGetUbGlobal(var)));
8900 
8901  /* change bounds of attached variables */
8902  switch( SCIPvarGetStatus(var) )
8903  {
8905  if( var->data.original.transvar != NULL )
8906  {
8907  SCIP_CALL( SCIPvarAddHoleGlobal(var->data.original.transvar, blkmem, set, stat, eventqueue,
8908  left, right, added) );
8909  }
8910  else
8911  {
8912  assert(set->stage == SCIP_STAGE_PROBLEM);
8913 
8914  SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
8915  if( *added )
8916  {
8917  SCIP_Bool localadded;
8918 
8919  SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
8920  }
8921  }
8922  break;
8923 
8924  case SCIP_VARSTATUS_COLUMN:
8925  case SCIP_VARSTATUS_LOOSE:
8926  SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
8927  if( *added )
8928  {
8929  SCIP_Bool localadded;
8930 
8931  SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
8932  }
8933  break;
8934 
8935  case SCIP_VARSTATUS_FIXED:
8936  SCIPerrorMessage("cannot add hole of a fixed variable\n");
8937  return SCIP_INVALIDDATA;
8938 
8939  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8940  assert(var->data.aggregate.var != NULL);
8941 
8942  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8943  {
8944  /* a > 0 -> change lower bound of y */
8945  childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8946  childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8947  }
8948  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8949  {
8950  childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8951  childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8952  }
8953  else
8954  {
8955  SCIPerrorMessage("scalar is zero in aggregation\n");
8956  return SCIP_INVALIDDATA;
8957  }
8958  SCIP_CALL( SCIPvarAddHoleGlobal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
8959  childnewleft, childnewright, added) );
8960  break;
8961 
8963  SCIPerrorMessage("cannot add a hole of a multi-aggregated variable.\n");
8964  return SCIP_INVALIDDATA;
8965 
8966  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8967  assert(var->negatedvar != NULL);
8969  assert(var->negatedvar->negatedvar == var);
8970 
8971  childnewright = -left + var->data.negate.constant;
8972  childnewleft = -right + var->data.negate.constant;
8973 
8974  SCIP_CALL( SCIPvarAddHoleGlobal(var->negatedvar, blkmem, set, stat, eventqueue,
8975  childnewleft, childnewright, added) );
8976  break;
8977 
8978  default:
8979  SCIPerrorMessage("unknown variable status\n");
8980  return SCIP_INVALIDDATA;
8981  }
8982 
8983  return SCIP_OKAY;
8984 }
8985 
8986 /** performs the current add of domain, changes all parents accordingly */
8987 static
8989  SCIP_VAR* var, /**< problem variable */
8990  BMS_BLKMEM* blkmem, /**< block memory */
8991  SCIP_SET* set, /**< global SCIP settings */
8992  SCIP_STAT* stat, /**< problem statistics */
8993  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8994  SCIP_Real left, /**< left bound of open interval in new hole */
8995  SCIP_Real right, /**< right bound of open interval in new hole */
8996  SCIP_Bool* added /**< pointer to store whether the hole was added, or NULL */
8997  )
8998 {
8999  SCIP_VAR* parentvar;
9000  SCIP_Real newlb;
9001  SCIP_Real newub;
9002  int i;
9003 
9004  assert(var != NULL);
9005  assert(added != NULL);
9006  assert(blkmem != NULL);
9007 
9008  /* the interval should not be empty */
9009  assert(SCIPsetIsLT(set, left, right));
9010 
9011  /* the the interval bound should already be adjusted */
9012  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
9013  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
9014 
9015  /* the the interval should lay between the lower and upper bound */
9016  assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
9017  assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
9018 
9019  /* add hole to hole list */
9020  SCIP_CALL( domAddHole(&var->locdom, blkmem, set, left, right, added) );
9021 
9022  /* check if the hole is redundant */
9023  if( !(*added) )
9024  return SCIP_OKAY;
9025 
9026  /* current bounds */
9027  newlb = var->locdom.lb;
9028  newub = var->locdom.ub;
9029 
9030  /* merge domain holes */
9031  domMerge(&var->locdom, blkmem, set, &newlb, &newub);
9032 
9033  /* the bound should not be changed */
9034  assert(SCIPsetIsEQ(set, newlb, var->locdom.lb));
9035  assert(SCIPsetIsEQ(set, newub, var->locdom.ub));
9036 
9037 #if 0
9038  /* issue bound change event */
9039  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
9040  if( var->eventfilter != NULL )
9041  {
9042  SCIP_CALL( varEventLholeAdded(var, blkmem, set, lp, branchcand, eventqueue, left, right) );
9043  }
9044 #endif
9045 
9046  /* process parent variables */
9047  for( i = 0; i < var->nparentvars; ++i )
9048  {
9049  SCIP_Real parentnewleft;
9050  SCIP_Real parentnewright;
9051  SCIP_Bool localadded;
9052 
9053  parentvar = var->parentvars[i];
9054  assert(parentvar != NULL);
9055 
9056  switch( SCIPvarGetStatus(parentvar) )
9057  {
9059  parentnewleft = left;
9060  parentnewright = right;
9061  break;
9062 
9063  case SCIP_VARSTATUS_COLUMN:
9064  case SCIP_VARSTATUS_LOOSE:
9065  case SCIP_VARSTATUS_FIXED:
9067  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
9068  return SCIP_INVALIDDATA;
9069 
9070  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
9071  assert(parentvar->data.aggregate.var == var);
9072 
9073  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
9074  {
9075  /* a > 0 -> change upper bound of x */
9076  parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
9077  parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
9078  }
9079  else
9080  {
9081  /* a < 0 -> change lower bound of x */
9082  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
9083 
9084  parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
9085  parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
9086  }
9087  break;
9088 
9089  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
9090  assert(parentvar->negatedvar != NULL);
9091  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
9092  assert(parentvar->negatedvar->negatedvar == parentvar);
9093 
9094  parentnewright = -left + parentvar->data.negate.constant;
9095  parentnewleft = -right + parentvar->data.negate.constant;
9096  break;
9097 
9098  default:
9099  SCIPerrorMessage("unknown variable status\n");
9100  return SCIP_INVALIDDATA;
9101  }
9102 
9103  SCIPsetDebugMsg(set, "add local hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
9104 
9105  /* perform hole added for parent variable */
9106  assert(blkmem != NULL);
9107  assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
9108  SCIP_CALL( varProcessAddHoleLocal(parentvar, blkmem, set, stat, eventqueue,
9109  parentnewleft, parentnewright, &localadded) );
9110  assert(localadded);
9111  }
9112 
9113  return SCIP_OKAY;
9114 }
9115 
9116 /** adds a hole to the variable's current local domain */
9118  SCIP_VAR* var, /**< problem variable */
9119  BMS_BLKMEM* blkmem, /**< block memory */
9120  SCIP_SET* set, /**< global SCIP settings */
9121  SCIP_STAT* stat, /**< problem statistics */
9122  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
9123  SCIP_Real left, /**< left bound of open interval in new hole */
9124  SCIP_Real right, /**< right bound of open interval in new hole */
9125  SCIP_Bool* added /**< pointer to store whether the hole was added */
9126  )
9127 {
9128  SCIP_Real childnewleft;
9129  SCIP_Real childnewright;
9130 
9131  assert(var != NULL);
9132 
9133  SCIPsetDebugMsg(set, "adding local hole (%g,%g) to <%s>\n", left, right, var->name);
9134 
9135  assert(set != NULL);
9136  assert(var->scip == set->scip);
9137  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
9138  assert(blkmem != NULL);
9139  assert(added != NULL);
9140 
9141  /* the interval should not be empty */
9142  assert(SCIPsetIsLT(set, left, right));
9143 
9144  /* the the interval bound should already be adjusted */
9145  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
9146  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
9147 
9148  /* the the interval should lay between the lower and upper bound */
9149  assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
9150  assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
9151 
9152  /* change bounds of attached variables */
9153  switch( SCIPvarGetStatus(var) )
9154  {
9156  if( var->data.original.transvar != NULL )
9157  {
9158  SCIP_CALL( SCIPvarAddHoleLocal(var->data.original.transvar, blkmem, set, stat, eventqueue,
9159  left, right, added) );
9160  }
9161  else
9162  {
9163  assert(set->stage == SCIP_STAGE_PROBLEM);
9164  SCIPstatIncrement(stat, set, domchgcount);
9165  SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
9166  }
9167  break;
9168 
9169  case SCIP_VARSTATUS_COLUMN:
9170  case SCIP_VARSTATUS_LOOSE:
9171  SCIPstatIncrement(stat, set, domchgcount);
9172  SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
9173  break;
9174 
9175  case SCIP_VARSTATUS_FIXED:
9176  SCIPerrorMessage("cannot add domain hole to a fixed variable\n");
9177  return SCIP_INVALIDDATA;
9178 
9179  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
9180  assert(var->data.aggregate.var != NULL);
9181 
9182  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
9183  {
9184  /* a > 0 -> change lower bound of y */
9185  childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
9186  childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
9187  }
9188  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
9189  {
9190  childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
9191  childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
9192  }
9193  else
9194  {
9195  SCIPerrorMessage("scalar is zero in aggregation\n");
9196  return SCIP_INVALIDDATA;
9197  }
9198  SCIP_CALL( SCIPvarAddHoleLocal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
9199  childnewleft, childnewright, added) );
9200  break;
9201 
9203  SCIPerrorMessage("cannot add domain hole to a multi-aggregated variable.\n");
9204  return SCIP_INVALIDDATA;
9205 
9206  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
9207  assert(var->negatedvar != NULL);
9209  assert(var->negatedvar->negatedvar == var);
9210 
9211  childnewright = -left + var->data.negate.constant;
9212  childnewleft = -right + var->data.negate.constant;
9213 
9214  SCIP_CALL( SCIPvarAddHoleLocal(var->negatedvar, blkmem, set, stat, eventqueue, childnewleft, childnewright, added) );
9215  break;
9216 
9217  default:
9218  SCIPerrorMessage("unknown variable status\n");
9219  return SCIP_INVALIDDATA;
9220  }
9221 
9222  return SCIP_OKAY;
9223 }
9224 
9225 /** resets the global and local bounds of original variable to their original values */
9227  SCIP_VAR* var, /**< problem variable */
9228  BMS_BLKMEM* blkmem, /**< block memory */
9229  SCIP_SET* set, /**< global SCIP settings */
9230  SCIP_STAT* stat /**< problem statistics */
9231  )
9232 {
9233  assert(var != NULL);
9234  assert(set != NULL);
9235  assert(var->scip == set->scip);
9236  assert(SCIPvarIsOriginal(var));
9237  /* resetting of bounds on original variables which have a transformed counterpart easily fails if, e.g.,
9238  * the transformed variable has been fixed */
9239  assert(SCIPvarGetTransVar(var) == NULL);
9240 
9241  /* copy the original bounds back to the global and local bounds */
9242  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.lb) );
9243  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.ub) );
9244  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.lb) );
9245  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.ub) );
9246 
9247  /* free the global and local holelists and duplicate the original ones */
9248  /**@todo this has also to be called recursively with methods similar to SCIPvarChgLbGlobal() */
9249  holelistFree(&var->glbdom.holelist, blkmem);
9250  holelistFree(&var->locdom.holelist, blkmem);
9251  SCIP_CALL( holelistDuplicate(&var->glbdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
9252  SCIP_CALL( holelistDuplicate(&var->locdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
9253 
9254  return SCIP_OKAY;
9255 }
9256 
9257 /** issues a IMPLADDED event on the given variable */
9258 static
9260  SCIP_VAR* var, /**< problem variable to change */
9261  BMS_BLKMEM* blkmem, /**< block memory */
9262  SCIP_SET* set, /**< global SCIP settings */
9263  SCIP_EVENTQUEUE* eventqueue /**< event queue */
9264  )
9265 {
9266  SCIP_EVENT* event;
9267 
9268  assert(var != NULL);
9269 
9270  /* issue IMPLADDED event on variable */
9271  SCIP_CALL( SCIPeventCreateImplAdded(&event, blkmem, var) );
9272  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
9273 
9274  return SCIP_OKAY;
9275 }
9276 
9277 /** actually performs the addition of a variable bound to the variable's vbound arrays */
9278 static
9280  SCIP_VAR* var, /**< problem variable x in x <= b*z + d or x >= b*z + d */
9281  BMS_BLKMEM* blkmem, /**< block memory */
9282  SCIP_SET* set, /**< global SCIP settings */
9283  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9284  SCIP_BOUNDTYPE vbtype, /**< type of variable bound (LOWER or UPPER) */
9285  SCIP_VAR* vbvar, /**< variable z in x <= b*z + d or x >= b*z + d */
9286  SCIP_Real vbcoef, /**< coefficient b in x <= b*z + d or x >= b*z + d */
9287  SCIP_Real vbconstant /**< constant d in x <= b*z + d or x >= b*z + d */
9288  )
9289 {
9290  SCIP_Bool added;
9291 
9292  /* It can happen that the variable "var" and the variable "vbvar" are the same variable. For example if a variable
9293  * gets aggregated, the variable bounds (vbound) of that variable are copied to the other variable. A variable bound
9294  * variable of the aggregated variable might be the same as the one its gets aggregated too.
9295  *
9296  * If the variable "var" and the variable "vbvar" are the same, the variable bound which should be added here has to
9297  * be redundant. This is the case since an infeasibility should have be detected in the previous methods. As well as
9298  * the bounds of the variable which should be also already be tightened in the previous methods. Therefore, the
9299  * variable bound can be ignored.
9300  *
9301  * From the way the the variable bound system is implemented (detecting infeasibility, tighten bounds), the
9302  * equivalence of the variables should be checked here.
9303  */
9304  if( var == vbvar )
9305  {
9306  /* in this case the variable bound has to be redundant, this means for possible assignments to this variable; this
9307  * can be checked via the global bounds of the variable */
9308 #ifndef NDEBUG
9309  SCIP_Real lb;
9310  SCIP_Real ub;
9311 
9312  lb = SCIPvarGetLbGlobal(var);
9313  ub = SCIPvarGetUbGlobal(var);
9314 
9315  if(vbtype == SCIP_BOUNDTYPE_LOWER)
9316  {
9317  if( vbcoef > 0.0 )
9318  {
9319  assert(SCIPsetIsGE(set, lb, lb * vbcoef + vbconstant) );
9320  assert(SCIPsetIsGE(set, ub, ub * vbcoef + vbconstant) );
9321  }
9322  else
9323  {
9324  assert(SCIPsetIsGE(set, lb, ub * vbcoef + vbconstant) );
9325  assert(SCIPsetIsGE(set, ub, lb * vbcoef + vbconstant) );
9326  }
9327  }
9328  else
9329  {
9330  assert(vbtype == SCIP_BOUNDTYPE_UPPER);
9331  if( vbcoef > 0.0 )
9332  {
9333  assert(SCIPsetIsLE(set, lb, lb * vbcoef + vbconstant) );
9334  assert(SCIPsetIsLE(set, ub, ub * vbcoef + vbconstant) );
9335  }
9336  else
9337  {
9338  assert(SCIPsetIsLE(set, lb, ub * vbcoef + vbconstant) );
9339  assert(SCIPsetIsLE(set, ub, lb * vbcoef + vbconstant) );
9340  }
9341  }
9342 #endif
9343  SCIPsetDebugMsg(set, "redundant variable bound: <%s> %s %g<%s> %+g\n",
9344  SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
9345 
9346  return SCIP_OKAY;
9347  }
9348 
9349  SCIPsetDebugMsg(set, "adding variable bound: <%s> %s %g<%s> %+g\n",
9350  SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
9351 
9352  /* check variable bound on debugging solution */
9353  SCIP_CALL( SCIPdebugCheckVbound(set, var, vbtype, vbvar, vbcoef, vbconstant) ); /*lint !e506 !e774*/
9354 
9355  /* perform the addition */
9356  if( vbtype == SCIP_BOUNDTYPE_LOWER )
9357  {
9358  SCIP_CALL( SCIPvboundsAdd(&var->vlbs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
9359  }
9360  else
9361  {
9362  SCIP_CALL( SCIPvboundsAdd(&var->vubs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
9363  }
9364  var->closestvblpcount = -1;
9365 
9366  if( added )
9367  {
9368  /* issue IMPLADDED event */
9369  SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
9370  }
9371 
9372  return SCIP_OKAY;
9373 }
9374 
9375 /** checks whether the given implication is redundant or infeasible w.r.t. the implied variables global bounds */
9376 static
9377 void checkImplic(
9378  SCIP_SET* set, /**< global SCIP settings */
9379  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9380  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9381  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9382  SCIP_Bool* redundant, /**< pointer to store whether the implication is redundant */
9383  SCIP_Bool* infeasible /**< pointer to store whether the implication is infeasible */
9384  )
9385 {
9386  SCIP_Real impllb;
9387  SCIP_Real implub;
9388 
9389  assert(redundant != NULL);
9390  assert(infeasible != NULL);
9391 
9392  impllb = SCIPvarGetLbGlobal(implvar);
9393  implub = SCIPvarGetUbGlobal(implvar);
9394  if( impltype == SCIP_BOUNDTYPE_LOWER )
9395  {
9396  *infeasible = SCIPsetIsFeasGT(set, implbound, implub);
9397  *redundant = SCIPsetIsFeasLE(set, implbound, impllb);
9398  }
9399  else
9400  {
9401  *infeasible = SCIPsetIsFeasLT(set, implbound, impllb);
9402  *redundant = SCIPsetIsFeasGE(set, implbound, implub);
9403  }
9404 }
9405 
9406 /** applies the given implication, if it is not redundant */
9407 static
9409  BMS_BLKMEM* blkmem, /**< block memory */
9410  SCIP_SET* set, /**< global SCIP settings */
9411  SCIP_STAT* stat, /**< problem statistics */
9412  SCIP_PROB* transprob, /**< transformed problem */
9413  SCIP_PROB* origprob, /**< original problem */
9414  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9415  SCIP_REOPT* reopt, /**< reoptimization data structure */
9416  SCIP_LP* lp, /**< current LP data */
9417  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9418  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9419  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9420  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9421  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9422  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9423  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9424  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9425  )
9426 {
9427  SCIP_Real implub;
9428  SCIP_Real impllb;
9429 
9430  assert(infeasible != NULL);
9431 
9432  *infeasible = FALSE;
9433 
9434  implub = SCIPvarGetUbGlobal(implvar);
9435  impllb = SCIPvarGetLbGlobal(implvar);
9436  if( impltype == SCIP_BOUNDTYPE_LOWER )
9437  {
9438  if( SCIPsetIsFeasGT(set, implbound, implub) )
9439  {
9440  /* the implication produces a conflict: the problem is infeasible */
9441  *infeasible = TRUE;
9442  }
9443  else if( SCIPsetIsFeasGT(set, implbound, impllb) )
9444  {
9445  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9446  * with the local bound, in this case we need to store the bound change as pending bound change
9447  */
9448  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9449  {
9450  assert(tree != NULL);
9451  assert(transprob != NULL);
9452  assert(SCIPprobIsTransformed(transprob));
9453 
9454  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9455  tree, reopt, lp, branchcand, eventqueue, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
9456  }
9457  else
9458  {
9459  SCIP_CALL( SCIPvarChgLbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
9460  }
9461 
9462  if( nbdchgs != NULL )
9463  (*nbdchgs)++;
9464  }
9465  }
9466  else
9467  {
9468  if( SCIPsetIsFeasLT(set, implbound, impllb) )
9469  {
9470  /* the implication produces a conflict: the problem is infeasible */
9471  *infeasible = TRUE;
9472  }
9473  else if( SCIPsetIsFeasLT(set, implbound, implub) )
9474  {
9475  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9476  * with the local bound, in this case we need to store the bound change as pending bound change
9477  */
9478  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9479  {
9480  assert(tree != NULL);
9481  assert(transprob != NULL);
9482  assert(SCIPprobIsTransformed(transprob));
9483 
9484  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9485  tree, reopt, lp, branchcand, eventqueue, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
9486  }
9487  else
9488  {
9489  SCIP_CALL( SCIPvarChgUbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
9490  }
9491 
9492  if( nbdchgs != NULL )
9493  (*nbdchgs)++;
9494  }
9495  }
9496 
9497  return SCIP_OKAY;
9498 }
9499 
9500 /** actually performs the addition of an implication to the variable's implication arrays,
9501  * and adds the corresponding implication or variable bound to the implied variable;
9502  * if the implication is conflicting, the variable is fixed to the opposite value;
9503  * if the variable is already fixed to the given value, the implication is performed immediately;
9504  * if the implication is redundant with respect to the variables' global bounds, it is ignored
9505  */
9506 static
9508  SCIP_VAR* var, /**< problem variable */
9509  BMS_BLKMEM* blkmem, /**< block memory */
9510  SCIP_SET* set, /**< global SCIP settings */
9511  SCIP_STAT* stat, /**< problem statistics */
9512  SCIP_PROB* transprob, /**< transformed problem */
9513  SCIP_PROB* origprob, /**< original problem */
9514  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9515  SCIP_REOPT* reopt, /**< reoptimization data structure */
9516  SCIP_LP* lp, /**< current LP data */
9517  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9518  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9519  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9520  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9521  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9522  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9523  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9524  SCIP_Bool isshortcut, /**< is the implication a shortcut, i.e., added as part of the transitive closure of another implication? */
9525  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9526  int* nbdchgs, /**< pointer to count the number of performed bound changes, or NULL */
9527  SCIP_Bool* added /**< pointer to store whether an implication was added */
9528  )
9529 {
9530  SCIP_Bool redundant;
9531  SCIP_Bool conflict;
9532 
9533  assert(var != NULL);
9534  assert(SCIPvarIsActive(var));
9536  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
9537  assert(SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED);
9538  assert(infeasible != NULL);
9539  assert(added != NULL);
9540 
9541  /* check implication on debugging solution */
9542  SCIP_CALL( SCIPdebugCheckImplic(set, var, varfixing, implvar, impltype, implbound) ); /*lint !e506 !e774*/
9543 
9544  *infeasible = FALSE;
9545  *added = FALSE;
9546 
9547  /* check, if the implication is redundant or infeasible */
9548  checkImplic(set, implvar, impltype, implbound, &redundant, &conflict);
9549  assert(!redundant || !conflict);
9550  if( redundant )
9551  return SCIP_OKAY;
9552 
9553  if( var == implvar )
9554  {
9555  /* special cases appear were a bound to a variable implies itself to be outside the bounds:
9556  * x == varfixing => x < 0 or x > 1
9557  */
9558  if( SCIPsetIsLT(set, implbound, 0.0) || SCIPsetIsGT(set, implbound, 1.0) )
9559  conflict = TRUE;
9560  else
9561  {
9562  /* variable implies itself: x == varfixing => x == (impltype == SCIP_BOUNDTYPE_LOWER) */
9563  assert(SCIPsetIsZero(set, implbound) || SCIPsetIsEQ(set, implbound, 1.0));
9564  assert(SCIPsetIsZero(set, implbound) == (impltype == SCIP_BOUNDTYPE_UPPER));
9565  assert(SCIPsetIsEQ(set, implbound, 1.0) == (impltype == SCIP_BOUNDTYPE_LOWER));
9566  conflict = conflict || ((varfixing == TRUE) == (impltype == SCIP_BOUNDTYPE_UPPER));
9567  if( !conflict )
9568  return SCIP_OKAY;
9569  }
9570  }
9571 
9572  /* check, if the variable is already fixed */
9573  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
9574  {
9575  /* if the variable is fixed to the given value, perform the implication; otherwise, ignore the implication */
9576  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
9577  {
9578  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
9579  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
9580  }
9581  return SCIP_OKAY;
9582  }
9583 
9584  assert((impltype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, implbound, SCIPvarGetLbGlobal(implvar)))
9585  || (impltype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, implbound, SCIPvarGetUbGlobal(implvar))));
9586 
9587  if( !conflict )
9588  {
9589  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9590 
9591  if( SCIPvarIsBinary(implvar) )
9592  {
9593  SCIP_VAR* vars[2];
9594  SCIP_Bool vals[2];
9595 
9596  assert(SCIPsetIsFeasEQ(set, implbound, 1.0) || SCIPsetIsFeasZero(set, implbound));
9597  assert((impltype == SCIP_BOUNDTYPE_UPPER) == SCIPsetIsFeasZero(set, implbound));
9598 
9599  vars[0] = var;
9600  vars[1] = implvar;
9601  vals[0] = varfixing;
9602  vals[1] = (impltype == SCIP_BOUNDTYPE_UPPER);
9603 
9604  /* add the clique to the clique table */
9605  SCIP_CALL( SCIPcliquetableAdd(cliquetable, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
9606  eventqueue, vars, vals, 2, FALSE, &conflict, nbdchgs) );
9607 
9608  if( !conflict )
9609  return SCIP_OKAY;
9610  }
9611  else
9612  {
9613  /* add implication x == 0/1 -> y <= b / y >= b to the implications list of x */
9614  SCIPsetDebugMsg(set, "adding implication: <%s> == %u ==> <%s> %s %g\n",
9615  SCIPvarGetName(var), varfixing,
9616  SCIPvarGetName(implvar), impltype == SCIP_BOUNDTYPE_UPPER ? "<=" : ">=", implbound);
9617  SCIP_CALL( SCIPimplicsAdd(&var->implics, blkmem, set, stat, varfixing, implvar, impltype, implbound,
9618  isshortcut, &conflict, added) );
9619  }
9620  }
9621  assert(!conflict || !(*added));
9622 
9623  /* on conflict, fix the variable to the opposite value */
9624  if( conflict )
9625  {
9626  SCIPsetDebugMsg(set, " -> implication yields a conflict: fix <%s> == %d\n", SCIPvarGetName(var), !varfixing);
9627 
9628  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9629  * with the local bound, in this case we need to store the bound change as pending bound change
9630  */
9631  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9632  {
9633  assert(tree != NULL);
9634  assert(transprob != NULL);
9635  assert(SCIPprobIsTransformed(transprob));
9636 
9637  if( varfixing )
9638  {
9639  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9640  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
9641  }
9642  else
9643  {
9644  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9645  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
9646  }
9647  }
9648  else
9649  {
9650  if( varfixing )
9651  {
9652  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
9653  }
9654  else
9655  {
9656  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
9657  }
9658  }
9659  if( nbdchgs != NULL )
9660  (*nbdchgs)++;
9661 
9662  return SCIP_OKAY;
9663  }
9664  else if( *added )
9665  {
9666  /* issue IMPLADDED event */
9667  SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
9668  }
9669  else
9670  {
9671  /* the implication was redundant: the inverse is also redundant */
9672  return SCIP_OKAY;
9673  }
9674 
9675  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9676 
9677  /* check, whether implied variable is binary */
9678  if( !SCIPvarIsBinary(implvar) )
9679  {
9680  SCIP_Real lb;
9681  SCIP_Real ub;
9682 
9683  /* add inverse variable bound to the variable bounds of y with global bounds y \in [lb,ub]:
9684  * x == 0 -> y <= b <-> y <= (ub - b)*x + b
9685  * x == 1 -> y <= b <-> y <= (b - ub)*x + ub
9686  * x == 0 -> y >= b <-> y >= (lb - b)*x + b
9687  * x == 1 -> y >= b <-> y >= (b - lb)*x + lb
9688  * for numerical reasons, ignore variable bounds with large absolute coefficient
9689  */
9690  lb = SCIPvarGetLbGlobal(implvar);
9691  ub = SCIPvarGetUbGlobal(implvar);
9692  if( impltype == SCIP_BOUNDTYPE_UPPER )
9693  {
9694  if( REALABS(implbound - ub) <= MAXABSVBCOEF )
9695  {
9696  SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, var,
9697  varfixing ? implbound - ub : ub - implbound, varfixing ? ub : implbound) );
9698  }
9699  }
9700  else
9701  {
9702  if( REALABS(implbound - lb) <= MAXABSVBCOEF )
9703  {
9704  SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, var,
9705  varfixing ? implbound - lb : lb - implbound, varfixing ? lb : implbound) );
9706  }
9707  }
9708  }
9709 
9710  return SCIP_OKAY;
9711 }
9712 
9713 /** adds transitive closure for binary implication x = a -> y = b */
9714 static
9716  SCIP_VAR* var, /**< problem variable */
9717  BMS_BLKMEM* blkmem, /**< block memory */
9718  SCIP_SET* set, /**< global SCIP settings */
9719  SCIP_STAT* stat, /**< problem statistics */
9720  SCIP_PROB* transprob, /**< transformed problem */
9721  SCIP_PROB* origprob, /**< original problem */
9722  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9723  SCIP_REOPT* reopt, /**< reoptimization data structure */
9724  SCIP_LP* lp, /**< current LP data */
9725  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9726  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9727  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9728  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9729  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9730  SCIP_Bool implvarfixing, /**< fixing b in implication */
9731  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9732  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9733  )
9734 {
9735  SCIP_VAR** implvars;
9736  SCIP_BOUNDTYPE* impltypes;
9737  SCIP_Real* implbounds;
9738  int nimpls;
9739  int i;
9740 
9741  *infeasible = FALSE;
9742 
9743  /* binary variable: implications of implvar */
9744  nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
9745  implvars = SCIPimplicsGetVars(implvar->implics, implvarfixing);
9746  impltypes = SCIPimplicsGetTypes(implvar->implics, implvarfixing);
9747  implbounds = SCIPimplicsGetBounds(implvar->implics, implvarfixing);
9748 
9749  /* if variable has too many implications, the implication graph may become too dense */
9750  i = MIN(nimpls, MAXIMPLSCLOSURE) - 1;
9751 
9752  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9753  * implvars[i] is fixed, s.t. the implication y == varfixing -> z <= b / z >= b is deleted; this affects the
9754  * array over which we currently iterate; the only thing that can happen, is that elements of the array are
9755  * deleted; in this case, the subsequent elements are moved to the front; if we iterate from back to front, the
9756  * only thing that can happen is that we add the same implication twice - this does no harm
9757  */
9758  while ( i >= 0 && !(*infeasible) )
9759  {
9760  SCIP_Bool added;
9761 
9762  assert(implvars[i] != implvar);
9763 
9764  /* we have x == varfixing -> y == implvarfixing -> z <= b / z >= b:
9765  * add implication x == varfixing -> z <= b / z >= b to the implications list of x
9766  */
9767  if( SCIPvarIsActive(implvars[i]) )
9768  {
9769  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
9770  eventqueue, varfixing, implvars[i], impltypes[i], implbounds[i], TRUE, infeasible, nbdchgs, &added) );
9771  assert(SCIPimplicsGetNImpls(implvar->implics, implvarfixing) <= nimpls);
9772  nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
9773  i = MIN(i, nimpls); /* some elements from the array could have been removed */
9774  }
9775  --i;
9776  }
9777 
9778  return SCIP_OKAY;
9779 }
9780 
9781 /** adds given implication to the variable's implication list, and adds all implications directly implied by this
9782  * implication to the variable's implication list;
9783  * if the implication is conflicting, the variable is fixed to the opposite value;
9784  * if the variable is already fixed to the given value, the implication is performed immediately;
9785  * if the implication is redundant with respect to the variables' global bounds, it is ignored
9786  */
9787 static
9789  SCIP_VAR* var, /**< problem variable */
9790  BMS_BLKMEM* blkmem, /**< block memory */
9791  SCIP_SET* set, /**< global SCIP settings */
9792  SCIP_STAT* stat, /**< problem statistics */
9793  SCIP_PROB* transprob, /**< transformed problem */
9794  SCIP_PROB* origprob, /**< original problem */
9795  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9796  SCIP_REOPT* reopt, /**< reoptimization data structure */
9797  SCIP_LP* lp, /**< current LP data */
9798  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9799  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9800  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9801  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9802  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9803  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9804  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9805  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
9806  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9807  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9808  )
9809 {
9810  SCIP_Bool added;
9811 
9812  assert(var != NULL);
9813  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
9814  assert(SCIPvarIsActive(var));
9815  assert(implvar != NULL);
9816  assert(SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED);
9817  assert(infeasible != NULL);
9818 
9819  /* add implication x == varfixing -> y <= b / y >= b to the implications list of x */
9820  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
9821  eventqueue, varfixing, implvar, impltype, implbound, FALSE, infeasible, nbdchgs, &added) );
9822 
9823  if( *infeasible || var == implvar || !transitive || !added )
9824  return SCIP_OKAY;
9825 
9826  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9827 
9828  /* add transitive closure */
9829  if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
9830  {
9831  SCIP_Bool implvarfixing;
9832 
9833  implvarfixing = (impltype == SCIP_BOUNDTYPE_LOWER);
9834 
9835  /* binary variable: implications of implvar */
9836  SCIP_CALL( varAddTransitiveBinaryClosureImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9837  cliquetable, branchcand, eventqueue, varfixing, implvar, implvarfixing, infeasible, nbdchgs) );
9838 
9839  /* inverse implication */
9840  if( !(*infeasible) )
9841  {
9842  SCIP_CALL( varAddTransitiveBinaryClosureImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9843  cliquetable, branchcand, eventqueue, !implvarfixing, var, !varfixing, infeasible, nbdchgs) );
9844  }
9845  }
9846  else
9847  {
9848  /* non-binary variable: variable lower bounds of implvar */
9849  if( impltype == SCIP_BOUNDTYPE_UPPER && implvar->vlbs != NULL )
9850  {
9851  SCIP_VAR** vlbvars;
9852  SCIP_Real* vlbcoefs;
9853  SCIP_Real* vlbconstants;
9854  int nvlbvars;
9855  int i;
9856 
9857  nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
9858  vlbvars = SCIPvboundsGetVars(implvar->vlbs);
9859  vlbcoefs = SCIPvboundsGetCoefs(implvar->vlbs);
9860  vlbconstants = SCIPvboundsGetConstants(implvar->vlbs);
9861 
9862  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9863  * vlbvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
9864  * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
9865  * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
9866  * is that we add the same implication twice - this does no harm
9867  */
9868  i = nvlbvars-1;
9869  while ( i >= 0 && !(*infeasible) )
9870  {
9871  assert(vlbvars[i] != implvar);
9872  assert(!SCIPsetIsZero(set, vlbcoefs[i]));
9873 
9874  /* we have x == varfixing -> y <= b and y >= c*z + d:
9875  * c > 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
9876  * c < 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
9877  *
9878  * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
9879  * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
9880  * aggregation variable (the one which will stay active);
9881  *
9882  * W.l.o.g. we consider the variable upper bounds for now. Let "vubvar" be a variable upper bound of
9883  * the aggregated variable "aggvar"; During that copying of that variable upper bound variable
9884  * "vubvar" the variable lower and upper bounds of this variable "vubvar" are also considered; note
9885  * that the "aggvar" can be a variable lower bound variable of the variable "vubvar"; Due to that
9886  * situation it can happen that we reach that code place where "vlbvars[i] == aggvar". In particular
9887  * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
9888  * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
9889  * have to explicitly check that the active variable has not a variable status
9890  * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
9891  */
9892  if( SCIPvarIsActive(vlbvars[i]) && SCIPvarGetStatus(vlbvars[i]) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(vlbvars[i]) != SCIP_VARSTATUS_NEGATED )
9893  {
9894  SCIP_Real vbimplbound;
9895 
9896  vbimplbound = (implbound - vlbconstants[i])/vlbcoefs[i];
9897  if( vlbcoefs[i] >= 0.0 )
9898  {
9899  vbimplbound = adjustedUb(set, SCIPvarGetType(vlbvars[i]), vbimplbound);
9900  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9901  branchcand, eventqueue, varfixing, vlbvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
9902  infeasible, nbdchgs, &added) );
9903  }
9904  else
9905  {
9906  vbimplbound = adjustedLb(set, SCIPvarGetType(vlbvars[i]), vbimplbound);
9907  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9908  branchcand, eventqueue, varfixing, vlbvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
9909  infeasible, nbdchgs, &added) );
9910  }
9911  nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
9912  i = MIN(i, nvlbvars); /* some elements from the array could have been removed */
9913  }
9914  --i;
9915  }
9916  }
9917 
9918  /* non-binary variable: variable upper bounds of implvar */
9919  if( impltype == SCIP_BOUNDTYPE_LOWER && implvar->vubs != NULL )
9920  {
9921  SCIP_VAR** vubvars;
9922  SCIP_Real* vubcoefs;
9923  SCIP_Real* vubconstants;
9924  int nvubvars;
9925  int i;
9926 
9927  nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
9928  vubvars = SCIPvboundsGetVars(implvar->vubs);
9929  vubcoefs = SCIPvboundsGetCoefs(implvar->vubs);
9930  vubconstants = SCIPvboundsGetConstants(implvar->vubs);
9931 
9932  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9933  * vubvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
9934  * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
9935  * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
9936  * is that we add the same implication twice - this does no harm
9937  */
9938  i = nvubvars-1;
9939  while ( i >= 0 && !(*infeasible) )
9940  {
9941  assert(vubvars[i] != implvar);
9942  assert(!SCIPsetIsZero(set, vubcoefs[i]));
9943 
9944  /* we have x == varfixing -> y >= b and y <= c*z + d:
9945  * c > 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
9946  * c < 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
9947  *
9948  * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
9949  * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
9950  * aggregation variable (the one which will stay active);
9951  *
9952  * W.l.o.g. we consider the variable lower bounds for now. Let "vlbvar" be a variable lower bound of
9953  * the aggregated variable "aggvar"; During that copying of that variable lower bound variable
9954  * "vlbvar" the variable lower and upper bounds of this variable "vlbvar" are also considered; note
9955  * that the "aggvar" can be a variable upper bound variable of the variable "vlbvar"; Due to that
9956  * situation it can happen that we reach that code place where "vubvars[i] == aggvar". In particular
9957  * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
9958  * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
9959  * have to explicitly check that the active variable has not a variable status
9960  * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
9961  */
9962  if( SCIPvarIsActive(vubvars[i]) && SCIPvarGetStatus(vubvars[i]) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(vubvars[i]) != SCIP_VARSTATUS_NEGATED )
9963  {
9964  SCIP_Real vbimplbound;
9965 
9966  vbimplbound = (implbound - vubconstants[i])/vubcoefs[i];
9967  if( vubcoefs[i] >= 0.0 )
9968  {
9969  vbimplbound = adjustedLb(set, SCIPvarGetType(vubvars[i]), vbimplbound);
9970  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9971  branchcand, eventqueue, varfixing, vubvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
9972  infeasible, nbdchgs, &added) );
9973  }
9974  else
9975  {
9976  vbimplbound = adjustedUb(set, SCIPvarGetType(vubvars[i]), vbimplbound);
9977  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9978  branchcand, eventqueue, varfixing, vubvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
9979  infeasible, nbdchgs, &added) );
9980  }
9981  nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
9982  i = MIN(i, nvubvars); /* some elements from the array could have been removed */
9983  }
9984  --i;
9985  }
9986  }
9987  }
9988 
9989  return SCIP_OKAY;
9990 }
9991 
9992 /** informs variable x about a globally valid variable lower bound x >= b*z + d with integer variable z;
9993  * if z is binary, the corresponding valid implication for z is also added;
9994  * improves the global bounds of the variable and the vlb variable if possible
9995  */
9997  SCIP_VAR* var, /**< problem variable */
9998  BMS_BLKMEM* blkmem, /**< block memory */
9999  SCIP_SET* set, /**< global SCIP settings */
10000  SCIP_STAT* stat, /**< problem statistics */
10001  SCIP_PROB* transprob, /**< transformed problem */
10002  SCIP_PROB* origprob, /**< original problem */
10003  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10004  SCIP_REOPT* reopt, /**< reoptimization data structure */
10005  SCIP_LP* lp, /**< current LP data */
10006  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10007  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10008  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10009  SCIP_VAR* vlbvar, /**< variable z in x >= b*z + d */
10010  SCIP_Real vlbcoef, /**< coefficient b in x >= b*z + d */
10011  SCIP_Real vlbconstant, /**< constant d in x >= b*z + d */
10012  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
10013  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10014  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
10015  )
10016 {
10017  assert(var != NULL);
10018  assert(set != NULL);
10019  assert(var->scip == set->scip);
10020  assert(SCIPvarGetType(vlbvar) != SCIP_VARTYPE_CONTINUOUS);
10021  assert(infeasible != NULL);
10022 
10023  SCIPsetDebugMsg(set, "adding variable lower bound <%s> >= %g<%s> + %g\n", SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
10024 
10025  *infeasible = FALSE;
10026  if( nbdchgs != NULL )
10027  *nbdchgs = 0;
10028 
10029  switch( SCIPvarGetStatus(var) )
10030  {
10032  assert(var->data.original.transvar != NULL);
10033  SCIP_CALL( SCIPvarAddVlb(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10034  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef, vlbconstant, transitive, infeasible, nbdchgs) );
10035  break;
10036 
10037  case SCIP_VARSTATUS_COLUMN:
10038  case SCIP_VARSTATUS_LOOSE:
10039  case SCIP_VARSTATUS_FIXED:
10040  /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
10041  SCIP_CALL( SCIPvarGetProbvarSum(&vlbvar, set, &vlbcoef, &vlbconstant) );
10042  SCIPsetDebugMsg(set, " -> transformed to variable lower bound <%s> >= %g<%s> + %g\n", SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
10043 
10044  /* if the vlb coefficient is zero, just update the lower bound of the variable */
10045  if( SCIPsetIsZero(set, vlbcoef) )
10046  {
10047  if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetUbGlobal(var)) )
10048  *infeasible = TRUE;
10049  else if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetLbGlobal(var)) )
10050  {
10051  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10052  * with the local bound, in this case we need to store the bound change as pending bound change
10053  */
10054  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10055  {
10056  assert(tree != NULL);
10057  assert(transprob != NULL);
10058  assert(SCIPprobIsTransformed(transprob));
10059 
10060  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10061  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vlbconstant, SCIP_BOUNDTYPE_LOWER, FALSE) );
10062  }
10063  else
10064  {
10065  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vlbconstant) );
10066  }
10067 
10068  if( nbdchgs != NULL )
10069  (*nbdchgs)++;
10070  }
10071  }
10072  else if( var == vlbvar )
10073  {
10074  /* the variables cancels out, the variable bound constraint is either redundant or proves global infeasibility */
10075  if( SCIPsetIsEQ(set, vlbcoef, 1.0) )
10076  {
10077  if( SCIPsetIsPositive(set, vlbconstant) )
10078  *infeasible = TRUE;
10079  return SCIP_OKAY;
10080  }
10081  else
10082  {
10083  SCIP_Real lb = SCIPvarGetLbGlobal(var);
10084  SCIP_Real ub = SCIPvarGetUbGlobal(var);
10085 
10086  /* the variable bound constraint defines a new upper bound */
10087  if( SCIPsetIsGT(set, vlbcoef, 1.0) )
10088  {
10089  SCIP_Real newub = vlbconstant / (1.0 - vlbcoef);
10090 
10091  if( SCIPsetIsFeasLT(set, newub, lb) )
10092  {
10093  *infeasible = TRUE;
10094  return SCIP_OKAY;
10095  }
10096  else if( SCIPsetIsFeasLT(set, newub, ub) )
10097  {
10098  /* bound might be adjusted due to integrality condition */
10099  newub = adjustedUb(set, SCIPvarGetType(var), newub);
10100 
10101  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10102  * with the local bound, in this case we need to store the bound change as pending bound change
10103  */
10104  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10105  {
10106  assert(tree != NULL);
10107  assert(transprob != NULL);
10108  assert(SCIPprobIsTransformed(transprob));
10109 
10110  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10111  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10112  }
10113  else
10114  {
10115  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newub) );
10116  }
10117 
10118  if( nbdchgs != NULL )
10119  (*nbdchgs)++;
10120  }
10121  }
10122  /* the variable bound constraint defines a new lower bound */
10123  else
10124  {
10125  SCIP_Real newlb;
10126 
10127  assert(SCIPsetIsLT(set, vlbcoef, 1.0));
10128 
10129  newlb = vlbconstant / (1.0 - vlbcoef);
10130 
10131  if( SCIPsetIsFeasGT(set, newlb, ub) )
10132  {
10133  *infeasible = TRUE;
10134  return SCIP_OKAY;
10135  }
10136  else if( SCIPsetIsFeasGT(set, newlb, lb) )
10137  {
10138  /* bound might be adjusted due to integrality condition */
10139  newlb = adjustedLb(set, SCIPvarGetType(var), newlb);
10140 
10141  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10142  * with the local bound, in this case we need to store the bound change as pending bound change
10143  */
10144  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10145  {
10146  assert(tree != NULL);
10147  assert(transprob != NULL);
10148  assert(SCIPprobIsTransformed(transprob));
10149 
10150  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10151  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10152  }
10153  else
10154  {
10155  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newlb) );
10156  }
10157 
10158  if( nbdchgs != NULL )
10159  (*nbdchgs)++;
10160  }
10161  }
10162  }
10163  }
10164  else if( SCIPvarIsActive(vlbvar) )
10165  {
10166  SCIP_Real xlb;
10167  SCIP_Real xub;
10168  SCIP_Real zlb;
10169  SCIP_Real zub;
10170  SCIP_Real minvlb;
10171  SCIP_Real maxvlb;
10172 
10174  assert(vlbcoef != 0.0);
10175 
10176  minvlb = -SCIPsetInfinity(set);
10177  maxvlb = SCIPsetInfinity(set);
10178 
10179  xlb = SCIPvarGetLbGlobal(var);
10180  xub = SCIPvarGetUbGlobal(var);
10181  zlb = SCIPvarGetLbGlobal(vlbvar);
10182  zub = SCIPvarGetUbGlobal(vlbvar);
10183 
10184  /* improve global bounds of vlb variable, and calculate minimal and maximal value of variable bound */
10185  if( vlbcoef >= 0.0 )
10186  {
10187  SCIP_Real newzub;
10188 
10189  if( !SCIPsetIsInfinity(set, xub) )
10190  {
10191  /* x >= b*z + d -> z <= (x-d)/b */
10192  newzub = (xub - vlbconstant)/vlbcoef;
10193 
10194  /* return if the new bound is less than -infinity */
10195  if( SCIPsetIsInfinity(set, REALABS(newzub)) )
10196  return SCIP_OKAY;
10197 
10198  if( SCIPsetIsFeasLT(set, newzub, zlb) )
10199  {
10200  *infeasible = TRUE;
10201  return SCIP_OKAY;
10202  }
10203  if( SCIPsetIsFeasLT(set, newzub, zub) )
10204  {
10205  /* bound might be adjusted due to integrality condition */
10206  newzub = adjustedUb(set, SCIPvarGetType(vlbvar), newzub);
10207 
10208  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10209  * with the local bound, in this case we need to store the bound change as pending bound change
10210  */
10211  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10212  {
10213  assert(tree != NULL);
10214  assert(transprob != NULL);
10215  assert(SCIPprobIsTransformed(transprob));
10216 
10217  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10218  tree, reopt, lp, branchcand, eventqueue, cliquetable, vlbvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10219  }
10220  else
10221  {
10222  SCIP_CALL( SCIPvarChgUbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
10223  }
10224  zub = newzub;
10225 
10226  if( nbdchgs != NULL )
10227  (*nbdchgs)++;
10228  }
10229  maxvlb = vlbcoef * zub + vlbconstant;
10230  if( !SCIPsetIsInfinity(set, -zlb) )
10231  minvlb = vlbcoef * zlb + vlbconstant;
10232  }
10233  else
10234  {
10235  if( !SCIPsetIsInfinity(set, zub) )
10236  maxvlb = vlbcoef * zub + vlbconstant;
10237  if( !SCIPsetIsInfinity(set, -zlb) )
10238  minvlb = vlbcoef * zlb + vlbconstant;
10239  }
10240  }
10241  else
10242  {
10243  SCIP_Real newzlb;
10244 
10245  if( !SCIPsetIsInfinity(set, xub) )
10246  {
10247  /* x >= b*z + d -> z >= (x-d)/b */
10248  newzlb = (xub - vlbconstant)/vlbcoef;
10249 
10250  /* return if the new bound is larger than infinity */
10251  if( SCIPsetIsInfinity(set, REALABS(newzlb)) )
10252  return SCIP_OKAY;
10253 
10254  if( SCIPsetIsFeasGT(set, newzlb, zub) )
10255  {
10256  *infeasible = TRUE;
10257  return SCIP_OKAY;
10258  }
10259  if( SCIPsetIsFeasGT(set, newzlb, zlb) )
10260  {
10261  /* bound might be adjusted due to integrality condition */
10262  newzlb = adjustedLb(set, SCIPvarGetType(vlbvar), newzlb);
10263 
10264  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10265  * with the local bound, in this case we need to store the bound change as pending bound change
10266  */
10267  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10268  {
10269  assert(tree != NULL);
10270  assert(transprob != NULL);
10271  assert(SCIPprobIsTransformed(transprob));
10272 
10273  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10274  tree, reopt, lp, branchcand, eventqueue, cliquetable, vlbvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10275  }
10276  else
10277  {
10278  SCIP_CALL( SCIPvarChgLbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
10279  }
10280  zlb = newzlb;
10281 
10282  if( nbdchgs != NULL )
10283  (*nbdchgs)++;
10284  }
10285  maxvlb = vlbcoef * zlb + vlbconstant;
10286  if( !SCIPsetIsInfinity(set, zub) )
10287  minvlb = vlbcoef * zub + vlbconstant;
10288  }
10289  else
10290  {
10291  if( !SCIPsetIsInfinity(set, -zlb) )
10292  maxvlb = vlbcoef * zlb + vlbconstant;
10293  if( !SCIPsetIsInfinity(set, zub) )
10294  minvlb = vlbcoef * zub + vlbconstant;
10295  }
10296  }
10297  if( maxvlb < minvlb )
10298  maxvlb = minvlb;
10299 
10300  /* adjust bounds due to integrality of variable */
10301  minvlb = adjustedLb(set, SCIPvarGetType(var), minvlb);
10302  maxvlb = adjustedLb(set, SCIPvarGetType(var), maxvlb);
10303 
10304  /* check bounds for feasibility */
10305  if( SCIPsetIsFeasGT(set, minvlb, xub) || (var == vlbvar && SCIPsetIsEQ(set, vlbcoef, 1.0) && SCIPsetIsFeasPositive(set, vlbconstant)) )
10306  {
10307  *infeasible = TRUE;
10308  return SCIP_OKAY;
10309  }
10310  /* improve global lower bound of variable */
10311  if( SCIPsetIsFeasGT(set, minvlb, xlb) )
10312  {
10313  /* bound might be adjusted due to integrality condition */
10314  minvlb = adjustedLb(set, SCIPvarGetType(var), minvlb);
10315 
10316  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10317  * with the local bound, in this case we need to store the bound change as pending bound change
10318  */
10319  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10320  {
10321  assert(tree != NULL);
10322  assert(transprob != NULL);
10323  assert(SCIPprobIsTransformed(transprob));
10324 
10325  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10326  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, minvlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10327  }
10328  else
10329  {
10330  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, minvlb) );
10331  }
10332  xlb = minvlb;
10333 
10334  if( nbdchgs != NULL )
10335  (*nbdchgs)++;
10336  }
10337  minvlb = xlb;
10338 
10339  /* improve variable bound for binary z by moving the variable's global bound to the vlb constant */
10340  if( SCIPvarGetType(vlbvar) == SCIP_VARTYPE_BINARY )
10341  {
10342  /* b > 0: x >= (maxvlb - minvlb) * z + minvlb
10343  * b < 0: x >= (minvlb - maxvlb) * z + maxvlb
10344  */
10345 
10346  assert(!SCIPsetIsInfinity(set, maxvlb) && !SCIPsetIsInfinity(set, -minvlb));
10347 
10348  if( vlbcoef >= 0.0 )
10349  {
10350  vlbcoef = maxvlb - minvlb;
10351  vlbconstant = minvlb;
10352  }
10353  else
10354  {
10355  vlbcoef = minvlb - maxvlb;
10356  vlbconstant = maxvlb;
10357  }
10358  }
10359 
10360  /* add variable bound to the variable bounds list */
10361  if( SCIPsetIsFeasGT(set, maxvlb, xlb) )
10362  {
10363  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED);
10364  assert(!SCIPsetIsZero(set, vlbcoef));
10365 
10366  /* if one of the variables is binary, add the corresponding implication to the variable's implication
10367  * list, thereby also adding the variable bound (or implication) to the other variable
10368  */
10369  if( SCIPvarGetType(vlbvar) == SCIP_VARTYPE_BINARY )
10370  {
10371  /* add corresponding implication:
10372  * b > 0, x >= b*z + d <-> z == 1 -> x >= b+d
10373  * b < 0, x >= b*z + d <-> z == 0 -> x >= d
10374  */
10375  SCIP_CALL( varAddTransitiveImplic(vlbvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10376  cliquetable, branchcand, eventqueue, (vlbcoef >= 0.0), var, SCIP_BOUNDTYPE_LOWER, maxvlb, transitive,
10377  infeasible, nbdchgs) );
10378  }
10379  else if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
10380  {
10381  /* add corresponding implication:
10382  * b > 0, x >= b*z + d <-> x == 0 -> z <= -d/b
10383  * b < 0, x >= b*z + d <-> x == 0 -> z >= -d/b
10384  */
10385  SCIP_Real implbound;
10386  implbound = -vlbconstant/vlbcoef;
10387 
10388  /* tighten the implication bound if the variable is integer */
10389  if( SCIPvarIsIntegral(vlbvar) )
10390  {
10391  if( vlbcoef >= 0 )
10392  implbound = SCIPsetFloor(set, implbound);
10393  else
10394  implbound = SCIPsetCeil(set, implbound);
10395  }
10396  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10397  cliquetable, branchcand, eventqueue, FALSE, vlbvar, (vlbcoef >= 0.0 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER),
10398  implbound, transitive, infeasible, nbdchgs) );
10399  }
10400  else
10401  {
10402  SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, vlbvar, vlbcoef, vlbconstant) );
10403  }
10404  }
10405  }
10406  break;
10407 
10409  /* x = a*y + c: x >= b*z + d <=> a*y + c >= b*z + d <=> y >= b/a * z + (d-c)/a, if a > 0
10410  * y <= b/a * z + (d-c)/a, if a < 0
10411  */
10412  assert(var->data.aggregate.var != NULL);
10413  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
10414  {
10415  /* a > 0 -> add variable lower bound */
10416  SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10417  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef/var->data.aggregate.scalar,
10418  (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10419  }
10420  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
10421  {
10422  /* a < 0 -> add variable upper bound */
10423  SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10424  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef/var->data.aggregate.scalar,
10425  (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10426  }
10427  else
10428  {
10429  SCIPerrorMessage("scalar is zero in aggregation\n");
10430  return SCIP_INVALIDDATA;
10431  }
10432  break;
10433 
10435  /* nothing to do here */
10436  break;
10437 
10439  /* x = offset - x': x >= b*z + d <=> offset - x' >= b*z + d <=> x' <= -b*z + (offset-d) */
10440  assert(var->negatedvar != NULL);
10442  assert(var->negatedvar->negatedvar == var);
10443  SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10444  branchcand, eventqueue, vlbvar, -vlbcoef, var->data.negate.constant - vlbconstant, transitive, infeasible,
10445  nbdchgs) );
10446  break;
10447 
10448  default:
10449  SCIPerrorMessage("unknown variable status\n");
10450  return SCIP_INVALIDDATA;
10451  }
10452 
10453  return SCIP_OKAY;
10454 }
10455 
10456 /** informs variable x about a globally valid variable upper bound x <= b*z + d with integer variable z;
10457  * if z is binary, the corresponding valid implication for z is also added;
10458  * updates the global bounds of the variable and the vub variable correspondingly
10459  */
10461  SCIP_VAR* var, /**< problem variable */
10462  BMS_BLKMEM* blkmem, /**< block memory */
10463  SCIP_SET* set, /**< global SCIP settings */
10464  SCIP_STAT* stat, /**< problem statistics */
10465  SCIP_PROB* transprob, /**< transformed problem */
10466  SCIP_PROB* origprob, /**< original problem */
10467  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10468  SCIP_REOPT* reopt, /**< reoptimization data structure */
10469  SCIP_LP* lp, /**< current LP data */
10470  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10471  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10472  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10473  SCIP_VAR* vubvar, /**< variable z in x <= b*z + d */
10474  SCIP_Real vubcoef, /**< coefficient b in x <= b*z + d */
10475  SCIP_Real vubconstant, /**< constant d in x <= b*z + d */
10476  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
10477  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10478  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
10479  )
10480 {
10481  assert(var != NULL);
10482  assert(set != NULL);
10483  assert(var->scip == set->scip);
10484  assert(SCIPvarGetType(vubvar) != SCIP_VARTYPE_CONTINUOUS);
10485  assert(infeasible != NULL);
10486 
10487  SCIPsetDebugMsg(set, "adding variable upper bound <%s> <= %g<%s> + %g\n", SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
10488 
10489  *infeasible = FALSE;
10490  if( nbdchgs != NULL )
10491  *nbdchgs = 0;
10492 
10493  switch( SCIPvarGetStatus(var) )
10494  {
10496  assert(var->data.original.transvar != NULL);
10497  SCIP_CALL( SCIPvarAddVub(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10498  cliquetable, branchcand, eventqueue, vubvar, vubcoef, vubconstant, transitive, infeasible, nbdchgs) );
10499  break;
10500 
10501  case SCIP_VARSTATUS_COLUMN:
10502  case SCIP_VARSTATUS_LOOSE:
10503  case SCIP_VARSTATUS_FIXED:
10504  /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
10505  SCIP_CALL( SCIPvarGetProbvarSum(&vubvar, set, &vubcoef, &vubconstant) );
10506  SCIPsetDebugMsg(set, " -> transformed to variable upper bound <%s> <= %g<%s> + %g\n",
10507  SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
10508 
10509  /* if the vub coefficient is zero, just update the upper bound of the variable */
10510  if( SCIPsetIsZero(set, vubcoef) )
10511  {
10512  if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetLbGlobal(var)) )
10513  *infeasible = TRUE;
10514  else if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetUbGlobal(var)) )
10515  {
10516  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10517  * with the local bound, in this case we need to store the bound change as pending bound change
10518  */
10519  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10520  {
10521  assert(tree != NULL);
10522  assert(transprob != NULL);
10523  assert(SCIPprobIsTransformed(transprob));
10524 
10525  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10526  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vubconstant, SCIP_BOUNDTYPE_UPPER, FALSE) );
10527  }
10528  else
10529  {
10530  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vubconstant) );
10531  }
10532 
10533  if( nbdchgs != NULL )
10534  (*nbdchgs)++;
10535  }
10536  }
10537  else if( var == vubvar )
10538  {
10539  /* the variables cancels out, the variable bound constraint is either redundant or proves global infeasibility */
10540  if( SCIPsetIsEQ(set, vubcoef, 1.0) )
10541  {
10542  if( SCIPsetIsNegative(set, vubconstant) )
10543  *infeasible = TRUE;
10544  return SCIP_OKAY;
10545  }
10546  else
10547  {
10548  SCIP_Real lb = SCIPvarGetLbGlobal(var);
10549  SCIP_Real ub = SCIPvarGetUbGlobal(var);
10550 
10551  /* the variable bound constraint defines a new lower bound */
10552  if( SCIPsetIsGT(set, vubcoef, 1.0) )
10553  {
10554  SCIP_Real newlb = vubconstant / (1.0 - vubcoef);
10555 
10556  if( SCIPsetIsFeasGT(set, newlb, ub) )
10557  {
10558  *infeasible = TRUE;
10559  return SCIP_OKAY;
10560  }
10561  else if( SCIPsetIsFeasGT(set, newlb, lb) )
10562  {
10563  /* bound might be adjusted due to integrality condition */
10564  newlb = adjustedLb(set, SCIPvarGetType(var), newlb);
10565 
10566  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10567  * with the local bound, in this case we need to store the bound change as pending bound change
10568  */
10569  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10570  {
10571  assert(tree != NULL);
10572  assert(transprob != NULL);
10573  assert(SCIPprobIsTransformed(transprob));
10574 
10575  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10576  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10577  }
10578  else
10579  {
10580  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newlb) );
10581  }
10582 
10583  if( nbdchgs != NULL )
10584  (*nbdchgs)++;
10585  }
10586  }
10587  /* the variable bound constraint defines a new upper bound */
10588  else
10589  {
10590  SCIP_Real newub;
10591 
10592  assert(SCIPsetIsLT(set, vubcoef, 1.0));
10593 
10594  newub = vubconstant / (1.0 - vubcoef);
10595 
10596  if( SCIPsetIsFeasLT(set, newub, lb) )
10597  {
10598  *infeasible = TRUE;
10599  return SCIP_OKAY;
10600  }
10601  else if( SCIPsetIsFeasLT(set, newub, ub) )
10602  {
10603  /* bound might be adjusted due to integrality condition */
10604  newub = adjustedUb(set, SCIPvarGetType(var), newub);
10605 
10606  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10607  * with the local bound, in this case we need to store the bound change as pending bound change
10608  */
10609  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10610  {
10611  assert(tree != NULL);
10612  assert(transprob != NULL);
10613  assert(SCIPprobIsTransformed(transprob));
10614 
10615  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10616  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10617  }
10618  else
10619  {
10620  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newub) );
10621  }
10622 
10623  if( nbdchgs != NULL )
10624  (*nbdchgs)++;
10625  }
10626  }
10627  }
10628  }
10629  else if( SCIPvarIsActive(vubvar) )
10630  {
10631  SCIP_Real xlb;
10632  SCIP_Real xub;
10633  SCIP_Real zlb;
10634  SCIP_Real zub;
10635  SCIP_Real minvub;
10636  SCIP_Real maxvub;
10637 
10639  assert(vubcoef != 0.0);
10640 
10641  minvub = -SCIPsetInfinity(set);
10642  maxvub = SCIPsetInfinity(set);
10643 
10644  xlb = SCIPvarGetLbGlobal(var);
10645  xub = SCIPvarGetUbGlobal(var);
10646  zlb = SCIPvarGetLbGlobal(vubvar);
10647  zub = SCIPvarGetUbGlobal(vubvar);
10648 
10649  /* improve global bounds of vub variable, and calculate minimal and maximal value of variable bound */
10650  if( vubcoef >= 0.0 )
10651  {
10652  SCIP_Real newzlb;
10653 
10654  if( !SCIPsetIsInfinity(set, -xlb) )
10655  {
10656  /* x <= b*z + d -> z >= (x-d)/b */
10657  newzlb = (xlb - vubconstant)/vubcoef;
10658  if( SCIPsetIsFeasGT(set, newzlb, zub) )
10659  {
10660  *infeasible = TRUE;
10661  return SCIP_OKAY;
10662  }
10663  if( SCIPsetIsFeasGT(set, newzlb, zlb) )
10664  {
10665  /* bound might be adjusted due to integrality condition */
10666  newzlb = adjustedLb(set, SCIPvarGetType(vubvar), newzlb);
10667 
10668  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10669  * with the local bound, in this case we need to store the bound change as pending bound change
10670  */
10671  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10672  {
10673  assert(tree != NULL);
10674  assert(transprob != NULL);
10675  assert(SCIPprobIsTransformed(transprob));
10676 
10677  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10678  tree, reopt, lp, branchcand, eventqueue, cliquetable, vubvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10679  }
10680  else
10681  {
10682  SCIP_CALL( SCIPvarChgLbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
10683  }
10684  zlb = newzlb;
10685 
10686  if( nbdchgs != NULL )
10687  (*nbdchgs)++;
10688  }
10689  minvub = vubcoef * zlb + vubconstant;
10690  if( !SCIPsetIsInfinity(set, zub) )
10691  maxvub = vubcoef * zub + vubconstant;
10692  }
10693  else
10694  {
10695  if( !SCIPsetIsInfinity(set, zub) )
10696  maxvub = vubcoef * zub + vubconstant;
10697  if( !SCIPsetIsInfinity(set, -zlb) )
10698  minvub = vubcoef * zlb + vubconstant;
10699  }
10700  }
10701  else
10702  {
10703  SCIP_Real newzub;
10704 
10705  if( !SCIPsetIsInfinity(set, -xlb) )
10706  {
10707  /* x <= b*z + d -> z <= (x-d)/b */
10708  newzub = (xlb - vubconstant)/vubcoef;
10709  if( SCIPsetIsFeasLT(set, newzub, zlb) )
10710  {
10711  *infeasible = TRUE;
10712  return SCIP_OKAY;
10713  }
10714  if( SCIPsetIsFeasLT(set, newzub, zub) )
10715  {
10716  /* bound might be adjusted due to integrality condition */
10717  newzub = adjustedUb(set, SCIPvarGetType(vubvar), newzub);
10718 
10719  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10720  * with the local bound, in this case we need to store the bound change as pending bound change
10721  */
10722  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10723  {
10724  assert(tree != NULL);
10725  assert(transprob != NULL);
10726  assert(SCIPprobIsTransformed(transprob));
10727 
10728  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10729  tree, reopt, lp, branchcand, eventqueue, cliquetable, vubvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10730  }
10731  else
10732  {
10733  SCIP_CALL( SCIPvarChgUbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
10734  }
10735  zub = newzub;
10736 
10737  if( nbdchgs != NULL )
10738  (*nbdchgs)++;
10739  }
10740  minvub = vubcoef * zub + vubconstant;
10741  if( !SCIPsetIsInfinity(set, -zlb) )
10742  maxvub = vubcoef * zlb + vubconstant;
10743  }
10744  else
10745  {
10746  if( !SCIPsetIsInfinity(set, zub) )
10747  minvub = vubcoef * zub + vubconstant;
10748  if( !SCIPsetIsInfinity(set, -zlb) )
10749  maxvub = vubcoef * zlb + vubconstant;
10750  }
10751  }
10752  if( minvub > maxvub )
10753  minvub = maxvub;
10754 
10755  /* adjust bounds due to integrality of vub variable */
10756  minvub = adjustedUb(set, SCIPvarGetType(var), minvub);
10757  maxvub = adjustedUb(set, SCIPvarGetType(var), maxvub);
10758 
10759  /* check bounds for feasibility */
10760  if( SCIPsetIsFeasLT(set, maxvub, xlb) || (var == vubvar && SCIPsetIsEQ(set, vubcoef, 1.0) && SCIPsetIsFeasNegative(set, vubconstant)) )
10761  {
10762  *infeasible = TRUE;
10763  return SCIP_OKAY;
10764  }
10765 
10766  /* improve global upper bound of variable */
10767  if( SCIPsetIsFeasLT(set, maxvub, xub) )
10768  {
10769  /* bound might be adjusted due to integrality condition */
10770  maxvub = adjustedUb(set, SCIPvarGetType(var), maxvub);
10771 
10772  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10773  * with the local bound, in this case we need to store the bound change as pending bound change
10774  */
10775  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10776  {
10777  assert(tree != NULL);
10778  assert(transprob != NULL);
10779  assert(SCIPprobIsTransformed(transprob));
10780 
10781  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10782  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, maxvub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10783  }
10784  else
10785  {
10786  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, maxvub) );
10787  }
10788  xub = maxvub;
10789 
10790  if( nbdchgs != NULL )
10791  (*nbdchgs)++;
10792  }
10793  maxvub = xub;
10794 
10795  /* improve variable bound for binary z by moving the variable's global bound to the vub constant */
10796  if( SCIPvarIsBinary(vubvar) )
10797  {
10798  /* b > 0: x <= (maxvub - minvub) * z + minvub
10799  * b < 0: x <= (minvub - maxvub) * z + maxvub
10800  */
10801 
10802  assert(!SCIPsetIsInfinity(set, maxvub) && !SCIPsetIsInfinity(set, -minvub));
10803 
10804  if( vubcoef >= 0.0 )
10805  {
10806  vubcoef = maxvub - minvub;
10807  vubconstant = minvub;
10808  }
10809  else
10810  {
10811  vubcoef = minvub - maxvub;
10812  vubconstant = maxvub;
10813  }
10814  }
10815 
10816  /* add variable bound to the variable bounds list */
10817  if( SCIPsetIsFeasLT(set, minvub, xub) )
10818  {
10819  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED);
10820  assert(!SCIPsetIsZero(set, vubcoef));
10821 
10822  /* if one of the variables is binary, add the corresponding implication to the variable's implication
10823  * list, thereby also adding the variable bound (or implication) to the other variable
10824  */
10825  if( SCIPvarGetType(vubvar) == SCIP_VARTYPE_BINARY )
10826  {
10827  /* add corresponding implication:
10828  * b > 0, x <= b*z + d <-> z == 0 -> x <= d
10829  * b < 0, x <= b*z + d <-> z == 1 -> x <= b+d
10830  */
10831  SCIP_CALL( varAddTransitiveImplic(vubvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10832  cliquetable, branchcand, eventqueue, (vubcoef < 0.0), var, SCIP_BOUNDTYPE_UPPER, minvub, transitive,
10833  infeasible, nbdchgs) );
10834  }
10835  else if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
10836  {
10837  /* add corresponding implication:
10838  * b > 0, x <= b*z + d <-> x == 1 -> z >= (1-d)/b
10839  * b < 0, x <= b*z + d <-> x == 1 -> z <= (1-d)/b
10840  */
10841  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10842  cliquetable, branchcand, eventqueue, TRUE, vubvar, (vubcoef >= 0.0 ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER),
10843  (1.0-vubconstant)/vubcoef, transitive, infeasible, nbdchgs) );
10844  }
10845  else
10846  {
10847  SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, vubvar, vubcoef, vubconstant) );
10848  }
10849  }
10850  }
10851  break;
10852 
10854  /* x = a*y + c: x <= b*z + d <=> a*y + c <= b*z + d <=> y <= b/a * z + (d-c)/a, if a > 0
10855  * y >= b/a * z + (d-c)/a, if a < 0
10856  */
10857  assert(var->data.aggregate.var != NULL);
10858  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
10859  {
10860  /* a > 0 -> add variable upper bound */
10861  SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10862  cliquetable, branchcand, eventqueue, vubvar, vubcoef/var->data.aggregate.scalar,
10863  (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10864  }
10865  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
10866  {
10867  /* a < 0 -> add variable lower bound */
10868  SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10869  cliquetable, branchcand, eventqueue, vubvar, vubcoef/var->data.aggregate.scalar,
10870  (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10871  }
10872  else
10873  {
10874  SCIPerrorMessage("scalar is zero in aggregation\n");
10875  return SCIP_INVALIDDATA;
10876  }
10877  break;
10878 
10880  /* nothing to do here */
10881  break;
10882 
10884  /* x = offset - x': x <= b*z + d <=> offset - x' <= b*z + d <=> x' >= -b*z + (offset-d) */
10885  assert(var->negatedvar != NULL);
10887  assert(var->negatedvar->negatedvar == var);
10888  SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10889  branchcand, eventqueue, vubvar, -vubcoef, var->data.negate.constant - vubconstant, transitive, infeasible,
10890  nbdchgs) );
10891  break;
10892 
10893  default:
10894  SCIPerrorMessage("unknown variable status\n");
10895  return SCIP_INVALIDDATA;
10896  }
10897 
10898  return SCIP_OKAY;
10899 }
10900 
10901 /** informs binary variable x about a globally valid implication: x == 0 or x == 1 ==> y <= b or y >= b;
10902  * also adds the corresponding implication or variable bound to the implied variable;
10903  * if the implication is conflicting, the variable is fixed to the opposite value;
10904  * if the variable is already fixed to the given value, the implication is performed immediately;
10905  * if the implication is redundant with respect to the variables' global bounds, it is ignored
10906  */
10908  SCIP_VAR* var, /**< problem variable */
10909  BMS_BLKMEM* blkmem, /**< block memory */
10910  SCIP_SET* set, /**< global SCIP settings */
10911  SCIP_STAT* stat, /**< problem statistics */
10912  SCIP_PROB* transprob, /**< transformed problem */
10913  SCIP_PROB* origprob, /**< original problem */
10914  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10915  SCIP_REOPT* reopt, /**< reoptimization data structure */
10916  SCIP_LP* lp, /**< current LP data */
10917  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10918  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10919  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10920  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
10921  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
10922  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
10923  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
10924  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
10925  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10926  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
10927  )
10928 {
10929  assert(var != NULL);
10930  assert(set != NULL);
10931  assert(var->scip == set->scip);
10932  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
10933  assert(infeasible != NULL);
10934 
10935  *infeasible = FALSE;
10936  if( nbdchgs != NULL )
10937  *nbdchgs = 0;
10938 
10939  switch( SCIPvarGetStatus(var) )
10940  {
10942  assert(var->data.original.transvar != NULL);
10943  SCIP_CALL( SCIPvarAddImplic(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10944  cliquetable, branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible,
10945  nbdchgs) );
10946  break;
10947 
10948  case SCIP_VARSTATUS_COLUMN:
10949  case SCIP_VARSTATUS_LOOSE:
10950  /* if the variable is fixed (although it has no FIXED status), and varfixing corresponds to the fixed value of
10951  * the variable, the implication can be applied directly;
10952  * otherwise, add implication to the implications list (and add inverse of implication to the implied variable)
10953  */
10954  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
10955  {
10956  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
10957  {
10958  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
10959  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
10960  }
10961  }
10962  else
10963  {
10964  SCIP_CALL( SCIPvarGetProbvarBound(&implvar, &implbound, &impltype) );
10965  SCIPvarAdjustBd(implvar, set, impltype, &implbound);
10966  if( SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED )
10967  {
10968  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10969  branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
10970  }
10971  }
10972  break;
10973 
10974  case SCIP_VARSTATUS_FIXED:
10975  /* if varfixing corresponds to the fixed value of the variable, the implication can be applied directly */
10976  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
10977  {
10978  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
10979  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
10980  }
10981  break;
10982 
10984  /* implication added for x == 1:
10985  * x == 1 && x = 1*z + 0 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10986  * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10987  * implication added for x == 0:
10988  * x == 0 && x = 1*z + 0 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10989  * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10990  *
10991  * use only binary variables z
10992  */
10993  assert(var->data.aggregate.var != NULL);
10994  if( SCIPvarIsBinary(var->data.aggregate.var) )
10995  {
10996  assert( (SCIPsetIsEQ(set, var->data.aggregate.scalar, 1.0) && SCIPsetIsZero(set, var->data.aggregate.constant))
10997  || (SCIPsetIsEQ(set, var->data.aggregate.scalar, -1.0) && SCIPsetIsEQ(set, var->data.aggregate.constant, 1.0)) );
10998 
10999  if( var->data.aggregate.scalar > 0 )
11000  {
11001  SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11002  cliquetable, branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible,
11003  nbdchgs) );
11004  }
11005  else
11006  {
11007  SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11008  cliquetable, branchcand, eventqueue, !varfixing, implvar, impltype, implbound, transitive, infeasible,
11009  nbdchgs) );
11010  }
11011  }
11012  break;
11013 
11015  /* nothing to do here */
11016  break;
11017 
11019  /* implication added for x == 1:
11020  * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
11021  * implication added for x == 0:
11022  * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
11023  */
11024  assert(var->negatedvar != NULL);
11026  assert(var->negatedvar->negatedvar == var);
11027  assert(SCIPvarIsBinary(var->negatedvar));
11028 
11030  {
11031  SCIP_CALL( SCIPvarAddImplic(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11032  cliquetable, branchcand, eventqueue, !varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
11033  }
11034  /* in case one both variables are not of binary type we have to add the implication as variable bounds */
11035  else
11036  {
11037  /* if the implied variable is of binary type exchange the variables */
11038  if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
11039  {
11040  SCIP_CALL( SCIPvarAddImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
11041  branchcand, eventqueue, (impltype == SCIP_BOUNDTYPE_UPPER) ? TRUE : FALSE, var->negatedvar,
11042  varfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER, varfixing ? 1.0 : 0.0, transitive,
11043  infeasible, nbdchgs) );
11044  }
11045  else
11046  {
11047  /* both variables are not of binary type but are implicit binary; in that case we can only add this
11048  * implication as variable bounds
11049  */
11050 
11051  /* add variable lower bound on the negation of var */
11052  if( varfixing )
11053  {
11054  /* (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
11055  * as variable lower bound
11056  */
11057  SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11058  cliquetable, branchcand, eventqueue, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : -1.0,
11059  (impltype == SCIP_BOUNDTYPE_UPPER) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
11060  }
11061  else
11062  {
11063  /* (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
11064  * as variable upper bound
11065  */
11066  SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11067  cliquetable, branchcand, eventqueue, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? -1.0 : 1.0,
11068  (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : 0.0, transitive, infeasible, nbdchgs) );
11069  }
11070 
11071  /* add variable bound on implvar */
11072  if( impltype == SCIP_BOUNDTYPE_UPPER )
11073  {
11074  /* (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
11075  * as variable upper bound
11076  */
11077  SCIP_CALL( SCIPvarAddVub(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
11078  branchcand, eventqueue, var->negatedvar, (varfixing) ? 1.0 : -1.0,
11079  (varfixing) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
11080  }
11081  else
11082  {
11083  /* (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
11084  * as variable upper bound
11085  */
11086  SCIP_CALL( SCIPvarAddVlb(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
11087  branchcand, eventqueue, var->negatedvar, (varfixing) ? -1.0 : 1.0, (varfixing) ? 1.0 : 0.0,
11088  transitive, infeasible, nbdchgs) );
11089  }
11090  }
11091  }
11092  break;
11093 
11094  default:
11095  SCIPerrorMessage("unknown variable status\n");
11096  return SCIP_INVALIDDATA;
11097  }
11098 
11099  return SCIP_OKAY;
11100 }
11101 
11102 /** returns whether there is an implication x == varfixing -> y <= b or y >= b in the implication graph;
11103  * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
11104  * both variables must be active, variable x must be binary
11105  */
11107  SCIP_VAR* var, /**< problem variable x */
11108  SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
11109  SCIP_VAR* implvar, /**< variable y to search for */
11110  SCIP_BOUNDTYPE impltype /**< type of implication y <=/>= b to search for */
11111  )
11112 {
11113  assert(var != NULL);
11114  assert(implvar != NULL);
11115  assert(SCIPvarIsActive(var));
11116  assert(SCIPvarIsActive(implvar));
11117  assert(SCIPvarIsBinary(var));
11118 
11119  return var->implics != NULL && SCIPimplicsContainsImpl(var->implics, varfixing, implvar, impltype);
11120 }
11121 
11122 /** returns whether there is an implication x == varfixing -> y == implvarfixing in the implication graph;
11123  * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
11124  * both variables must be active binary variables
11125  */
11127  SCIP_VAR* var, /**< problem variable x */
11128  SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
11129  SCIP_VAR* implvar, /**< variable y to search for */
11130  SCIP_Bool implvarfixing /**< value of the implied variable to search for */
11131  )
11132 {
11133  assert(SCIPvarIsBinary(implvar));
11134 
11135  return SCIPvarHasImplic(var, varfixing, implvar, implvarfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER);
11136 }
11137 
11138 /** gets the values of b in implications x == varfixing -> y <= b or y >= b in the implication graph;
11139  * the values are set to SCIP_INVALID if there is no implied bound
11140  */
11142  SCIP_VAR* var, /**< problem variable x */
11143  SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
11144  SCIP_VAR* implvar, /**< variable y to search for */
11145  SCIP_Real* lb, /**< buffer to store the value of the implied lower bound */
11146  SCIP_Real* ub /**< buffer to store the value of the implied upper bound */
11147  )
11148 {
11149  int lowerpos;
11150  int upperpos;
11151  SCIP_Real* bounds;
11152 
11153  assert(lb != NULL);
11154  assert(ub != NULL);
11155 
11156  *lb = SCIP_INVALID;
11157  *ub = SCIP_INVALID;
11158 
11159  if( var->implics == NULL )
11160  return;
11161 
11162  SCIPimplicsGetVarImplicPoss(var->implics, varfixing, implvar, &lowerpos, &upperpos);
11163  bounds = SCIPvarGetImplBounds(var, varfixing);
11164 
11165  if( bounds == NULL )
11166  return;
11167 
11168  if( lowerpos >= 0 )
11169  *lb = bounds[lowerpos];
11170 
11171  if( upperpos >= 0 )
11172  *ub = bounds[upperpos];
11173 }
11174 
11175 
11176 /** fixes the bounds of a binary variable to the given value, counting bound changes and detecting infeasibility */
11178  SCIP_VAR* var, /**< problem variable */
11179  BMS_BLKMEM* blkmem, /**< block memory */
11180  SCIP_SET* set, /**< global SCIP settings */
11181  SCIP_STAT* stat, /**< problem statistics */
11182  SCIP_PROB* transprob, /**< transformed problem */
11183  SCIP_PROB* origprob, /**< original problem */
11184  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
11185  SCIP_REOPT* reopt, /**< reoptimization data structure */
11186  SCIP_LP* lp, /**< current LP data */
11187  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
11188  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
11189  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11190  SCIP_Bool value, /**< value to fix variable to */
11191  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
11192  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
11193  )
11194 {
11195  assert(var != NULL);
11196  assert(set != NULL);
11197  assert(var->scip == set->scip);
11198  assert(infeasible != NULL);
11199 
11200  *infeasible = FALSE;
11201 
11202  if( value == FALSE )
11203  {
11204  if( var->glbdom.lb > 0.5 )
11205  *infeasible = TRUE;
11206  else if( var->glbdom.ub > 0.5 )
11207  {
11208  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
11209  * with the local bound, in this case we need to store the bound change as pending bound change
11210  */
11211  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
11212  {
11213  assert(tree != NULL);
11214  assert(transprob != NULL);
11215  assert(SCIPprobIsTransformed(transprob));
11216 
11217  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
11218  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
11219  }
11220  else
11221  {
11222  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
11223  }
11224 
11225  if( nbdchgs != NULL )
11226  (*nbdchgs)++;
11227  }
11228  }
11229  else
11230  {
11231  if( var->glbdom.ub < 0.5 )
11232  *infeasible = TRUE;
11233  else if( var->glbdom.lb < 0.5 )
11234  {
11235  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
11236  * with the local bound, in this case we need to store the bound change as pending bound change
11237  */
11238  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
11239  {
11240  assert(tree != NULL);
11241  assert(transprob != NULL);
11242  assert(SCIPprobIsTransformed(transprob));
11243 
11244  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
11245  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
11246  }
11247  else
11248  {
11249  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
11250  }
11251 
11252  if( nbdchgs != NULL )
11253  (*nbdchgs)++;
11254  }
11255  }
11256 
11257  /* during presolving, the variable should have been removed immediately from all its cliques */
11258  assert(SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING || var->cliquelist == NULL);
11259 
11260  return SCIP_OKAY;
11261 }
11262 
11263 /** adds the variable to the given clique and updates the list of cliques the binary variable is member of;
11264  * if the variable now appears twice in the clique with the same value, it is fixed to the opposite value;
11265  * if the variable now appears twice in the clique with opposite values, all other variables are fixed to
11266  * the opposite of the value they take in the clique
11267  */
11269  SCIP_VAR* var, /**< problem variable */
11270  BMS_BLKMEM* blkmem, /**< block memory */
11271  SCIP_SET* set, /**< global SCIP settings */
11272  SCIP_STAT* stat, /**< problem statistics */
11273  SCIP_PROB* transprob, /**< transformed problem */
11274  SCIP_PROB* origprob, /**< original problem */
11275  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
11276  SCIP_REOPT* reopt, /**< reoptimization data structure */
11277  SCIP_LP* lp, /**< current LP data */
11278  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
11279  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
11280  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11281  SCIP_Bool value, /**< value of the variable in the clique */
11282  SCIP_CLIQUE* clique, /**< clique the variable should be added to */
11283  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
11284  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
11285  )
11286 {
11287  assert(var != NULL);
11288  assert(set != NULL);
11289  assert(var->scip == set->scip);
11290  assert(SCIPvarIsBinary(var));
11291  assert(infeasible != NULL);
11292 
11293  *infeasible = FALSE;
11294 
11295  /* get corresponding active problem variable */
11296  SCIP_CALL( SCIPvarGetProbvarBinary(&var, &value) );
11301  assert(SCIPvarIsBinary(var));
11302 
11303  /* only column and loose variables may be member of a clique */
11305  {
11306  SCIP_Bool doubleentry;
11307  SCIP_Bool oppositeentry;
11308 
11309  /* add variable to clique */
11310  SCIP_CALL( SCIPcliqueAddVar(clique, blkmem, set, var, value, &doubleentry, &oppositeentry) );
11311 
11312  /* add clique to variable's clique list */
11313  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
11314 
11315  /* check consistency of cliquelist */
11316  SCIPcliquelistCheck(var->cliquelist, var);
11317 
11318  /* if the variable now appears twice with the same value in the clique, it can be fixed to the opposite value */
11319  if( doubleentry )
11320  {
11321  SCIP_CALL( SCIPvarFixBinary(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
11322  eventqueue, cliquetable, !value, infeasible, nbdchgs) );
11323  }
11324 
11325  /* if the variable appears with both values in the clique, all other variables of the clique can be fixed
11326  * to the opposite of the value they take in the clique
11327  */
11328  if( oppositeentry )
11329  {
11330  SCIP_VAR** vars;
11331  SCIP_Bool* values;
11332  int nvars;
11333  int i;
11334 
11335  nvars = SCIPcliqueGetNVars(clique);
11336  vars = SCIPcliqueGetVars(clique);
11337  values = SCIPcliqueGetValues(clique);
11338  for( i = 0; i < nvars && !(*infeasible); ++i )
11339  {
11340  if( vars[i] == var )
11341  continue;
11342 
11343  SCIP_CALL( SCIPvarFixBinary(vars[i], blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
11344  eventqueue, cliquetable, !values[i], infeasible, nbdchgs) );
11345  }
11346  }
11347  }
11348 
11349  return SCIP_OKAY;
11350 }
11351 
11352 /** adds a filled clique to the cliquelists of all corresponding variables */
11354  SCIP_VAR** vars, /**< problem variables */
11355  SCIP_Bool* values, /**< values of the variables in the clique */
11356  int nvars, /**< number of problem variables */
11357  BMS_BLKMEM* blkmem, /**< block memory */
11358  SCIP_SET* set, /**< global SCIP settings */
11359  SCIP_CLIQUE* clique /**< clique that contains all given variables and values */
11360  )
11361 {
11362  SCIP_VAR* var;
11363  int v;
11364 
11365  assert(vars != NULL);
11366  assert(values != NULL);
11367  assert(nvars > 0);
11368  assert(set != NULL);
11369  assert(blkmem != NULL);
11370  assert(clique != NULL);
11371 
11372  for( v = nvars - 1; v >= 0; --v )
11373  {
11374  var = vars[v];
11375  assert(SCIPvarIsBinary(var));
11377 
11378  /* add clique to variable's clique list */
11379  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, values[v], clique) );
11380 
11381  /* check consistency of cliquelist */
11382  SCIPcliquelistCheck(var->cliquelist, var);
11383  }
11384 
11385  return SCIP_OKAY;
11386 }
11387 
11388 /** adds a clique to the list of cliques of the given binary variable, but does not change the clique
11389  * itself
11390  */
11392  SCIP_VAR* var, /**< problem variable */
11393  BMS_BLKMEM* blkmem, /**< block memory */
11394  SCIP_SET* set, /**< global SCIP settings */
11395  SCIP_Bool value, /**< value of the variable in the clique */
11396  SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
11397  )
11398 {
11399  assert(var != NULL);
11400  assert(SCIPvarIsBinary(var));
11402 
11403  /* add clique to variable's clique list */
11404  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
11405 
11406  return SCIP_OKAY;
11407 }
11408 
11409 
11410 /** deletes a clique from the list of cliques the binary variable is member of, but does not change the clique
11411  * itself
11412  */
11414  SCIP_VAR* var, /**< problem variable */
11415  BMS_BLKMEM* blkmem, /**< block memory */
11416  SCIP_Bool value, /**< value of the variable in the clique */
11417  SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
11418  )
11419 {
11420  assert(var != NULL);
11421  assert(SCIPvarIsBinary(var));
11422 
11423  /* delete clique from variable's clique list */
11424  SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
11425 
11426  return SCIP_OKAY;
11427 }
11428 
11429 /** deletes the variable from the given clique and updates the list of cliques the binary variable is member of */
11431  SCIP_VAR* var, /**< problem variable */
11432  BMS_BLKMEM* blkmem, /**< block memory */
11433  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11434  SCIP_Bool value, /**< value of the variable in the clique */
11435  SCIP_CLIQUE* clique /**< clique the variable should be removed from */
11436  )
11437 {
11438  assert(var != NULL);
11439  assert(SCIPvarIsBinary(var));
11440 
11441  /* get corresponding active problem variable */
11442  SCIP_CALL( SCIPvarGetProbvarBinary(&var, &value) );
11447  assert(SCIPvarIsBinary(var));
11448 
11449  /* only column and loose variables may be member of a clique */
11451  {
11452  /* delete clique from variable's clique list */
11453  SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
11454 
11455  /* delete variable from clique */
11456  SCIPcliqueDelVar(clique, cliquetable, var, value);
11457 
11458  /* check consistency of cliquelist */
11459  SCIPcliquelistCheck(var->cliquelist, var);
11460  }
11461 
11462  return SCIP_OKAY;
11463 }
11464 
11465 /** returns whether there is a clique that contains both given variable/value pairs;
11466  * the variables must be active binary variables;
11467  * if regardimplics is FALSE, only the cliques in the clique table are looked at;
11468  * if regardimplics is TRUE, both the cliques and the implications of the implication graph are regarded
11469  *
11470  * @note a variable with it's negated variable are NOT! in a clique
11471  * @note a variable with itself are in a clique
11472  */
11474  SCIP_VAR* var1, /**< first variable */
11475  SCIP_Bool value1, /**< value of first variable */
11476  SCIP_VAR* var2, /**< second variable */
11477  SCIP_Bool value2, /**< value of second variable */
11478  SCIP_Bool regardimplics /**< should the implication graph also be searched for a clique? */
11479  )
11480 {
11481  assert(var1 != NULL);
11482  assert(var2 != NULL);
11483  assert(SCIPvarIsActive(var1));
11484  assert(SCIPvarIsActive(var2));
11485  assert(SCIPvarIsBinary(var1));
11486  assert(SCIPvarIsBinary(var2));
11487 
11488  return (SCIPcliquelistsHaveCommonClique(var1->cliquelist, value1, var2->cliquelist, value2)
11489  || (regardimplics && SCIPvarHasImplic(var1, value1, var2, value2 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER)));
11490 }
11491 
11492 /** actually changes the branch factor of the variable and of all parent variables */
11493 static
11495  SCIP_VAR* var, /**< problem variable */
11496  SCIP_SET* set, /**< global SCIP settings */
11497  SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
11498  )
11499 {
11500  SCIP_VAR* parentvar;
11501  SCIP_Real eps;
11502  int i;
11503 
11504  assert(var != NULL);
11505  assert(set != NULL);
11506  assert(var->scip == set->scip);
11507 
11508  /* only use positive values */
11509  eps = SCIPsetEpsilon(set);
11510  branchfactor = MAX(branchfactor, eps);
11511 
11512  SCIPsetDebugMsg(set, "process changing branch factor of <%s> from %f to %f\n", var->name, var->branchfactor, branchfactor);
11513 
11514  if( SCIPsetIsEQ(set, branchfactor, var->branchfactor) )
11515  return SCIP_OKAY;
11516 
11517  /* change the branch factor */
11518  var->branchfactor = branchfactor;
11519 
11520  /* process parent variables */
11521  for( i = 0; i < var->nparentvars; ++i )
11522  {
11523  parentvar = var->parentvars[i];
11524  assert(parentvar != NULL);
11525 
11526  switch( SCIPvarGetStatus(parentvar) )
11527  {
11529  /* do not change priorities across the border between transformed and original problem */
11530  break;
11531 
11532  case SCIP_VARSTATUS_COLUMN:
11533  case SCIP_VARSTATUS_LOOSE:
11534  case SCIP_VARSTATUS_FIXED:
11536  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11537  SCIPABORT();
11538  return SCIP_INVALIDDATA; /*lint !e527*/
11539 
11542  SCIP_CALL( varProcessChgBranchFactor(parentvar, set, branchfactor) );
11543  break;
11544 
11545  default:
11546  SCIPerrorMessage("unknown variable status\n");
11547  SCIPABORT();
11548  return SCIP_ERROR; /*lint !e527*/
11549  }
11550  }
11551 
11552  return SCIP_OKAY;
11553 }
11554 
11555 /** sets the branch factor of the variable; this value can be used in the branching methods to scale the score
11556  * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
11557  */
11559  SCIP_VAR* var, /**< problem variable */
11560  SCIP_SET* set, /**< global SCIP settings */
11561  SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
11562  )
11563 {
11564  int v;
11565 
11566  assert(var != NULL);
11567  assert(set != NULL);
11568  assert(var->scip == set->scip);
11569  assert(branchfactor >= 0.0);
11570 
11571  SCIPdebugMessage("changing branch factor of <%s> from %g to %g\n", var->name, var->branchfactor, branchfactor);
11572 
11573  if( SCIPsetIsEQ(set, var->branchfactor, branchfactor) )
11574  return SCIP_OKAY;
11575 
11576  /* change priorities of attached variables */
11577  switch( SCIPvarGetStatus(var) )
11578  {
11580  if( var->data.original.transvar != NULL )
11581  {
11582  SCIP_CALL( SCIPvarChgBranchFactor(var->data.original.transvar, set, branchfactor) );
11583  }
11584  else
11585  {
11586  assert(set->stage == SCIP_STAGE_PROBLEM);
11587  var->branchfactor = branchfactor;
11588  }
11589  break;
11590 
11591  case SCIP_VARSTATUS_COLUMN:
11592  case SCIP_VARSTATUS_LOOSE:
11593  case SCIP_VARSTATUS_FIXED:
11594  SCIP_CALL( varProcessChgBranchFactor(var, set, branchfactor) );
11595  break;
11596 
11598  assert(!var->donotaggr);
11599  assert(var->data.aggregate.var != NULL);
11600  SCIP_CALL( SCIPvarChgBranchFactor(var->data.aggregate.var, set, branchfactor) );
11601  break;
11602 
11604  assert(!var->donotmultaggr);
11605  for( v = 0; v < var->data.multaggr.nvars; ++v )
11606  {
11607  SCIP_CALL( SCIPvarChgBranchFactor(var->data.multaggr.vars[v], set, branchfactor) );
11608  }
11609  break;
11610 
11612  assert(var->negatedvar != NULL);
11614  assert(var->negatedvar->negatedvar == var);
11615  SCIP_CALL( SCIPvarChgBranchFactor(var->negatedvar, set, branchfactor) );
11616  break;
11617 
11618  default:
11619  SCIPerrorMessage("unknown variable status\n");
11620  SCIPABORT();
11621  return SCIP_ERROR; /*lint !e527*/
11622  }
11623 
11624  return SCIP_OKAY;
11625 }
11626 
11627 /** actually changes the branch priority of the variable and of all parent variables */
11628 static
11630  SCIP_VAR* var, /**< problem variable */
11631  int branchpriority /**< branching priority of the variable */
11632  )
11633 {
11634  SCIP_VAR* parentvar;
11635  int i;
11636 
11637  assert(var != NULL);
11638 
11639  SCIPdebugMessage("process changing branch priority of <%s> from %d to %d\n",
11640  var->name, var->branchpriority, branchpriority);
11641 
11642  if( branchpriority == var->branchpriority )
11643  return SCIP_OKAY;
11644 
11645  /* change the branch priority */
11646  var->branchpriority = branchpriority;
11647 
11648  /* process parent variables */
11649  for( i = 0; i < var->nparentvars; ++i )
11650  {
11651  parentvar = var->parentvars[i];
11652  assert(parentvar != NULL);
11653 
11654  switch( SCIPvarGetStatus(parentvar) )
11655  {
11657  /* do not change priorities across the border between transformed and original problem */
11658  break;
11659 
11660  case SCIP_VARSTATUS_COLUMN:
11661  case SCIP_VARSTATUS_LOOSE:
11662  case SCIP_VARSTATUS_FIXED:
11664  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11665  SCIPABORT();
11666  return SCIP_INVALIDDATA; /*lint !e527*/
11667 
11670  SCIP_CALL( varProcessChgBranchPriority(parentvar, branchpriority) );
11671  break;
11672 
11673  default:
11674  SCIPerrorMessage("unknown variable status\n");
11675  return SCIP_ERROR;
11676  }
11677  }
11678 
11679  return SCIP_OKAY;
11680 }
11681 
11682 /** sets the branch priority of the variable; variables with higher branch priority are always preferred to variables
11683  * with lower priority in selection of branching variable
11684  */
11686  SCIP_VAR* var, /**< problem variable */
11687  int branchpriority /**< branching priority of the variable */
11688  )
11689 {
11690  int v;
11691 
11692  assert(var != NULL);
11693 
11694  SCIPdebugMessage("changing branch priority of <%s> from %d to %d\n", var->name, var->branchpriority, branchpriority);
11695 
11696  if( var->branchpriority == branchpriority )
11697  return SCIP_OKAY;
11698 
11699  /* change priorities of attached variables */
11700  switch( SCIPvarGetStatus(var) )
11701  {
11703  if( var->data.original.transvar != NULL )
11704  {
11705  SCIP_CALL( SCIPvarChgBranchPriority(var->data.original.transvar, branchpriority) );
11706  }
11707  else
11708  var->branchpriority = branchpriority;
11709  break;
11710 
11711  case SCIP_VARSTATUS_COLUMN:
11712  case SCIP_VARSTATUS_LOOSE:
11713  case SCIP_VARSTATUS_FIXED:
11714  SCIP_CALL( varProcessChgBranchPriority(var, branchpriority) );
11715  break;
11716 
11718  assert(!var->donotaggr);
11719  assert(var->data.aggregate.var != NULL);
11720  SCIP_CALL( SCIPvarChgBranchPriority(var->data.aggregate.var, branchpriority) );
11721  break;
11722 
11724  assert(!var->donotmultaggr);
11725  for( v = 0; v < var->data.multaggr.nvars; ++v )
11726  {
11727  SCIP_CALL( SCIPvarChgBranchPriority(var->data.multaggr.vars[v], branchpriority) );
11728  }
11729  break;
11730 
11732  assert(var->negatedvar != NULL);
11734  assert(var->negatedvar->negatedvar == var);
11735  SCIP_CALL( SCIPvarChgBranchPriority(var->negatedvar, branchpriority) );
11736  break;
11737 
11738  default:
11739  SCIPerrorMessage("unknown variable status\n");
11740  SCIPABORT();
11741  return SCIP_ERROR; /*lint !e527*/
11742  }
11743 
11744  return SCIP_OKAY;
11745 }
11746 
11747 /** actually changes the branch direction of the variable and of all parent variables */
11748 static
11750  SCIP_VAR* var, /**< problem variable */
11751  SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
11752  )
11753 {
11754  SCIP_VAR* parentvar;
11755  int i;
11756 
11757  assert(var != NULL);
11758 
11759  SCIPdebugMessage("process changing branch direction of <%s> from %u to %d\n",
11760  var->name, var->branchdirection, branchdirection);
11761 
11762  if( branchdirection == (SCIP_BRANCHDIR)var->branchdirection )
11763  return SCIP_OKAY;
11764 
11765  /* change the branch direction */
11766  var->branchdirection = branchdirection; /*lint !e641*/
11767 
11768  /* process parent variables */
11769  for( i = 0; i < var->nparentvars; ++i )
11770  {
11771  parentvar = var->parentvars[i];
11772  assert(parentvar != NULL);
11773 
11774  switch( SCIPvarGetStatus(parentvar) )
11775  {
11777  /* do not change directions across the border between transformed and original problem */
11778  break;
11779 
11780  case SCIP_VARSTATUS_COLUMN:
11781  case SCIP_VARSTATUS_LOOSE:
11782  case SCIP_VARSTATUS_FIXED:
11784  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11785  SCIPABORT();
11786  return SCIP_INVALIDDATA; /*lint !e527*/
11787 
11789  if( parentvar->data.aggregate.scalar > 0.0 )
11790  {
11791  SCIP_CALL( varProcessChgBranchDirection(parentvar, branchdirection) );
11792  }
11793  else
11794  {
11795  SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
11796  }
11797  break;
11798 
11800  SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
11801  break;
11802 
11803  default:
11804  SCIPerrorMessage("unknown variable status\n");
11805  SCIPABORT();
11806  return SCIP_ERROR; /*lint !e527*/
11807  }
11808  }
11809 
11810  return SCIP_OKAY;
11811 }
11812 
11813 /** sets the branch direction of the variable; variables with higher branch direction are always preferred to variables
11814  * with lower direction in selection of branching variable
11815  */
11817  SCIP_VAR* var, /**< problem variable */
11818  SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
11819  )
11820 {
11821  int v;
11822 
11823  assert(var != NULL);
11824 
11825  SCIPdebugMessage("changing branch direction of <%s> from %u to %d\n", var->name, var->branchdirection, branchdirection);
11826 
11827  if( (SCIP_BRANCHDIR)var->branchdirection == branchdirection )
11828  return SCIP_OKAY;
11829 
11830  /* change directions of attached variables */
11831  switch( SCIPvarGetStatus(var) )
11832  {
11834  if( var->data.original.transvar != NULL )
11835  {
11836  SCIP_CALL( SCIPvarChgBranchDirection(var->data.original.transvar, branchdirection) );
11837  }
11838  else
11839  var->branchdirection = branchdirection; /*lint !e641*/
11840  break;
11841 
11842  case SCIP_VARSTATUS_COLUMN:
11843  case SCIP_VARSTATUS_LOOSE:
11844  case SCIP_VARSTATUS_FIXED:
11845  SCIP_CALL( varProcessChgBranchDirection(var, branchdirection) );
11846  break;
11847 
11849  assert(!var->donotaggr);
11850  assert(var->data.aggregate.var != NULL);
11851  if( var->data.aggregate.scalar > 0.0 )
11852  {
11853  SCIP_CALL( SCIPvarChgBranchDirection(var->data.aggregate.var, branchdirection) );
11854  }
11855  else
11856  {
11858  }
11859  break;
11860 
11862  assert(!var->donotmultaggr);
11863  for( v = 0; v < var->data.multaggr.nvars; ++v )
11864  {
11865  /* only update branching direction of aggregation variables, if they don't have a preferred direction yet */
11866  assert(var->data.multaggr.vars[v] != NULL);
11868  {
11869  if( var->data.multaggr.scalars[v] > 0.0 )
11870  {
11871  SCIP_CALL( SCIPvarChgBranchDirection(var->data.multaggr.vars[v], branchdirection) );
11872  }
11873  else
11874  {
11876  }
11877  }
11878  }
11879  break;
11880 
11882  assert(var->negatedvar != NULL);
11884  assert(var->negatedvar->negatedvar == var);
11886  break;
11887 
11888  default:
11889  SCIPerrorMessage("unknown variable status\n");
11890  SCIPABORT();
11891  return SCIP_ERROR; /*lint !e527*/
11892  }
11893 
11894  return SCIP_OKAY;
11895 }
11896 
11897 /** compares the index of two variables, only active, fixed or negated variables are allowed, if a variable
11898  * is negated then the index of the corresponding active variable is taken, returns -1 if first is
11899  * smaller than, and +1 if first is greater than second variable index; returns 0 if both indices
11900  * are equal, which means both variables are equal
11901  */
11903  SCIP_VAR* var1, /**< first problem variable */
11904  SCIP_VAR* var2 /**< second problem variable */
11905  )
11906 {
11907  assert(var1 != NULL);
11908  assert(var2 != NULL);
11911 
11913  var1 = SCIPvarGetNegatedVar(var1);
11915  var2 = SCIPvarGetNegatedVar(var2);
11916 
11917  assert(var1 != NULL);
11918  assert(var2 != NULL);
11919 
11920  if( SCIPvarGetIndex(var1) < SCIPvarGetIndex(var2) )
11921  return -1;
11922  else if( SCIPvarGetIndex(var1) > SCIPvarGetIndex(var2) )
11923  return +1;
11924 
11925  assert(var1 == var2);
11926  return 0;
11927 }
11928 
11929 /** comparison method for sorting active and negated variables by non-decreasing index, active and negated
11930  * variables are handled as the same variables
11931  */
11932 SCIP_DECL_SORTPTRCOMP(SCIPvarCompActiveAndNegated)
11934  return SCIPvarCompareActiveAndNegated((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
11935 }
11936 
11937 /** compares the index of two variables, returns -1 if first is smaller than, and +1 if first is greater than second
11938  * variable index; returns 0 if both indices are equal, which means both variables are equal
11939  */
11940 int SCIPvarCompare(
11941  SCIP_VAR* var1, /**< first problem variable */
11942  SCIP_VAR* var2 /**< second problem variable */
11943  )
11944 {
11945  assert(var1 != NULL);
11946  assert(var2 != NULL);
11947 
11948  if( var1->index < var2->index )
11949  return -1;
11950  else if( var1->index > var2->index )
11951  return +1;
11952  else
11953  {
11954  assert(var1 == var2);
11955  return 0;
11956  }
11957 }
11958 
11959 /** comparison method for sorting variables by non-decreasing index */
11960 SCIP_DECL_SORTPTRCOMP(SCIPvarComp)
11962  return SCIPvarCompare((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
11963 }
11964 
11965 /** comparison method for sorting variables by non-decreasing objective coefficient */
11966 SCIP_DECL_SORTPTRCOMP(SCIPvarCompObj)
11968  SCIP_Real obj1;
11969  SCIP_Real obj2;
11970 
11971  obj1 = SCIPvarGetObj((SCIP_VAR*)elem1);
11972  obj2 = SCIPvarGetObj((SCIP_VAR*)elem2);
11973 
11974  if( obj1 < obj2 )
11975  return -1;
11976  else if( obj1 > obj2 )
11977  return +1;
11978  else
11979  return 0;
11980 }
11981 
11982 /** hash key retrieval function for variables */
11983 SCIP_DECL_HASHGETKEY(SCIPvarGetHashkey)
11984 { /*lint --e{715}*/
11985  return elem;
11986 }
11987 
11988 /** returns TRUE iff the indices of both variables are equal */
11989 SCIP_DECL_HASHKEYEQ(SCIPvarIsHashkeyEq)
11990 { /*lint --e{715}*/
11991  if( key1 == key2 )
11992  return TRUE;
11993  return FALSE;
11994 }
11995 
11996 /** returns the hash value of the key */
11997 SCIP_DECL_HASHKEYVAL(SCIPvarGetHashkeyVal)
11998 { /*lint --e{715}*/
11999  assert( SCIPvarGetIndex((SCIP_VAR*) key) >= 0 );
12000  return (unsigned int) SCIPvarGetIndex((SCIP_VAR*) key);
12001 }
12002 
12003 /** return for given variables all their active counterparts; all active variables will be pairwise different */
12005  SCIP_SET* set, /**< global SCIP settings */
12006  SCIP_VAR** vars, /**< variable array with given variables and as output all active
12007  * variables, if enough slots exist
12008  */
12009  int* nvars, /**< number of given variables, and as output number of active variables,
12010  * if enough slots exist
12011  */
12012  int varssize, /**< available slots in vars array */
12013  int* requiredsize /**< pointer to store the required array size for the active variables */
12014  )
12015 {
12016  SCIP_VAR** activevars;
12017  int nactivevars;
12018  int activevarssize;
12019 
12020  SCIP_VAR* var;
12021  int v;
12022 
12023  SCIP_VAR** tmpvars;
12024  SCIP_VAR** multvars;
12025  int tmpvarssize;
12026  int ntmpvars;
12027  int noldtmpvars;
12028  int nmultvars;
12029 
12030  assert(set != NULL);
12031  assert(nvars != NULL);
12032  assert(vars != NULL || *nvars == 0);
12033  assert(varssize >= *nvars);
12034  assert(requiredsize != NULL);
12035 
12036  *requiredsize = 0;
12037 
12038  if( *nvars == 0 )
12039  return SCIP_OKAY;
12040 
12041  nactivevars = 0;
12042  activevarssize = *nvars;
12043  ntmpvars = *nvars;
12044  tmpvarssize = *nvars;
12045 
12046  /* temporary memory */
12047  SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
12048  /* coverity[copy_paste_error] */
12049  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
12050 
12051  noldtmpvars = ntmpvars;
12052 
12053  /* sort all variables to combine equal variables easily */
12054  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
12055  for( v = ntmpvars - 1; v > 0; --v )
12056  {
12057  /* combine same variables */
12058  if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
12059  {
12060  --ntmpvars;
12061  tmpvars[v] = tmpvars[ntmpvars];
12062  }
12063  }
12064  /* sort all variables again to combine equal variables later on */
12065  if( noldtmpvars > ntmpvars )
12066  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
12067 
12068  /* collect for each variable the representation in active variables */
12069  while( ntmpvars >= 1 )
12070  {
12071  --ntmpvars;
12072  var = tmpvars[ntmpvars];
12073  assert( var != NULL );
12074 
12075  switch( SCIPvarGetStatus(var) )
12076  {
12078  if( var->data.original.transvar == NULL )
12079  {
12080  SCIPerrorMessage("original variable has no transformed variable attached\n");
12081  SCIPABORT();
12082  return SCIP_INVALIDDATA; /*lint !e527*/
12083  }
12084  tmpvars[ntmpvars] = var->data.original.transvar;
12085  ++ntmpvars;
12086  break;
12087 
12089  tmpvars[ntmpvars] = var->data.aggregate.var;
12090  ++ntmpvars;
12091  break;
12092 
12094  tmpvars[ntmpvars] = var->negatedvar;
12095  ++ntmpvars;
12096  break;
12097 
12098  case SCIP_VARSTATUS_LOOSE:
12099  case SCIP_VARSTATUS_COLUMN:
12100  /* check for space in temporary memory */
12101  if( nactivevars >= activevarssize )
12102  {
12103  activevarssize *= 2;
12104  SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
12105  assert(nactivevars < activevarssize);
12106  }
12107  activevars[nactivevars] = var;
12108  nactivevars++;
12109  break;
12110 
12112  /* x = a_1*y_1 + ... + a_n*y_n + c */
12113  nmultvars = var->data.multaggr.nvars;
12114  multvars = var->data.multaggr.vars;
12115 
12116  /* check for space in temporary memory */
12117  if( nmultvars + ntmpvars > tmpvarssize )
12118  {
12119  while( nmultvars + ntmpvars > tmpvarssize )
12120  tmpvarssize *= 2;
12121  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
12122  assert(nmultvars + ntmpvars <= tmpvarssize);
12123  }
12124 
12125  /* copy all multi-aggregation variables into our working array */
12126  BMScopyMemoryArray(&tmpvars[ntmpvars], multvars, nmultvars); /*lint !e866*/
12127 
12128  /* get active, fixed or multi-aggregated corresponding variables for all new ones */
12129  SCIPvarsGetProbvar(&tmpvars[ntmpvars], nmultvars);
12130 
12131  ntmpvars += nmultvars;
12132  noldtmpvars = ntmpvars;
12133 
12134  /* sort all variables to combine equal variables easily */
12135  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
12136  for( v = ntmpvars - 1; v > 0; --v )
12137  {
12138  /* combine same variables */
12139  if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
12140  {
12141  --ntmpvars;
12142  tmpvars[v] = tmpvars[ntmpvars];
12143  }
12144  }
12145  /* sort all variables again to combine equal variables later on */
12146  if( noldtmpvars > ntmpvars )
12147  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
12148 
12149  break;
12150 
12151  case SCIP_VARSTATUS_FIXED:
12152  /* no need for memorizing fixed variables */
12153  break;
12154 
12155  default:
12156  SCIPerrorMessage("unknown variable status\n");
12157  SCIPABORT();
12158  return SCIP_INVALIDDATA; /*lint !e527*/
12159  }
12160  }
12161 
12162  /* sort variable array by variable index */
12163  SCIPsortPtr((void**)activevars, SCIPvarComp, nactivevars);
12164 
12165  /* eliminate duplicates and count required size */
12166  v = nactivevars - 1;
12167  while( v > 0 )
12168  {
12169  /* combine both variable since they are the same */
12170  if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
12171  {
12172  --nactivevars;
12173  activevars[v] = activevars[nactivevars];
12174  }
12175  --v;
12176  }
12177  *requiredsize = nactivevars;
12178 
12179  if( varssize >= *requiredsize )
12180  {
12181  assert(vars != NULL);
12182 
12183  *nvars = *requiredsize;
12184  BMScopyMemoryArray(vars, activevars, nactivevars);
12185  }
12186 
12187  SCIPsetFreeBufferArray(set, &tmpvars);
12188  SCIPsetFreeBufferArray(set, &activevars);
12189 
12190  return SCIP_OKAY;
12191 }
12192 
12193 /** gets corresponding active, fixed, or multi-aggregated problem variables of given variables,
12194  * @note the content of the given array will/might change
12195  */
12196 void SCIPvarsGetProbvar(
12197  SCIP_VAR** vars, /**< array of problem variables */
12198  int nvars /**< number of variables */
12199  )
12200 {
12201  int v;
12202 
12203  assert(vars != NULL || nvars == 0);
12204 
12205  for( v = nvars - 1; v >= 0; --v )
12206  {
12207  assert(vars != NULL);
12208  assert(vars[v] != NULL);
12209 
12210  vars[v] = SCIPvarGetProbvar(vars[v]);
12211  assert(vars[v] != NULL);
12212  }
12213 }
12214 
12215 /** gets corresponding active, fixed, or multi-aggregated problem variable of a variable */
12217  SCIP_VAR* var /**< problem variable */
12218  )
12219 {
12220  SCIP_VAR* retvar;
12221 
12222  assert(var != NULL);
12223 
12224  retvar = var;
12225 
12226  SCIPdebugMessage("get problem variable of <%s>\n", var->name);
12227 
12228  while( TRUE ) /*lint !e716 */
12229  {
12230  assert(retvar != NULL);
12231 
12232  switch( SCIPvarGetStatus(retvar) )
12233  {
12235  if( retvar->data.original.transvar == NULL )
12236  {
12237  SCIPerrorMessage("original variable has no transformed variable attached\n");
12238  SCIPABORT();
12239  return NULL; /*lint !e527 */
12240  }
12241  retvar = retvar->data.original.transvar;
12242  break;
12243 
12244  case SCIP_VARSTATUS_LOOSE:
12245  case SCIP_VARSTATUS_COLUMN:
12246  case SCIP_VARSTATUS_FIXED:
12247  return retvar;
12248 
12250  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12251  if ( retvar->data.multaggr.nvars == 1 )
12252  retvar = retvar->data.multaggr.vars[0];
12253  else
12254  return retvar;
12255  break;
12256 
12258  retvar = retvar->data.aggregate.var;
12259  break;
12260 
12262  retvar = retvar->negatedvar;
12263  break;
12264 
12265  default:
12266  SCIPerrorMessage("unknown variable status\n");
12267  SCIPABORT();
12268  return NULL; /*lint !e527*/
12269  }
12270  }
12271 }
12272 
12273 /** gets corresponding active, fixed, or multi-aggregated problem variables of binary variables and updates the given
12274  * negation status of each variable
12275  */
12277  SCIP_VAR*** vars, /**< pointer to binary problem variables */
12278  SCIP_Bool** negatedarr, /**< pointer to corresponding array to update the negation status */
12279  int nvars /**< number of variables and values in vars and negated array */
12280  )
12281 {
12282  SCIP_VAR** var;
12283  SCIP_Bool* negated;
12284  int v;
12285 
12286  assert(vars != NULL);
12287  assert(*vars != NULL || nvars == 0);
12288  assert(negatedarr != NULL);
12289  assert(*negatedarr != NULL || nvars == 0);
12290 
12291  for( v = nvars - 1; v >= 0; --v )
12292  {
12293  var = &((*vars)[v]);
12294  negated = &((*negatedarr)[v]);
12295 
12296  /* get problem variable */
12297  SCIP_CALL( SCIPvarGetProbvarBinary(var, negated) );
12298  }
12299 
12300  return SCIP_OKAY;
12301 }
12302 
12303 
12304 /** gets corresponding active, fixed, or multi-aggregated problem variable of a binary variable and updates the given
12305  * negation status (this means you have to assign a value to SCIP_Bool negated before calling this method, usually
12306  * FALSE is used)
12307  */
12309  SCIP_VAR** var, /**< pointer to binary problem variable */
12310  SCIP_Bool* negated /**< pointer to update the negation status */
12311  )
12312 {
12314 #ifndef NDEBUG
12315  SCIP_Real constant = 0.0;
12316  SCIP_Bool orignegated;
12317 #endif
12318 
12319  assert(var != NULL);
12320  assert(*var != NULL);
12321  assert(negated != NULL);
12322  assert(SCIPvarIsBinary(*var));
12323 
12324 #ifndef NDEBUG
12325  orignegated = *negated;
12326 #endif
12327 
12328  while( !active && *var != NULL )
12329  {
12330  switch( SCIPvarGetStatus(*var) )
12331  {
12333  if( (*var)->data.original.transvar == NULL )
12334  return SCIP_OKAY;
12335  *var = (*var)->data.original.transvar;
12336  break;
12337 
12338  case SCIP_VARSTATUS_LOOSE:
12339  case SCIP_VARSTATUS_COLUMN:
12340  case SCIP_VARSTATUS_FIXED:
12341  active = TRUE;
12342  break;
12343 
12345  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12346  if ( (*var)->data.multaggr.nvars == 1 )
12347  {
12348  assert( (*var)->data.multaggr.vars != NULL );
12349  assert( (*var)->data.multaggr.scalars != NULL );
12350  assert( SCIPvarIsBinary((*var)->data.multaggr.vars[0]) );
12351  assert(!EPSZ((*var)->data.multaggr.scalars[0], 1e-06));
12352 
12353  /* if not all variables were fully propagated, it might happen that a variable is multi-aggregated to
12354  * another variable which needs to be fixed
12355  *
12356  * e.g. x = y - 1 => (x = 0 && y = 1)
12357  * e.g. x = y + 1 => (x = 1 && y = 0)
12358  *
12359  * is this special case we need to return the muti-aggregation
12360  */
12361  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)) )
12362  {
12363  assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06));
12364  }
12365  else
12366  {
12367  /* @note due to fixations, a multi-aggregation can have a constant of zero and a negative scalar or even
12368  * a scalar in absolute value unequal to one, in this case this aggregation variable needs to be
12369  * fixed to zero, but this should be done by another enforcement; so not depending on the scalar,
12370  * we will return the aggregated variable;
12371  */
12372  if( !EPSEQ(REALABS((*var)->data.multaggr.scalars[0]), 1.0, 1e-06) )
12373  {
12374  active = TRUE;
12375  break;
12376  }
12377 
12378  /* @note it may also happen that the constant is larger than 1 or smaller than 0, in that case the
12379  * aggregation variable needs to be fixed to one, but this should be done by another enforcement;
12380  * so if this is the case, we will return the aggregated variable
12381  */
12382  assert(EPSZ((*var)->data.multaggr.constant, 1e-06) || EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06)
12383  || EPSZ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1e-06)
12384  || EPSEQ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1.0, 1e-06));
12385 
12386  if( !EPSZ((*var)->data.multaggr.constant, 1e-06) && !EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06) )
12387  {
12388  active = TRUE;
12389  break;
12390  }
12391 
12392  assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06) || EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
12393 
12394  if( EPSZ((*var)->data.multaggr.constant, 1e-06) )
12395  {
12396  /* if the scalar is negative, either the aggregation variable is already fixed to zero or has at
12397  * least one uplock (that hopefully will enforce this fixation to zero); can it happen that this
12398  * variable itself is multi-aggregated again?
12399  */
12400  assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06) ?
12401  ((SCIPvarGetUbGlobal((*var)->data.multaggr.vars[0]) < 0.5) ||
12402  SCIPvarGetNLocksUpType((*var)->data.multaggr.vars[0], SCIP_LOCKTYPE_MODEL) > 0) : TRUE);
12403  }
12404  else
12405  {
12406  assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
12407 #ifndef NDEBUG
12408  constant += (*negated) != orignegated ? -1.0 : 1.0;
12409 #endif
12410 
12411  *negated = !(*negated);
12412  }
12413  *var = (*var)->data.multaggr.vars[0];
12414  break;
12415  }
12416  }
12417  active = TRUE; /*lint !e838*/
12418  break;
12419 
12420  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
12421  assert((*var)->data.aggregate.var != NULL);
12422  assert(EPSEQ((*var)->data.aggregate.scalar, 1.0, 1e-06) || EPSEQ((*var)->data.aggregate.scalar, -1.0, 1e-06));
12423  assert(EPSLE((*var)->data.aggregate.var->glbdom.ub - (*var)->data.aggregate.var->glbdom.lb, 1.0, 1e-06));
12424 #ifndef NDEBUG
12425  constant += (*negated) != orignegated ? -(*var)->data.aggregate.constant : (*var)->data.aggregate.constant;
12426 #endif
12427 
12428  *negated = ((*var)->data.aggregate.scalar > 0.0) ? *negated : !(*negated);
12429  *var = (*var)->data.aggregate.var;
12430  break;
12431 
12432  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
12433  assert((*var)->negatedvar != NULL);
12434 #ifndef NDEBUG
12435  constant += (*negated) != orignegated ? -1.0 : 1.0;
12436 #endif
12437 
12438  *negated = !(*negated);
12439  *var = (*var)->negatedvar;
12440  break;
12441 
12442  default:
12443  SCIPerrorMessage("unknown variable status\n");
12444  return SCIP_INVALIDDATA;
12445  }
12446  }
12447  assert(active == (*var != NULL));
12448 
12449  if( active )
12450  {
12451  assert(SCIPvarIsBinary(*var));
12452  assert(EPSZ(constant, 1e-06) || EPSEQ(constant, 1.0, 1e-06));
12453  assert(EPSZ(constant, 1e-06) == ((*negated) == orignegated));
12454 
12455  return SCIP_OKAY;
12456  }
12457  else
12458  {
12459  SCIPerrorMessage("active variable path leads to NULL pointer\n");
12460  return SCIP_INVALIDDATA;
12461  }
12462 }
12463 
12464 /** transforms given variable, boundtype and bound to the corresponding active, fixed, or multi-aggregated variable
12465  * values
12466  */
12468  SCIP_VAR** var, /**< pointer to problem variable */
12469  SCIP_Real* bound, /**< pointer to bound value to transform */
12470  SCIP_BOUNDTYPE* boundtype /**< pointer to type of bound: lower or upper bound */
12471  )
12472 {
12473  assert(var != NULL);
12474  assert(*var != NULL);
12475  assert(bound != NULL);
12476  assert(boundtype != NULL);
12477 
12478  SCIPdebugMessage("get probvar bound %g of type %d of variable <%s>\n", *bound, *boundtype, (*var)->name);
12479 
12480  switch( SCIPvarGetStatus(*var) )
12481  {
12483  if( (*var)->data.original.transvar == NULL )
12484  {
12485  SCIPerrorMessage("original variable has no transformed variable attached\n");
12486  return SCIP_INVALIDDATA;
12487  }
12488  *var = (*var)->data.original.transvar;
12489  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12490  break;
12491 
12492  case SCIP_VARSTATUS_LOOSE:
12493  case SCIP_VARSTATUS_COLUMN:
12494  case SCIP_VARSTATUS_FIXED:
12495  break;
12496 
12498  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12499  if ( (*var)->data.multaggr.nvars == 1 )
12500  {
12501  assert( (*var)->data.multaggr.vars != NULL );
12502  assert( (*var)->data.multaggr.scalars != NULL );
12503  assert( (*var)->data.multaggr.scalars[0] != 0.0 );
12504 
12505  (*bound) /= (*var)->data.multaggr.scalars[0];
12506  (*bound) -= (*var)->data.multaggr.constant/(*var)->data.multaggr.scalars[0];
12507  if ( (*var)->data.multaggr.scalars[0] < 0.0 )
12508  {
12509  if ( *boundtype == SCIP_BOUNDTYPE_LOWER )
12510  *boundtype = SCIP_BOUNDTYPE_UPPER;
12511  else
12512  *boundtype = SCIP_BOUNDTYPE_LOWER;
12513  }
12514  *var = (*var)->data.multaggr.vars[0];
12515  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12516  }
12517  break;
12518 
12519  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
12520  assert((*var)->data.aggregate.var != NULL);
12521  assert((*var)->data.aggregate.scalar != 0.0);
12522 
12523  (*bound) /= (*var)->data.aggregate.scalar;
12524  (*bound) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12525  if( (*var)->data.aggregate.scalar < 0.0 )
12526  {
12527  if( *boundtype == SCIP_BOUNDTYPE_LOWER )
12528  *boundtype = SCIP_BOUNDTYPE_UPPER;
12529  else
12530  *boundtype = SCIP_BOUNDTYPE_LOWER;
12531  }
12532  *var = (*var)->data.aggregate.var;
12533  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12534  break;
12535 
12536  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12537  assert((*var)->negatedvar != NULL);
12538  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12539  assert((*var)->negatedvar->negatedvar == *var);
12540  (*bound) = (*var)->data.negate.constant - *bound;
12541  if( *boundtype == SCIP_BOUNDTYPE_LOWER )
12542  *boundtype = SCIP_BOUNDTYPE_UPPER;
12543  else
12544  *boundtype = SCIP_BOUNDTYPE_LOWER;
12545  *var = (*var)->negatedvar;
12546  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12547  break;
12548 
12549  default:
12550  SCIPerrorMessage("unknown variable status\n");
12551  return SCIP_INVALIDDATA;
12552  }
12553 
12554  return SCIP_OKAY;
12555 }
12556 
12557 /** transforms given variable and domain hole to the corresponding active, fixed, or multi-aggregated variable
12558  * values
12559  */
12561  SCIP_VAR** var, /**< pointer to problem variable */
12562  SCIP_Real* left, /**< pointer to left bound of open interval in hole to transform */
12563  SCIP_Real* right /**< pointer to right bound of open interval in hole to transform */
12564  )
12565 {
12566  assert(var != NULL);
12567  assert(*var != NULL);
12568  assert(left != NULL);
12569  assert(right != NULL);
12570 
12571  SCIPdebugMessage("get probvar hole (%g,%g) of variable <%s>\n", *left, *right, (*var)->name);
12572 
12573  switch( SCIPvarGetStatus(*var) )
12574  {
12576  if( (*var)->data.original.transvar == NULL )
12577  {
12578  SCIPerrorMessage("original variable has no transformed variable attached\n");
12579  return SCIP_INVALIDDATA;
12580  }
12581  *var = (*var)->data.original.transvar;
12582  SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
12583  break;
12584 
12585  case SCIP_VARSTATUS_LOOSE:
12586  case SCIP_VARSTATUS_COLUMN:
12587  case SCIP_VARSTATUS_FIXED:
12589  break;
12590 
12591  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
12592  assert((*var)->data.aggregate.var != NULL);
12593  assert((*var)->data.aggregate.scalar != 0.0);
12594 
12595  /* scale back */
12596  (*left) /= (*var)->data.aggregate.scalar;
12597  (*right) /= (*var)->data.aggregate.scalar;
12598 
12599  /* shift back */
12600  (*left) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12601  (*right) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12602 
12603  *var = (*var)->data.aggregate.var;
12604 
12605  /* check if the interval bounds have to swapped */
12606  if( (*var)->data.aggregate.scalar < 0.0 )
12607  {
12608  SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
12609  }
12610  else
12611  {
12612  SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
12613  }
12614  break;
12615 
12616  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12617  assert((*var)->negatedvar != NULL);
12618  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12619  assert((*var)->negatedvar->negatedvar == *var);
12620 
12621  /* shift and scale back */
12622  (*left) = (*var)->data.negate.constant - (*left);
12623  (*right) = (*var)->data.negate.constant - (*right);
12624 
12625  *var = (*var)->negatedvar;
12626 
12627  /* through the negated variable the left and right interval bound have to swapped */
12628  SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
12629  break;
12630 
12631  default:
12632  SCIPerrorMessage("unknown variable status\n");
12633  return SCIP_INVALIDDATA;
12634  }
12635 
12636  return SCIP_OKAY;
12637 }
12638 
12639 /** transforms given variable, scalar and constant to the corresponding active, fixed, or
12640  * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed variable,
12641  * "scalar" will be 0.0 and the value of the sum will be stored in "constant"; a multi-aggregation
12642  * with only one active variable (this can happen due to fixings after the multi-aggregation),
12643  * is treated like an aggregation; if the multi-aggregation constant is infinite, "scalar" will be 0.0
12644  */
12646  SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
12647  SCIP_SET* set, /**< global SCIP settings */
12648  SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
12649  SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
12650  )
12651 {
12652  assert(var != NULL);
12653  assert(scalar != NULL);
12654  assert(constant != NULL);
12655 
12656  while( *var != NULL )
12657  {
12658  switch( SCIPvarGetStatus(*var) )
12659  {
12661  if( (*var)->data.original.transvar == NULL )
12662  {
12663  SCIPerrorMessage("original variable has no transformed variable attached\n");
12664  return SCIP_INVALIDDATA;
12665  }
12666  *var = (*var)->data.original.transvar;
12667  break;
12668 
12669  case SCIP_VARSTATUS_LOOSE:
12670  case SCIP_VARSTATUS_COLUMN:
12671  return SCIP_OKAY;
12672 
12673  case SCIP_VARSTATUS_FIXED: /* x = c' => a*x + c == (a*c' + c) */
12674  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12675  {
12676  if( SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)) )
12677  {
12678  assert(*scalar != 0.0);
12679  if( (*scalar) * (*var)->glbdom.lb > 0.0 )
12680  (*constant) = SCIPsetInfinity(set);
12681  else
12682  (*constant) = -SCIPsetInfinity(set);
12683  }
12684  else
12685  (*constant) += *scalar * (*var)->glbdom.lb;
12686  }
12687 #ifndef NDEBUG
12688  else
12689  {
12690  assert(!SCIPsetIsInfinity(set, (*constant)) || !((*scalar) * (*var)->glbdom.lb < 0.0 &&
12691  (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
12692  assert(!SCIPsetIsInfinity(set, -(*constant)) || !((*scalar) * (*var)->glbdom.lb > 0.0 &&
12693  (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
12694  }
12695 #endif
12696  *scalar = 0.0;
12697  return SCIP_OKAY;
12698 
12700  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12701  if ( (*var)->data.multaggr.nvars == 1 )
12702  {
12703  assert((*var)->data.multaggr.vars != NULL);
12704  assert((*var)->data.multaggr.scalars != NULL);
12705  assert((*var)->data.multaggr.vars[0] != NULL);
12706  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12707  {
12708  /* the multi-aggregation constant can be infinite, if one of the multi-aggregation variables
12709  * was fixed to +/-infinity; ensure that the constant is set to +/-infinity, too, and the scalar
12710  * is set to 0.0, because the multi-aggregated variable can be seen as fixed, too
12711  */
12712  if( SCIPsetIsInfinity(set, (*var)->data.multaggr.constant)
12713  || SCIPsetIsInfinity(set, -((*var)->data.multaggr.constant)) )
12714  {
12715  if( (*scalar) * (*var)->data.multaggr.constant > 0 )
12716  {
12717  assert(!SCIPsetIsInfinity(set, -(*constant)));
12718  (*constant) = SCIPsetInfinity(set);
12719  }
12720  else
12721  {
12722  assert(!SCIPsetIsInfinity(set, *constant));
12723  (*constant) = -SCIPsetInfinity(set);
12724  }
12725  (*scalar) = 0.0;
12726  }
12727  else
12728  (*constant) += *scalar * (*var)->data.multaggr.constant;
12729  }
12730  (*scalar) *= (*var)->data.multaggr.scalars[0];
12731  *var = (*var)->data.multaggr.vars[0];
12732  break;
12733  }
12734  return SCIP_OKAY;
12735 
12736  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
12737  assert((*var)->data.aggregate.var != NULL);
12738  assert(!SCIPsetIsInfinity(set, (*var)->data.aggregate.constant)
12739  && !SCIPsetIsInfinity(set, (*var)->data.aggregate.constant));
12740  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12741  (*constant) += *scalar * (*var)->data.aggregate.constant;
12742  (*scalar) *= (*var)->data.aggregate.scalar;
12743  *var = (*var)->data.aggregate.var;
12744  break;
12745 
12746  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
12747  assert((*var)->negatedvar != NULL);
12748  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12749  assert((*var)->negatedvar->negatedvar == *var);
12750  assert(!SCIPsetIsInfinity(set, (*var)->data.negate.constant)
12751  && !SCIPsetIsInfinity(set, (*var)->data.negate.constant));
12752  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12753  (*constant) += *scalar * (*var)->data.negate.constant;
12754  (*scalar) *= -1.0;
12755  *var = (*var)->negatedvar;
12756  break;
12757 
12758  default:
12759  SCIPerrorMessage("unknown variable status\n");
12760  SCIPABORT();
12761  return SCIP_INVALIDDATA; /*lint !e527*/
12762  }
12763  }
12764  *scalar = 0.0;
12765 
12766  return SCIP_OKAY;
12767 }
12768 
12769 /** retransforms given variable, scalar and constant to the corresponding original variable, scalar
12770  * and constant, if possible; if the retransformation is impossible, NULL is returned as variable
12771  */
12773  SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
12774  SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
12775  SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
12776  )
12777 {
12778  SCIP_VAR* parentvar;
12779 
12780  assert(var != NULL);
12781  assert(*var != NULL);
12782  assert(scalar != NULL);
12783  assert(constant != NULL);
12784 
12785  while( !SCIPvarIsOriginal(*var) )
12786  {
12787  /* if the variable has no parent variables, it was generated during solving and has no corresponding original
12788  * var
12789  */
12790  if( (*var)->nparentvars == 0 )
12791  {
12792  /* negated variables do not need to have a parent variables, and negated variables can exist in original
12793  * space
12794  */
12796  ((*var)->negatedvar->nparentvars == 0 || (*var)->negatedvar->parentvars[0] != *var) )
12797  {
12798  *scalar *= -1.0;
12799  *constant -= (*var)->data.negate.constant * (*scalar);
12800  *var = (*var)->negatedvar;
12801 
12802  continue;
12803  }
12804  /* if the variables does not have any parent the variables was created during solving and has no original
12805  * counterpart
12806  */
12807  else
12808  {
12809  *var = NULL;
12810 
12811  return SCIP_OKAY;
12812  }
12813  }
12814 
12815  /* follow the link to the first parent variable */
12816  parentvar = (*var)->parentvars[0];
12817  assert(parentvar != NULL);
12818 
12819  switch( SCIPvarGetStatus(parentvar) )
12820  {
12822  break;
12823 
12824  case SCIP_VARSTATUS_COLUMN:
12825  case SCIP_VARSTATUS_LOOSE:
12826  case SCIP_VARSTATUS_FIXED:
12828  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
12829  return SCIP_INVALIDDATA;
12830 
12831  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + b -> y = (x-b)/a, s*y + c = (s/a)*x + c-b*s/a */
12832  assert(parentvar->data.aggregate.var == *var);
12833  assert(parentvar->data.aggregate.scalar != 0.0);
12834  *scalar /= parentvar->data.aggregate.scalar;
12835  *constant -= parentvar->data.aggregate.constant * (*scalar);
12836  break;
12837 
12838  case SCIP_VARSTATUS_NEGATED: /* x = b - y -> y = b - x, s*y + c = -s*x + c+b*s */
12839  assert(parentvar->negatedvar != NULL);
12840  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
12841  assert(parentvar->negatedvar->negatedvar == parentvar);
12842  *scalar *= -1.0;
12843  *constant -= parentvar->data.negate.constant * (*scalar);
12844  break;
12845 
12846  default:
12847  SCIPerrorMessage("unknown variable status\n");
12848  return SCIP_INVALIDDATA;
12849  }
12850 
12851  assert( parentvar != NULL );
12852  *var = parentvar;
12853  }
12854 
12855  return SCIP_OKAY;
12856 }
12857 
12858 /** returns whether the given variable is the direct counterpart of an original problem variable */
12860  SCIP_VAR* var /**< problem variable */
12861  )
12862 {
12863  SCIP_VAR* parentvar;
12864  assert(var != NULL);
12865 
12866  if( !SCIPvarIsTransformed(var) || var->nparentvars < 1 )
12867  return FALSE;
12868 
12869  assert(var->parentvars != NULL);
12870  parentvar = var->parentvars[0];
12871  assert(parentvar != NULL);
12872 
12873  /* we follow the aggregation tree to the root unless an original variable has been found - the first entries in the parentlist are candidates */
12874  while( parentvar->nparentvars >= 1 && SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL )
12875  parentvar = parentvar->parentvars[0];
12876  assert( parentvar != NULL );
12877 
12878  return ( SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_ORIGINAL );
12879 }
12880 
12881 /** gets objective value of variable in current SCIP_LP; the value can be different from the objective value stored in
12882  * the variable's own data due to diving, that operate only on the LP without updating the variables
12883  */
12885  SCIP_VAR* var /**< problem variable */
12886  )
12887 {
12888  assert(var != NULL);
12889 
12890  /* get bounds of attached variables */
12891  switch( SCIPvarGetStatus(var) )
12892  {
12894  assert(var->data.original.transvar != NULL);
12895  return SCIPvarGetObjLP(var->data.original.transvar);
12896 
12897  case SCIP_VARSTATUS_COLUMN:
12898  assert(var->data.col != NULL);
12899  return SCIPcolGetObj(var->data.col);
12900 
12901  case SCIP_VARSTATUS_LOOSE:
12902  case SCIP_VARSTATUS_FIXED:
12903  return var->obj;
12904 
12905  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12906  assert(var->data.aggregate.var != NULL);
12907  return var->data.aggregate.scalar * SCIPvarGetObjLP(var->data.aggregate.var);
12908 
12910  SCIPerrorMessage("cannot get the objective value of a multiple aggregated variable\n");
12911  SCIPABORT();
12912  return 0.0; /*lint !e527*/
12913 
12914  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12915  assert(var->negatedvar != NULL);
12917  assert(var->negatedvar->negatedvar == var);
12918  return -SCIPvarGetObjLP(var->negatedvar);
12919 
12920  default:
12921  SCIPerrorMessage("unknown variable status\n");
12922  SCIPABORT();
12923  return 0.0; /*lint !e527*/
12924  }
12925 }
12926 
12927 /** gets lower bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
12928  * data due to diving or conflict analysis, that operate only on the LP without updating the variables
12929  */
12931  SCIP_VAR* var, /**< problem variable */
12932  SCIP_SET* set /**< global SCIP settings */
12933  )
12934 {
12935  assert(var != NULL);
12936  assert(set != NULL);
12937  assert(var->scip == set->scip);
12938 
12939  /* get bounds of attached variables */
12940  switch( SCIPvarGetStatus(var) )
12941  {
12943  assert(var->data.original.transvar != NULL);
12944  return SCIPvarGetLbLP(var->data.original.transvar, set);
12945 
12946  case SCIP_VARSTATUS_COLUMN:
12947  assert(var->data.col != NULL);
12948  return SCIPcolGetLb(var->data.col);
12949 
12950  case SCIP_VARSTATUS_LOOSE:
12951  case SCIP_VARSTATUS_FIXED:
12952  return var->locdom.lb;
12953 
12954  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12955  assert(var->data.aggregate.var != NULL);
12956  if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set)))
12957  || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set))) )
12958  {
12959  return -SCIPsetInfinity(set);
12960  }
12961  else if( var->data.aggregate.scalar > 0.0 )
12962  {
12963  /* a > 0 -> get lower bound of y */
12964  return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12965  }
12966  else if( var->data.aggregate.scalar < 0.0 )
12967  {
12968  /* a < 0 -> get upper bound of y */
12969  return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12970  }
12971  else
12972  {
12973  SCIPerrorMessage("scalar is zero in aggregation\n");
12974  SCIPABORT();
12975  return SCIP_INVALID; /*lint !e527*/
12976  }
12977 
12979  /**@todo get the sides of the corresponding linear constraint */
12980  SCIPerrorMessage("getting the bounds of a multiple aggregated variable is not implemented yet\n");
12981  SCIPABORT();
12982  return SCIP_INVALID; /*lint !e527*/
12983 
12984  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12985  assert(var->negatedvar != NULL);
12987  assert(var->negatedvar->negatedvar == var);
12988  return var->data.negate.constant - SCIPvarGetUbLP(var->negatedvar, set);
12989 
12990  default:
12991  SCIPerrorMessage("unknown variable status\n");
12992  SCIPABORT();
12993  return SCIP_INVALID; /*lint !e527*/
12994  }
12995 }
12996 
12997 /** gets upper bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
12998  * data due to diving or conflict analysis, that operate only on the LP without updating the variables
12999  */
13001  SCIP_VAR* var, /**< problem variable */
13002  SCIP_SET* set /**< global SCIP settings */
13003  )
13004 {
13005  assert(var != NULL);
13006  assert(set != NULL);
13007  assert(var->scip == set->scip);
13008 
13009  /* get bounds of attached variables */
13010  switch( SCIPvarGetStatus(var) )
13011  {
13013  assert(var->data.original.transvar != NULL);
13014  return SCIPvarGetUbLP(var->data.original.transvar, set);
13015 
13016  case SCIP_VARSTATUS_COLUMN:
13017  assert(var->data.col != NULL);
13018  return SCIPcolGetUb(var->data.col);
13019 
13020  case SCIP_VARSTATUS_LOOSE:
13021  case SCIP_VARSTATUS_FIXED:
13022  return var->locdom.ub;
13023 
13024  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
13025  assert(var->data.aggregate.var != NULL);
13026  if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set)))
13027  || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set))) )
13028  {
13029  return SCIPsetInfinity(set);
13030  }
13031  if( var->data.aggregate.scalar > 0.0 )
13032  {
13033  /* a > 0 -> get upper bound of y */
13034  return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
13035  }
13036  else if( var->data.aggregate.scalar < 0.0 )
13037  {
13038  /* a < 0 -> get lower bound of y */
13039  return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
13040  }
13041  else
13042  {
13043  SCIPerrorMessage("scalar is zero in aggregation\n");
13044  SCIPABORT();
13045  return SCIP_INVALID; /*lint !e527*/
13046  }
13047 
13049  SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
13050  SCIPABORT();
13051  return SCIP_INVALID; /*lint !e527*/
13052 
13053  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13054  assert(var->negatedvar != NULL);
13056  assert(var->negatedvar->negatedvar == var);
13057  return var->data.negate.constant - SCIPvarGetLbLP(var->negatedvar, set);
13058 
13059  default:
13060  SCIPerrorMessage("unknown variable status\n");
13061  SCIPABORT();
13062  return SCIP_INVALID; /*lint !e527*/
13063  }
13064 }
13065 
13066 /** gets primal LP solution value of variable */
13068  SCIP_VAR* var /**< problem variable */
13069  )
13070 {
13071  assert(var != NULL);
13072 
13073  switch( SCIPvarGetStatus(var) )
13074  {
13076  if( var->data.original.transvar == NULL )
13077  return SCIP_INVALID;
13078  return SCIPvarGetLPSol(var->data.original.transvar);
13079 
13080  case SCIP_VARSTATUS_LOOSE:
13081  return SCIPvarGetBestBoundLocal(var);
13082 
13083  case SCIP_VARSTATUS_COLUMN:
13084  assert(var->data.col != NULL);
13085  return SCIPcolGetPrimsol(var->data.col);
13086 
13087  case SCIP_VARSTATUS_FIXED:
13088  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13089  return var->locdom.lb;
13090 
13092  {
13093  SCIP_Real lpsolval;
13094 
13095  assert(!var->donotaggr);
13096  assert(var->data.aggregate.var != NULL);
13097  lpsolval = SCIPvarGetLPSol(var->data.aggregate.var);
13098 
13099  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13100  * corresponding infinity value instead of performing an arithmetical transformation (compare method
13101  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13102  * (or is called by) a public interface method; instead, we only assert that values are finite
13103  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13104  * positives and negatives if the parameter <numerics/infinity> is modified by the user
13105  */
13106  assert(lpsolval > -SCIP_DEFAULT_INFINITY);
13107  assert(lpsolval < +SCIP_DEFAULT_INFINITY);
13108  return var->data.aggregate.scalar * lpsolval + var->data.aggregate.constant;
13109  }
13111  {
13112  SCIP_Real primsol;
13113  int i;
13114 
13115  assert(!var->donotmultaggr);
13116  assert(var->data.multaggr.vars != NULL);
13117  assert(var->data.multaggr.scalars != NULL);
13118  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13119  * assert(var->data.multaggr.nvars >= 2);
13120  */
13121  primsol = var->data.multaggr.constant;
13122  for( i = 0; i < var->data.multaggr.nvars; ++i )
13123  primsol += var->data.multaggr.scalars[i] * SCIPvarGetLPSol(var->data.multaggr.vars[i]);
13124  return primsol;
13125  }
13126  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13127  assert(var->negatedvar != NULL);
13129  assert(var->negatedvar->negatedvar == var);
13130  return var->data.negate.constant - SCIPvarGetLPSol(var->negatedvar);
13131 
13132  default:
13133  SCIPerrorMessage("unknown variable status\n");
13134  SCIPABORT();
13135  return SCIP_INVALID; /*lint !e527*/
13136  }
13137 }
13138 
13139 /** gets primal NLP solution value of variable */
13141  SCIP_VAR* var /**< problem variable */
13142  )
13143 {
13144  SCIP_Real solval;
13145  int i;
13146 
13147  assert(var != NULL);
13148 
13149  /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
13150  switch( SCIPvarGetStatus(var) )
13151  {
13153  return SCIPvarGetNLPSol(var->data.original.transvar);
13154 
13155  case SCIP_VARSTATUS_LOOSE:
13156  case SCIP_VARSTATUS_COLUMN:
13157  return var->nlpsol;
13158 
13159  case SCIP_VARSTATUS_FIXED:
13160  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
13161  assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
13162  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
13163  return SCIPvarGetLbGlobal(var);
13164 
13165  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13166  solval = SCIPvarGetNLPSol(var->data.aggregate.var);
13167  return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
13168 
13170  solval = var->data.multaggr.constant;
13171  for( i = 0; i < var->data.multaggr.nvars; ++i )
13172  solval += var->data.multaggr.scalars[i] * SCIPvarGetNLPSol(var->data.multaggr.vars[i]);
13173  return solval;
13174 
13176  solval = SCIPvarGetNLPSol(var->negatedvar);
13177  return var->data.negate.constant - solval;
13178 
13179  default:
13180  SCIPerrorMessage("unknown variable status\n");
13181  SCIPABORT();
13182  return SCIP_INVALID; /*lint !e527*/
13183  }
13184 }
13185 
13186 /** gets pseudo solution value of variable at current node */
13187 static
13189  SCIP_VAR* var /**< problem variable */
13190  )
13191 {
13192  SCIP_Real pseudosol;
13193  int i;
13194 
13195  assert(var != NULL);
13196 
13197  switch( SCIPvarGetStatus(var) )
13198  {
13200  if( var->data.original.transvar == NULL )
13201  return SCIP_INVALID;
13203 
13204  case SCIP_VARSTATUS_LOOSE:
13205  case SCIP_VARSTATUS_COLUMN:
13206  return SCIPvarGetBestBoundLocal(var);
13207 
13208  case SCIP_VARSTATUS_FIXED:
13209  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13210  return var->locdom.lb;
13211 
13213  {
13214  SCIP_Real pseudosolval;
13215  assert(!var->donotaggr);
13216  assert(var->data.aggregate.var != NULL);
13217  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13218  * corresponding infinity value instead of performing an arithmetical transformation (compare method
13219  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13220  * (or is called by) a public interface method; instead, we only assert that values are finite
13221  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13222  * positives and negatives if the parameter <numerics/infinity> is modified by the user
13223  */
13224  pseudosolval = SCIPvarGetPseudoSol(var->data.aggregate.var);
13225  assert(pseudosolval > -SCIP_DEFAULT_INFINITY);
13226  assert(pseudosolval < +SCIP_DEFAULT_INFINITY);
13227  return var->data.aggregate.scalar * pseudosolval + var->data.aggregate.constant;
13228  }
13230  assert(!var->donotmultaggr);
13231  assert(var->data.multaggr.vars != NULL);
13232  assert(var->data.multaggr.scalars != NULL);
13233  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13234  * assert(var->data.multaggr.nvars >= 2);
13235  */
13236  pseudosol = var->data.multaggr.constant;
13237  for( i = 0; i < var->data.multaggr.nvars; ++i )
13238  pseudosol += var->data.multaggr.scalars[i] * SCIPvarGetPseudoSol(var->data.multaggr.vars[i]);
13239  return pseudosol;
13240 
13241  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13242  assert(var->negatedvar != NULL);
13244  assert(var->negatedvar->negatedvar == var);
13245  return var->data.negate.constant - SCIPvarGetPseudoSol(var->negatedvar);
13246 
13247  default:
13248  SCIPerrorMessage("unknown variable status\n");
13249  SCIPABORT();
13250  return SCIP_INVALID; /*lint !e527*/
13251  }
13252 }
13253 
13254 /** gets current LP or pseudo solution value of variable */
13256  SCIP_VAR* var, /**< problem variable */
13257  SCIP_Bool getlpval /**< should the LP solution value be returned? */
13258  )
13259 {
13260  if( getlpval )
13261  return SCIPvarGetLPSol(var);
13262  else
13263  return SCIPvarGetPseudoSol(var);
13264 }
13265 
13266 /** remembers the current solution as root solution in the problem variables */
13267 void SCIPvarStoreRootSol(
13268  SCIP_VAR* var, /**< problem variable */
13269  SCIP_Bool roothaslp /**< is the root solution from LP? */
13270  )
13271 {
13272  assert(var != NULL);
13273 
13274  var->rootsol = SCIPvarGetSol(var, roothaslp);
13275 }
13276 
13277 /** updates the current solution as best root solution of the given variable if it is better */
13279  SCIP_VAR* var, /**< problem variable */
13280  SCIP_SET* set, /**< global SCIP settings */
13281  SCIP_Real rootsol, /**< root solution value */
13282  SCIP_Real rootredcost, /**< root reduced cost */
13283  SCIP_Real rootlpobjval /**< objective value of the root LP */
13284  )
13285 {
13286  assert(var != NULL);
13287  assert(set != NULL);
13288  assert(var->scip == set->scip);
13289 
13290  /* if reduced cost are zero nothing to update */
13291  if( SCIPsetIsDualfeasZero(set, rootredcost) )
13292  return;
13293 
13294  /* check if we have already a best combination stored */
13295  if( !SCIPsetIsDualfeasZero(set, var->bestrootredcost) )
13296  {
13297  SCIP_Real currcutoffbound;
13298  SCIP_Real cutoffbound;
13299  SCIP_Real bound;
13300 
13301  /* compute the cutoff bound which would improve the corresponding bound with the current stored root solution,
13302  * root reduced cost, and root LP objective value combination
13303  */
13304  if( var->bestrootredcost > 0.0 )
13305  bound = SCIPvarGetUbGlobal(var);
13306  else
13307  bound = SCIPvarGetLbGlobal(var);
13308 
13309  currcutoffbound = (bound - var->bestrootsol) * var->bestrootredcost + var->bestrootlpobjval;
13310 
13311  /* compute the cutoff bound which would improve the corresponding bound with new root solution, root reduced
13312  * cost, and root LP objective value combination
13313  */
13314  if( rootredcost > 0.0 )
13315  bound = SCIPvarGetUbGlobal(var);
13316  else
13317  bound = SCIPvarGetLbGlobal(var);
13318 
13319  cutoffbound = (bound - rootsol) * rootredcost + rootlpobjval;
13320 
13321  /* check if an improving root solution, root reduced cost, and root LP objective value is at hand */
13322  if( cutoffbound > currcutoffbound )
13323  {
13324  SCIPsetDebugMsg(set, "-> <%s> update potential cutoff bound <%g> -> <%g>\n",
13325  SCIPvarGetName(var), currcutoffbound, cutoffbound);
13326 
13327  var->bestrootsol = rootsol;
13328  var->bestrootredcost = rootredcost;
13329  var->bestrootlpobjval = rootlpobjval;
13330  }
13331  }
13332  else
13333  {
13334  SCIPsetDebugMsg(set, "-> <%s> initialize best root reduced cost information\n", SCIPvarGetName(var));
13335  SCIPsetDebugMsg(set, " -> rootsol <%g>\n", rootsol);
13336  SCIPsetDebugMsg(set, " -> rootredcost <%g>\n", rootredcost);
13337  SCIPsetDebugMsg(set, " -> rootlpobjval <%g>\n", rootlpobjval);
13338 
13339  var->bestrootsol = rootsol;
13340  var->bestrootredcost = rootredcost;
13341  var->bestrootlpobjval = rootlpobjval;
13342  }
13343 }
13344 
13345 /** returns the solution of the variable in the last root node's relaxation, if the root relaxation is not yet
13346  * completely solved, zero is returned
13347  */
13349  SCIP_VAR* var /**< problem variable */
13350  )
13351 {
13352  SCIP_Real rootsol;
13353  int i;
13354 
13355  assert(var != NULL);
13356 
13357  switch( SCIPvarGetStatus(var) )
13358  {
13360  if( var->data.original.transvar == NULL )
13361  return 0.0;
13362  return SCIPvarGetRootSol(var->data.original.transvar);
13363 
13364  case SCIP_VARSTATUS_LOOSE:
13365  case SCIP_VARSTATUS_COLUMN:
13366  return var->rootsol;
13367 
13368  case SCIP_VARSTATUS_FIXED:
13369  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13370  return var->locdom.lb;
13371 
13373  assert(!var->donotaggr);
13374  assert(var->data.aggregate.var != NULL);
13375  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13376  * corresponding infinity value instead of performing an arithmetical transformation (compare method
13377  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13378  * (or is called by) a public interface method; instead, we only assert that values are finite
13379  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13380  * positives and negatives if the parameter <numerics/infinity> is modified by the user
13381  */
13385 
13387  assert(!var->donotmultaggr);
13388  assert(var->data.multaggr.vars != NULL);
13389  assert(var->data.multaggr.scalars != NULL);
13390  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13391  * assert(var->data.multaggr.nvars >= 2);
13392  */
13393  rootsol = var->data.multaggr.constant;
13394  for( i = 0; i < var->data.multaggr.nvars; ++i )
13395  rootsol += var->data.multaggr.scalars[i] * SCIPvarGetRootSol(var->data.multaggr.vars[i]);
13396  return rootsol;
13397 
13398  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13399  assert(var->negatedvar != NULL);
13401  assert(var->negatedvar->negatedvar == var);
13402  return var->data.negate.constant - SCIPvarGetRootSol(var->negatedvar);
13403 
13404  default:
13405  SCIPerrorMessage("unknown variable status\n");
13406  SCIPABORT();
13407  return SCIP_INVALID; /*lint !e527*/
13408  }
13409 }
13410 
13411 /** returns for given variable the reduced cost */
13412 static
13414  SCIP_VAR* var, /**< problem variable */
13415  SCIP_SET* set, /**< global SCIP settings */
13416  SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
13417  SCIP_STAT* stat, /**< problem statistics */
13418  SCIP_LP* lp /**< current LP data */
13419  )
13420 {
13422  {
13423  SCIP_COL* col;
13424  SCIP_Real primsol;
13425  SCIP_BASESTAT basestat;
13426  SCIP_Bool lpissolbasic;
13427 
13428  col = SCIPvarGetCol(var);
13429  assert(col != NULL);
13430 
13431  basestat = SCIPcolGetBasisStatus(col);
13432  lpissolbasic = SCIPlpIsSolBasic(lp);
13433  primsol = SCIPcolGetPrimsol(col);
13434 
13435  if( (lpissolbasic && (basestat == SCIP_BASESTAT_LOWER || basestat == SCIP_BASESTAT_UPPER)) ||
13436  (!lpissolbasic && (SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol) || SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol))) )
13437  {
13438  SCIP_Real redcost = SCIPcolGetRedcost(col, stat, lp);
13439 
13440  assert(((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)) ||
13441  (lpissolbasic && basestat == SCIP_BASESTAT_LOWER)) ? (!SCIPsetIsDualfeasNegative(set, redcost) ||
13443  assert(((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)) ||
13444  (lpissolbasic && basestat == SCIP_BASESTAT_UPPER)) ? (!SCIPsetIsDualfeasPositive(set, redcost) ||
13445  SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var))) : TRUE);
13446 
13447  if( (varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_LOWER) ||
13448  (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)))) ||
13449  (!varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_UPPER) ||
13450  (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)))) )
13451  return redcost;
13452  else
13453  return 0.0;
13454  }
13455 
13456  return 0.0;
13457  }
13458 
13459  return 0.0;
13460 }
13461 
13462 #define MAX_CLIQUELENGTH 50
13463 /** returns for the given binary variable the reduced cost which are given by the variable itself and its implication if
13464  * the binary variable is fixed to the given value
13465  */
13467  SCIP_VAR* var, /**< problem variable */
13468  SCIP_SET* set, /**< global SCIP settings */
13469  SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
13470  SCIP_STAT* stat, /**< problem statistics */
13471  SCIP_PROB* prob, /**< transformed problem, or NULL */
13472  SCIP_LP* lp /**< current LP data */
13473  )
13474 {
13475  SCIP_Real implredcost;
13476  int ncliques;
13477  int nvars;
13478 
13479  assert(SCIPvarIsBinary(var));
13480  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
13481 
13482  /* get reduced cost of given variable */
13483  implredcost = getImplVarRedcost(var, set, varfixing, stat, lp);
13484 
13485 #ifdef SCIP_MORE_DEBUG
13486  SCIPsetDebugMsg(set, "variable <%s> itself has reduced cost of %g\n", SCIPvarGetName(var), implredcost);
13487 #endif
13488 
13489  /* the following algorithm is expensive */
13490  ncliques = SCIPvarGetNCliques(var, varfixing);
13491 
13492  if( ncliques > 0 )
13493  {
13494  SCIP_CLIQUE** cliques;
13495  SCIP_CLIQUE* clique;
13496  SCIP_VAR** clqvars;
13497  SCIP_VAR** probvars;
13498  SCIP_VAR* clqvar;
13499  SCIP_Bool* clqvalues;
13500  int* entries;
13501  int* ids;
13502  SCIP_Real redcost;
13503  SCIP_Bool cleanedup;
13504  int nclqvars;
13505  int nentries;
13506  int nids;
13507  int id;
13508  int c;
13509  int v;
13510 
13511  assert(prob != NULL);
13512  assert(SCIPprobIsTransformed(prob));
13513 
13514  nentries = SCIPprobGetNVars(prob) - SCIPprobGetNContVars(prob) + 1;
13515 
13516  SCIP_CALL_ABORT( SCIPsetAllocBufferArray(set, &ids, nentries) );
13517  nids = 0;
13518  SCIP_CALL_ABORT( SCIPsetAllocCleanBufferArray(set, &entries, nentries) );
13519 
13520  cliques = SCIPvarGetCliques(var, varfixing);
13521  assert(cliques != NULL);
13522 
13523  for( c = ncliques - 1; c >= 0; --c )
13524  {
13525  clique = cliques[c];
13526  assert(clique != NULL);
13527  nclqvars = SCIPcliqueGetNVars(clique);
13528  assert(nclqvars > 0);
13529 
13530  if( nclqvars > MAX_CLIQUELENGTH )
13531  continue;
13532 
13533  clqvars = SCIPcliqueGetVars(clique);
13534  clqvalues = SCIPcliqueGetValues(clique);
13535  assert(clqvars != NULL);
13536  assert(clqvalues != NULL);
13537 
13538  cleanedup = SCIPcliqueIsCleanedUp(clique);
13539 
13540  for( v = nclqvars - 1; v >= 0; --v )
13541  {
13542  clqvar = clqvars[v];
13543  assert(clqvar != NULL);
13544 
13545  /* ignore binary variable which are fixed */
13546  if( clqvar != var && (cleanedup || SCIPvarIsActive(clqvar)) &&
13547  (SCIPvarGetLbLocal(clqvar) < 0.5 && SCIPvarGetUbLocal(clqvar) > 0.5) )
13548  {
13549  int probindex = SCIPvarGetProbindex(clqvar) + 1;
13550  assert(0 < probindex && probindex < nentries);
13551 
13552 #if 0
13553  /* check that the variable was not yet visited or does not appear with two contradicting implications, ->
13554  * can appear since there is no guarantee that all these infeasible bounds were found
13555  */
13556  assert(!entries[probindex] || entries[probindex] == (clqvalues[v] ? probindex : -probindex));
13557 #endif
13558  if( entries[probindex] == 0 )
13559  {
13560  ids[nids] = probindex;
13561  ++nids;
13562 
13563  /* mark variable as visited */
13564  entries[probindex] = (clqvalues[v] ? probindex : -probindex);
13565  }
13566  }
13567  }
13568  }
13569 
13570  probvars = SCIPprobGetVars(prob);
13571  assert(probvars != NULL);
13572 
13573  /* add all implied reduced cost */
13574  for( v = nids - 1; v >= 0; --v )
13575  {
13576  id = ids[v];
13577  assert(0 < id && id < nentries);
13578  assert(entries[id] != 0);
13579  assert(probvars[id - 1] != NULL);
13580  assert(SCIPvarIsActive(probvars[id - 1]));
13581  assert(SCIPvarIsBinary(probvars[id - 1]));
13582  assert(SCIPvarGetLbLocal(probvars[id - 1]) < 0.5 && SCIPvarGetUbLocal(probvars[id - 1]) > 0.5);
13583 
13584  if( (entries[id] > 0) != varfixing )
13585  redcost = getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
13586  else
13587  redcost = -getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
13588 
13589  if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
13590  implredcost += redcost;
13591 
13592  /* reset entries clear buffer array */
13593  entries[id] = 0;
13594  }
13595 
13596  SCIPsetFreeCleanBufferArray(set, &entries);
13597  SCIPsetFreeBufferArray(set, &ids);
13598  }
13599 
13600 #ifdef SCIP_MORE_DEBUG
13601  SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) has implied reduced cost of %g\n", SCIPvarGetName(var), ncliques,
13602  implredcost);
13603 #endif
13604 
13605  /* collect non-binary implication information */
13606  nvars = SCIPimplicsGetNImpls(var->implics, varfixing);
13607 
13608  if( nvars > 0 )
13609  {
13610  SCIP_VAR** vars;
13611  SCIP_VAR* implvar;
13612  SCIP_COL* col;
13613  SCIP_Real* bounds;
13614  SCIP_BOUNDTYPE* boundtypes;
13615  SCIP_Real redcost;
13616  SCIP_Real lb;
13617  SCIP_Real ub;
13618  SCIP_Bool lpissolbasic;
13619  int v;
13620 
13621  vars = SCIPimplicsGetVars(var->implics, varfixing);
13622  boundtypes = SCIPimplicsGetTypes(var->implics, varfixing);
13623  bounds = SCIPimplicsGetBounds(var->implics, varfixing);
13624  lpissolbasic = SCIPlpIsSolBasic(lp);
13625 
13626  for( v = nvars - 1; v >= 0; --v )
13627  {
13628  implvar = vars[v];
13629  assert(implvar != NULL);
13630 
13631  lb = SCIPvarGetLbLocal(implvar);
13632  ub = SCIPvarGetUbLocal(implvar);
13633 
13634  /* ignore binary variable which are fixed or not of column status */
13635  if( SCIPvarGetStatus(implvar) != SCIP_VARSTATUS_COLUMN || SCIPsetIsFeasEQ(set, lb, ub) )
13636  continue;
13637 
13638  col = SCIPvarGetCol(implvar);
13639  assert(col != NULL);
13640  redcost = 0.0;
13641 
13642  /* solved lp with basis information or not? */
13643  if( lpissolbasic )
13644  {
13645  SCIP_BASESTAT basestat = SCIPcolGetBasisStatus(col);
13646 
13647  /* check if the implication is not not yet applied */
13648  if( basestat == SCIP_BASESTAT_LOWER && boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGT(set, bounds[v], lb) )
13649  {
13650  redcost = SCIPcolGetRedcost(col, stat, lp);
13651  assert(!SCIPsetIsDualfeasNegative(set, redcost));
13652 
13653  if( !varfixing )
13654  redcost *= (lb - bounds[v]);
13655  else
13656  redcost *= (bounds[v] - lb);
13657  }
13658  else if( basestat == SCIP_BASESTAT_UPPER && boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLT(set, bounds[v], ub) )
13659  {
13660  redcost = SCIPcolGetRedcost(col, stat, lp);
13661  assert(!SCIPsetIsDualfeasPositive(set, redcost));
13662 
13663  if( varfixing )
13664  redcost *= (bounds[v] - ub);
13665  else
13666  redcost *= (ub - bounds[v]);
13667  }
13668  }
13669  else
13670  {
13671  SCIP_Real primsol = SCIPcolGetPrimsol(col);
13672 
13673  /* check if the implication is not not yet applied */
13674  if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasEQ(set, lb, primsol) && SCIPsetIsFeasGT(set, bounds[v], lb) )
13675  {
13676  redcost = SCIPcolGetRedcost(col, stat, lp);
13677  assert(!SCIPsetIsDualfeasNegative(set, redcost));
13678 
13679  if( varfixing )
13680  redcost *= (lb - bounds[v]);
13681  else
13682  redcost *= (bounds[v] - lb);
13683  }
13684  else if( boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasEQ(set, ub, primsol) && SCIPsetIsFeasLT(set, bounds[v], ub) )
13685  {
13686  redcost = SCIPcolGetRedcost(col, stat, lp);
13687  assert(!SCIPsetIsDualfeasPositive(set, redcost));
13688 
13689  if( varfixing )
13690  redcost *= (bounds[v] - ub);
13691  else
13692  redcost *= (ub - bounds[v]);
13693  }
13694  }
13695 
13696  /* improve implied reduced cost */
13697  if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
13698  implredcost += redcost;
13699  }
13700  }
13701 
13702 #ifdef SCIP_MORE_DEBUG
13703  SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) and implications (%d) has implied reduced cost of %g\n",
13704  SCIPvarGetName(var), ncliques, nvars, implredcost);
13705 #endif
13706 
13707  return implredcost;
13708 }
13709 
13710 /** returns the best solution (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation, if
13711  * the root relaxation is not yet completely solved, zero is returned
13712  */
13714  SCIP_VAR* var /**< problem variable */
13715  )
13716 {
13717  SCIP_Real rootsol;
13718  int i;
13719 
13720  assert(var != NULL);
13721 
13722  switch( SCIPvarGetStatus(var) )
13723  {
13725  if( var->data.original.transvar == NULL )
13726  return 0.0;
13728 
13729  case SCIP_VARSTATUS_LOOSE:
13730  case SCIP_VARSTATUS_COLUMN:
13731  return var->bestrootsol;
13732 
13733  case SCIP_VARSTATUS_FIXED:
13734  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13735  return var->locdom.lb;
13736 
13738  assert(!var->donotaggr);
13739  assert(var->data.aggregate.var != NULL);
13740  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13741  * corresponding infinity value instead of performing an arithmetical transformation (compare method
13742  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13743  * (or is called by) a public interface method; instead, we only assert that values are finite
13744  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13745  * positives and negatives if the parameter <numerics/infinity> is modified by the user
13746  */
13750 
13752  assert(!var->donotmultaggr);
13753  assert(var->data.multaggr.vars != NULL);
13754  assert(var->data.multaggr.scalars != NULL);
13755  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13756  * assert(var->data.multaggr.nvars >= 2);
13757  */
13758  rootsol = var->data.multaggr.constant;
13759  for( i = 0; i < var->data.multaggr.nvars; ++i )
13760  rootsol += var->data.multaggr.scalars[i] * SCIPvarGetBestRootSol(var->data.multaggr.vars[i]);
13761  return rootsol;
13762 
13763  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13764  assert(var->negatedvar != NULL);
13766  assert(var->negatedvar->negatedvar == var);
13767  return var->data.negate.constant - SCIPvarGetBestRootSol(var->negatedvar);
13768 
13769  default:
13770  SCIPerrorMessage("unknown variable status\n");
13771  SCIPABORT();
13772  return 0.0; /*lint !e527*/
13773  }
13774 }
13775 
13776 /** returns the best reduced costs (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation,
13777  * if the root relaxation is not yet completely solved, or the variable was no column of the root LP, SCIP_INVALID is
13778  * returned
13779  */
13781  SCIP_VAR* var /**< problem variable */
13782  )
13783 {
13784  assert(var != NULL);
13785 
13786  switch( SCIPvarGetStatus(var) )
13787  {
13789  if( var->data.original.transvar == NULL )
13790  return SCIP_INVALID;
13792 
13793  case SCIP_VARSTATUS_LOOSE:
13794  case SCIP_VARSTATUS_COLUMN:
13795  return var->bestrootredcost;
13796 
13797  case SCIP_VARSTATUS_FIXED:
13801  return 0.0;
13802 
13803  default:
13804  SCIPerrorMessage("unknown variable status\n");
13805  SCIPABORT();
13806  return 0.0; /*lint !e527*/
13807  }
13808 }
13809 
13810 /** returns the best objective value (w.r.t. root reduced cost propagation) of the root LP which belongs the root
13811  * reduced cost which is accessible via SCIPvarGetRootRedcost() or the variable was no column of the root LP,
13812  * SCIP_INVALID is returned
13813  */
13815  SCIP_VAR* var /**< problem variable */
13816  )
13817 {
13818  assert(var != NULL);
13819 
13820  switch( SCIPvarGetStatus(var) )
13821  {
13823  if( var->data.original.transvar == NULL )
13824  return SCIP_INVALID;
13826 
13827  case SCIP_VARSTATUS_LOOSE:
13828  case SCIP_VARSTATUS_COLUMN:
13829  return var->bestrootlpobjval;
13830 
13831  case SCIP_VARSTATUS_FIXED:
13835  return SCIP_INVALID;
13836 
13837  default:
13838  SCIPerrorMessage("unknown variable status\n");
13839  SCIPABORT();
13840  return SCIP_INVALID; /*lint !e527*/
13841  }
13842 }
13843 
13844 /** set the given solution as the best root solution w.r.t. root reduced cost propagation in the variables */
13846  SCIP_VAR* var, /**< problem variable */
13847  SCIP_Real rootsol, /**< root solution value */
13848  SCIP_Real rootredcost, /**< root reduced cost */
13849  SCIP_Real rootlpobjval /**< objective value of the root LP */
13850  )
13851 {
13852  assert(var != NULL);
13853 
13854  var->bestrootsol = rootsol;
13855  var->bestrootredcost = rootredcost;
13856  var->bestrootlpobjval = rootlpobjval;
13857 }
13858 
13859 /** stores the solution value as relaxation solution in the problem variable */
13861  SCIP_VAR* var, /**< problem variable */
13862  SCIP_SET* set, /**< global SCIP settings */
13863  SCIP_RELAXATION* relaxation, /**< global relaxation data */
13864  SCIP_Real solval, /**< solution value in the current relaxation solution */
13865  SCIP_Bool updateobj /**< should the objective value be updated? */
13866  )
13867 {
13868  assert(var != NULL);
13869  assert(relaxation != NULL);
13870  assert(set != NULL);
13871  assert(var->scip == set->scip);
13872 
13873  /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
13874  switch( SCIPvarGetStatus(var) )
13875  {
13877  SCIP_CALL( SCIPvarSetRelaxSol(var->data.original.transvar, set, relaxation, solval, updateobj) );
13878  break;
13879 
13880  case SCIP_VARSTATUS_LOOSE:
13881  case SCIP_VARSTATUS_COLUMN:
13882  if( updateobj )
13883  SCIPrelaxationSolObjAdd(relaxation, var->obj * (solval - var->relaxsol));
13884  var->relaxsol = solval;
13885  break;
13886 
13887  case SCIP_VARSTATUS_FIXED:
13888  if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
13889  {
13890  SCIPerrorMessage("cannot set relaxation solution value for variable <%s> fixed to %.15g to different value %.15g\n",
13891  SCIPvarGetName(var), var->glbdom.lb, solval);
13892  return SCIP_INVALIDDATA;
13893  }
13894  break;
13895 
13896  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13897  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
13898  SCIP_CALL( SCIPvarSetRelaxSol(var->data.aggregate.var, set, relaxation,
13899  (solval - var->data.aggregate.constant)/var->data.aggregate.scalar, updateobj) );
13900  break;
13902  SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
13903  return SCIP_INVALIDDATA;
13904 
13906  SCIP_CALL( SCIPvarSetRelaxSol(var->negatedvar, set, relaxation, var->data.negate.constant - solval, updateobj) );
13907  break;
13908 
13909  default:
13910  SCIPerrorMessage("unknown variable status\n");
13911  return SCIP_INVALIDDATA;
13912  }
13913 
13914  return SCIP_OKAY;
13915 }
13916 
13917 /** returns the solution value of the problem variable in the relaxation solution
13918  *
13919  * @todo Inline this function - similar to SCIPvarGetLPSol_rec.
13920  */
13922  SCIP_VAR* var, /**< problem variable */
13923  SCIP_SET* set /**< global SCIP settings */
13924  )
13925 {
13926  SCIP_Real solvalsum;
13927  SCIP_Real solval;
13928  int i;
13929 
13930  assert(var != NULL);
13931  assert(set != NULL);
13932  assert(var->scip == set->scip);
13933 
13934  /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
13935  switch( SCIPvarGetStatus(var) )
13936  {
13938  return SCIPvarGetRelaxSol(var->data.original.transvar, set);
13939 
13940  case SCIP_VARSTATUS_LOOSE:
13941  case SCIP_VARSTATUS_COLUMN:
13942  return var->relaxsol;
13943 
13944  case SCIP_VARSTATUS_FIXED:
13945  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
13946  assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
13947  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
13948  return SCIPvarGetLbGlobal(var);
13949 
13950  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13951  solval = SCIPvarGetRelaxSol(var->data.aggregate.var, set);
13952  if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
13953  {
13954  if( var->data.aggregate.scalar * solval > 0.0 )
13955  return SCIPsetInfinity(set);
13956  if( var->data.aggregate.scalar * solval < 0.0 )
13957  return -SCIPsetInfinity(set);
13958  }
13959  return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
13960 
13962  solvalsum = var->data.multaggr.constant;
13963  for( i = 0; i < var->data.multaggr.nvars; ++i )
13964  {
13965  solval = SCIPvarGetRelaxSol(var->data.multaggr.vars[i], set);
13966  if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
13967  {
13968  if( var->data.multaggr.scalars[i] * solval > 0.0 )
13969  return SCIPsetInfinity(set);
13970  if( var->data.multaggr.scalars[i] * solval < 0.0 )
13971  return -SCIPsetInfinity(set);
13972  }
13973  solvalsum += var->data.multaggr.scalars[i] * solval;
13974  }
13975  return solvalsum;
13976 
13978  solval = SCIPvarGetRelaxSol(var->negatedvar, set);
13979  if( SCIPsetIsInfinity(set, solval) )
13980  return -SCIPsetInfinity(set);
13981  if( SCIPsetIsInfinity(set, -solval) )
13982  return SCIPsetInfinity(set);
13983  return var->data.negate.constant - solval;
13984 
13985  default:
13986  SCIPerrorMessage("unknown variable status\n");
13987  SCIPABORT();
13988  return SCIP_INVALID; /*lint !e527*/
13989  }
13990 }
13991 
13992 /** returns the solution value of the transformed problem variable in the relaxation solution */
13994  SCIP_VAR* var /**< problem variable */
13995  )
13996 {
13997  assert(var != NULL);
13999 
14000  return var->relaxsol;
14001 }
14002 
14003 /** stores the solution value as NLP solution in the problem variable */
14005  SCIP_VAR* var, /**< problem variable */
14006  SCIP_SET* set, /**< global SCIP settings */
14007  SCIP_Real solval /**< solution value in the current NLP solution */
14008  )
14009 {
14010  assert(var != NULL);
14011  assert(set != NULL);
14012  assert(var->scip == set->scip);
14013 
14014  /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
14015  switch( SCIPvarGetStatus(var) )
14016  {
14018  SCIP_CALL( SCIPvarSetNLPSol(var->data.original.transvar, set, solval) );
14019  break;
14020 
14021  case SCIP_VARSTATUS_LOOSE:
14022  case SCIP_VARSTATUS_COLUMN:
14023  var->nlpsol = solval;
14024  break;
14025 
14026  case SCIP_VARSTATUS_FIXED:
14027  if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
14028  {
14029  SCIPerrorMessage("cannot set NLP solution value for variable <%s> fixed to %.15g to different value %.15g\n",
14030  SCIPvarGetName(var), var->glbdom.lb, solval);
14031  SCIPABORT();
14032  return SCIP_INVALIDCALL; /*lint !e527*/
14033  }
14034  break;
14035 
14036  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
14037  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
14038  SCIP_CALL( SCIPvarSetNLPSol(var->data.aggregate.var, set, (solval - var->data.aggregate.constant)/var->data.aggregate.scalar) );
14039  break;
14040 
14042  SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
14043  SCIPABORT();
14044  return SCIP_INVALIDCALL; /*lint !e527*/
14045 
14047  SCIP_CALL( SCIPvarSetNLPSol(var->negatedvar, set, var->data.negate.constant - solval) );
14048  break;
14049 
14050  default:
14051  SCIPerrorMessage("unknown variable status\n");
14052  SCIPABORT();
14053  return SCIP_ERROR; /*lint !e527*/
14054  }
14055 
14056  return SCIP_OKAY;
14057 }
14058 
14059 /** returns a weighted average solution value of the variable in all feasible primal solutions found so far */
14061  SCIP_VAR* var /**< problem variable */
14062  )
14063 {
14064  SCIP_Real avgsol;
14065  int i;
14066 
14067  assert(var != NULL);
14068 
14069  switch( SCIPvarGetStatus(var) )
14070  {
14072  if( var->data.original.transvar == NULL )
14073  return 0.0;
14074  return SCIPvarGetAvgSol(var->data.original.transvar);
14075 
14076  case SCIP_VARSTATUS_LOOSE:
14077  case SCIP_VARSTATUS_COLUMN:
14078  avgsol = var->primsolavg;
14079  avgsol = MAX(avgsol, var->glbdom.lb);
14080  avgsol = MIN(avgsol, var->glbdom.ub);
14081  return avgsol;
14082 
14083  case SCIP_VARSTATUS_FIXED:
14084  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
14085  return var->locdom.lb;
14086 
14088  assert(!var->donotaggr);
14089  assert(var->data.aggregate.var != NULL);
14090  return var->data.aggregate.scalar * SCIPvarGetAvgSol(var->data.aggregate.var)
14091  + var->data.aggregate.constant;
14092 
14094  assert(!var->donotmultaggr);
14095  assert(var->data.multaggr.vars != NULL);
14096  assert(var->data.multaggr.scalars != NULL);
14097  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
14098  * assert(var->data.multaggr.nvars >= 2);
14099  */
14100  avgsol = var->data.multaggr.constant;
14101  for( i = 0; i < var->data.multaggr.nvars; ++i )
14102  avgsol += var->data.multaggr.scalars[i] * SCIPvarGetAvgSol(var->data.multaggr.vars[i]);
14103  return avgsol;
14104 
14105  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
14106  assert(var->negatedvar != NULL);
14108  assert(var->negatedvar->negatedvar == var);
14109  return var->data.negate.constant - SCIPvarGetAvgSol(var->negatedvar);
14110 
14111  default:
14112  SCIPerrorMessage("unknown variable status\n");
14113  SCIPABORT();
14114  return 0.0; /*lint !e527*/
14115  }
14116 }
14117 
14118 /** returns solution value and index of variable lower bound that is closest to the variable's value in the given primal solution
14119  * or current LP solution if no primal solution is given; returns an index of -1 if no variable lower bound is available
14120  */
14122  SCIP_VAR* var, /**< active problem variable */
14123  SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
14124  SCIP_SET* set, /**< global SCIP settings */
14125  SCIP_STAT* stat, /**< problem statistics */
14126  SCIP_Real* closestvlb, /**< pointer to store the value of the closest variable lower bound */
14127  int* closestvlbidx /**< pointer to store the index of the closest variable lower bound */
14128  )
14129 {
14130  int nvlbs;
14131 
14132  assert(var != NULL);
14133  assert(stat != NULL);
14134  assert(set != NULL);
14135  assert(var->scip == set->scip);
14136  assert(closestvlb != NULL);
14137  assert(closestvlbidx != NULL);
14138 
14139  *closestvlbidx = -1;
14140  *closestvlb = SCIP_REAL_MIN;
14141 
14142  nvlbs = SCIPvarGetNVlbs(var);
14143  if( nvlbs > 0 )
14144  {
14145  SCIP_VAR** vlbvars;
14146  SCIP_Real* vlbcoefs;
14147  SCIP_Real* vlbconsts;
14148  int i;
14149 
14150  vlbvars = SCIPvarGetVlbVars(var);
14151  vlbcoefs = SCIPvarGetVlbCoefs(var);
14152  vlbconsts = SCIPvarGetVlbConstants(var);
14153 
14154  /* check for cached values */
14155  if( var->closestvblpcount == stat->lpcount && var->closestvlbidx != -1 && sol == NULL)
14156  {
14157  i = var->closestvlbidx;
14158  assert(0 <= i && i < nvlbs);
14159  assert(SCIPvarIsActive(vlbvars[i]));
14160  *closestvlbidx = i;
14161  *closestvlb = vlbcoefs[i] * SCIPvarGetLPSol(vlbvars[i]) + vlbconsts[i];
14162  }
14163  else
14164  {
14165  /* search best VUB */
14166  for( i = 0; i < nvlbs; i++ )
14167  {
14168  if( SCIPvarIsActive(vlbvars[i]) )
14169  {
14170  SCIP_Real vlbsol;
14171 
14172  vlbsol = vlbcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vlbvars[i]) : SCIPsolGetVal(sol, set, stat, vlbvars[i])) + vlbconsts[i];
14173  if( vlbsol > *closestvlb )
14174  {
14175  *closestvlb = vlbsol;
14176  *closestvlbidx = i;
14177  }
14178  }
14179  }
14180 
14181  if( sol == NULL )
14182  {
14183  /* update cached value */
14184  if( var->closestvblpcount != stat->lpcount )
14185  var->closestvubidx = -1;
14186  var->closestvlbidx = *closestvlbidx;
14187  var->closestvblpcount = stat->lpcount;
14188  }
14189  }
14190  }
14191 }
14192 
14193 /** returns solution value and index of variable upper bound that is closest to the variable's value in the given primal solution;
14194  * or current LP solution if no primal solution is given; returns an index of -1 if no variable upper bound is available
14195  */
14197  SCIP_VAR* var, /**< active problem variable */
14198  SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
14199  SCIP_SET* set, /**< global SCIP settings */
14200  SCIP_STAT* stat, /**< problem statistics */
14201  SCIP_Real* closestvub, /**< pointer to store the value of the closest variable upper bound */
14202  int* closestvubidx /**< pointer to store the index of the closest variable upper bound */
14203  )
14204 {
14205  int nvubs;
14206 
14207  assert(var != NULL);
14208  assert(set != NULL);
14209  assert(var->scip == set->scip);
14210  assert(closestvub != NULL);
14211  assert(closestvubidx != NULL);
14212 
14213  *closestvubidx = -1;
14214  *closestvub = SCIP_REAL_MAX;
14215 
14216  nvubs = SCIPvarGetNVubs(var);
14217  if( nvubs > 0 )
14218  {
14219  SCIP_VAR** vubvars;
14220  SCIP_Real* vubcoefs;
14221  SCIP_Real* vubconsts;
14222  int i;
14223 
14224  vubvars = SCIPvarGetVubVars(var);
14225  vubcoefs = SCIPvarGetVubCoefs(var);
14226  vubconsts = SCIPvarGetVubConstants(var);
14227 
14228  /* check for cached values */
14229  if( var->closestvblpcount == stat->lpcount && var->closestvubidx != -1 && sol == NULL)
14230  {
14231  i = var->closestvubidx;
14232  assert(0 <= i && i < nvubs);
14233  assert(SCIPvarIsActive(vubvars[i]));
14234  *closestvubidx = i;
14235  *closestvub = vubcoefs[i] * SCIPvarGetLPSol(vubvars[i]) + vubconsts[i];
14236  }
14237  else
14238  {
14239  /* search best VUB */
14240  for( i = 0; i < nvubs; i++ )
14241  {
14242  if( SCIPvarIsActive(vubvars[i]) )
14243  {
14244  SCIP_Real vubsol;
14245 
14246  vubsol = vubcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vubvars[i]) : SCIPsolGetVal(sol, set, stat, vubvars[i])) + vubconsts[i];
14247  if( vubsol < *closestvub )
14248  {
14249  *closestvub = vubsol;
14250  *closestvubidx = i;
14251  }
14252  }
14253  }
14254 
14255  if( sol == NULL )
14256  {
14257  /* update cached value */
14258  if( var->closestvblpcount != stat->lpcount )
14259  var->closestvlbidx = -1;
14260  var->closestvubidx = *closestvubidx;
14261  var->closestvblpcount = stat->lpcount;
14262  }
14263  }
14264  }
14265 }
14266 
14267 /** resolves variable to columns and adds them with the coefficient to the row */
14269  SCIP_VAR* var, /**< problem variable */
14270  BMS_BLKMEM* blkmem, /**< block memory */
14271  SCIP_SET* set, /**< global SCIP settings */
14272  SCIP_STAT* stat, /**< problem statistics */
14273  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
14274  SCIP_PROB* prob, /**< problem data */
14275  SCIP_LP* lp, /**< current LP data */
14276  SCIP_ROW* row, /**< LP row */
14277  SCIP_Real val /**< value of coefficient */
14278  )
14279 {
14280  int i;
14281 
14282  assert(var != NULL);
14283  assert(set != NULL);
14284  assert(var->scip == set->scip);
14285  assert(row != NULL);
14286  assert(!SCIPsetIsInfinity(set, REALABS(val)));
14287 
14288  SCIPsetDebugMsg(set, "adding coefficient %g<%s> to row <%s>\n", val, var->name, row->name);
14289 
14290  if ( SCIPsetIsZero(set, val) )
14291  return SCIP_OKAY;
14292 
14293  switch( SCIPvarGetStatus(var) )
14294  {
14296  if( var->data.original.transvar == NULL )
14297  {
14298  SCIPerrorMessage("cannot add untransformed original variable <%s> to LP row <%s>\n", var->name, row->name);
14299  return SCIP_INVALIDDATA;
14300  }
14301  SCIP_CALL( SCIPvarAddToRow(var->data.original.transvar, blkmem, set, stat, eventqueue, prob, lp, row, val) );
14302  return SCIP_OKAY;
14303 
14304  case SCIP_VARSTATUS_LOOSE:
14305  /* add globally fixed variables as constant */
14306  if( SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub) )
14307  {
14308  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->glbdom.lb) );
14309  return SCIP_OKAY;
14310  }
14311  /* convert loose variable into column */
14312  SCIP_CALL( SCIPvarColumn(var, blkmem, set, stat, prob, lp) );
14313  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
14314  /*lint -fallthrough*/
14315 
14316  case SCIP_VARSTATUS_COLUMN:
14317  assert(var->data.col != NULL);
14318  assert(var->data.col->var == var);
14319  SCIP_CALL( SCIProwIncCoef(row, blkmem, set, eventqueue, lp, var->data.col, val) );
14320  return SCIP_OKAY;
14321 
14322  case SCIP_VARSTATUS_FIXED:
14323  assert(var->glbdom.lb == var->glbdom.ub); /*lint !e777*/
14324  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
14325  assert(var->locdom.lb == var->glbdom.lb); /*lint !e777*/
14326  assert(!SCIPsetIsInfinity(set, REALABS(var->locdom.lb)));
14327  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->locdom.lb) );
14328  return SCIP_OKAY;
14329 
14331  assert(!var->donotaggr);
14332  assert(var->data.aggregate.var != NULL);
14333  SCIP_CALL( SCIPvarAddToRow(var->data.aggregate.var, blkmem, set, stat, eventqueue, prob, lp,
14334  row, var->data.aggregate.scalar * val) );
14335  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.aggregate.constant * val) );
14336  return SCIP_OKAY;
14337 
14339  assert(!var->donotmultaggr);
14340  assert(var->data.multaggr.vars != NULL);
14341  assert(var->data.multaggr.scalars != NULL);
14342  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
14343  * assert(var->data.multaggr.nvars >= 2);
14344  */
14345  for( i = 0; i < var->data.multaggr.nvars; ++i )
14346  {
14347  SCIP_CALL( SCIPvarAddToRow(var->data.multaggr.vars[i], blkmem, set, stat, eventqueue, prob, lp,
14348  row, var->data.multaggr.scalars[i] * val) );
14349  }
14350  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.multaggr.constant * val) );
14351  return SCIP_OKAY;
14352 
14353  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
14354  assert(var->negatedvar != NULL);
14356  assert(var->negatedvar->negatedvar == var);
14357  SCIP_CALL( SCIPvarAddToRow(var->negatedvar, blkmem, set, stat, eventqueue, prob, lp, row, -val) );
14358  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.negate.constant * val) );
14359  return SCIP_OKAY;
14360 
14361  default:
14362  SCIPerrorMessage("unknown variable status\n");
14363  return SCIP_INVALIDDATA;
14364  }
14365 }
14366 
14367 /* optionally, define this compiler flag to write complete variable histories to a file */
14368 #ifdef SCIP_HISTORYTOFILE
14369 SCIP_Longint counter = 0l;
14370 const char* historypath="."; /* allows for user-defined path; use '.' for calling directory of SCIP */
14371 #include "scip/scip.h"
14372 #endif
14373 
14374 /** updates the pseudo costs of the given variable and the global pseudo costs after a change of
14375  * "solvaldelta" in the variable's solution value and resulting change of "objdelta" in the in the LP's objective value
14376  */
14378  SCIP_VAR* var, /**< problem variable */
14379  SCIP_SET* set, /**< global SCIP settings */
14380  SCIP_STAT* stat, /**< problem statistics */
14381  SCIP_Real solvaldelta, /**< difference of variable's new LP value - old LP value */
14382  SCIP_Real objdelta, /**< difference of new LP's objective value - old LP's objective value */
14383  SCIP_Real weight /**< weight in (0,1] of this update in pseudo cost sum */
14384  )
14385 {
14386  SCIP_Real oldrootpseudocosts;
14387  assert(var != NULL);
14388  assert(set != NULL);
14389  assert(var->scip == set->scip);
14390  assert(stat != NULL);
14391 
14392  /* check if history statistics should be collected for a variable */
14393  if( !stat->collectvarhistory )
14394  return SCIP_OKAY;
14395 
14396  switch( SCIPvarGetStatus(var) )
14397  {
14399  if( var->data.original.transvar == NULL )
14400  {
14401  SCIPerrorMessage("cannot update pseudo costs of original untransformed variable\n");
14402  return SCIP_INVALIDDATA;
14403  }
14404  SCIP_CALL( SCIPvarUpdatePseudocost(var->data.original.transvar, set, stat, solvaldelta, objdelta, weight) );
14405  return SCIP_OKAY;
14406 
14407  case SCIP_VARSTATUS_LOOSE:
14408  case SCIP_VARSTATUS_COLUMN:
14409  /* store old pseudo-costs for root LP best-estimate update */
14410  oldrootpseudocosts = SCIPvarGetMinPseudocostScore(var, stat, set, SCIPvarGetRootSol(var));
14411 
14412  /* update history */
14413  SCIPhistoryUpdatePseudocost(var->history, set, solvaldelta, objdelta, weight);
14414  SCIPhistoryUpdatePseudocost(var->historycrun, set, solvaldelta, objdelta, weight);
14415  SCIPhistoryUpdatePseudocost(stat->glbhistory, set, solvaldelta, objdelta, weight);
14416  SCIPhistoryUpdatePseudocost(stat->glbhistorycrun, set, solvaldelta, objdelta, weight);
14417 
14418  /* update root LP best-estimate */
14419  SCIP_CALL( SCIPstatUpdateVarRootLPBestEstimate(stat, set, var, oldrootpseudocosts) );
14420 
14421  /* append history to file */
14422 #ifdef SCIP_HISTORYTOFILE
14423  {
14424  FILE* f;
14425  char filename[256];
14426  SCIP_NODE* currentnode;
14427  SCIP_NODE* parentnode;
14428  currentnode = SCIPgetFocusNode(set->scip);
14429  parentnode = SCIPnodeGetParent(currentnode);
14430 
14431  sprintf(filename, "%s/%s.pse", historypath, SCIPgetProbName(set->scip));
14432  f = fopen(filename, "a");
14433  if( NULL != f )
14434  {
14435  fprintf(f, "%lld %s \t %lld \t %lld \t %lld \t %d \t %15.9f \t %.3f\n",
14436  ++counter,
14437  SCIPvarGetName(var),
14438  SCIPnodeGetNumber(currentnode),
14439  parentnode != NULL ? SCIPnodeGetNumber(parentnode) : -1,
14440  SCIPgetNLPIterations(set->scip),
14441  SCIPgetDepth(set->scip),
14442  objdelta,
14443  solvaldelta);
14444  fclose(f);
14445  }
14446  }
14447 #endif
14448  return SCIP_OKAY;
14449 
14450  case SCIP_VARSTATUS_FIXED:
14451  SCIPerrorMessage("cannot update pseudo cost values of a fixed variable\n");
14452  return SCIP_INVALIDDATA;
14453 
14455  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
14457  solvaldelta/var->data.aggregate.scalar, objdelta, weight) );
14458  return SCIP_OKAY;
14459 
14461  SCIPerrorMessage("cannot update pseudo cost values of a multi-aggregated variable\n");
14462  return SCIP_INVALIDDATA;
14463 
14465  SCIP_CALL( SCIPvarUpdatePseudocost(var->negatedvar, set, stat, -solvaldelta, objdelta, weight) );
14466  return SCIP_OKAY;
14467 
14468  default:
14469  SCIPerrorMessage("unknown variable status\n");
14470  return SCIP_INVALIDDATA;
14471  }
14472 }
14473 
14474 /** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value */
14476  SCIP_VAR* var, /**< problem variable */
14477  SCIP_STAT* stat, /**< problem statistics */
14478  SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
14479  )
14480 {
14481  SCIP_BRANCHDIR dir;
14482 
14483  assert(var != NULL);
14484  assert(stat != NULL);
14485 
14486  switch( SCIPvarGetStatus(var) )
14487  {
14489  if( var->data.original.transvar == NULL )
14490  return SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
14491  else
14492  return SCIPvarGetPseudocost(var->data.original.transvar, stat, solvaldelta);
14493 
14494  case SCIP_VARSTATUS_LOOSE:
14495  case SCIP_VARSTATUS_COLUMN:
14496  dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
14497 
14498  return SCIPhistoryGetPseudocostCount(var->history, dir) > 0.0
14499  ? SCIPhistoryGetPseudocost(var->history, solvaldelta)
14500  : SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
14501 
14502  case SCIP_VARSTATUS_FIXED:
14503  return 0.0;
14504 
14506  return SCIPvarGetPseudocost(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
14507 
14509  return 0.0;
14510 
14512  return SCIPvarGetPseudocost(var->negatedvar, stat, -solvaldelta);
14513 
14514  default:
14515  SCIPerrorMessage("unknown variable status\n");
14516  SCIPABORT();
14517  return 0.0; /*lint !e527*/
14518  }
14519 }
14520 
14521 /** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value,
14522  * only using the pseudo cost information of the current run
14523  */
14525  SCIP_VAR* var, /**< problem variable */
14526  SCIP_STAT* stat, /**< problem statistics */
14527  SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
14528  )
14529 {
14530  SCIP_BRANCHDIR dir;
14531 
14532  assert(var != NULL);
14533  assert(stat != NULL);
14534 
14535  switch( SCIPvarGetStatus(var) )
14536  {
14538  if( var->data.original.transvar == NULL )
14539  return SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
14540  else
14541  return SCIPvarGetPseudocostCurrentRun(var->data.original.transvar, stat, solvaldelta);
14542 
14543  case SCIP_VARSTATUS_LOOSE:
14544  case SCIP_VARSTATUS_COLUMN:
14545  dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
14546 
14547  return SCIPhistoryGetPseudocostCount(var->historycrun, dir) > 0.0
14548  ? SCIPhistoryGetPseudocost(var->historycrun, solvaldelta)
14549  : SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
14550 
14551  case SCIP_VARSTATUS_FIXED:
14552  return 0.0;
14553 
14555  return SCIPvarGetPseudocostCurrentRun(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
14556 
14558  return 0.0;
14559 
14561  return SCIPvarGetPseudocostCurrentRun(var->negatedvar, stat, -solvaldelta);
14562 
14563  default:
14564  SCIPerrorMessage("unknown variable status\n");
14565  SCIPABORT();
14566  return 0.0; /*lint !e527*/
14567  }
14568 }
14569 
14570 /** gets the variable's (possible fractional) number of pseudo cost updates for the given direction */
14572  SCIP_VAR* var, /**< problem variable */
14573  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14574  )
14575 {
14576  assert(var != NULL);
14577  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14578 
14579  switch( SCIPvarGetStatus(var) )
14580  {
14582  if( var->data.original.transvar == NULL )
14583  return 0.0;
14584  else
14585  return SCIPvarGetPseudocostCount(var->data.original.transvar, dir);
14586 
14587  case SCIP_VARSTATUS_LOOSE:
14588  case SCIP_VARSTATUS_COLUMN:
14589  return SCIPhistoryGetPseudocostCount(var->history, dir);
14590 
14591  case SCIP_VARSTATUS_FIXED:
14592  return 0.0;
14593 
14595  if( var->data.aggregate.scalar > 0.0 )
14596  return SCIPvarGetPseudocostCount(var->data.aggregate.var, dir);
14597  else
14599 
14601  return 0.0;
14602 
14605 
14606  default:
14607  SCIPerrorMessage("unknown variable status\n");
14608  SCIPABORT();
14609  return 0.0; /*lint !e527*/
14610  }
14611 }
14612 
14613 /** gets the variable's (possible fractional) number of pseudo cost updates for the given direction,
14614  * only using the pseudo cost information of the current run
14615  */
14617  SCIP_VAR* var, /**< problem variable */
14618  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14619  )
14620 {
14621  assert(var != NULL);
14622  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14623 
14624  switch( SCIPvarGetStatus(var) )
14625  {
14627  if( var->data.original.transvar == NULL )
14628  return 0.0;
14629  else
14631 
14632  case SCIP_VARSTATUS_LOOSE:
14633  case SCIP_VARSTATUS_COLUMN:
14634  return SCIPhistoryGetPseudocostCount(var->historycrun, dir);
14635 
14636  case SCIP_VARSTATUS_FIXED:
14637  return 0.0;
14638 
14640  if( var->data.aggregate.scalar > 0.0 )
14642  else
14644 
14646  return 0.0;
14647 
14650 
14651  default:
14652  SCIPerrorMessage("unknown variable status\n");
14653  SCIPABORT();
14654  return 0.0; /*lint !e527*/
14655  }
14656 }
14657 
14658 /** compares both possible directions for rounding the given solution value and returns the minimum pseudo-costs of the variable */
14660  SCIP_VAR* var, /**< problem variable */
14661  SCIP_STAT* stat, /**< problem statistics */
14662  SCIP_SET* set, /**< global SCIP settings */
14663  SCIP_Real solval /**< solution value, e.g., LP solution value */
14664  )
14665 {
14666  SCIP_Real upscore;
14667  SCIP_Real downscore;
14668  SCIP_Real solvaldeltaup;
14669  SCIP_Real solvaldeltadown;
14670 
14671  /* LP root estimate only works for variables with fractional LP root solution */
14672  if( SCIPsetIsFeasIntegral(set, solval) )
14673  return 0.0;
14674 
14675  /* no min pseudo-cost score is calculated as long as the variable was not initialized in a direction */
14677  return 0.0;
14678 
14679  /* compute delta's to ceil and floor of root LP solution value */
14680  solvaldeltaup = SCIPsetCeil(set, solval) - solval;
14681  solvaldeltadown = SCIPsetFloor(set, solval) - solval;
14682 
14683  upscore = SCIPvarGetPseudocost(var, stat, solvaldeltaup);
14684  downscore = SCIPvarGetPseudocost(var, stat, solvaldeltadown);
14685 
14686  return MIN(upscore, downscore);
14687 }
14688 
14689 /** gets the an estimate of the variable's pseudo cost variance in direction \p dir */
14691  SCIP_VAR* var, /**< problem variable */
14692  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
14693  SCIP_Bool onlycurrentrun /**< return pseudo cost variance only for current branch and bound run */
14694  )
14695 {
14696  assert(var != NULL);
14697  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14698 
14699  switch( SCIPvarGetStatus(var) )
14700  {
14702  if( var->data.original.transvar == NULL )
14703  return 0.0;
14704  else
14705  return SCIPvarGetPseudocostVariance(var->data.original.transvar, dir, onlycurrentrun);
14706 
14707  case SCIP_VARSTATUS_LOOSE:
14708  case SCIP_VARSTATUS_COLUMN:
14709  if( onlycurrentrun )
14711  else
14712  return SCIPhistoryGetPseudocostVariance(var->history, dir);
14713 
14714  case SCIP_VARSTATUS_FIXED:
14715  return 0.0;
14716 
14718  if( var->data.aggregate.scalar > 0.0 )
14719  return SCIPvarGetPseudocostVariance(var->data.aggregate.var, dir, onlycurrentrun);
14720  else
14721  return SCIPvarGetPseudocostVariance(var->data.aggregate.var, SCIPbranchdirOpposite(dir), onlycurrentrun);
14722 
14724  return 0.0;
14725 
14727  return SCIPvarGetPseudocostVariance(var->negatedvar, SCIPbranchdirOpposite(dir), onlycurrentrun);
14728 
14729  default:
14730  SCIPerrorMessage("unknown variable status\n");
14731  SCIPABORT();
14732  return 0.0; /*lint !e527*/
14733  }
14734 }
14735 
14736 /** calculates a confidence bound for this variable under the assumption of normally distributed pseudo costs
14737  *
14738  * The confidence bound \f$ \theta \geq 0\f$ denotes the interval borders \f$ [X - \theta, \ X + \theta]\f$, which contains
14739  * the true pseudo costs of the variable, i.e., the expected value of the normal distribution, with a probability
14740  * of 2 * clevel - 1.
14741  *
14742  * @return value of confidence bound for this variable
14743  */
14745  SCIP_VAR* var, /**< variable in question */
14746  SCIP_SET* set, /**< global SCIP settings */
14747  SCIP_BRANCHDIR dir, /**< the branching direction for the confidence bound */
14748  SCIP_Bool onlycurrentrun, /**< should only the current run be taken into account */
14749  SCIP_CONFIDENCELEVEL clevel /**< confidence level for the interval */
14750  )
14751 {
14752  SCIP_Real confidencebound;
14753 
14754  confidencebound = SCIPvarGetPseudocostVariance(var, dir, onlycurrentrun);
14755  if( SCIPsetIsFeasPositive(set, confidencebound) )
14756  {
14757  SCIP_Real count;
14758 
14759  if( onlycurrentrun )
14760  count = SCIPvarGetPseudocostCountCurrentRun(var, dir);
14761  else
14762  count = SCIPvarGetPseudocostCount(var, dir);
14763  /* assertion is valid because variance is positive */
14764  assert(count >= 1.9);
14765 
14766  confidencebound /= count; /*lint !e414 division by zero can obviously not occur */
14767  confidencebound = sqrt(confidencebound);
14768 
14769  /* the actual, underlying distribution of the mean is a student-t-distribution with degrees of freedom equal to
14770  * the number of pseudo cost evaluations of this variable in the respective direction. */
14771  confidencebound *= SCIPstudentTGetCriticalValue(clevel, (int)SCIPsetFloor(set, count) - 1);
14772  }
14773  else
14774  confidencebound = 0.0;
14775 
14776  return confidencebound;
14777 }
14778 
14779 /** check if the current pseudo cost relative error in a direction violates the given threshold. The Relative
14780  * Error is calculated at a specific confidence level
14781  */
14783  SCIP_VAR* var, /**< variable in question */
14784  SCIP_SET* set, /**< global SCIP settings */
14785  SCIP_STAT* stat, /**< problem statistics */
14786  SCIP_Real threshold, /**< threshold for relative errors to be considered reliable (enough) */
14787  SCIP_CONFIDENCELEVEL clevel /**< a given confidence level */
14788  )
14789 {
14790  SCIP_Real downsize;
14791  SCIP_Real upsize;
14792  SCIP_Real size;
14793  SCIP_Real relerrorup;
14794  SCIP_Real relerrordown;
14795  SCIP_Real relerror;
14796 
14797  /* check, if the pseudo cost score of the variable is reliable */
14800  size = MIN(downsize, upsize);
14801 
14802  /* Pseudo costs relative error can only be reliable if both directions have been tried at least twice */
14803  if( size <= 1.9 )
14804  return FALSE;
14805 
14806  /* use the relative error between the current mean pseudo cost value of the candidate and its upper
14807  * confidence interval bound at confidence level of 95% for individual variable reliability.
14808  * this is only possible if we have at least 2 measurements and therefore a valid variance estimate.
14809  */
14810  if( downsize >= 1.9 )
14811  {
14812  SCIP_Real normval;
14813 
14814  relerrordown = SCIPvarCalcPscostConfidenceBound(var, set, SCIP_BRANCHDIR_DOWNWARDS, TRUE, clevel);
14815  normval = SCIPvarGetPseudocostCurrentRun(var, stat, -1.0);
14816  normval = MAX(1.0, normval);
14817 
14818  relerrordown /= normval;
14819  }
14820  else
14821  relerrordown = 0.0;
14822 
14823  if( upsize >= 1.9 )
14824  {
14825  SCIP_Real normval;
14826 
14827  relerrorup = SCIPvarCalcPscostConfidenceBound(var, set, SCIP_BRANCHDIR_UPWARDS, TRUE, clevel);
14828  normval = SCIPvarGetPseudocostCurrentRun(var, stat, +1.0);
14829  normval = MAX(1.0, normval);
14830  relerrorup /= normval;
14831  }
14832  else
14833  relerrorup = 0.0;
14834 
14835  /* consider the relative error threshold violated, if it is violated in at least one branching direction */
14836  relerror = MAX(relerrorup, relerrordown);
14837 
14838  return (relerror <= threshold);
14839 }
14840 
14841 /** check if variable pseudo-costs have a significant difference in location. The significance depends on
14842  * the choice of \p clevel and on the kind of tested hypothesis. The one-sided hypothesis, which
14843  * should be rejected, is that fracy * mu_y >= fracx * mu_x, where mu_y and mu_x denote the
14844  * unknown location means of the underlying pseudo-cost distributions of x and y.
14845  *
14846  * This method is applied best if variable x has a better pseudo-cost score than y. The method hypothesizes that y were actually
14847  * better than x (despite the current information), meaning that y can be expected to yield branching
14848  * decisions as least as good as x in the long run. If the method returns TRUE, the current history information is
14849  * sufficient to safely rely on the alternative hypothesis that x yields indeed a better branching score (on average)
14850  * than y.
14851  *
14852  * @note The order of x and y matters for the one-sided hypothesis
14853  *
14854  * @note set \p onesided to FALSE if you are not sure which variable is better. The hypothesis tested then reads
14855  * fracy * mu_y == fracx * mu_x vs the alternative hypothesis fracy * mu_y != fracx * mu_x.
14856  *
14857  * @return TRUE if the hypothesis can be safely rejected at the given confidence level
14858  */
14860  SCIP_SET* set, /**< global SCIP settings */
14861  SCIP_STAT* stat, /**< problem statistics */
14862  SCIP_VAR* varx, /**< variable x */
14863  SCIP_Real fracx, /**< the fractionality of variable x */
14864  SCIP_VAR* vary, /**< variable y */
14865  SCIP_Real fracy, /**< the fractionality of variable y */
14866  SCIP_BRANCHDIR dir, /**< branching direction */
14867  SCIP_CONFIDENCELEVEL clevel, /**< confidence level for rejecting hypothesis */
14868  SCIP_Bool onesided /**< should a one-sided hypothesis y >= x be tested? */
14869  )
14870 {
14871  SCIP_Real meanx;
14872  SCIP_Real meany;
14873  SCIP_Real variancex;
14874  SCIP_Real variancey;
14875  SCIP_Real countx;
14876  SCIP_Real county;
14877  SCIP_Real tresult;
14878  SCIP_Real realdirection;
14879 
14880  if( varx == vary )
14881  return FALSE;
14882 
14883  countx = SCIPvarGetPseudocostCount(varx, dir);
14884  county = SCIPvarGetPseudocostCount(vary, dir);
14885 
14886  /* if not at least 2 measurements were taken, return FALSE */
14887  if( countx <= 1.9 || county <= 1.9 )
14888  return FALSE;
14889 
14890  realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
14891 
14892  meanx = fracx * SCIPvarGetPseudocost(varx, stat, realdirection);
14893  meany = fracy * SCIPvarGetPseudocost(vary, stat, realdirection);
14894 
14895  variancex = SQR(fracx) * SCIPvarGetPseudocostVariance(varx, dir, FALSE);
14896  variancey = SQR(fracy) * SCIPvarGetPseudocostVariance(vary, dir, FALSE);
14897 
14898  /* if there is no variance, the means are taken from a constant distribution */
14899  if( SCIPsetIsFeasEQ(set, variancex + variancey, 0.0) )
14900  return (onesided ? SCIPsetIsFeasGT(set, meanx, meany) : !SCIPsetIsFeasEQ(set, meanx, meany));
14901 
14902  tresult = SCIPcomputeTwoSampleTTestValue(meanx, meany, variancex, variancey, countx, county);
14903 
14904  /* for the two-sided hypothesis, just take the absolute of t */
14905  if( !onesided )
14906  tresult = REALABS(tresult);
14907 
14908  return (tresult >= SCIPstudentTGetCriticalValue(clevel, (int)(countx + county - 2)));
14909 }
14910 
14911 /** tests at a given confidence level whether the variable pseudo-costs only have a small probability to
14912  * exceed a \p threshold. This is useful to determine if past observations provide enough evidence
14913  * to skip an expensive strong-branching step if there is already a candidate that has been proven to yield an improvement
14914  * of at least \p threshold.
14915  *
14916  * @note use \p clevel to adjust the level of confidence. For SCIP_CONFIDENCELEVEL_MIN, the method returns TRUE if
14917  * the estimated probability to exceed \p threshold is less than 25 %.
14918  *
14919  * @see SCIP_Confidencelevel for a list of available levels. The used probability limits refer to the one-sided levels
14920  * of confidence.
14921  *
14922  * @return TRUE if the variable pseudo-cost probabilistic model is likely to be smaller than \p threshold
14923  * at the given confidence level \p clevel.
14924  */
14926  SCIP_SET* set, /**< global SCIP settings */
14927  SCIP_STAT* stat, /**< problem statistics */
14928  SCIP_VAR* var, /**< variable x */
14929  SCIP_Real frac, /**< the fractionality of variable x */
14930  SCIP_Real threshold, /**< the threshold to test against */
14931  SCIP_BRANCHDIR dir, /**< branching direction */
14932  SCIP_CONFIDENCELEVEL clevel /**< confidence level for rejecting hypothesis */
14933  )
14934 {
14935  SCIP_Real mean;
14936  SCIP_Real variance;
14937  SCIP_Real count;
14938  SCIP_Real realdirection;
14939  SCIP_Real probability;
14940  SCIP_Real problimit;
14941 
14942  count = SCIPvarGetPseudocostCount(var, dir);
14943 
14944  /* if not at least 2 measurements were taken, return FALSE */
14945  if( count <= 1.9 )
14946  return FALSE;
14947 
14948  realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
14949 
14950  mean = frac * SCIPvarGetPseudocost(var, stat, realdirection);
14951  variance = SQR(frac) * SCIPvarGetPseudocostVariance(var, dir, FALSE);
14952 
14953  /* if mean is at least threshold, it has at least a 50% probability to exceed threshold, we therefore return FALSE */
14954  if( SCIPsetIsFeasGE(set, mean, threshold) )
14955  return FALSE;
14956 
14957  /* if there is no variance, the means are taken from a constant distribution */
14958  if( SCIPsetIsFeasEQ(set, variance, 0.0) )
14959  return SCIPsetIsFeasLT(set, mean, threshold);
14960 
14961  /* obtain probability of a normally distributed random variable at given mean and variance to yield at most threshold */
14962  probability = SCIPnormalCDF(mean, variance, threshold);
14963 
14964  /* determine a probability limit corresponding to the given confidence level */
14965  switch( clevel )
14966  {
14968  problimit = 0.75;
14969  break;
14971  problimit = 0.875;
14972  break;
14974  problimit = 0.9;
14975  break;
14977  problimit = 0.95;
14978  break;
14980  problimit = 0.975;
14981  break;
14982  default:
14983  problimit = -1;
14984  SCIPerrorMessage("Confidence level set to unknown value <%d>", (int)clevel);
14985  SCIPABORT();
14986  break;
14987  }
14988 
14989  return (probability >= problimit);
14990 }
14991 
14992 /** find the corresponding history entry if already existing, otherwise create new entry */
14993 static
14995  SCIP_VAR* var, /**< problem variable */
14996  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14997  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14998  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14999  SCIP_HISTORY** history /**< pointer to store the value based history, or NULL */
15000  )
15001 {
15002  assert(var != NULL);
15003  assert(blkmem != NULL);
15004  assert(set != NULL);
15005  assert(history != NULL);
15006 
15007  (*history) = NULL;
15008 
15009  if( var->valuehistory == NULL )
15010  {
15011  SCIP_CALL( SCIPvaluehistoryCreate(&var->valuehistory, blkmem) );
15012  }
15013 
15014  SCIP_CALL( SCIPvaluehistoryFind(var->valuehistory, blkmem, set, value, history) );
15015 
15016  return SCIP_OKAY;
15017 }
15018 
15019 /** check if value based history should be used */
15020 static
15022  SCIP_VAR* var, /**< problem variable */
15023  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15024  SCIP_SET* set /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15025  )
15026 {
15027  /* check if the domain value is unknown (not specific) */
15028  if( value == SCIP_UNKNOWN ) /*lint !e777*/
15029  return FALSE;
15030 
15031  assert(set != NULL);
15032 
15033  /* check if value based history should be collected */
15034  if( !set->history_valuebased )
15035  return FALSE;
15036 
15037  /* value based history is not collected for binary variable since the standard history already contains all information */
15038  if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
15039  return FALSE;
15040 
15041  /* value based history is not collected for continuous variables */
15043  return FALSE;
15044 
15045  return TRUE;
15046 }
15047 
15048 /** increases VSIDS of the variable by the given weight */
15050  SCIP_VAR* var, /**< problem variable */
15051  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15052  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15053  SCIP_STAT* stat, /**< problem statistics */
15054  SCIP_BRANCHDIR dir, /**< branching direction */
15055  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15056  SCIP_Real weight /**< weight of this update in VSIDS */
15057  )
15058 {
15059  assert(var != NULL);
15060  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15061 
15062  /* check if history statistics should be collected for a variable */
15063  if( !stat->collectvarhistory )
15064  return SCIP_OKAY;
15065 
15066  if( SCIPsetIsZero(set, weight) )
15067  return SCIP_OKAY;
15068 
15069  switch( SCIPvarGetStatus(var) )
15070  {
15072  if( var->data.original.transvar == NULL )
15073  {
15074  SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
15075  return SCIP_INVALIDDATA;
15076  }
15077  SCIP_CALL( SCIPvarIncVSIDS(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
15078  return SCIP_OKAY;
15079 
15080  case SCIP_VARSTATUS_LOOSE:
15081  case SCIP_VARSTATUS_COLUMN:
15082  {
15083  SCIPhistoryIncVSIDS(var->history, dir, weight);
15084  SCIPhistoryIncVSIDS(var->historycrun, dir, weight);
15085 
15086  if( useValuehistory(var, value, set) )
15087  {
15088  SCIP_HISTORY* history;
15089 
15090  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15091  assert(history != NULL);
15092 
15093  SCIPhistoryIncVSIDS(history, dir, weight);
15094  SCIPsetDebugMsg(set, "variable (<%s> %s %g) + <%g> = <%g>\n", SCIPvarGetName(var), dir == SCIP_BRANCHDIR_UPWARDS ? ">=" : "<=",
15095  value, weight, SCIPhistoryGetVSIDS(history, dir));
15096  }
15097 
15098  return SCIP_OKAY;
15099  }
15100  case SCIP_VARSTATUS_FIXED:
15101  SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
15102  return SCIP_INVALIDDATA;
15103 
15105  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15106 
15107  if( var->data.aggregate.scalar > 0.0 )
15108  {
15109  SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
15110  }
15111  else
15112  {
15113  assert(var->data.aggregate.scalar < 0.0);
15114  SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15115  }
15116  return SCIP_OKAY;
15117 
15119  SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
15120  return SCIP_INVALIDDATA;
15121 
15123  value = 1.0 - value;
15124 
15125  SCIP_CALL( SCIPvarIncVSIDS(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15126  return SCIP_OKAY;
15127 
15128  default:
15129  SCIPerrorMessage("unknown variable status\n");
15130  return SCIP_INVALIDDATA;
15131  }
15132 }
15133 
15134 /** scales the VSIDS of the variable by the given scalar */
15136  SCIP_VAR* var, /**< problem variable */
15137  SCIP_Real scalar /**< scalar to multiply the VSIDSs with */
15138  )
15139 {
15140  assert(var != NULL);
15141 
15142  switch( SCIPvarGetStatus(var) )
15143  {
15145  if( var->data.original.transvar == NULL )
15146  {
15147  SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
15148  return SCIP_INVALIDDATA;
15149  }
15151  return SCIP_OKAY;
15152 
15153  case SCIP_VARSTATUS_LOOSE:
15154  case SCIP_VARSTATUS_COLUMN:
15155  {
15156  SCIPhistoryScaleVSIDS(var->history, scalar);
15157  SCIPhistoryScaleVSIDS(var->historycrun, scalar);
15159 
15160  return SCIP_OKAY;
15161  }
15162  case SCIP_VARSTATUS_FIXED:
15163  SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
15164  return SCIP_INVALIDDATA;
15165 
15167  SCIP_CALL( SCIPvarScaleVSIDS(var->data.aggregate.var, scalar) );
15168  return SCIP_OKAY;
15169 
15171  SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
15172  return SCIP_INVALIDDATA;
15173 
15175  SCIP_CALL( SCIPvarScaleVSIDS(var->negatedvar, scalar) );
15176  return SCIP_OKAY;
15177 
15178  default:
15179  SCIPerrorMessage("unknown variable status\n");
15180  return SCIP_INVALIDDATA;
15181  }
15182 }
15183 
15184 /** increases the number of active conflicts by one and the overall length of the variable by the given length */
15186  SCIP_VAR* var, /**< problem variable */
15187  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15188  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15189  SCIP_STAT* stat, /**< problem statistics */
15190  SCIP_BRANCHDIR dir, /**< branching direction */
15191  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15192  SCIP_Real length /**< length of the conflict */
15193  )
15194 {
15195  assert(var != NULL);
15196  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15197 
15198  /* check if history statistics should be collected for a variable */
15199  if( !stat->collectvarhistory )
15200  return SCIP_OKAY;
15201 
15202  switch( SCIPvarGetStatus(var) )
15203  {
15205  if( var->data.original.transvar == NULL )
15206  {
15207  SCIPerrorMessage("cannot update conflict score of original untransformed variable\n");
15208  return SCIP_INVALIDDATA;
15209  }
15210  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.original.transvar, blkmem, set, stat, dir, value, length) );
15211  return SCIP_OKAY;
15212 
15213  case SCIP_VARSTATUS_LOOSE:
15214  case SCIP_VARSTATUS_COLUMN:
15215  {
15216  SCIPhistoryIncNActiveConflicts(var->history, dir, length);
15217  SCIPhistoryIncNActiveConflicts(var->historycrun, dir, length);
15218 
15219  if( useValuehistory(var, value, set) )
15220  {
15221  SCIP_HISTORY* history;
15222 
15223  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15224  assert(history != NULL);
15225 
15226  SCIPhistoryIncNActiveConflicts(history, dir, length);
15227  }
15228 
15229  return SCIP_OKAY;
15230  }
15231  case SCIP_VARSTATUS_FIXED:
15232  SCIPerrorMessage("cannot update conflict score of a fixed variable\n");
15233  return SCIP_INVALIDDATA;
15234 
15236  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15237 
15238  if( var->data.aggregate.scalar > 0.0 )
15239  {
15240  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, dir, value, length) );
15241  }
15242  else
15243  {
15244  assert(var->data.aggregate.scalar < 0.0);
15245  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
15246  }
15247  return SCIP_OKAY;
15248 
15250  SCIPerrorMessage("cannot update conflict score of a multi-aggregated variable\n");
15251  return SCIP_INVALIDDATA;
15252 
15254  value = 1.0 - value;
15255 
15256  SCIP_CALL( SCIPvarIncNActiveConflicts(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
15257  return SCIP_OKAY;
15258 
15259  default:
15260  SCIPerrorMessage("unknown variable status\n");
15261  return SCIP_INVALIDDATA;
15262  }
15263 }
15264 
15265 /** gets the number of active conflicts containing this variable in given direction */
15267  SCIP_VAR* var, /**< problem variable */
15268  SCIP_STAT* stat, /**< problem statistics */
15269  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15270  )
15271 {
15272  assert(var != NULL);
15273  assert(stat != NULL);
15274  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15275 
15276  switch( SCIPvarGetStatus(var) )
15277  {
15279  if( var->data.original.transvar == NULL )
15280  return 0;
15281  else
15282  return SCIPvarGetNActiveConflicts(var->data.original.transvar, stat, dir);
15283 
15284  case SCIP_VARSTATUS_LOOSE:
15285  case SCIP_VARSTATUS_COLUMN:
15286  return SCIPhistoryGetNActiveConflicts(var->history, dir);
15287 
15288  case SCIP_VARSTATUS_FIXED:
15289  return 0;
15290 
15292  if( var->data.aggregate.scalar > 0.0 )
15293  return SCIPvarGetNActiveConflicts(var->data.aggregate.var, stat, dir);
15294  else
15296 
15298  return 0;
15299 
15302 
15303  default:
15304  SCIPerrorMessage("unknown variable status\n");
15305  SCIPABORT();
15306  return 0; /*lint !e527*/
15307  }
15308 }
15309 
15310 /** gets the number of active conflicts containing this variable in given direction
15311  * in the current run
15312  */
15314  SCIP_VAR* var, /**< problem variable */
15315  SCIP_STAT* stat, /**< problem statistics */
15316  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15317  )
15318 {
15319  assert(var != NULL);
15320  assert(stat != NULL);
15321  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15322 
15323  switch( SCIPvarGetStatus(var) )
15324  {
15326  if( var->data.original.transvar == NULL )
15327  return 0;
15328  else
15330 
15331  case SCIP_VARSTATUS_LOOSE:
15332  case SCIP_VARSTATUS_COLUMN:
15333  return SCIPhistoryGetNActiveConflicts(var->historycrun, dir);
15334 
15335  case SCIP_VARSTATUS_FIXED:
15336  return 0;
15337 
15339  if( var->data.aggregate.scalar > 0.0 )
15340  return SCIPvarGetNActiveConflictsCurrentRun(var->data.aggregate.var, stat, dir);
15341  else
15343 
15345  return 0;
15346 
15349 
15350  default:
15351  SCIPerrorMessage("unknown variable status\n");
15352  SCIPABORT();
15353  return 0; /*lint !e527*/
15354  }
15355 }
15356 
15357 /** gets the average conflict length in given direction due to branching on the variable */
15359  SCIP_VAR* var, /**< problem variable */
15360  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15361  )
15362 {
15363  assert(var != NULL);
15364  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15365 
15366  switch( SCIPvarGetStatus(var) )
15367  {
15369  if( var->data.original.transvar == NULL )
15370  return 0.0;
15371  else
15373 
15374  case SCIP_VARSTATUS_LOOSE:
15375  case SCIP_VARSTATUS_COLUMN:
15376  return SCIPhistoryGetAvgConflictlength(var->history, dir);
15377  case SCIP_VARSTATUS_FIXED:
15378  return 0.0;
15379 
15381  if( var->data.aggregate.scalar > 0.0 )
15382  return SCIPvarGetAvgConflictlength(var->data.aggregate.var, dir);
15383  else
15385 
15387  return 0.0;
15388 
15391 
15392  default:
15393  SCIPerrorMessage("unknown variable status\n");
15394  SCIPABORT();
15395  return 0.0; /*lint !e527*/
15396  }
15397 }
15398 
15399 /** gets the average conflict length in given direction due to branching on the variable
15400  * in the current run
15401  */
15403  SCIP_VAR* var, /**< problem variable */
15404  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15405  )
15406 {
15407  assert(var != NULL);
15408  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15409 
15410  switch( SCIPvarGetStatus(var) )
15411  {
15413  if( var->data.original.transvar == NULL )
15414  return 0.0;
15415  else
15417 
15418  case SCIP_VARSTATUS_LOOSE:
15419  case SCIP_VARSTATUS_COLUMN:
15420  return SCIPhistoryGetAvgConflictlength(var->historycrun, dir);
15421 
15422  case SCIP_VARSTATUS_FIXED:
15423  return 0.0;
15424 
15426  if( var->data.aggregate.scalar > 0.0 )
15428  else
15430 
15432  return 0.0;
15433 
15436 
15437  default:
15438  SCIPerrorMessage("unknown variable status\n");
15439  SCIPABORT();
15440  return 0.0; /*lint !e527*/
15441  }
15442 }
15443 
15444 /** increases the number of branchings counter of the variable */
15446  SCIP_VAR* var, /**< problem variable */
15447  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15448  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15449  SCIP_STAT* stat, /**< problem statistics */
15450  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
15451  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15452  int depth /**< depth at which the bound change took place */
15453  )
15454 {
15455  assert(var != NULL);
15456  assert(stat != NULL);
15457  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15458 
15459  /* check if history statistics should be collected for a variable */
15460  if( !stat->collectvarhistory )
15461  return SCIP_OKAY;
15462 
15463  switch( SCIPvarGetStatus(var) )
15464  {
15466  if( var->data.original.transvar == NULL )
15467  {
15468  SCIPerrorMessage("cannot update branching counter of original untransformed variable\n");
15469  return SCIP_INVALIDDATA;
15470  }
15471  SCIP_CALL( SCIPvarIncNBranchings(var->data.original.transvar, blkmem, set, stat, dir, value, depth) );
15472  return SCIP_OKAY;
15473 
15474  case SCIP_VARSTATUS_LOOSE:
15475  case SCIP_VARSTATUS_COLUMN:
15476  {
15477  SCIPhistoryIncNBranchings(var->history, dir, depth);
15478  SCIPhistoryIncNBranchings(var->historycrun, dir, depth);
15479  SCIPhistoryIncNBranchings(stat->glbhistory, dir, depth);
15480  SCIPhistoryIncNBranchings(stat->glbhistorycrun, dir, depth);
15481 
15482  if( useValuehistory(var, value, set) )
15483  {
15484  SCIP_HISTORY* history;
15485 
15486  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15487  assert(history != NULL);
15488 
15489  SCIPhistoryIncNBranchings(history, dir, depth);
15490  }
15491 
15492  return SCIP_OKAY;
15493  }
15494  case SCIP_VARSTATUS_FIXED:
15495  SCIPerrorMessage("cannot update branching counter of a fixed variable\n");
15496  return SCIP_INVALIDDATA;
15497 
15499  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15500 
15501  if( var->data.aggregate.scalar > 0.0 )
15502  {
15503  SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, dir, value, depth) );
15504  }
15505  else
15506  {
15507  assert(var->data.aggregate.scalar < 0.0);
15508  SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
15509  }
15510  return SCIP_OKAY;
15511 
15513  SCIPerrorMessage("cannot update branching counter of a multi-aggregated variable\n");
15514  return SCIP_INVALIDDATA;
15515 
15517  value = 1.0 - value;
15518 
15519  SCIP_CALL( SCIPvarIncNBranchings(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
15520  return SCIP_OKAY;
15521 
15522  default:
15523  SCIPerrorMessage("unknown variable status\n");
15524  return SCIP_INVALIDDATA;
15525  }
15526 }
15527 
15528 /** increases the inference sum of the variable by the given weight */
15530  SCIP_VAR* var, /**< problem variable */
15531  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15532  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15533  SCIP_STAT* stat, /**< problem statistics */
15534  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
15535  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15536  SCIP_Real weight /**< weight of this update in inference score */
15537  )
15538 {
15539  assert(var != NULL);
15540  assert(stat != NULL);
15541  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15542 
15543  /* check if history statistics should be collected for a variable */
15544  if( !stat->collectvarhistory )
15545  return SCIP_OKAY;
15546 
15547  switch( SCIPvarGetStatus(var) )
15548  {
15550  if( var->data.original.transvar == NULL )
15551  {
15552  SCIPerrorMessage("cannot update inference counter of original untransformed variable\n");
15553  return SCIP_INVALIDDATA;
15554  }
15555  SCIP_CALL( SCIPvarIncInferenceSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
15556  return SCIP_OKAY;
15557 
15558  case SCIP_VARSTATUS_LOOSE:
15559  case SCIP_VARSTATUS_COLUMN:
15560  {
15561  SCIPhistoryIncInferenceSum(var->history, dir, weight);
15562  SCIPhistoryIncInferenceSum(var->historycrun, dir, weight);
15563  SCIPhistoryIncInferenceSum(stat->glbhistory, dir, weight);
15564  SCIPhistoryIncInferenceSum(stat->glbhistorycrun, dir, weight);
15565 
15566  if( useValuehistory(var, value, set) )
15567  {
15568  SCIP_HISTORY* history;
15569 
15570  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15571  assert(history != NULL);
15572 
15573  SCIPhistoryIncInferenceSum(history, dir, weight);
15574  }
15575 
15576  return SCIP_OKAY;
15577  }
15578  case SCIP_VARSTATUS_FIXED:
15579  SCIPerrorMessage("cannot update inference counter of a fixed variable\n");
15580  return SCIP_INVALIDDATA;
15581 
15583  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15584 
15585  if( var->data.aggregate.scalar > 0.0 )
15586  {
15587  SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
15588  }
15589  else
15590  {
15591  assert(var->data.aggregate.scalar < 0.0);
15592  SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15593  }
15594  return SCIP_OKAY;
15595 
15597  SCIPerrorMessage("cannot update inference counter of a multi-aggregated variable\n");
15598  return SCIP_INVALIDDATA;
15599 
15601  value = 1.0 - value;
15602 
15603  SCIP_CALL( SCIPvarIncInferenceSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15604  return SCIP_OKAY;
15605 
15606  default:
15607  SCIPerrorMessage("unknown variable status\n");
15608  return SCIP_INVALIDDATA;
15609  }
15610 }
15611 
15612 /** increases the cutoff sum of the variable by the given weight */
15614  SCIP_VAR* var, /**< problem variable */
15615  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15616  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15617  SCIP_STAT* stat, /**< problem statistics */
15618  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
15619  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15620  SCIP_Real weight /**< weight of this update in cutoff score */
15621  )
15622 {
15623  assert(var != NULL);
15624  assert(stat != NULL);
15625  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15626 
15627  /* check if history statistics should be collected for a variable */
15628  if( !stat->collectvarhistory )
15629  return SCIP_OKAY;
15630 
15631  switch( SCIPvarGetStatus(var) )
15632  {
15634  if( var->data.original.transvar == NULL )
15635  {
15636  SCIPerrorMessage("cannot update cutoff sum of original untransformed variable\n");
15637  return SCIP_INVALIDDATA;
15638  }
15639  SCIP_CALL( SCIPvarIncCutoffSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
15640  return SCIP_OKAY;
15641 
15642  case SCIP_VARSTATUS_LOOSE:
15643  case SCIP_VARSTATUS_COLUMN:
15644  {
15645  SCIPhistoryIncCutoffSum(var->history, dir, weight);
15646  SCIPhistoryIncCutoffSum(var->historycrun, dir, weight);
15647  SCIPhistoryIncCutoffSum(stat->glbhistory, dir, weight);
15648  SCIPhistoryIncCutoffSum(stat->glbhistorycrun, dir, weight);
15649 
15650  if( useValuehistory(var, value, set) )
15651  {
15652  SCIP_HISTORY* history;
15653 
15654  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15655  assert(history != NULL);
15656 
15657  SCIPhistoryIncCutoffSum(history, dir, weight);
15658  }
15659 
15660  return SCIP_OKAY;
15661  }
15662  case SCIP_VARSTATUS_FIXED:
15663  SCIPerrorMessage("cannot update cutoff sum of a fixed variable\n");
15664  return SCIP_INVALIDDATA;
15665 
15667  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15668 
15669  if( var->data.aggregate.scalar > 0.0 )
15670  {
15671  SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
15672  }
15673  else
15674  {
15675  assert(var->data.aggregate.scalar < 0.0);
15676  SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15677  }
15678  return SCIP_OKAY;
15679 
15681  SCIPerrorMessage("cannot update cutoff sum of a multi-aggregated variable\n");
15682  return SCIP_INVALIDDATA;
15683 
15685  value = 1.0 - value;
15686 
15687  SCIP_CALL( SCIPvarIncCutoffSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15688  return SCIP_OKAY;
15689 
15690  default:
15691  SCIPerrorMessage("unknown variable status\n");
15692  return SCIP_INVALIDDATA;
15693  }
15694 }
15695 
15696 /** returns the number of times, a bound of the variable was changed in given direction due to branching */
15698  SCIP_VAR* var, /**< problem variable */
15699  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15700  )
15701 {
15702  assert(var != NULL);
15703  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15704 
15705  switch( SCIPvarGetStatus(var) )
15706  {
15708  if( var->data.original.transvar == NULL )
15709  return 0;
15710  else
15711  return SCIPvarGetNBranchings(var->data.original.transvar, dir);
15712 
15713  case SCIP_VARSTATUS_LOOSE:
15714  case SCIP_VARSTATUS_COLUMN:
15715  return SCIPhistoryGetNBranchings(var->history, dir);
15716 
15717  case SCIP_VARSTATUS_FIXED:
15718  return 0;
15719 
15721  if( var->data.aggregate.scalar > 0.0 )
15722  return SCIPvarGetNBranchings(var->data.aggregate.var, dir);
15723  else
15725 
15727  return 0;
15728 
15731 
15732  default:
15733  SCIPerrorMessage("unknown variable status\n");
15734  SCIPABORT();
15735  return 0; /*lint !e527*/
15736  }
15737 }
15738 
15739 /** returns the number of times, a bound of the variable was changed in given direction due to branching
15740  * in the current run
15741  */
15743  SCIP_VAR* var, /**< problem variable */
15744  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15745  )
15746 {
15747  assert(var != NULL);
15748  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15749 
15750  switch( SCIPvarGetStatus(var) )
15751  {
15753  if( var->data.original.transvar == NULL )
15754  return 0;
15755  else
15757 
15758  case SCIP_VARSTATUS_LOOSE:
15759  case SCIP_VARSTATUS_COLUMN:
15760  return SCIPhistoryGetNBranchings(var->historycrun, dir);
15761 
15762  case SCIP_VARSTATUS_FIXED:
15763  return 0;
15764 
15766  if( var->data.aggregate.scalar > 0.0 )
15768  else
15770 
15772  return 0;
15773 
15776 
15777  default:
15778  SCIPerrorMessage("unknown variable status\n");
15779  SCIPABORT();
15780  return 0; /*lint !e527*/
15781  }
15782 }
15783 
15784 /** returns the average depth of bound changes in given direction due to branching on the variable */
15786  SCIP_VAR* var, /**< problem variable */
15787  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15788  )
15789 {
15790  assert(var != NULL);
15791  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15792 
15793  switch( SCIPvarGetStatus(var) )
15794  {
15796  if( var->data.original.transvar == NULL )
15797  return 0.0;
15798  else
15799  return SCIPvarGetAvgBranchdepth(var->data.original.transvar, dir);
15800 
15801  case SCIP_VARSTATUS_LOOSE:
15802  case SCIP_VARSTATUS_COLUMN:
15803  return SCIPhistoryGetAvgBranchdepth(var->history, dir);
15804 
15805  case SCIP_VARSTATUS_FIXED:
15806  return 0.0;
15807 
15809  if( var->data.aggregate.scalar > 0.0 )
15810  return SCIPvarGetAvgBranchdepth(var->data.aggregate.var, dir);
15811  else
15813 
15815  return 0.0;
15816 
15819 
15820  default:
15821  SCIPerrorMessage("unknown variable status\n");
15822  SCIPABORT();
15823  return 0.0; /*lint !e527*/
15824  }
15825 }
15826 
15827 /** returns the average depth of bound changes in given direction due to branching on the variable
15828  * in the current run
15829  */
15831  SCIP_VAR* var, /**< problem variable */
15832  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15833  )
15834 {
15835  assert(var != NULL);
15836  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15837 
15838  switch( SCIPvarGetStatus(var) )
15839  {
15841  if( var->data.original.transvar == NULL )
15842  return 0.0;
15843  else
15845 
15846  case SCIP_VARSTATUS_LOOSE:
15847  case SCIP_VARSTATUS_COLUMN:
15848  return SCIPhistoryGetAvgBranchdepth(var->historycrun, dir);
15849 
15850  case SCIP_VARSTATUS_FIXED:
15851  return 0.0;
15852 
15854  if( var->data.aggregate.scalar > 0.0 )
15856  else
15859 
15861  return 0.0;
15862 
15865  dir == SCIP_BRANCHDIR_DOWNWARDS ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
15866 
15867  default:
15868  SCIPerrorMessage("unknown variable status\n");
15869  SCIPABORT();
15870  return 0.0; /*lint !e527*/
15871  }
15872 }
15873 
15874 /** returns the variable's VSIDS score */
15876  SCIP_VAR* var, /**< problem variable */
15877  SCIP_STAT* stat, /**< problem statistics */
15878  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15879  )
15880 {
15881  assert(var != NULL);
15882  assert(stat != NULL);
15883  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15884 
15886  return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
15887 
15888  switch( SCIPvarGetStatus(var) )
15889  {
15891  if( var->data.original.transvar == NULL )
15892  return 0.0;
15893  else
15894  return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
15895 
15896  case SCIP_VARSTATUS_LOOSE:
15897  case SCIP_VARSTATUS_COLUMN:
15898  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE); /* column case already handled in if condition above */
15899  return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
15900 
15901  case SCIP_VARSTATUS_FIXED:
15902  return 0.0;
15903 
15905  if( var->data.aggregate.scalar > 0.0 )
15906  return SCIPvarGetVSIDS(var->data.aggregate.var, stat, dir);
15907  else
15908  /* coverity[overrun-local] */
15909  return SCIPvarGetVSIDS(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
15910 
15912  return 0.0;
15913 
15915  /* coverity[overrun-local] */
15916  return SCIPvarGetVSIDS(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15917 
15918  default:
15919  SCIPerrorMessage("unknown variable status\n");
15920  SCIPABORT();
15921  return 0.0; /*lint !e527*/
15922  }
15923 }
15924 
15925 /** returns the variable's VSIDS score only using conflicts of the current run */
15927  SCIP_VAR* var, /**< problem variable */
15928  SCIP_STAT* stat, /**< problem statistics */
15929  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15930  )
15931 {
15932  assert(var != NULL);
15933  assert(stat != NULL);
15934  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15935 
15936  if( dir != SCIP_BRANCHDIR_DOWNWARDS && dir != SCIP_BRANCHDIR_UPWARDS )
15937  {
15938  SCIPerrorMessage("invalid branching direction %d when asking for VSIDS value\n", dir);
15939  return SCIP_INVALID;
15940  }
15941 
15942  switch( SCIPvarGetStatus(var) )
15943  {
15945  if( var->data.original.transvar == NULL )
15946  return 0.0;
15947  else
15948  return SCIPvarGetVSIDSCurrentRun(var->data.original.transvar, stat, dir);
15949 
15950  case SCIP_VARSTATUS_LOOSE:
15951  case SCIP_VARSTATUS_COLUMN:
15952  return SCIPhistoryGetVSIDS(var->historycrun, dir)/stat->vsidsweight;
15953 
15954  case SCIP_VARSTATUS_FIXED:
15955  return 0.0;
15956 
15958  if( var->data.aggregate.scalar > 0.0 )
15959  return SCIPvarGetVSIDSCurrentRun(var->data.aggregate.var, stat, dir);
15960  else
15962 
15964  return 0.0;
15965 
15968 
15969  default:
15970  SCIPerrorMessage("unknown variable status\n");
15971  SCIPABORT();
15972  return 0.0; /*lint !e527*/
15973  }
15974 }
15975 
15976 /** returns the number of inferences branching on this variable in given direction triggered */
15978  SCIP_VAR* var, /**< problem variable */
15979  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15980  )
15981 {
15982  assert(var != NULL);
15983  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15984 
15985  switch( SCIPvarGetStatus(var) )
15986  {
15988  if( var->data.original.transvar == NULL )
15989  return 0.0;
15990  else
15991  return SCIPvarGetInferenceSum(var->data.original.transvar, dir);
15992 
15993  case SCIP_VARSTATUS_LOOSE:
15994  case SCIP_VARSTATUS_COLUMN:
15995  return SCIPhistoryGetInferenceSum(var->history, dir);
15996 
15997  case SCIP_VARSTATUS_FIXED:
15998  return 0.0;
15999 
16001  if( var->data.aggregate.scalar > 0.0 )
16002  return SCIPvarGetInferenceSum(var->data.aggregate.var, dir);
16003  else
16005 
16007  return 0.0;
16008 
16011 
16012  default:
16013  SCIPerrorMessage("unknown variable status\n");
16014  SCIPABORT();
16015  return 0.0; /*lint !e527*/
16016  }
16017 }
16018 
16019 /** returns the number of inferences branching on this variable in given direction triggered
16020  * in the current run
16021  */
16023  SCIP_VAR* var, /**< problem variable */
16024  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16025  )
16026 {
16027  assert(var != NULL);
16028  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16029 
16030  switch( SCIPvarGetStatus(var) )
16031  {
16033  if( var->data.original.transvar == NULL )
16034  return 0.0;
16035  else
16037 
16038  case SCIP_VARSTATUS_LOOSE:
16039  case SCIP_VARSTATUS_COLUMN:
16040  return SCIPhistoryGetInferenceSum(var->historycrun, dir);
16041 
16042  case SCIP_VARSTATUS_FIXED:
16043  return 0.0;
16044 
16046  if( var->data.aggregate.scalar > 0.0 )
16048  else
16050 
16052  return 0.0;
16053 
16056 
16057  default:
16058  SCIPerrorMessage("unknown variable status\n");
16059  SCIPABORT();
16060  return 0.0; /*lint !e527*/
16061  }
16062 }
16063 
16064 /** returns the average number of inferences found after branching on the variable in given direction */
16066  SCIP_VAR* var, /**< problem variable */
16067  SCIP_STAT* stat, /**< problem statistics */
16068  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16069  )
16070 {
16071  assert(var != NULL);
16072  assert(stat != NULL);
16073  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16074 
16075  switch( SCIPvarGetStatus(var) )
16076  {
16078  if( var->data.original.transvar == NULL )
16079  return SCIPhistoryGetAvgInferences(stat->glbhistory, dir);
16080  else
16081  return SCIPvarGetAvgInferences(var->data.original.transvar, stat, dir);
16082 
16083  case SCIP_VARSTATUS_LOOSE:
16084  case SCIP_VARSTATUS_COLUMN:
16085  if( SCIPhistoryGetNBranchings(var->history, dir) > 0 )
16086  return SCIPhistoryGetAvgInferences(var->history, dir);
16087  else
16088  {
16089  int nimpls;
16090  int ncliques;
16091 
16092  nimpls = SCIPvarGetNImpls(var, dir == SCIP_BRANCHDIR_UPWARDS);
16093  ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
16094  return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistory, dir); /*lint !e790*/
16095  }
16096 
16097  case SCIP_VARSTATUS_FIXED:
16098  return 0.0;
16099 
16101  if( var->data.aggregate.scalar > 0.0 )
16102  return SCIPvarGetAvgInferences(var->data.aggregate.var, stat, dir);
16103  else
16105 
16107  return 0.0;
16108 
16110  return SCIPvarGetAvgInferences(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
16111 
16112  default:
16113  SCIPerrorMessage("unknown variable status\n");
16114  SCIPABORT();
16115  return 0.0; /*lint !e527*/
16116  }
16117 }
16118 
16119 /** returns the average number of inferences found after branching on the variable in given direction
16120  * in the current run
16121  */
16123  SCIP_VAR* var, /**< problem variable */
16124  SCIP_STAT* stat, /**< problem statistics */
16125  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16126  )
16127 {
16128  assert(var != NULL);
16129  assert(stat != NULL);
16130  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16131 
16132  switch( SCIPvarGetStatus(var) )
16133  {
16135  if( var->data.original.transvar == NULL )
16136  return SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir);
16137  else
16138  return SCIPvarGetAvgInferencesCurrentRun(var->data.original.transvar, stat, dir);
16139 
16140  case SCIP_VARSTATUS_LOOSE:
16141  case SCIP_VARSTATUS_COLUMN:
16142  if( SCIPhistoryGetNBranchings(var->historycrun, dir) > 0 )
16143  return SCIPhistoryGetAvgInferences(var->historycrun, dir);
16144  else
16145  {
16146  int nimpls;
16147  int ncliques;
16148 
16149  nimpls = SCIPvarGetNImpls(var, dir == SCIP_BRANCHDIR_UPWARDS);
16150  ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
16151  return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir); /*lint !e790*/
16152  }
16153 
16154  case SCIP_VARSTATUS_FIXED:
16155  return 0.0;
16156 
16158  if( var->data.aggregate.scalar > 0.0 )
16159  return SCIPvarGetAvgInferencesCurrentRun(var->data.aggregate.var, stat, dir);
16160  else
16162 
16164  return 0.0;
16165 
16168 
16169  default:
16170  SCIPerrorMessage("unknown variable status\n");
16171  SCIPABORT();
16172  return 0.0; /*lint !e527*/
16173  }
16174 }
16175 
16176 /** returns the number of cutoffs branching on this variable in given direction produced */
16178  SCIP_VAR* var, /**< problem variable */
16179  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16180  )
16181 {
16182  assert(var != NULL);
16183  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16184 
16185  switch( SCIPvarGetStatus(var) )
16186  {
16188  if( var->data.original.transvar == NULL )
16189  return 0;
16190  else
16191  return SCIPvarGetCutoffSum(var->data.original.transvar, dir);
16192 
16193  case SCIP_VARSTATUS_LOOSE:
16194  case SCIP_VARSTATUS_COLUMN:
16195  return SCIPhistoryGetCutoffSum(var->history, dir);
16196 
16197  case SCIP_VARSTATUS_FIXED:
16198  return 0;
16199 
16201  if( var->data.aggregate.scalar > 0.0 )
16202  return SCIPvarGetCutoffSum(var->data.aggregate.var, dir);
16203  else
16205 
16207  return 0;
16208 
16211 
16212  default:
16213  SCIPerrorMessage("unknown variable status\n");
16214  SCIPABORT();
16215  return 0; /*lint !e527*/
16216  }
16217 }
16218 
16219 /** returns the number of cutoffs branching on this variable in given direction produced in the current run */
16221  SCIP_VAR* var, /**< problem variable */
16222  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16223  )
16224 {
16225  assert(var != NULL);
16226  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16227 
16228  switch( SCIPvarGetStatus(var) )
16229  {
16231  if( var->data.original.transvar == NULL )
16232  return 0;
16233  else
16235 
16236  case SCIP_VARSTATUS_LOOSE:
16237  case SCIP_VARSTATUS_COLUMN:
16238  return SCIPhistoryGetCutoffSum(var->historycrun, dir);
16239 
16240  case SCIP_VARSTATUS_FIXED:
16241  return 0;
16242 
16244  if( var->data.aggregate.scalar > 0.0 )
16245  return SCIPvarGetCutoffSumCurrentRun(var->data.aggregate.var, dir);
16246  else
16248 
16250  return 0;
16251 
16254 
16255  default:
16256  SCIPerrorMessage("unknown variable status\n");
16257  SCIPABORT();
16258  return 0; /*lint !e527*/
16259  }
16260 }
16261 
16262 /** returns the average number of cutoffs found after branching on the variable in given direction */
16264  SCIP_VAR* var, /**< problem variable */
16265  SCIP_STAT* stat, /**< problem statistics */
16266  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16267  )
16268 {
16269  assert(var != NULL);
16270  assert(stat != NULL);
16271  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16272 
16273  switch( SCIPvarGetStatus(var) )
16274  {
16276  if( var->data.original.transvar == NULL )
16277  return SCIPhistoryGetAvgCutoffs(stat->glbhistory, dir);
16278  else
16279  return SCIPvarGetAvgCutoffs(var->data.original.transvar, stat, dir);
16280 
16281  case SCIP_VARSTATUS_LOOSE:
16282  case SCIP_VARSTATUS_COLUMN:
16283  return SCIPhistoryGetNBranchings(var->history, dir) > 0
16284  ? SCIPhistoryGetAvgCutoffs(var->history, dir)
16285  : SCIPhistoryGetAvgCutoffs(stat->glbhistory, dir);
16286 
16287  case SCIP_VARSTATUS_FIXED:
16288  return 0.0;
16289 
16291  if( var->data.aggregate.scalar > 0.0 )
16292  return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, dir);
16293  else
16294  return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
16295 
16297  return 0.0;
16298 
16300  return SCIPvarGetAvgCutoffs(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
16301 
16302  default:
16303  SCIPerrorMessage("unknown variable status\n");
16304  SCIPABORT();
16305  return 0.0; /*lint !e527*/
16306  }
16307 }
16308 
16309 /** returns the average number of cutoffs found after branching on the variable in given direction in the current run */
16311  SCIP_VAR* var, /**< problem variable */
16312  SCIP_STAT* stat, /**< problem statistics */
16313  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16314  )
16315 {
16316  assert(var != NULL);
16317  assert(stat != NULL);
16318  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16319 
16320  switch( SCIPvarGetStatus(var) )
16321  {
16323  if( var->data.original.transvar == NULL )
16324  return SCIPhistoryGetAvgCutoffs(stat->glbhistorycrun, dir);
16325  else
16326  return SCIPvarGetAvgCutoffsCurrentRun(var->data.original.transvar, stat, dir);
16327 
16328  case SCIP_VARSTATUS_LOOSE:
16329  case SCIP_VARSTATUS_COLUMN:
16330  return SCIPhistoryGetNBranchings(var->historycrun, dir) > 0
16333 
16334  case SCIP_VARSTATUS_FIXED:
16335  return 0.0;
16336 
16338  if( var->data.aggregate.scalar > 0.0 )
16339  return SCIPvarGetAvgCutoffsCurrentRun(var->data.aggregate.var, stat, dir);
16340  else
16342 
16344  return 0.0;
16345 
16348 
16349  default:
16350  SCIPerrorMessage("unknown variable status\n");
16351  SCIPABORT();
16352  return 0.0; /*lint !e527*/
16353  }
16354 }
16355 
16356 
16357 
16358 
16359 /*
16360  * information methods for bound changes
16361  */
16362 
16363 /** creates an artificial bound change information object with depth = INT_MAX and pos = -1 */
16365  SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
16366  BMS_BLKMEM* blkmem, /**< block memory */
16367  SCIP_VAR* var, /**< active variable that changed the bounds */
16368  SCIP_BOUNDTYPE boundtype, /**< type of bound for var: lower or upper bound */
16369  SCIP_Real oldbound, /**< old value for bound */
16370  SCIP_Real newbound /**< new value for bound */
16371  )
16372 {
16373  assert(bdchginfo != NULL);
16374 
16375  SCIP_ALLOC( BMSallocBlockMemory(blkmem, bdchginfo) );
16376  (*bdchginfo)->oldbound = oldbound;
16377  (*bdchginfo)->newbound = newbound;
16378  (*bdchginfo)->var = var;
16379  (*bdchginfo)->inferencedata.var = var;
16380  (*bdchginfo)->inferencedata.reason.prop = NULL;
16381  (*bdchginfo)->inferencedata.info = 0;
16382  (*bdchginfo)->bdchgidx.depth = INT_MAX;
16383  (*bdchginfo)->bdchgidx.pos = -1;
16384  (*bdchginfo)->pos = 0;
16385  (*bdchginfo)->boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
16386  (*bdchginfo)->boundtype = boundtype; /*lint !e641*/
16387  (*bdchginfo)->inferboundtype = boundtype; /*lint !e641*/
16388  (*bdchginfo)->redundant = FALSE;
16389 
16390  return SCIP_OKAY;
16391 }
16392 
16393 /** frees a bound change information object */
16394 void SCIPbdchginfoFree(
16395  SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
16396  BMS_BLKMEM* blkmem /**< block memory */
16397  )
16398 {
16399  assert(bdchginfo != NULL);
16400 
16401  BMSfreeBlockMemory(blkmem, bdchginfo);
16402 }
16403 
16404 /** returns the bound change information for the last lower bound change on given active problem variable before or
16405  * after the bound change with the given index was applied;
16406  * returns NULL, if no change to the lower bound was applied up to this point of time
16407  */
16409  SCIP_VAR* var, /**< active problem variable */
16410  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16411  SCIP_Bool after /**< should the bound change with given index be included? */
16412  )
16413 {
16414  int i;
16415 
16416  assert(var != NULL);
16417  assert(SCIPvarIsActive(var));
16418 
16419  /* search the correct bound change information for the given bound change index */
16420  if( after )
16421  {
16422  for( i = var->nlbchginfos-1; i >= 0; --i )
16423  {
16424  assert(var->lbchginfos[i].var == var);
16426  assert(var->lbchginfos[i].pos == i);
16427 
16428  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16429  if( var->lbchginfos[i].redundant )
16430  return NULL;
16431  assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
16432 
16433  /* if we reached the bound change index, return the current bound change info */
16434  if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->lbchginfos[i].bdchgidx) )
16435  return &var->lbchginfos[i];
16436  }
16437  }
16438  else
16439  {
16440  for( i = var->nlbchginfos-1; i >= 0; --i )
16441  {
16442  assert(var->lbchginfos[i].var == var);
16444  assert(var->lbchginfos[i].pos == i);
16445 
16446  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16447  if( var->lbchginfos[i].redundant )
16448  return NULL;
16449  assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
16450 
16451  /* if we reached the bound change index, return the current bound change info */
16452  if( SCIPbdchgidxIsEarlier(&var->lbchginfos[i].bdchgidx, bdchgidx) )
16453  return &var->lbchginfos[i];
16454  }
16455  }
16456 
16457  return NULL;
16458 }
16459 
16460 /** returns the bound change information for the last upper bound change on given active problem variable before or
16461  * after the bound change with the given index was applied;
16462  * returns NULL, if no change to the upper bound was applied up to this point of time
16463  */
16465  SCIP_VAR* var, /**< active problem variable */
16466  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16467  SCIP_Bool after /**< should the bound change with given index be included? */
16468  )
16469 {
16470  int i;
16471 
16472  assert(var != NULL);
16473  assert(SCIPvarIsActive(var));
16474 
16475  /* search the correct bound change information for the given bound change index */
16476  if( after )
16477  {
16478  for( i = var->nubchginfos-1; i >= 0; --i )
16479  {
16480  assert(var->ubchginfos[i].var == var);
16482  assert(var->ubchginfos[i].pos == i);
16483 
16484  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16485  if( var->ubchginfos[i].redundant )
16486  return NULL;
16487  assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
16488 
16489  /* if we reached the bound change index, return the current bound change info */
16490  if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->ubchginfos[i].bdchgidx) )
16491  return &var->ubchginfos[i];
16492  }
16493  }
16494  else
16495  {
16496  for( i = var->nubchginfos-1; i >= 0; --i )
16497  {
16498  assert(var->ubchginfos[i].var == var);
16500  assert(var->ubchginfos[i].pos == i);
16501 
16502  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16503  if( var->ubchginfos[i].redundant )
16504  return NULL;
16505  assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
16506 
16507  /* if we reached the bound change index, return the current bound change info */
16508  if( SCIPbdchgidxIsEarlier(&var->ubchginfos[i].bdchgidx, bdchgidx) )
16509  return &var->ubchginfos[i];
16510  }
16511  }
16512 
16513  return NULL;
16514 }
16515 
16516 /** returns the bound change information for the last lower or upper bound change on given active problem variable
16517  * before or after the bound change with the given index was applied;
16518  * returns NULL, if no change to the lower/upper bound was applied up to this point of time
16519  */
16521  SCIP_VAR* var, /**< active problem variable */
16522  SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
16523  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16524  SCIP_Bool after /**< should the bound change with given index be included? */
16525  )
16526 {
16527  if( boundtype == SCIP_BOUNDTYPE_LOWER )
16528  return SCIPvarGetLbchgInfo(var, bdchgidx, after);
16529  else
16530  {
16531  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16532  return SCIPvarGetUbchgInfo(var, bdchgidx, after);
16533  }
16534 }
16535 
16536 /** returns lower bound of variable directly before or after the bound change given by the bound change index
16537  * was applied
16538  *
16539  * @deprecated Please use SCIPgetVarLbAtIndex()
16540  */
16542  SCIP_VAR* var, /**< problem variable */
16543  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16544  SCIP_Bool after /**< should the bound change with given index be included? */
16545  )
16546 {
16547  SCIP_VARSTATUS varstatus;
16548  assert(var != NULL);
16549 
16550  varstatus = SCIPvarGetStatus(var);
16551 
16552  /* get bounds of attached variables */
16553  switch( varstatus )
16554  {
16556  assert(var->data.original.transvar != NULL);
16557  return SCIPvarGetLbAtIndex(var->data.original.transvar, bdchgidx, after);
16558 
16559  case SCIP_VARSTATUS_LOOSE:
16560  case SCIP_VARSTATUS_COLUMN:
16561  if( bdchgidx == NULL )
16562  return SCIPvarGetLbLocal(var);
16563  else
16564  {
16565  SCIP_BDCHGINFO* bdchginfo;
16566 
16567  bdchginfo = SCIPvarGetLbchgInfo(var, bdchgidx, after);
16568  if( bdchginfo != NULL )
16569  return SCIPbdchginfoGetNewbound(bdchginfo);
16570  else
16571  return var->glbdom.lb;
16572  }
16573  case SCIP_VARSTATUS_FIXED:
16574  return var->glbdom.lb;
16575 
16576  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
16577  assert(var->data.aggregate.var != NULL);
16578  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
16579  * corresponding infinity value instead of performing an arithmetical transformation (compare method
16580  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
16581  * (or is called by) a public interface method; instead, we only assert that values are finite
16582  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
16583  * positives and negatives if the parameter <numerics/infinity> is modified by the user
16584  */
16585  if( var->data.aggregate.scalar > 0.0 )
16586  {
16587  /* a > 0 -> get lower bound of y */
16588  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16589  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16590  return var->data.aggregate.scalar * SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after)
16591  + var->data.aggregate.constant;
16592  }
16593  else if( var->data.aggregate.scalar < 0.0 )
16594  {
16595  /* a < 0 -> get upper bound of y */
16596  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16597  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16598  return var->data.aggregate.scalar * SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after)
16599  + var->data.aggregate.constant;
16600  }
16601  else
16602  {
16603  SCIPerrorMessage("scalar is zero in aggregation\n");
16604  SCIPABORT();
16605  return SCIP_INVALID; /*lint !e527*/
16606  }
16607 
16609  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
16610  if ( var->data.multaggr.nvars == 1 )
16611  {
16612  assert(var->data.multaggr.vars != NULL);
16613  assert(var->data.multaggr.scalars != NULL);
16614  assert(var->data.multaggr.vars[0] != NULL);
16615 
16616  if( var->data.multaggr.scalars[0] > 0.0 )
16617  {
16618  /* a > 0 -> get lower bound of y */
16619  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16620  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16621  return var->data.multaggr.scalars[0] * SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16622  + var->data.multaggr.constant;
16623  }
16624  else if( var->data.multaggr.scalars[0] < 0.0 )
16625  {
16626  /* a < 0 -> get upper bound of y */
16627  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16628  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16629  return var->data.multaggr.scalars[0] * SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16630  + var->data.multaggr.constant;
16631  }
16632  else
16633  {
16634  SCIPerrorMessage("scalar is zero in multi-aggregation\n");
16635  SCIPABORT();
16636  return SCIP_INVALID; /*lint !e527*/
16637  }
16638  }
16639  SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
16640  SCIPABORT();
16641  return SCIP_INVALID; /*lint !e527*/
16642 
16643  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
16644  assert(var->negatedvar != NULL);
16646  assert(var->negatedvar->negatedvar == var);
16647  return var->data.negate.constant - SCIPvarGetUbAtIndex(var->negatedvar, bdchgidx, after);
16648  default:
16649  SCIPerrorMessage("unknown variable status\n");
16650  SCIPABORT();
16651  return SCIP_INVALID; /*lint !e527*/
16652  }
16653 }
16654 
16655 /** returns upper bound of variable directly before or after the bound change given by the bound change index
16656  * was applied
16657  *
16658  * @deprecated Please use SCIPgetVarUbAtIndex()
16659  */
16661  SCIP_VAR* var, /**< problem variable */
16662  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16663  SCIP_Bool after /**< should the bound change with given index be included? */
16664  )
16665 {
16666  SCIP_VARSTATUS varstatus;
16667  assert(var != NULL);
16668 
16669  varstatus = SCIPvarGetStatus(var);
16670 
16671  /* get bounds of attached variables */
16672  switch( varstatus )
16673  {
16675  assert(var->data.original.transvar != NULL);
16676  return SCIPvarGetUbAtIndex(var->data.original.transvar, bdchgidx, after);
16677 
16678  case SCIP_VARSTATUS_COLUMN:
16679  case SCIP_VARSTATUS_LOOSE:
16680  if( bdchgidx == NULL )
16681  return SCIPvarGetUbLocal(var);
16682  else
16683  {
16684  SCIP_BDCHGINFO* bdchginfo;
16685 
16686  bdchginfo = SCIPvarGetUbchgInfo(var, bdchgidx, after);
16687  if( bdchginfo != NULL )
16688  return SCIPbdchginfoGetNewbound(bdchginfo);
16689  else
16690  return var->glbdom.ub;
16691  }
16692 
16693  case SCIP_VARSTATUS_FIXED:
16694  return var->glbdom.ub;
16695 
16696  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
16697  assert(var->data.aggregate.var != NULL);
16698  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
16699  * corresponding infinity value instead of performing an arithmetical transformation (compare method
16700  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
16701  * (or is called by) a public interface method; instead, we only assert that values are finite
16702  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
16703  * positives and negatives if the parameter <numerics/infinity> is modified by the user
16704  */
16705  if( var->data.aggregate.scalar > 0.0 )
16706  {
16707  /* a > 0 -> get lower bound of y */
16708  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16709  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16710  return var->data.aggregate.scalar * SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after)
16711  + var->data.aggregate.constant;
16712  }
16713  else if( var->data.aggregate.scalar < 0.0 )
16714  {
16715  /* a < 0 -> get upper bound of y */
16716  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16717  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16718  return var->data.aggregate.scalar * SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after)
16719  + var->data.aggregate.constant;
16720  }
16721  else
16722  {
16723  SCIPerrorMessage("scalar is zero in aggregation\n");
16724  SCIPABORT();
16725  return SCIP_INVALID; /*lint !e527*/
16726  }
16727 
16729  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
16730  if ( var->data.multaggr.nvars == 1 )
16731  {
16732  assert(var->data.multaggr.vars != NULL);
16733  assert(var->data.multaggr.scalars != NULL);
16734  assert(var->data.multaggr.vars[0] != NULL);
16735 
16736  if( var->data.multaggr.scalars[0] > 0.0 )
16737  {
16738  /* a > 0 -> get lower bound of y */
16739  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16740  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16741  return var->data.multaggr.scalars[0] * SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16742  + var->data.multaggr.constant;
16743  }
16744  else if( var->data.multaggr.scalars[0] < 0.0 )
16745  {
16746  /* a < 0 -> get upper bound of y */
16747  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16748  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16749  return var->data.multaggr.scalars[0] * SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16750  + var->data.multaggr.constant;
16751  }
16752  else
16753  {
16754  SCIPerrorMessage("scalar is zero in multi-aggregation\n");
16755  SCIPABORT();
16756  return SCIP_INVALID; /*lint !e527*/
16757  }
16758  }
16759  SCIPerrorMessage("cannot get the bounds of a multiple aggregated variable.\n");
16760  SCIPABORT();
16761  return SCIP_INVALID; /*lint !e527*/
16762 
16763  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
16764  assert(var->negatedvar != NULL);
16766  assert(var->negatedvar->negatedvar == var);
16767  return var->data.negate.constant - SCIPvarGetLbAtIndex(var->negatedvar, bdchgidx, after);
16768 
16769  default:
16770  SCIPerrorMessage("unknown variable status\n");
16771  SCIPABORT();
16772  return SCIP_INVALID; /*lint !e527*/
16773  }
16774 }
16775 
16776 /** returns lower or upper bound of variable directly before or after the bound change given by the bound change index
16777  * was applied
16778  *
16779  * @deprecated Please use SCIPgetVarBdAtIndex()
16780  */
16782  SCIP_VAR* var, /**< problem variable */
16783  SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
16784  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16785  SCIP_Bool after /**< should the bound change with given index be included? */
16786  )
16787 {
16788  if( boundtype == SCIP_BOUNDTYPE_LOWER )
16789  return SCIPvarGetLbAtIndex(var, bdchgidx, after);
16790  else
16791  {
16792  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16793  return SCIPvarGetUbAtIndex(var, bdchgidx, after);
16794  }
16795 }
16796 
16797 /** returns whether the binary variable was fixed at the time given by the bound change index
16798  *
16799  * @deprecated Please use SCIPgetVarWasFixedAtIndex()
16800  */
16802  SCIP_VAR* var, /**< problem variable */
16803  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16804  SCIP_Bool after /**< should the bound change with given index be included? */
16805  )
16806 {
16807  assert(var != NULL);
16808  assert(SCIPvarIsBinary(var));
16809 
16810  /* check the current bounds first in order to decide at which bound change information we have to look
16811  * (which is expensive because we have to follow the aggregation tree to the active variable)
16812  */
16813  return ((SCIPvarGetLbLocal(var) > 0.5 && SCIPvarGetLbAtIndex(var, bdchgidx, after) > 0.5)
16814  || (SCIPvarGetUbLocal(var) < 0.5 && SCIPvarGetUbAtIndex(var, bdchgidx, after) < 0.5));
16815 }
16816 
16817 /** bound change index representing the initial time before any bound changes took place */
16818 static SCIP_BDCHGIDX initbdchgidx = {-2, 0};
16820 /** bound change index representing the presolving stage */
16821 static SCIP_BDCHGIDX presolvebdchgidx = {-1, 0};
16823 /** returns the last bound change index, at which the bounds of the given variable were tightened */
16825  SCIP_VAR* var /**< problem variable */
16826  )
16827 {
16828  SCIP_BDCHGIDX* lbchgidx;
16829  SCIP_BDCHGIDX* ubchgidx;
16830 
16831  assert(var != NULL);
16832 
16833  var = SCIPvarGetProbvar(var);
16834 
16835  /* check, if variable is original without transformed variable */
16836  if( var == NULL )
16837  return &initbdchgidx;
16838 
16839  /* check, if variable was fixed in presolving */
16840  if( !SCIPvarIsActive(var) )
16841  return &presolvebdchgidx;
16842 
16844 
16845  /* get depths of last bound change information for the lower and upper bound */
16846  lbchgidx = (var->nlbchginfos > 0 && !var->lbchginfos[var->nlbchginfos-1].redundant
16847  ? &var->lbchginfos[var->nlbchginfos-1].bdchgidx : &initbdchgidx);
16848  ubchgidx = (var->nubchginfos > 0 && !var->ubchginfos[var->nubchginfos-1].redundant
16849  ? &var->ubchginfos[var->nubchginfos-1].bdchgidx : &initbdchgidx);
16850 
16851  if( SCIPbdchgidxIsEarlierNonNull(lbchgidx, ubchgidx) )
16852  return ubchgidx;
16853  else
16854  return lbchgidx;
16855 }
16856 
16857 /** returns the last depth level, at which the bounds of the given variable were tightened;
16858  * returns -2, if the variable's bounds are still the global bounds
16859  * returns -1, if the variable was fixed in presolving
16860  */
16862  SCIP_VAR* var /**< problem variable */
16863  )
16864 {
16865  SCIP_BDCHGIDX* bdchgidx;
16866 
16867  bdchgidx = SCIPvarGetLastBdchgIndex(var);
16868  assert(bdchgidx != NULL);
16869 
16870  return bdchgidx->depth;
16871 }
16872 
16873 /** returns at which depth in the tree a bound change was applied to the variable that conflicts with the
16874  * given bound; returns -1 if the bound does not conflict with the current local bounds of the variable
16875  */
16877  SCIP_VAR* var, /**< problem variable */
16878  SCIP_SET* set, /**< global SCIP settings */
16879  SCIP_BOUNDTYPE boundtype, /**< bound type of the conflicting bound */
16880  SCIP_Real bound /**< conflicting bound */
16881  )
16882 {
16883  int i;
16884 
16885  assert(var != NULL);
16886  assert(set != NULL);
16887  assert(var->scip == set->scip);
16888 
16889  if( boundtype == SCIP_BOUNDTYPE_LOWER )
16890  {
16891  /* check if the bound is in conflict with the current local bounds */
16892  if( SCIPsetIsLE(set, bound, var->locdom.ub) )
16893  return -1;
16894 
16895  /* check if the bound is in conflict with the global bound */
16896  if( SCIPsetIsGT(set, bound, var->glbdom.ub) )
16897  return 0;
16898 
16899  /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
16900  assert(var->nubchginfos > 0);
16901  assert(SCIPsetIsGT(set, bound, var->ubchginfos[var->nubchginfos-1].newbound));
16902 
16903  /* search for the first conflicting bound change */
16904  for( i = var->nubchginfos-1; i > 0 && SCIPsetIsGT(set, bound, var->ubchginfos[i-1].newbound); --i )
16905  {
16906  assert(var->ubchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
16908  }
16909  assert(SCIPsetIsGT(set, bound, var->ubchginfos[i].newbound)); /* bound change i is conflicting */
16910  assert(i == 0 || SCIPsetIsLE(set, bound, var->ubchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
16911 
16912  /* return the depth at which the first conflicting bound change took place */
16913  return var->ubchginfos[i].bdchgidx.depth;
16914  }
16915  else
16916  {
16917  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16918 
16919  /* check if the bound is in conflict with the current local bounds */
16920  if( SCIPsetIsGE(set, bound, var->locdom.lb) )
16921  return -1;
16922 
16923  /* check if the bound is in conflict with the global bound */
16924  if( SCIPsetIsLT(set, bound, var->glbdom.lb) )
16925  return 0;
16926 
16927  /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
16928  assert(var->nlbchginfos > 0);
16929  assert(SCIPsetIsLT(set, bound, var->lbchginfos[var->nlbchginfos-1].newbound));
16930 
16931  /* search for the first conflicting bound change */
16932  for( i = var->nlbchginfos-1; i > 0 && SCIPsetIsLT(set, bound, var->lbchginfos[i-1].newbound); --i )
16933  {
16934  assert(var->lbchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
16936  }
16937  assert(SCIPsetIsLT(set, bound, var->lbchginfos[i].newbound)); /* bound change i is conflicting */
16938  assert(i == 0 || SCIPsetIsGE(set, bound, var->lbchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
16939 
16940  /* return the depth at which the first conflicting bound change took place */
16941  return var->lbchginfos[i].bdchgidx.depth;
16942  }
16943 }
16944 
16945 /** returns whether the first binary variable was fixed earlier than the second one;
16946  * returns FALSE, if the first variable is not fixed, and returns TRUE, if the first variable is fixed, but the
16947  * second one is not fixed
16948  */
16950  SCIP_VAR* var1, /**< first binary variable */
16951  SCIP_VAR* var2 /**< second binary variable */
16952  )
16953 {
16954  SCIP_BDCHGIDX* bdchgidx1;
16955  SCIP_BDCHGIDX* bdchgidx2;
16956 
16957  assert(var1 != NULL);
16958  assert(var2 != NULL);
16959  assert(SCIPvarIsBinary(var1));
16960  assert(SCIPvarIsBinary(var2));
16961 
16962  var1 = SCIPvarGetProbvar(var1);
16963  var2 = SCIPvarGetProbvar(var2);
16964  assert(var1 != NULL);
16965  assert(var2 != NULL);
16966 
16967  /* check, if variables are globally fixed */
16968  if( !SCIPvarIsActive(var2) || var2->glbdom.lb > 0.5 || var2->glbdom.ub < 0.5 )
16969  return FALSE;
16970  if( !SCIPvarIsActive(var1) || var1->glbdom.lb > 0.5 || var1->glbdom.ub < 0.5 )
16971  return TRUE;
16972 
16975  assert(SCIPvarIsBinary(var1));
16976  assert(SCIPvarIsBinary(var2));
16977  assert(var1->nlbchginfos + var1->nubchginfos <= 1);
16978  assert(var2->nlbchginfos + var2->nubchginfos <= 1);
16979  assert(var1->nlbchginfos == 0 || !var1->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
16980  assert(var1->nubchginfos == 0 || !var1->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
16981  assert(var2->nlbchginfos == 0 || !var2->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
16982  assert(var2->nubchginfos == 0 || !var2->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
16983 
16984  if( var1->nlbchginfos == 1 )
16985  bdchgidx1 = &var1->lbchginfos[0].bdchgidx;
16986  else if( var1->nubchginfos == 1 )
16987  bdchgidx1 = &var1->ubchginfos[0].bdchgidx;
16988  else
16989  bdchgidx1 = NULL;
16990 
16991  if( var2->nlbchginfos == 1 )
16992  bdchgidx2 = &var2->lbchginfos[0].bdchgidx;
16993  else if( var2->nubchginfos == 1 )
16994  bdchgidx2 = &var2->ubchginfos[0].bdchgidx;
16995  else
16996  bdchgidx2 = NULL;
16997 
16998  return SCIPbdchgidxIsEarlier(bdchgidx1, bdchgidx2);
16999 }
17000 
17001 
17002 
17003 /*
17004  * Hash functions
17005  */
17006 
17007 /** gets the key (i.e. the name) of the given variable */
17008 SCIP_DECL_HASHGETKEY(SCIPhashGetKeyVar)
17009 { /*lint --e{715}*/
17010  SCIP_VAR* var = (SCIP_VAR*)elem;
17011 
17012  assert(var != NULL);
17013  return var->name;
17014 }
17015 
17016 
17017 
17018 
17019 /*
17020  * simple functions implemented as defines
17021  */
17022 
17023 /* In debug mode, the following methods are implemented as function calls to ensure
17024  * type validity.
17025  * In optimized mode, the methods are implemented as defines to improve performance.
17026  * However, we want to have them in the library anyways, so we have to undef the defines.
17027  */
17028 
17029 #undef SCIPboundchgGetNewbound
17030 #undef SCIPboundchgGetVar
17031 #undef SCIPboundchgGetBoundchgtype
17032 #undef SCIPboundchgGetBoundtype
17033 #undef SCIPboundchgIsRedundant
17034 #undef SCIPdomchgGetNBoundchgs
17035 #undef SCIPdomchgGetBoundchg
17036 #undef SCIPholelistGetLeft
17037 #undef SCIPholelistGetRight
17038 #undef SCIPholelistGetNext
17039 #undef SCIPvarGetName
17040 #undef SCIPvarGetNUses
17041 #undef SCIPvarGetData
17042 #undef SCIPvarSetData
17043 #undef SCIPvarSetDelorigData
17044 #undef SCIPvarSetTransData
17045 #undef SCIPvarSetDeltransData
17046 #undef SCIPvarGetStatus
17047 #undef SCIPvarIsOriginal
17048 #undef SCIPvarIsTransformed
17049 #undef SCIPvarIsNegated
17050 #undef SCIPvarGetType
17051 #undef SCIPvarIsBinary
17052 #undef SCIPvarIsIntegral
17053 #undef SCIPvarIsInitial
17054 #undef SCIPvarIsRemovable
17055 #undef SCIPvarIsDeleted
17056 #undef SCIPvarIsDeletable
17057 #undef SCIPvarMarkDeletable
17058 #undef SCIPvarMarkNotDeletable
17059 #undef SCIPvarIsActive
17060 #undef SCIPvarGetIndex
17061 #undef SCIPvarGetProbindex
17062 #undef SCIPvarGetTransVar
17063 #undef SCIPvarGetCol
17064 #undef SCIPvarIsInLP
17065 #undef SCIPvarGetAggrVar
17066 #undef SCIPvarGetAggrScalar
17067 #undef SCIPvarGetAggrConstant
17068 #undef SCIPvarGetMultaggrNVars
17069 #undef SCIPvarGetMultaggrVars
17070 #undef SCIPvarGetMultaggrScalars
17071 #undef SCIPvarGetMultaggrConstant
17072 #undef SCIPvarGetNegatedVar
17073 #undef SCIPvarGetNegationVar
17074 #undef SCIPvarGetNegationConstant
17075 #undef SCIPvarGetObj
17076 #undef SCIPvarGetLbOriginal
17077 #undef SCIPvarGetUbOriginal
17078 #undef SCIPvarGetHolelistOriginal
17079 #undef SCIPvarGetLbGlobal
17080 #undef SCIPvarGetUbGlobal
17081 #undef SCIPvarGetHolelistGlobal
17082 #undef SCIPvarGetBestBoundGlobal
17083 #undef SCIPvarGetWorstBoundGlobal
17084 #undef SCIPvarGetLbLocal
17085 #undef SCIPvarGetUbLocal
17086 #undef SCIPvarGetHolelistLocal
17087 #undef SCIPvarGetBestBoundLocal
17088 #undef SCIPvarGetWorstBoundLocal
17089 #undef SCIPvarGetBestBoundType
17090 #undef SCIPvarGetWorstBoundType
17091 #undef SCIPvarGetLbLazy
17092 #undef SCIPvarGetUbLazy
17093 #undef SCIPvarGetBranchFactor
17094 #undef SCIPvarGetBranchPriority
17095 #undef SCIPvarGetBranchDirection
17096 #undef SCIPvarGetNVlbs
17097 #undef SCIPvarGetVlbVars
17098 #undef SCIPvarGetVlbCoefs
17099 #undef SCIPvarGetVlbConstants
17100 #undef SCIPvarGetNVubs
17101 #undef SCIPvarGetVubVars
17102 #undef SCIPvarGetVubCoefs
17103 #undef SCIPvarGetVubConstants
17104 #undef SCIPvarGetNImpls
17105 #undef SCIPvarGetImplVars
17106 #undef SCIPvarGetImplTypes
17107 #undef SCIPvarGetImplBounds
17108 #undef SCIPvarGetImplIds
17109 #undef SCIPvarGetNCliques
17110 #undef SCIPvarGetCliques
17111 #undef SCIPvarGetLPSol
17112 #undef SCIPvarGetNLPSol
17113 #undef SCIPvarGetBdchgInfoLb
17114 #undef SCIPvarGetNBdchgInfosLb
17115 #undef SCIPvarGetBdchgInfoUb
17116 #undef SCIPvarGetNBdchgInfosUb
17117 #undef SCIPvarGetValuehistory
17118 #undef SCIPvarGetPseudoSol
17119 #undef SCIPvarCatchEvent
17120 #undef SCIPvarDropEvent
17121 #undef SCIPvarGetVSIDS
17122 #undef SCIPvarGetCliqueComponentIdx
17123 #undef SCIPvarIsRelaxationOnly
17124 #undef SCIPvarMarkRelaxationOnly
17125 #undef SCIPbdchgidxGetPos
17126 #undef SCIPbdchgidxIsEarlierNonNull
17127 #undef SCIPbdchgidxIsEarlier
17128 #undef SCIPbdchginfoGetOldbound
17129 #undef SCIPbdchginfoGetNewbound
17130 #undef SCIPbdchginfoGetVar
17131 #undef SCIPbdchginfoGetChgtype
17132 #undef SCIPbdchginfoGetBoundtype
17133 #undef SCIPbdchginfoGetDepth
17134 #undef SCIPbdchginfoGetPos
17135 #undef SCIPbdchginfoGetIdx
17136 #undef SCIPbdchginfoGetInferVar
17137 #undef SCIPbdchginfoGetInferCons
17138 #undef SCIPbdchginfoGetInferProp
17139 #undef SCIPbdchginfoGetInferInfo
17140 #undef SCIPbdchginfoGetInferBoundtype
17141 #undef SCIPbdchginfoIsRedundant
17142 #undef SCIPbdchginfoHasInferenceReason
17143 #undef SCIPbdchginfoIsTighter
17144 
17145 
17146 /** returns the new value of the bound in the bound change data */
17148  SCIP_BOUNDCHG* boundchg /**< bound change data */
17149  )
17150 {
17151  assert(boundchg != NULL);
17152 
17153  return boundchg->newbound;
17154 }
17155 
17156 /** returns the variable of the bound change in the bound change data */
17158  SCIP_BOUNDCHG* boundchg /**< bound change data */
17159  )
17160 {
17161  assert(boundchg != NULL);
17162 
17163  return boundchg->var;
17164 }
17165 
17166 /** returns the bound change type of the bound change in the bound change data */
17168  SCIP_BOUNDCHG* boundchg /**< bound change data */
17169  )
17170 {
17171  assert(boundchg != NULL);
17172 
17173  return (SCIP_BOUNDCHGTYPE)(boundchg->boundchgtype);
17174 }
17175 
17176 /** returns the bound type of the bound change in the bound change data */
17178  SCIP_BOUNDCHG* boundchg /**< bound change data */
17179  )
17180 {
17181  assert(boundchg != NULL);
17182 
17183  return (SCIP_BOUNDTYPE)(boundchg->boundtype);
17184 }
17185 
17186 /** returns whether the bound change is redundant due to a more global bound that is at least as strong */
17188  SCIP_BOUNDCHG* boundchg /**< bound change data */
17189  )
17190 {
17191  assert(boundchg != NULL);
17192 
17193  return boundchg->redundant;
17194 }
17195 
17196 /** returns the number of bound changes in the domain change data */
17198  SCIP_DOMCHG* domchg /**< domain change data */
17199  )
17200 {
17201  return domchg != NULL ? domchg->domchgbound.nboundchgs : 0;
17202 }
17203 
17204 /** returns a particular bound change in the domain change data */
17206  SCIP_DOMCHG* domchg, /**< domain change data */
17207  int pos /**< position of the bound change in the domain change data */
17208  )
17209 {
17210  assert(domchg != NULL);
17211  assert(0 <= pos && pos < (int)domchg->domchgbound.nboundchgs);
17212 
17213  return &domchg->domchgbound.boundchgs[pos];
17214 }
17215 
17216 /** returns left bound of open interval in hole */
17218  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
17219  )
17220 {
17221  assert(holelist != NULL);
17222 
17223  return holelist->hole.left;
17224 }
17225 
17226 /** returns right bound of open interval in hole */
17228  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
17229  )
17230 {
17231  assert(holelist != NULL);
17232 
17233  return holelist->hole.right;
17234 }
17235 
17236 /** returns next hole in list */
17238  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
17239  )
17240 {
17241  assert(holelist != NULL);
17242 
17243  return holelist->next;
17244 }
17245 
17246 /** returns the name of the variable
17247  *
17248  * @note to change the name of a variable, use SCIPchgVarName() from scip.h
17249  */
17250 const char* SCIPvarGetName(
17251  SCIP_VAR* var /**< problem variable */
17252  )
17253 {
17254  assert(var != NULL);
17255 
17256  return var->name;
17257 }
17258 
17259 /** gets number of times, the variable is currently captured */
17260 int SCIPvarGetNUses(
17261  SCIP_VAR* var /**< problem variable */
17262  )
17263 {
17264  assert(var != NULL);
17265 
17266  return var->nuses;
17267 }
17268 
17269 /** returns the user data of the variable */
17271  SCIP_VAR* var /**< problem variable */
17272  )
17273 {
17274  assert(var != NULL);
17275 
17276  return var->vardata;
17277 }
17278 
17279 /** sets the user data for the variable */
17280 void SCIPvarSetData(
17281  SCIP_VAR* var, /**< problem variable */
17282  SCIP_VARDATA* vardata /**< user variable data */
17283  )
17284 {
17285  assert(var != NULL);
17286 
17287  var->vardata = vardata;
17288 }
17289 
17290 /** sets method to free user data for the original variable */
17292  SCIP_VAR* var, /**< problem variable */
17293  SCIP_DECL_VARDELORIG ((*vardelorig)) /**< frees user data of original variable */
17294  )
17295 {
17296  assert(var != NULL);
17297  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
17298 
17299  var->vardelorig = vardelorig;
17300 }
17301 
17302 /** sets method to transform user data of the variable */
17303 void SCIPvarSetTransData(
17304  SCIP_VAR* var, /**< problem variable */
17305  SCIP_DECL_VARTRANS ((*vartrans)) /**< creates transformed user data by transforming original user data */
17306  )
17307 {
17308  assert(var != NULL);
17309  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
17310 
17311  var->vartrans = vartrans;
17312 }
17313 
17314 /** sets method to free transformed user data for the variable */
17316  SCIP_VAR* var, /**< problem variable */
17317  SCIP_DECL_VARDELTRANS ((*vardeltrans)) /**< frees user data of transformed variable */
17318  )
17319 {
17320  assert(var != NULL);
17321 
17322  var->vardeltrans = vardeltrans;
17323 }
17324 
17325 /** sets method to copy this variable into sub-SCIPs */
17326 void SCIPvarSetCopyData(
17327  SCIP_VAR* var, /**< problem variable */
17328  SCIP_DECL_VARCOPY ((*varcopy)) /**< copy method of the variable */
17329  )
17330 {
17331  assert(var != NULL);
17332 
17333  var->varcopy = varcopy;
17334 }
17335 
17336 /** sets the initial flag of a variable; only possible for original or loose variables */
17338  SCIP_VAR* var, /**< problem variable */
17339  SCIP_Bool initial /**< initial flag */
17340  )
17341 {
17342  assert(var != NULL);
17343 
17345  return SCIP_INVALIDCALL;
17346 
17347  var->initial = initial;
17348 
17349  return SCIP_OKAY;
17350 }
17351 
17352 /** sets the removable flag of a variable; only possible for original or loose variables */
17354  SCIP_VAR* var, /**< problem variable */
17355  SCIP_Bool removable /**< removable flag */
17356  )
17357 {
17358  assert(var != NULL);
17359 
17361  return SCIP_INVALIDCALL;
17362 
17363  var->removable = removable;
17364 
17365  return SCIP_OKAY;
17366 }
17367 
17368 /** gets status of variable */
17370  SCIP_VAR* var /**< problem variable */
17371  )
17372 {
17373  assert(var != NULL);
17374 
17375  return (SCIP_VARSTATUS)(var->varstatus);
17376 }
17377 
17378 /** returns whether the variable belongs to the original problem */
17380  SCIP_VAR* var /**< problem variable */
17381  )
17382 {
17383  assert(var != NULL);
17384  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED || var->negatedvar != NULL);
17385 
17389 }
17390 
17391 /** returns whether the variable belongs to the transformed problem */
17393  SCIP_VAR* var /**< problem variable */
17394  )
17395 {
17396  assert(var != NULL);
17397  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED || var->negatedvar != NULL);
17398 
17402 }
17403 
17404 /** returns whether the variable was created by negation of a different variable */
17406  SCIP_VAR* var /**< problem variable */
17407  )
17408 {
17409  assert(var != NULL);
17410 
17411  return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17412 }
17413 
17414 /** gets type of variable */
17416  SCIP_VAR* var /**< problem variable */
17417  )
17418 {
17419  assert(var != NULL);
17420 
17421  return (SCIP_VARTYPE)(var->vartype);
17422 }
17423 
17424 /** returns TRUE if the variable is of binary type; this is the case if:
17425  * (1) variable type is binary
17426  * (2) variable type is integer or implicit integer and
17427  * (i) the global lower bound is greater than or equal to zero
17428  * (ii) the global upper bound is less than or equal to one
17429  */
17431  SCIP_VAR* var /**< problem variable */
17432  )
17433 {
17434  assert(var != NULL);
17435 
17436  return (SCIPvarGetType(var) == SCIP_VARTYPE_BINARY ||
17437  (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && var->glbdom.lb >= 0.0 && var->glbdom.ub <= 1.0));
17438 }
17439 
17440 /** returns whether variable is of integral type (binary, integer, or implicit integer) */
17442  SCIP_VAR* var /**< problem variable */
17443  )
17444 {
17445  assert(var != NULL);
17446 
17447  return (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
17448 }
17449 
17450 /** returns whether variable's column should be present in the initial root LP */
17452  SCIP_VAR* var /**< problem variable */
17453  )
17454 {
17455  assert(var != NULL);
17456 
17457  return var->initial;
17458 }
17459 
17460 /** returns whether variable's column is removable from the LP (due to aging or cleanup) */
17462  SCIP_VAR* var /**< problem variable */
17463  )
17464 {
17465  assert(var != NULL);
17466 
17467  return var->removable;
17468 }
17469 
17470 /** returns whether the variable was deleted from the problem */
17472  SCIP_VAR* var /**< problem variable */
17473  )
17474 {
17475  assert(var != NULL);
17476 
17477  return var->deleted;
17478 }
17479 
17480 /** marks the variable to be deletable, i.e., it may be deleted completely from the problem;
17481  * method can only be called before the variable is added to the problem by SCIPaddVar() or SCIPaddPricedVar()
17482  */
17484  SCIP_VAR* var /**< problem variable */
17485  )
17486 {
17487  assert(var != NULL);
17488  assert(var->probindex == -1);
17489 
17490  var->deletable = TRUE;
17491 }
17492 
17493 /** marks the variable to be not deletable from the problem */
17496  )
17497 {
17498  assert(var != NULL);
17499 
17500  var->deletable = FALSE;
17501 }
17502 
17503 /** marks variable to be deleted from global structures (cliques etc.) when cleaning up
17504  *
17505  * @note: this is not equivalent to marking the variable itself for deletion, this is done by using SCIPvarMarkDeletable()
17506  */
17508  SCIP_VAR* var /**< problem variable */
17509  )
17510 {
17511  assert(var != NULL);
17512 
17513  var->delglobalstructs = TRUE;
17514 }
17515 
17516 /** returns whether the variable was flagged for deletion from global structures (cliques etc.) */
17518  SCIP_VAR* var /**< problem variable */
17519  )
17520 {
17521  assert(var != NULL);
17522 
17523  return var->delglobalstructs;
17524 }
17525 
17526 /** returns whether a variable has been introduced to define a relaxation
17527  *
17528  * These variables are only valid for the current SCIP solve round,
17529  * they are not contained in any (checked) constraints, but may be used
17530  * in cutting planes, for example.
17531  * Relaxation-only variables are not copied by SCIPcopyVars and cuts
17532  * that contain these variables are not added as linear constraints when
17533  * restarting or transferring information from a copied SCIP to a SCIP.
17534  * Also conflicts with relaxation-only variables are not generated at
17535  * the moment.
17536  */
17538  SCIP_VAR* var /**< problem variable */
17539  )
17540 {
17541  assert(var != NULL);
17542 
17543  return var->relaxationonly;
17544 }
17545 
17546 /** marks that this variable has only been introduced to define a relaxation
17547  *
17548  * The variable must not have a coefficient in the objective and must be deletable.
17549  * If it is not marked deletable, it will be marked as deletable, which is only possible
17550  * before the variable is added to a problem.
17551  *
17552  * @see SCIPvarIsRelaxationOnly
17553  * @see SCIPvarMarkDeletable
17554  */
17556  SCIP_VAR* var /**< problem variable */
17557  )
17558 {
17559  assert(var != NULL);
17560  assert(SCIPvarGetObj(var) == 0.0);
17561 
17562  if( !SCIPvarIsDeletable(var) )
17563  SCIPvarMarkDeletable(var);
17564 
17565  var->relaxationonly = TRUE;
17566 }
17567 
17568 /** returns whether variable is allowed to be deleted completely from the problem */
17571  )
17572 {
17573  assert(var != NULL);
17574 
17575  return var->deletable;
17576 }
17577 
17578 /** returns whether variable is an active (neither fixed nor aggregated) variable */
17580  SCIP_VAR* var /**< problem variable */
17581  )
17582 {
17583  assert(var != NULL);
17584 
17585  return (var->probindex >= 0);
17586 }
17587 
17588 /** gets unique index of variable */
17589 int SCIPvarGetIndex(
17590  SCIP_VAR* var /**< problem variable */
17591  )
17592 {
17593  assert(var != NULL);
17594 
17595  return var->index;
17596 }
17597 
17598 /** gets position of variable in problem, or -1 if variable is not active */
17600  SCIP_VAR* var /**< problem variable */
17601  )
17602 {
17603  assert(var != NULL);
17604 
17605  return var->probindex;
17606 }
17607 
17608 /** gets transformed variable of ORIGINAL variable */
17610  SCIP_VAR* var /**< problem variable */
17611  )
17612 {
17613  assert(var != NULL);
17614  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
17615 
17616  return var->data.original.transvar;
17617 }
17618 
17619 /** gets column of COLUMN variable */
17621  SCIP_VAR* var /**< problem variable */
17622  )
17623 {
17624  assert(var != NULL);
17625  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
17626 
17627  return var->data.col;
17628 }
17629 
17630 /** returns whether the variable is a COLUMN variable that is member of the current LP */
17632  SCIP_VAR* var /**< problem variable */
17633  )
17634 {
17635  assert(var != NULL);
17636 
17637  return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN && SCIPcolIsInLP(var->data.col));
17638 }
17639 
17640 /** gets aggregation variable y of an aggregated variable x = a*y + c */
17642  SCIP_VAR* var /**< problem variable */
17643  )
17644 {
17645  assert(var != NULL);
17647  assert(!var->donotaggr);
17648 
17649  return var->data.aggregate.var;
17650 }
17651 
17652 /** gets aggregation scalar a of an aggregated variable x = a*y + c */
17654  SCIP_VAR* var /**< problem variable */
17655  )
17656 {
17657  assert(var != NULL);
17659  assert(!var->donotaggr);
17660 
17661  return var->data.aggregate.scalar;
17662 }
17663 
17664 /** gets aggregation constant c of an aggregated variable x = a*y + c */
17666  SCIP_VAR* var /**< problem variable */
17667  )
17668 {
17669  assert(var != NULL);
17671  assert(!var->donotaggr);
17672 
17673  return var->data.aggregate.constant;
17674 }
17675 
17676 /** gets number n of aggregation variables of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17678  SCIP_VAR* var /**< problem variable */
17679  )
17680 {
17681  assert(var != NULL);
17682  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17683  assert(!var->donotmultaggr);
17684 
17685  return var->data.multaggr.nvars;
17686 }
17687 
17688 /** gets vector of aggregation variables y of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17690  SCIP_VAR* var /**< problem variable */
17691  )
17692 {
17693  assert(var != NULL);
17694  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17695  assert(!var->donotmultaggr);
17696 
17697  return var->data.multaggr.vars;
17698 }
17699 
17700 /** gets vector of aggregation scalars a of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17702  SCIP_VAR* var /**< problem variable */
17703  )
17704 {
17705  assert(var != NULL);
17706  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17707  assert(!var->donotmultaggr);
17708 
17709  return var->data.multaggr.scalars;
17710 }
17711 
17712 /** gets aggregation constant c of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17714  SCIP_VAR* var /**< problem variable */
17715  )
17716 {
17717  assert(var != NULL);
17718  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17719  assert(!var->donotmultaggr);
17720 
17721  return var->data.multaggr.constant;
17722 }
17723 
17724 /** gets the negation of the given variable; may return NULL, if no negation is existing yet */
17726  SCIP_VAR* var /**< negated problem variable */
17727  )
17728 {
17729  assert(var != NULL);
17730 
17731  return var->negatedvar;
17732 }
17733 
17734 /** gets the negation variable x of a negated variable x' = offset - x */
17736  SCIP_VAR* var /**< negated problem variable */
17737  )
17738 {
17739  assert(var != NULL);
17740  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17741 
17742  return var->negatedvar;
17743 }
17744 
17745 /** gets the negation offset of a negated variable x' = offset - x */
17747  SCIP_VAR* var /**< negated problem variable */
17748  )
17749 {
17750  assert(var != NULL);
17751  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17752 
17753  return var->data.negate.constant;
17754 }
17755 
17756 /** gets objective function value of variable */
17758  SCIP_VAR* var /**< problem variable */
17759  )
17760 {
17761  assert(var != NULL);
17762 
17763  return var->obj;
17764 }
17765 
17766 /** gets the unchanged objective function value of a variable (ignoring temproray changes performed in probing mode) */
17768  SCIP_VAR* var /**< problem variable */
17769  )
17770 {
17771  assert(var != NULL);
17772 
17773  return var->unchangedobj;
17774 }
17775 
17776 /** gets corresponding objective value of active, fixed, or multi-aggregated problem variable of given variable
17777  * e.g. obj(x) = 1 this method returns for ~x the value -1
17778  */
17780  SCIP_VAR* var, /**< problem variable */
17781  SCIP_Real* aggrobj /**< pointer to store the aggregated objective value */
17782  )
17783 {
17784  SCIP_VAR* probvar = var;
17785  SCIP_Real mult = 1.0;
17786 
17787  assert(probvar != NULL);
17788  assert(aggrobj != NULL);
17789 
17790  while( probvar != NULL )
17791  {
17792  switch( SCIPvarGetStatus(probvar) )
17793  {
17795  case SCIP_VARSTATUS_LOOSE:
17796  case SCIP_VARSTATUS_COLUMN:
17797  (*aggrobj) = mult * SCIPvarGetObj(probvar);
17798  return SCIP_OKAY;
17799 
17800  case SCIP_VARSTATUS_FIXED:
17801  assert(SCIPvarGetObj(probvar) == 0.0);
17802  (*aggrobj) = 0.0;
17803  return SCIP_OKAY;
17804 
17806  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
17807  if ( probvar->data.multaggr.nvars == 1 )
17808  {
17809  assert( probvar->data.multaggr.vars != NULL );
17810  assert( probvar->data.multaggr.scalars != NULL );
17811  assert( probvar->data.multaggr.vars[0] != NULL );
17812  mult *= probvar->data.multaggr.scalars[0];
17813  probvar = probvar->data.multaggr.vars[0];
17814  break;
17815  }
17816  else
17817  {
17818  SCIP_Real tmpobj;
17819  int v;
17820 
17821  (*aggrobj) = 0.0;
17822 
17823  for( v = probvar->data.multaggr.nvars - 1; v >= 0; --v )
17824  {
17825  SCIP_CALL( SCIPvarGetAggregatedObj(probvar->data.multaggr.vars[v], &tmpobj) );
17826  (*aggrobj) += probvar->data.multaggr.scalars[v] * tmpobj;
17827  }
17828  return SCIP_OKAY;
17829  }
17830 
17831  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
17832  assert(probvar->data.aggregate.var != NULL);
17833  mult *= probvar->data.aggregate.scalar;
17834  probvar = probvar->data.aggregate.var;
17835  break;
17836 
17837  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
17838  assert(probvar->negatedvar != NULL);
17839  assert(SCIPvarGetStatus(probvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
17840  assert(probvar->negatedvar->negatedvar == probvar);
17841  mult *= -1.0;
17842  probvar = probvar->negatedvar;
17843  break;
17844 
17845  default:
17846  SCIPABORT();
17847  return SCIP_INVALIDDATA; /*lint !e527*/
17848  }
17849  }
17850 
17851  return SCIP_INVALIDDATA;
17852 }
17853 
17854 /** gets original lower bound of original problem variable (i.e. the bound set in problem creation) */
17856  SCIP_VAR* var /**< original problem variable */
17857  )
17858 {
17859  assert(var != NULL);
17860  assert(SCIPvarIsOriginal(var));
17861 
17863  return var->data.original.origdom.lb;
17864  else
17865  {
17866  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17867  assert(var->negatedvar != NULL);
17869 
17870  return var->data.negate.constant - var->negatedvar->data.original.origdom.ub;
17871  }
17872 }
17873 
17874 /** gets original upper bound of original problem variable (i.e. the bound set in problem creation) */
17876  SCIP_VAR* var /**< original problem variable */
17877  )
17878 {
17879  assert(var != NULL);
17880  assert(SCIPvarIsOriginal(var));
17881 
17883  return var->data.original.origdom.ub;
17884  else
17885  {
17886  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17887  assert(var->negatedvar != NULL);
17889 
17890  return var->data.negate.constant - var->negatedvar->data.original.origdom.lb;
17891  }
17892 }
17893 
17894 /** gets the original hole list of an original variable */
17896  SCIP_VAR* var /**< problem variable */
17897  )
17898 {
17899  assert(var != NULL);
17900  assert(SCIPvarIsOriginal(var));
17901 
17903  return var->data.original.origdom.holelist;
17904 
17905  return NULL;
17906 }
17907 
17908 /** gets global lower bound of variable */
17910  SCIP_VAR* var /**< problem variable */
17911  )
17912 {
17913  assert(var != NULL);
17914 
17915  return var->glbdom.lb;
17916 }
17917 
17918 /** gets global upper bound of variable */
17920  SCIP_VAR* var /**< problem variable */
17921  )
17922 {
17923  assert(var != NULL);
17924 
17925  return var->glbdom.ub;
17926 }
17927 
17928 /** gets the global hole list of an active variable */
17930  SCIP_VAR* var /**< problem variable */
17931  )
17932 {
17933  assert(var != NULL);
17934 
17935  return var->glbdom.holelist;
17936 }
17937 
17938 /** gets best global bound of variable with respect to the objective function */
17940  SCIP_VAR* var /**< problem variable */
17941  )
17942 {
17943  assert(var != NULL);
17944 
17945  if( var->obj >= 0.0 )
17946  return var->glbdom.lb;
17947  else
17948  return var->glbdom.ub;
17949 }
17950 
17951 /** gets worst global bound of variable with respect to the objective function */
17953  SCIP_VAR* var /**< problem variable */
17954  )
17955 {
17956  assert(var != NULL);
17957 
17958  if( var->obj >= 0.0 )
17959  return var->glbdom.ub;
17960  else
17961  return var->glbdom.lb;
17962 }
17963 
17964 /** gets current lower bound of variable */
17966  SCIP_VAR* var /**< problem variable */
17967  )
17968 {
17969  assert(var != NULL);
17970 
17971  return var->locdom.lb;
17972 }
17973 
17974 /** gets current upper bound of variable */
17976  SCIP_VAR* var /**< problem variable */
17977  )
17978 {
17979  assert(var != NULL);
17980 
17981  return var->locdom.ub;
17982 }
17983 
17984 /** gets the current hole list of an active variable */
17986  SCIP_VAR* var /**< problem variable */
17987  )
17988 {
17989  assert(var != NULL);
17990 
17991  return var->locdom.holelist;
17992 }
17993 
17994 /** gets best local bound of variable with respect to the objective function */
17996  SCIP_VAR* var /**< problem variable */
17997  )
17998 {
17999  assert(var != NULL);
18000 
18001  if( var->obj >= 0.0 )
18002  return var->locdom.lb;
18003  else
18004  return var->locdom.ub;
18005 }
18006 
18007 /** gets worst local bound of variable with respect to the objective function */
18009  SCIP_VAR* var /**< problem variable */
18010  )
18011 {
18012  assert(var != NULL);
18013 
18014  if( var->obj >= 0.0 )
18015  return var->locdom.ub;
18016  else
18017  return var->locdom.lb;
18018 }
18019 
18020 /** gets type (lower or upper) of best bound of variable with respect to the objective function */
18022  SCIP_VAR* var /**< problem variable */
18023  )
18024 {
18025  assert(var != NULL);
18026 
18027  if( var->obj >= 0.0 )
18028  return SCIP_BOUNDTYPE_LOWER;
18029  else
18030  return SCIP_BOUNDTYPE_UPPER;
18031 }
18032 
18033 /** gets type (lower or upper) of worst bound of variable with respect to the objective function */
18035  SCIP_VAR* var /**< problem variable */
18036  )
18037 {
18038  assert(var != NULL);
18039 
18040  if( var->obj >= 0.0 )
18041  return SCIP_BOUNDTYPE_UPPER;
18042  else
18043  return SCIP_BOUNDTYPE_LOWER;
18044 }
18045 
18046 /** gets lazy lower bound of variable, returns -infinity if the variable has no lazy lower bound */
18048  SCIP_VAR* var /**< problem variable */
18049  )
18050 {
18051  assert(var != NULL);
18052 
18053  return var->lazylb;
18054 }
18055 
18056 /** gets lazy upper bound of variable, returns infinity if the variable has no lazy upper bound */
18058  SCIP_VAR* var /**< problem variable */
18059  )
18060 {
18061  assert(var != NULL);
18062 
18063  return var->lazyub;
18064 }
18065 
18066 /** gets the branch factor of the variable; this value can be used in the branching methods to scale the score
18067  * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
18068  */
18070  SCIP_VAR* var /**< problem variable */
18071  )
18072 {
18073  assert(var != NULL);
18074 
18075  return var->branchfactor;
18076 }
18077 
18078 /** gets the branch priority of the variable; variables with higher priority should always be preferred to variables
18079  * with lower priority
18080  */
18082  SCIP_VAR* var /**< problem variable */
18083  )
18084 {
18085  assert(var != NULL);
18086 
18087  return var->branchpriority;
18088 }
18089 
18090 /** gets the preferred branch direction of the variable (downwards, upwards, or auto) */
18092  SCIP_VAR* var /**< problem variable */
18093  )
18094 {
18095  assert(var != NULL);
18096 
18097  return (SCIP_BRANCHDIR)var->branchdirection;
18098 }
18099 
18100 /** gets number of variable lower bounds x >= b_i*z_i + d_i of given variable x */
18101 int SCIPvarGetNVlbs(
18102  SCIP_VAR* var /**< problem variable */
18103  )
18104 {
18105  assert(var != NULL);
18106 
18107  return SCIPvboundsGetNVbds(var->vlbs);
18108 }
18109 
18110 /** gets array with bounding variables z_i in variable lower bounds x >= b_i*z_i + d_i of given variable x;
18111  * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
18112  */
18114  SCIP_VAR* var /**< problem variable */
18115  )
18116 {
18117  assert(var != NULL);
18118 
18119  return SCIPvboundsGetVars(var->vlbs);
18120 }
18121 
18122 /** gets array with bounding coefficients b_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
18124  SCIP_VAR* var /**< problem variable */
18125  )
18126 {
18127  assert(var != NULL);
18128 
18129  return SCIPvboundsGetCoefs(var->vlbs);
18130 }
18131 
18132 /** gets array with bounding constants d_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
18134  SCIP_VAR* var /**< problem variable */
18135  )
18136 {
18137  assert(var != NULL);
18138 
18139  return SCIPvboundsGetConstants(var->vlbs);
18140 }
18141 
18142 /** gets number of variable upper bounds x <= b_i*z_i + d_i of given variable x */
18143 int SCIPvarGetNVubs(
18144  SCIP_VAR* var /**< problem variable */
18145  )
18146 {
18147  assert(var != NULL);
18148 
18149  return SCIPvboundsGetNVbds(var->vubs);
18150 }
18151 
18152 /** gets array with bounding variables z_i in variable upper bounds x <= b_i*z_i + d_i of given variable x;
18153  * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
18154  */
18156  SCIP_VAR* var /**< problem variable */
18157  )
18158 {
18159  assert(var != NULL);
18160 
18161  return SCIPvboundsGetVars(var->vubs);
18162 }
18163 
18164 /** gets array with bounding coefficients b_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
18166  SCIP_VAR* var /**< problem variable */
18167  )
18168 {
18169  assert(var != NULL);
18170 
18171  return SCIPvboundsGetCoefs(var->vubs);
18172 }
18173 
18174 /** gets array with bounding constants d_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
18176  SCIP_VAR* var /**< problem variable */
18177  )
18178 {
18179  assert(var != NULL);
18180 
18181  return SCIPvboundsGetConstants(var->vubs);
18182 }
18183 
18184 /** gets number of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
18185  * there are no implications for nonbinary variable x
18186  */
18187 int SCIPvarGetNImpls(
18188  SCIP_VAR* var, /**< active problem variable */
18189  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
18190  )
18191 {
18192  assert(var != NULL);
18193  assert(SCIPvarIsActive(var));
18194 
18195  return SCIPimplicsGetNImpls(var->implics, varfixing);
18196 }
18197 
18198 /** gets array with implication variables y of implications y <= b or y >= b for x == 0 or x == 1 of given active
18199  * problem variable x, there are no implications for nonbinary variable x;
18200  * the implications are sorted such that implications with binary implied variables precede the ones with non-binary
18201  * implied variables, and as a second criteria, the implied variables are sorted by increasing variable index
18202  * (see SCIPvarGetIndex())
18203  */
18205  SCIP_VAR* var, /**< active problem variable */
18206  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
18207  )
18208 {
18209  assert(var != NULL);
18210  assert(SCIPvarIsActive(var));
18211 
18212  return SCIPimplicsGetVars(var->implics, varfixing);
18213 }
18214 
18215 /** gets array with implication types of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
18216  * variable x (SCIP_BOUNDTYPE_UPPER if y <= b, SCIP_BOUNDTYPE_LOWER if y >= b),
18217  * there are no implications for nonbinary variable x
18218  */
18220  SCIP_VAR* var, /**< active problem variable */
18221  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
18222  )
18223 {
18224  assert(var != NULL);
18225  assert(SCIPvarIsActive(var));
18226 
18227  return SCIPimplicsGetTypes(var->implics, varfixing);
18228 }
18229 
18230 /** gets array with implication bounds b of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
18231  * variable x, there are no implications for nonbinary variable x
18232  */
18234  SCIP_VAR* var, /**< active problem variable */
18235  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
18236  )
18237 {
18238  assert(var != NULL);
18239  assert(SCIPvarIsActive(var));
18240 
18241  return SCIPimplicsGetBounds(var->implics, varfixing);
18242 }
18243 
18244 /** Gets array with unique ids of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
18245  * there are no implications for nonbinary variable x.
18246  * If an implication is a shortcut, i.e., it was added as part of the transitive closure of another implication,
18247  * its id is negative, otherwise it is nonnegative.
18248  */
18249 int* SCIPvarGetImplIds(
18250  SCIP_VAR* var, /**< active problem variable */
18251  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
18252  )
18253 {
18254  assert(var != NULL);
18255  assert(SCIPvarIsActive(var));
18256 
18257  return SCIPimplicsGetIds(var->implics, varfixing);
18258 }
18259 
18260 /** gets number of cliques, the active variable is contained in */
18261 int SCIPvarGetNCliques(
18262  SCIP_VAR* var, /**< active problem variable */
18263  SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
18264  )
18265 {
18266  assert(var != NULL);
18267 
18268  return SCIPcliquelistGetNCliques(var->cliquelist, varfixing);
18269 }
18270 
18271 /** gets array of cliques, the active variable is contained in */
18273  SCIP_VAR* var, /**< active problem variable */
18274  SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
18275  )
18276 {
18277  assert(var != NULL);
18278 
18279  return SCIPcliquelistGetCliques(var->cliquelist, varfixing);
18280 }
18281 
18282 /** gets primal LP solution value of variable */
18284  SCIP_VAR* var /**< problem variable */
18285  )
18286 {
18287  assert(var != NULL);
18288 
18290  return SCIPcolGetPrimsol(var->data.col);
18291  else
18292  return SCIPvarGetLPSol_rec(var);
18293 }
18294 
18295 /** gets primal NLP solution value of variable */
18297  SCIP_VAR* var /**< problem variable */
18298  )
18299 {
18300  assert(var != NULL);
18301 
18303  return var->nlpsol;
18304  else
18305  return SCIPvarGetNLPSol_rec(var);
18306 }
18307 
18308 /** return lower bound change info at requested position */
18310  SCIP_VAR* var, /**< problem variable */
18311  int pos /**< requested position */
18312  )
18313 {
18314  assert(pos >= 0);
18315  assert(pos < var->nlbchginfos);
18316 
18317  return &var->lbchginfos[pos];
18318 }
18319 
18320 /** gets the number of lower bound change info array */
18322  SCIP_VAR* var /**< problem variable */
18323  )
18324 {
18325  return var->nlbchginfos;
18326 }
18327 
18328 /** return upper bound change info at requested position */
18330  SCIP_VAR* var, /**< problem variable */
18331  int pos /**< requested position */
18332  )
18333 {
18334  assert(pos >= 0);
18335  assert(pos < var->nubchginfos);
18336 
18337  return &var->ubchginfos[pos];
18338 }
18339 
18340 /** gets the number upper bound change info array */
18342  SCIP_VAR* var /**< problem variable */
18343  )
18344 {
18345  assert(var != NULL);
18346 
18347  return var->nubchginfos;
18348 }
18349 
18350 /** returns the value based history for the variable */
18352  SCIP_VAR* var /**< problem variable */
18353  )
18354 {
18355  assert(var != NULL);
18356 
18357  return var->valuehistory;
18358 }
18359 
18360 /** gets pseudo solution value of variable */
18362  SCIP_VAR* var /**< problem variable */
18363  )
18364 {
18365  assert(var != NULL);
18366 
18368  return SCIPvarGetBestBoundLocal(var);
18369  else
18370  return SCIPvarGetPseudoSol_rec(var);
18371 }
18372 
18373 /** returns the variable's VSIDS score */
18375  SCIP_VAR* var, /**< problem variable */
18376  SCIP_STAT* stat, /**< problem statistics */
18377  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
18378  )
18379 {
18380  assert(var != NULL);
18381 
18383  return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
18384  else
18385  return SCIPvarGetVSIDS_rec(var, stat, dir);
18386 }
18387 
18388 /** includes event handler with given data in variable's event filter */
18390  SCIP_VAR* var, /**< problem variable */
18391  BMS_BLKMEM* blkmem, /**< block memory */
18392  SCIP_SET* set, /**< global SCIP settings */
18393  SCIP_EVENTTYPE eventtype, /**< event type to catch */
18394  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
18395  SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
18396  int* filterpos /**< pointer to store position of event filter entry, or NULL */
18397  )
18398 {
18399  assert(var != NULL);
18400  assert(set != NULL);
18401  assert(var->scip == set->scip);
18402  assert(var->eventfilter != NULL);
18403  assert((eventtype & ~SCIP_EVENTTYPE_VARCHANGED) == 0);
18404  assert((eventtype & SCIP_EVENTTYPE_VARCHANGED) != 0);
18405  assert(SCIPvarIsTransformed(var));
18406 
18407  SCIPsetDebugMsg(set, "catch event of type 0x%" SCIP_EVENTTYPE_FORMAT " of variable <%s> with handler %p and data %p\n",
18408  eventtype, var->name, (void*)eventhdlr, (void*)eventdata);
18409 
18410  SCIP_CALL( SCIPeventfilterAdd(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
18411 
18412  return SCIP_OKAY;
18413 }
18414 
18415 /** deletes event handler with given data from variable's event filter */
18417  SCIP_VAR* var, /**< problem variable */
18418  BMS_BLKMEM* blkmem, /**< block memory */
18419  SCIP_SET* set, /**< global SCIP settings */
18420  SCIP_EVENTTYPE eventtype, /**< event type mask of dropped event */
18421  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
18422  SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
18423  int filterpos /**< position of event filter entry returned by SCIPvarCatchEvent(), or -1 */
18424  )
18425 {
18426  assert(var != NULL);
18427  assert(set != NULL);
18428  assert(var->scip == set->scip);
18429  assert(var->eventfilter != NULL);
18430  assert(SCIPvarIsTransformed(var));
18431 
18432  SCIPsetDebugMsg(set, "drop event of variable <%s> with handler %p and data %p\n", var->name, (void*)eventhdlr,
18433  (void*)eventdata);
18434 
18435  SCIP_CALL( SCIPeventfilterDel(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
18436 
18437  return SCIP_OKAY;
18438 }
18439 
18440 /** returns the position of the bound change index */
18441 int SCIPbdchgidxGetPos(
18442  SCIP_BDCHGIDX* bdchgidx /**< bound change index */
18443  )
18444 {
18445  assert(bdchgidx != NULL);
18446 
18447  return bdchgidx->pos;
18448 }
18449 
18450 /** returns whether first bound change index belongs to an earlier applied bound change than second one */
18452  SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index */
18453  SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index */
18454  )
18455 {
18456  assert(bdchgidx1 != NULL);
18457  assert(bdchgidx1->depth >= -2);
18458  assert(bdchgidx1->pos >= 0);
18459  assert(bdchgidx2 != NULL);
18460  assert(bdchgidx2->depth >= -2);
18461  assert(bdchgidx2->pos >= 0);
18462 
18463  return (bdchgidx1->depth < bdchgidx2->depth)
18464  || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
18465 }
18466 
18467 /** returns whether first bound change index belongs to an earlier applied bound change than second one;
18468  * if a bound change index is NULL, the bound change index represents the current time, i.e. the time after the
18469  * last bound change was applied to the current node
18470  */
18472  SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index, or NULL */
18473  SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index, or NULL */
18474  )
18475 {
18476  assert(bdchgidx1 == NULL || bdchgidx1->depth >= -2);
18477  assert(bdchgidx1 == NULL || bdchgidx1->pos >= 0);
18478  assert(bdchgidx2 == NULL || bdchgidx2->depth >= -2);
18479  assert(bdchgidx2 == NULL || bdchgidx2->pos >= 0);
18480 
18481  if( bdchgidx1 == NULL )
18482  return FALSE;
18483  else if( bdchgidx2 == NULL )
18484  return TRUE;
18485  else
18486  return (bdchgidx1->depth < bdchgidx2->depth)
18487  || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
18488 }
18489 
18490 /** returns old bound that was overwritten for given bound change information */
18492  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18493  )
18494 {
18495  assert(bdchginfo != NULL);
18496 
18497  return bdchginfo->oldbound;
18498 }
18499 
18500 /** returns new bound installed for given bound change information */
18502  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18503  )
18504 {
18505  assert(bdchginfo != NULL);
18506 
18507  return bdchginfo->newbound;
18508 }
18509 
18510 /** returns variable that belongs to the given bound change information */
18512  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18513  )
18514 {
18515  assert(bdchginfo != NULL);
18516 
18517  return bdchginfo->var;
18518 }
18519 
18520 /** returns whether the bound change information belongs to a branching decision or a deduction */
18522  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18523  )
18524 {
18525  assert(bdchginfo != NULL);
18526 
18527  return (SCIP_BOUNDCHGTYPE)(bdchginfo->boundchgtype);
18528 }
18529 
18530 /** returns whether the bound change information belongs to a lower or upper bound change */
18532  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18533  )
18534 {
18535  assert(bdchginfo != NULL);
18536 
18537  return (SCIP_BOUNDTYPE)(bdchginfo->boundtype);
18538 }
18539 
18540 /** returns depth level of given bound change information */
18542  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18543  )
18544 {
18545  assert(bdchginfo != NULL);
18546 
18547  return bdchginfo->bdchgidx.depth;
18548 }
18549 
18550 /** returns bound change position in its depth level of given bound change information */
18552  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18553  )
18554 {
18555  assert(bdchginfo != NULL);
18556 
18557  return bdchginfo->bdchgidx.pos;
18558 }
18559 
18560 /** returns bound change index of given bound change information */
18562  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18563  )
18564 {
18565  assert(bdchginfo != NULL);
18566 
18567  return &bdchginfo->bdchgidx;
18568 }
18569 
18570 /** returns inference variable of given bound change information */
18572  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18573  )
18574 {
18575  assert(bdchginfo != NULL);
18578 
18579  return bdchginfo->inferencedata.var;
18580 }
18581 
18582 /** returns inference constraint of given bound change information */
18584  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18585  )
18586 {
18587  assert(bdchginfo != NULL);
18589  assert(bdchginfo->inferencedata.reason.cons != NULL);
18590 
18591  return bdchginfo->inferencedata.reason.cons;
18592 }
18593 
18594 /** returns inference propagator of given bound change information, or NULL if no propagator was responsible */
18596  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18597  )
18598 {
18599  assert(bdchginfo != NULL);
18601 
18602  return bdchginfo->inferencedata.reason.prop;
18603 }
18604 
18605 /** returns inference user information of given bound change information */
18607  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18608  )
18609 {
18610  assert(bdchginfo != NULL);
18613 
18614  return bdchginfo->inferencedata.info;
18615 }
18616 
18617 /** returns inference bound of inference variable of given bound change information */
18619  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18620  )
18621 {
18622  assert(bdchginfo != NULL);
18625 
18626  return (SCIP_BOUNDTYPE)(bdchginfo->inferboundtype);
18627 }
18628 
18629 /** returns the relaxed bound change type */
18631  SCIP_BDCHGINFO* bdchginfo /**< bound change to add to the conflict set */
18632  )
18633 {
18634  return ((SCIP_BOUNDTYPE)(bdchginfo->boundtype) == SCIP_BOUNDTYPE_LOWER ? bdchginfo->var->conflictrelaxedlb : bdchginfo->var->conflictrelaxedub);
18635 }
18636 
18637 
18638 /** returns whether the bound change information belongs to a redundant bound change */
18640  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18641  )
18642 {
18643  assert(bdchginfo != NULL);
18644  assert(bdchginfo->redundant == (bdchginfo->oldbound == bdchginfo->newbound)); /*lint !e777*/
18645 
18646  return bdchginfo->redundant;
18647 }
18648 
18649 /** returns whether the bound change has an inference reason (constraint or propagator), that can be resolved */
18651  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18652  )
18653 {
18654  assert(bdchginfo != NULL);
18655 
18658  && bdchginfo->inferencedata.reason.prop != NULL);
18659 }
18660 
18661 /** for two bound change informations belonging to the same variable and bound, returns whether the first bound change
18662  * has a tighter new bound as the second bound change
18663  */
18665  SCIP_BDCHGINFO* bdchginfo1, /**< first bound change information */
18666  SCIP_BDCHGINFO* bdchginfo2 /**< second bound change information */
18667  )
18668 {
18669  assert(bdchginfo1 != NULL);
18670  assert(bdchginfo2 != NULL);
18671  assert(bdchginfo1->var == bdchginfo2->var);
18672  assert(bdchginfo1->boundtype == bdchginfo2->boundtype);
18673 
18674  return (SCIPbdchginfoGetBoundtype(bdchginfo1) == SCIP_BOUNDTYPE_LOWER
18675  ? bdchginfo1->newbound > bdchginfo2->newbound
18676  : bdchginfo1->newbound < bdchginfo2->newbound);
18677 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:52
SCIP_Real SCIPhistoryGetAvgConflictlength(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:562
SCIP_HOLELIST * holelist
Definition: struct_var.h:163
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:50
SCIP_RETCODE SCIPeventfilterCreate(SCIP_EVENTFILTER **eventfilter, BMS_BLKMEM *blkmem)
Definition: event.c:1812
SCIP_Real SCIPbdchginfoGetRelaxedBound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18631
void SCIPcliquelistRemoveFromCliques(SCIP_CLIQUELIST *cliquelist, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Bool irrelevantvar)
Definition: implics.c:1674
static SCIP_Real adjustedUb(SCIP_SET *set, SCIP_VARTYPE vartype, SCIP_Real ub)
Definition: var.c:1580
SCIP_Real SCIPvarGetAvgConflictlengthCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15403
SCIP_Real SCIPvarGetWorstBoundLocal(SCIP_VAR *var)
Definition: var.c:18009
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6200
SCIP_Real * SCIPvarGetVlbCoefs(SCIP_VAR *var)
Definition: var.c:18124
#define BMSfreeBlockMemoryArrayNull(mem, ptr, num)
Definition: memory.h:461
void SCIPvarGetClosestVlb(SCIP_VAR *var, SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *closestvlb, int *closestvlbidx)
Definition: var.c:14122
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:994
SCIP_BOUNDTYPE SCIPvarGetWorstBoundType(SCIP_VAR *var)
Definition: var.c:18035
static void checkImplic(SCIP_SET *set, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool *redundant, SCIP_Bool *infeasible)
Definition: var.c:9378
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:15530
SCIP_Bool SCIPvarsHaveCommonClique(SCIP_VAR *var1, SCIP_Bool value1, SCIP_VAR *var2, SCIP_Bool value2, SCIP_Bool regardimplics)
Definition: var.c:11474
SCIP_BRANCHINGDATA branchingdata
Definition: struct_var.h:87
void SCIPhistoryIncNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, int depth)
Definition: history.c:575
SCIP_VAR ** SCIPcliqueGetVars(SCIP_CLIQUE *clique)
Definition: implics.c:3368
SCIP_Bool SCIPsetIsLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6258
SCIP_Bool SCIPsetIsFeasZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6708
internal methods for storing primal CIP solutions
void SCIPhistoryIncVSIDS(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition: history.c:494
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:15050
static SCIP_RETCODE varEventImplAdded(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:9260
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:10461
SCIP_Real SCIPvarGetBdAtIndex(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16782
SCIP_PROP * SCIPbdchginfoGetInferProp(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18596
void SCIPvarMarkNotDeletable(SCIP_VAR *var)
Definition: var.c:17495
void SCIPvarUpdateBestRootSol(SCIP_VAR *var, SCIP_SET *set, SCIP_Real rootsol, SCIP_Real rootredcost, SCIP_Real rootlpobjval)
Definition: var.c:13279
SCIP_RETCODE SCIPprimalUpdateObjoffset(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp)
Definition: primal.c:479
SCIP_RETCODE SCIPvarSetNLPSol(SCIP_VAR *var, SCIP_SET *set, SCIP_Real solval)
Definition: var.c:14005
int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:3289
public methods for branching and inference history structure
SCIP_Bool SCIPlpDiving(SCIP_LP *lp)
Definition: lp.c:17780
int nubchginfos
Definition: struct_var.h:260
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoLb(SCIP_VAR *var, int pos)
Definition: var.c:18310
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition: var.c:17702
internal methods for branch and bound tree
SCIP_Longint SCIPgetNLPIterations(SCIP *scip)
SCIP_BDCHGIDX bdchgidx
Definition: struct_var.h:112
void SCIPhistoryIncCutoffSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition: history.c:607
SCIP_Real SCIPvarGetAvgCutoffsCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:16311
SCIP_RETCODE SCIPvaluehistoryCreate(SCIP_VALUEHISTORY **valuehistory, BMS_BLKMEM *blkmem)
Definition: history.c:231
SCIP_Real SCIPsetFeastol(SCIP_SET *set)
Definition: set.c:6107
SCIP_Real SCIPvarGetBranchFactor(SCIP_VAR *var)
Definition: var.c:18070
unsigned int inferboundtype
Definition: struct_var.h:93
SCIP_Real SCIPbdchginfoGetOldbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18492
unsigned int relaxationonly
Definition: struct_var.h:277
char * name
Definition: struct_var.h:226
static SCIP_RETCODE domchgCreate(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem)
Definition: var.c:1031
unsigned int boundchgtype
Definition: struct_var.h:114
SCIP_BRANCHDIR SCIPvarGetBranchDirection(SCIP_VAR *var)
Definition: var.c:18092
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:1142
SCIP_HOLE hole
Definition: struct_var.h:51
SCIP_Real bestrootsol
Definition: struct_var.h:204
char * name
Definition: struct_lp.h:217
SCIP_Real SCIPvarGetUbLazy(SCIP_VAR *var)
Definition: var.c:18058
SCIP_Real SCIPsetFloor(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6387
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:6831
SCIP_Bool SCIPsetIsFeasEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6598
int SCIPvarGetNVlbs(SCIP_VAR *var)
Definition: var.c:18102
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18512
#define SCIPsetDuplicateBufferArray(set, ptr, source, num)
Definition: set.h:1727
SCIP_Real SCIPvarGetWorstBoundGlobal(SCIP_VAR *var)
Definition: var.c:17953
#define SCIP_DECL_VARTRANS(x)
Definition: type_var.h:138
SCIP_RETCODE SCIPvarChgLbGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Real newbound)
Definition: var.c:7181
enum SCIP_BaseStat SCIP_BASESTAT
Definition: type_lpi.h:87
SCIP_Bool SCIPvarDoNotMultaggr(SCIP_VAR *var)
Definition: var.c:5876
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:2112
public methods for implications, variable bounds, and cliques
SCIP_Real SCIPvarGetPseudocostCountCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14617
methods for implications, variable bounds, and cliques
int SCIPvarGetLastBdchgDepth(SCIP_VAR *var)
Definition: var.c:16862
SCIP_RETCODE SCIPeventqueueAdd(SCIP_EVENTQUEUE *eventqueue, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENT **event)
Definition: event.c:2231
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17910
SCIP_Real SCIPvarGetAvgBranchdepth(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15786
SCIP_RETCODE SCIPvarGetProbvarBinary(SCIP_VAR **var, SCIP_Bool *negated)
Definition: var.c:12309
SCIP_RETCODE SCIPdomchgAddHolechg(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HOLELIST **ptr, SCIP_HOLELIST *newlist, SCIP_HOLELIST *oldlist)
Definition: var.c:1511
SCIP_Bool SCIPvarIsPscostRelerrorReliable(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real threshold, SCIP_CONFIDENCELEVEL clevel)
Definition: var.c:14783
#define SCIP_MAXSTRLEN
Definition: def.h:293
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:3347
SCIP_DOM origdom
Definition: struct_var.h:169
SCIP_BASESTAT SCIPcolGetBasisStatus(SCIP_COL *col)
Definition: lp.c:16964
SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition: var.c:17452
SCIP_RETCODE SCIPeventCreateImplAdded(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition: event.c:805
SCIP_VAR ** SCIPimplicsGetVars(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3319
SCIP_RETCODE SCIPvarChgLbOriginal(SCIP_VAR *var, SCIP_SET *set, SCIP_Real newbound)
Definition: var.c:6563
SCIP_BOUNDCHG * boundchgs
Definition: struct_var.h:125
void SCIPhistoryIncInferenceSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition: history.c:591
SCIP_Bool SCIPsetIsPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6323
SCIP_Real lastbranchvalue
Definition: struct_stat.h:134
static SCIP_RETCODE domchgMakeDynamic(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem)
Definition: var.c:1101
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition: var.c:17690
static long bound
#define SCIPdebugCheckImplic(set, var, varfixing, implvar, impltype, implbound)
Definition: debug.h:274
static void printHolelist(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, SCIP_HOLELIST *holelist, const char *name)
Definition: var.c:2966
#define MAXABSVBCOEF
Definition: var.c:71
#define SCIPsetAllocCleanBufferArray(set, ptr, num)
Definition: set.h:1736
static SCIP_Real getImplVarRedcost(SCIP_VAR *var, SCIP_SET *set, SCIP_Bool varfixing, SCIP_STAT *stat, SCIP_LP *lp)
Definition: var.c:13414
SCIP_RETCODE SCIPbdchginfoCreate(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_Real oldbound, SCIP_Real newbound)
Definition: var.c:16365
SCIP_RETCODE SCIPeventfilterDel(SCIP_EVENTFILTER *eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: event.c:1970
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17966
SCIP_RETCODE SCIPvarChgLbLazy(SCIP_VAR *var, SCIP_SET *set, SCIP_Real lazylb)
Definition: var.c:7465
SCIP_Real constant
Definition: struct_var.h:184
SCIP_CLIQUE ** SCIPvarGetCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18273
SCIP_RETCODE SCIPprobVarChangedStatus(SCIP_PROB *prob, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_BRANCHCAND *branchcand, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var)
Definition: prob.c:1182
SCIP_Real bestrootredcost
Definition: struct_var.h:205
SCIP_Real SCIPvarGetMultaggrLbGlobal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8562
SCIP_HISTORY * historycrun
Definition: struct_var.h:242
SCIP_BRANCHDIR lastbranchdir
Definition: struct_stat.h:178
SCIP_VALUEHISTORY * SCIPvarGetValuehistory(SCIP_VAR *var)
Definition: var.c:18352
int SCIPcliquelistGetNCliques(SCIP_CLIQUELIST *cliquelist, SCIP_Bool value)
Definition: implics.c:3434
SCIP_NODE * SCIPnodeGetParent(SCIP_NODE *node)
Definition: tree.c:7712
void SCIPprobAddObjoffset(SCIP_PROB *prob, SCIP_Real addval)
Definition: prob.c:1431
void SCIPvarSetTransData(SCIP_VAR *var, SCIP_DECL_VARTRANS((*vartrans)))
Definition: var.c:17304
SCIP_RETCODE SCIPvarChgUbOriginal(SCIP_VAR *var, SCIP_SET *set, SCIP_Real newbound)
Definition: var.c:6622
SCIP_Longint closestvblpcount
Definition: struct_var.h:244
SCIP_RETCODE SCIPvarAddHoleGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_Real left, SCIP_Real right, SCIP_Bool *added)
Definition: var.c:8870
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:2490
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:17431
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:6758
SCIP_VAR ** SCIPvboundsGetVars(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3286
SCIP_Real SCIPsetInfinity(SCIP_SET *set)
Definition: set.c:6065
SCIP_DOMCHGBOTH domchgboth
Definition: struct_var.h:154
SCIP_RETCODE SCIPcolChgObj(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newobj)
Definition: lp.c:3692
SCIP_Real SCIPvarGetSol(SCIP_VAR *var, SCIP_Bool getlpval)
Definition: var.c:13256
int SCIPprobGetNVars(SCIP_PROB *prob)
Definition: prob.c:2343
SCIP_BDCHGINFO * ubchginfos
Definition: struct_var.h:240
SCIP_Bool SCIPbdchgidxIsEarlier(SCIP_BDCHGIDX *bdchgidx1, SCIP_BDCHGIDX *bdchgidx2)
Definition: var.c:18472
SCIP_Bool SCIPvarWasFixedAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16802
SCIP_Real SCIPvarGetBestBoundLocal(SCIP_VAR *var)
Definition: var.c:17996
SCIP_Real SCIPvarGetRootSol(SCIP_VAR *var)
Definition: var.c:13349
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:902
SCIP_RETCODE SCIPvarMarkDoNotMultaggr(SCIP_VAR *var)
Definition: var.c:6137
SCIP_RETCODE SCIPvarScaleVSIDS(SCIP_VAR *var, SCIP_Real scalar)
Definition: var.c:15136
SCIP_Real SCIPvarGetLbLP(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:12931
static SCIP_RETCODE holelistDuplicate(SCIP_HOLELIST **target, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HOLELIST *source)
Definition: var.c:194
SCIP_BOUNDTYPE SCIPboundchgGetBoundtype(SCIP_BOUNDCHG *boundchg)
Definition: var.c:17178
unsigned int nboundchgs
Definition: struct_var.h:123
SCIP_RETCODE SCIPvarCatchEvent(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: var.c:18390
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:3273
SCIP_HOLELIST * newlist
Definition: struct_var.h:59
SCIP_Real right
Definition: struct_var.h:45
void SCIPvaluehistoryScaleVSIDS(SCIP_VALUEHISTORY *valuehistory, SCIP_Real scalar)
Definition: history.c:317
void SCIPvarSetProbindex(SCIP_VAR *var, int probindex)
Definition: var.c:6021
#define NLOCKTYPES
Definition: type_var.h:81
SCIP_RETCODE SCIPhistoryCreate(SCIP_HISTORY **history, BMS_BLKMEM *blkmem)
Definition: history.c:42
SCIP_HOLELIST * SCIPholelistGetNext(SCIP_HOLELIST *holelist)
Definition: var.c:17238
#define FALSE
Definition: def.h:87
int lppos
Definition: struct_lp.h:163
#define EPSEQ(x, y, eps)
Definition: def.h:202
#define EPSISINT(x, eps)
Definition: def.h:214
SCIP_Bool SCIPlpIsSolBasic(SCIP_LP *lp)
Definition: lp.c:17770
datastructures for managing events
SCIP_Bool SCIPsetIsFeasIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6741
int SCIPvarGetNBdchgInfosLb(SCIP_VAR *var)
Definition: var.c:18322
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:546
struct SCIP_VarData SCIP_VARDATA
Definition: type_var.h:107
SCIP_RETCODE SCIPdomchgUndo(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:1340
SCIP_Real SCIPcolGetUb(SCIP_COL *col)
Definition: lp.c:16906
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:817
SCIP_RETCODE SCIPvarTransform(SCIP_VAR *origvar, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_OBJSENSE objsense, SCIP_VAR **transvar)
Definition: var.c:3455
void SCIPhistoryReset(SCIP_HISTORY *history)
Definition: history.c:69
SCIP_Real SCIPcolGetObj(SCIP_COL *col)
Definition: lp.c:16886
int nlocksup[NLOCKTYPES]
Definition: struct_var.h:255
static SCIP_RETCODE varEventVarUnlocked(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:3140
SCIP_Real constant
Definition: struct_var.h:194
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10755
SCIP_Bool SCIPsetIsZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6312
SCIP_RETCODE SCIPvboundsDel(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem, SCIP_VAR *vbdvar, SCIP_Bool negativecoef)
Definition: implics.c:279
static SCIP_Bool useValuehistory(SCIP_VAR *var, SCIP_Real value, SCIP_SET *set)
Definition: var.c:15022
#define TRUE
Definition: def.h:86
SCIP_Bool SCIPvarHasImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition: var.c:11107
static void varSetProbindex(SCIP_VAR *var, int probindex)
Definition: var.c:6002
SCIP_Real SCIPvarGetAvgConflictlength(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15359
SCIP_INFERENCEDATA inferencedata
Definition: struct_var.h:111
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:54
SCIP_HOLELIST * oldlist
Definition: struct_var.h:60
SCIP_Real SCIPvarGetNegationConstant(SCIP_VAR *var)
Definition: var.c:17747
#define MAXIMPLSCLOSURE
Definition: var.c:68
void SCIPimplicsGetVarImplicPoss(SCIP_IMPLICS *implics, SCIP_Bool varfixing, SCIP_VAR *implvar, int *lowerimplicpos, int *upperimplicpos)
Definition: implics.c:907
int SCIPvarGetNVubs(SCIP_VAR *var)
Definition: var.c:18144
SCIP_RETCODE SCIPeventCreateUbChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition: event.c:691
int SCIPbdchginfoGetInferInfo(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18607
int nlbchginfos
Definition: struct_var.h:258
static SCIP_BDCHGIDX presolvebdchgidx
Definition: var.c:16822
enum SCIP_Varstatus SCIP_VARSTATUS
Definition: type_var.h:48
#define SCIPsetAllocBufferArray(set, ptr, num)
Definition: set.h:1725
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:2069
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:17600
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:10908
#define SCIP_DECL_VARCOPY(x)
Definition: type_var.h:181
SCIP_RETCODE SCIPvarChgLbDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newbound)
Definition: var.c:8245
void SCIPvarSetNamePointer(SCIP_VAR *var, const char *name)
Definition: var.c:6036
int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
Definition: set.c:5779
#define SCIP_EVENTTYPE_GLBCHANGED
Definition: type_event.h:66
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:8219
SCIP_Real SCIPvarGetAggrScalar(SCIP_VAR *var)
Definition: var.c:17654
void SCIPvarInitSolve(SCIP_VAR *var)
Definition: var.c:2925
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:7324
public methods for problem variables
static GRAPHNODE ** active
SCIP_Real SCIPvarGetInferenceSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15978
void SCIPvarMarkDeletable(SCIP_VAR *var)
Definition: var.c:17484
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:1924
SCIP_RETCODE SCIPimplicsDel(SCIP_IMPLICS **implics, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition: implics.c:827
SCIP_Real SCIPvarGetAvgInferences(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:16066
SCIP_Real SCIPhistoryGetVSIDS(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:520
#define SCIPdebugMessage
Definition: pub_message.h:87
SCIP_RETCODE SCIPvarAddClique(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool value, SCIP_CLIQUE *clique, SCIP_Bool *infeasible, int *nbdchgs)
Definition: var.c:11269
SCIP_VAR ** SCIPvarGetVlbVars(SCIP_VAR *var)
Definition: var.c:18114
void SCIPprobUpdateNObjVars(SCIP_PROB *prob, SCIP_SET *set, SCIP_Real oldobj, SCIP_Real newobj)
Definition: prob.c:1542
SCIP_RETCODE SCIPvarsGetActiveVars(SCIP_SET *set, SCIP_VAR **vars, int *nvars, int varssize, int *requiredsize)
Definition: var.c:12005
int SCIPbdchgidxGetPos(SCIP_BDCHGIDX *bdchgidx)
Definition: var.c:18442
SCIP_CLIQUE ** SCIPcliquelistGetCliques(SCIP_CLIQUELIST *cliquelist, SCIP_Bool value)
Definition: implics.c:3443
SCIP_PROB * transprob
Definition: struct_scip.h:89
int index
Definition: struct_var.h:245
SCIP_Real constant
Definition: struct_var.h:177
unsigned int domchgtype
Definition: struct_var.h:142
SCIP_Bool SCIPsetIsNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6334
SCIP_RETCODE SCIPvarChgType(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_EVENTQUEUE *eventqueue, SCIP_VARTYPE vartype)
Definition: var.c:6173
SCIP_RETCODE SCIPcliquelistAdd(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: implics.c:1473
SCIP_Bool SCIPvarIsDeletable(SCIP_VAR *var)
Definition: var.c:17570
int SCIPvarGetConflictingBdchgDepth(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real bound)
Definition: var.c:16877
SCIP_RETCODE SCIPvarUpdatePseudocost(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition: var.c:14378
#define SCIPsetFreeBufferArray(set, ptr)
Definition: set.h:1732
SCIP_Longint SCIPvarGetNBranchingsCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15743
SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
Definition: var.c:17462
void SCIPvarAdjustLb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *lb)
Definition: var.c:6513
static SCIP_RETCODE domchgEnsureBoundchgsSize(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: var.c:1242
#define SCIPdebugCheckVbound(set, var, vbtype, vbvar, vbcoef, vbconstant)
Definition: debug.h:273
SCIP_RETCODE SCIPvarChgBranchDirection(SCIP_VAR *var, SCIP_BRANCHDIR branchdirection)
Definition: var.c:11817
SCIP_Real SCIPhistoryGetAvgCutoffs(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:675
SCIP_HOLECHG * holechgs
Definition: struct_var.h:134
SCIP_Real obj
Definition: struct_var.h:200
SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition: var.c:17736
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:5521
SCIP_Real relaxsol
Definition: struct_var.h:207
SCIP_RETCODE SCIPvarRemoveCliquesImplicsVbs(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_CLIQUETABLE *cliquetable, SCIP_SET *set, SCIP_Bool irrelevantvar, SCIP_Bool onlyredundant, SCIP_Bool removefromvar)
Definition: var.c:1601
static SCIP_RETCODE boundchgCaptureData(SCIP_BOUNDCHG *boundchg)
Definition: var.c:962
SCIP_Real SCIPsetCeil(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6398
int conflictlbcount
Definition: struct_var.h:261
SCIP_Real SCIPvarGetRelaxSolTransVar(SCIP_VAR *var)
Definition: var.c:13994
#define SCIPstatIncrement(stat, set, field)
Definition: stat.h:251
SCIP_Real SCIPsetGetHugeValue(SCIP_SET *set)
Definition: set.c:6077
internal methods for LP management
SCIP_BDCHGIDX * SCIPvarGetLastBdchgIndex(SCIP_VAR *var)
Definition: var.c:16825
int SCIPvarGetNCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18262
Definition: heur_padm.c:123
SCIP_PROB * origprob
Definition: struct_scip.h:71
SCIP_Real SCIPvarGetLPSol_rec(SCIP_VAR *var)
Definition: var.c:13068
SCIP_Real SCIPhistoryGetPseudocost(SCIP_HISTORY *history, SCIP_Real solvaldelta)
Definition: history.c:430
SCIP_VAR ** vars
Definition: struct_var.h:186
static void domMerge(SCIP_DOM *dom, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real *newlb, SCIP_Real *newub)
Definition: var.c:260
real eps
internal methods for branching and inference history
int nrootintfixings
Definition: struct_stat.h:215
int branchpriority
Definition: struct_var.h:256
SCIP_Real SCIPvarGetCutoffSumCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:16221
int * SCIPvarGetImplIds(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18250
SCIP_HOLELIST * SCIPvarGetHolelistOriginal(SCIP_VAR *var)
Definition: var.c:17896
SCIP_RETCODE SCIPeventCreateObjChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldobj, SCIP_Real newobj)
Definition: event.c:596
internal methods for collecting primal CIP solutions and primal informations
SCIP_Real SCIPsolGetVal(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var)
Definition: sol.c:1338
static SCIP_RETCODE varParse(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, const char *str, char *name, SCIP_Real *lb, SCIP_Real *ub, SCIP_Real *obj, SCIP_VARTYPE *vartype, SCIP_Real *lazylb, SCIP_Real *lazyub, SCIP_Bool local, char **endptr, SCIP_Bool *success)
Definition: var.c:2343
SCIP_RETCODE SCIPvboundsAdd(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_BOUNDTYPE vboundtype, SCIP_VAR *var, SCIP_Real coef, SCIP_Real constant, SCIP_Bool *added)
Definition: implics.c:197
SCIP_DECL_HASHKEYVAL(SCIPvarGetHashkeyVal)
Definition: var.c:11998
SCIP_VAR * var
Definition: struct_var.h:178
#define SCIP_EVENTTYPE_LBCHANGED
Definition: type_event.h:112
SCIP_Real SCIPvarGetUbLP(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:13001
int nrootboundchgs
Definition: struct_stat.h:213
#define SCIP_DECL_VARDELTRANS(x)
Definition: type_var.h:151
SCIP_Bool SCIPsetIsGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6294
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:7542
SCIP_HISTORY * glbhistorycrun
Definition: struct_stat.h:173
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:17726
const char * SCIPgetProbName(SCIP *scip)
Definition: scip_prob.c:1066
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3363
SCIP_Real SCIPvarGetVSIDSCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15927
void SCIPhistoryScaleVSIDS(SCIP_HISTORY *history, SCIP_Real scalar)
Definition: history.c:508
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:9295
SCIP_Real SCIPvarGetNLPSol_rec(SCIP_VAR *var)
Definition: var.c:13141
int SCIPvarGetNBdchgInfosUb(SCIP_VAR *var)
Definition: var.c:18342
void SCIPcliquelistFree(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem)
Definition: implics.c:1432
SCIP_Real conflictrelaxedub
Definition: struct_var.h:213
SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
Definition: tree.c:7432
SCIP_Bool SCIPbdchginfoIsTighter(SCIP_BDCHGINFO *bdchginfo1, SCIP_BDCHGINFO *bdchginfo2)
Definition: var.c:18665
unsigned int inferboundtype
Definition: struct_var.h:116
SCIP_RETCODE SCIPeventCreateVarFixed(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition: event.c:553
SCIP_RETCODE SCIPvarChgLbLocal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real newbound)
Definition: var.c:7966
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17920
SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6240
SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
Definition: var.c:12217
SCIP_Real SCIPvarGetObjLP(SCIP_VAR *var)
Definition: var.c:12885
SCIP_RETCODE SCIPvaluehistoryFind(SCIP_VALUEHISTORY *valuehistory, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real value, SCIP_HISTORY **history)
Definition: history.c:272
SCIP_Real SCIPvarGetBestRootLPObjval(SCIP_VAR *var)
Definition: var.c:13815
void SCIPvarSetHistory(SCIP_VAR *var, SCIP_HISTORY *history, SCIP_STAT *stat)
Definition: var.c:4519
public methods for managing constraints
static SCIP_RETCODE varProcessChgBranchFactor(SCIP_VAR *var, SCIP_SET *set, SCIP_Real branchfactor)
Definition: var.c:11495
SCIP_Real SCIPhistoryGetPseudocostVariance(SCIP_HISTORY *history, SCIP_BRANCHDIR direction)
Definition: history.c:444
SCIP_Real SCIPvarGetImplRedcost(SCIP_VAR *var, SCIP_SET *set, SCIP_Bool varfixing, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_LP *lp)
Definition: var.c:13467
SCIP_RETCODE SCIPstatUpdateVarRootLPBestEstimate(SCIP_STAT *stat, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldrootpscostscore)
Definition: stat.c:798
void SCIPvaluehistoryFree(SCIP_VALUEHISTORY **valuehistory, BMS_BLKMEM *blkmem)
Definition: history.c:250
SCIP_Real conflictrelaxedlb
Definition: struct_var.h:212
void SCIPvarSetDelorigData(SCIP_VAR *var, SCIP_DECL_VARDELORIG((*vardelorig)))
Definition: var.c:17292
enum SCIP_Confidencelevel SCIP_CONFIDENCELEVEL
Definition: type_misc.h:44
SCIP_RETCODE SCIPvarChgBranchPriority(SCIP_VAR *var, int branchpriority)
Definition: var.c:11686
SCIP_Real SCIPvarGetPseudocost(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition: var.c:14476
SCIP_AGGREGATE aggregate
Definition: struct_var.h:222
SCIP_Real lazylb
Definition: struct_var.h:214
#define BMSduplicateBlockMemoryArray(mem, ptr, source, num)
Definition: memory.h:455
SCIP_Real SCIPcolGetPrimsol(SCIP_COL *col)
Definition: lp.c:16929
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:7580
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:1375
SCIP_RETCODE SCIPeventfilterAdd(SCIP_EVENTFILTER *eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: event.c:1877
static SCIP_RETCODE varUpdateAggregationBounds(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *aggvar, SCIP_Real scalar, SCIP_Real constant, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: var.c:4534
void SCIPvarSetDeltransData(SCIP_VAR *var, SCIP_DECL_VARDELTRANS((*vardeltrans)))
Definition: var.c:17316
SCIP_RETCODE SCIPvarChgUbLazy(SCIP_VAR *var, SCIP_SET *set, SCIP_Real lazyub)
Definition: var.c:7488
SCIP_Real SCIPvarGetBestBoundGlobal(SCIP_VAR *var)
Definition: var.c:17940
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:7800
void SCIPvarMergeHistories(SCIP_VAR *targetvar, SCIP_VAR *othervar, SCIP_STAT *stat)
Definition: var.c:4503
enum SCIP_LockType SCIP_LOCKTYPE
Definition: type_var.h:87
void SCIPhistoryIncNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real length)
Definition: history.c:533
SCIP_BOUNDTYPE * SCIPimplicsGetTypes(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3328
SCIP_Bool SCIPvarDoNotAggr(SCIP_VAR *var)
Definition: var.c:5843
internal methods for storing and manipulating the main problem
#define MAX_CLIQUELENGTH
Definition: var.c:13463
#define SCIPerrorMessage
Definition: pub_message.h:55
SCIP_Bool SCIPboundchgIsRedundant(SCIP_BOUNDCHG *boundchg)
Definition: var.c:17188
void SCIPlpDecNLoosevars(SCIP_LP *lp)
Definition: lp.c:14308
SCIP_Real SCIPvarGetLbOriginal(SCIP_VAR *var)
Definition: var.c:17856
void SCIPcliqueDelVar(SCIP_CLIQUE *clique, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Bool value)
Definition: implics.c:1276
SCIP_RETCODE SCIPdomchgMakeStatic(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:1153
SCIP_VBOUNDS * vlbs
Definition: struct_var.h:234
SCIP_RETCODE SCIPdomchgFree(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:1052
static SCIP_BDCHGIDX initbdchgidx
Definition: var.c:16819
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:14926
static SCIP_RETCODE varEnsureUbchginfosSize(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: var.c:445
SCIP_Bool SCIPimplicsContainsImpl(SCIP_IMPLICS *implics, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition: implics.c:924
SCIP_Longint lpcount
Definition: struct_stat.h:181
SCIP_Bool SCIPbdchgidxIsEarlierNonNull(SCIP_BDCHGIDX *bdchgidx1, SCIP_BDCHGIDX *bdchgidx2)
Definition: var.c:18452
SCIP_RETCODE SCIPimplicsAdd(SCIP_IMPLICS **implics, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool isshortcut, SCIP_Bool *conflict, SCIP_Bool *added)
Definition: implics.c:624
SCIP_RETCODE SCIPvarChgObj(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PROB *prob, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_EVENTQUEUE *eventqueue, SCIP_Real newobj)
Definition: var.c:6260
int SCIPvarCompareActiveAndNegated(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11903
int lbchginfossize
Definition: struct_var.h:257
SCIP_Real SCIPvarGetAvgBranchdepthCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15831
unsigned int varstatus
Definition: struct_var.h:272
SCIP_RETCODE SCIPvarRelease(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:2866
SCIP_Real SCIPvarGetUbOriginal(SCIP_VAR *var)
Definition: var.c:17876
SCIP_Bool SCIPvarIsTransformedOrigvar(SCIP_VAR *var)
Definition: var.c:12860
SCIP_Real SCIPhistoryGetAvgBranchdepth(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:688
SCIP_Real bestrootlpobjval
Definition: struct_var.h:206
SCIP_VARDATA * vardata
Definition: struct_var.h:231
SCIP_RETCODE SCIPvarChgObjDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newobj)
Definition: var.c:6450
SCIP_EVENTTYPE eventmask
Definition: struct_event.h:189
SCIP_DECL_SORTPTRCOMP(SCIPvarCompActiveAndNegated)
Definition: var.c:11933
SCIP_Real SCIPvarGetPseudocostCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition: var.c:14525
SCIP_Real SCIPvarGetUbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16661
SCIP_Bool SCIPsortedvecFindPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), void *val, int len, int *pos)
SCIP_Real primsolavg
Definition: struct_var.h:209
void SCIPstrCopySection(const char *str, char startchar, char endchar, char *token, int size, char **endptr)
Definition: misc.c:10886
SCIP_Bool SCIPvarHasBinaryImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_Bool implvarfixing)
Definition: var.c:11127
SCIP_RETCODE SCIPvarAddLocks(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LOCKTYPE locktype, int addnlocksdown, int addnlocksup)
Definition: var.c:3161
SCIP_RETCODE SCIPvarGetTransformed(SCIP_VAR *origvar, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **transvar)
Definition: var.c:3542
#define SCIPdebugCheckAggregation(set, var, aggrvars, scalars, constant, naggrvars)
Definition: debug.h:275
SCIP_HOLECHG * holechgs
Definition: struct_var.h:144
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8085
union SCIP_BoundChg::@20 data
SCIP_Real * SCIPvarGetVubConstants(SCIP_VAR *var)
Definition: var.c:18176
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:7007
SCIP_OBJSENSE objsense
Definition: struct_prob.h:77
unsigned int pos
Definition: struct_var.h:113
static SCIP_RETCODE varSetName(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_STAT *stat, const char *name)
Definition: var.c:1892
SCIP_Real SCIPvarGetAggrConstant(SCIP_VAR *var)
Definition: var.c:17666
SCIP_Real SCIPcolGetLb(SCIP_COL *col)
Definition: lp.c:16896
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:164
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17251
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:5037
SCIP_VAR * transvar
Definition: struct_var.h:170
SCIP_DOMCHGDYN domchgdyn
Definition: struct_var.h:155
#define MAXDNOM
SCIP_Real SCIPsetFeasCeil(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6776
void SCIPhistoryUnite(SCIP_HISTORY *history, SCIP_HISTORY *addhistory, SCIP_Bool switcheddirs)
Definition: history.c:101
void SCIPmessagePrintWarning(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
Definition: message.c:418
#define SCIPsetReallocBufferArray(set, ptr, num)
Definition: set.h:1729
SCIP_Longint SCIPhistoryGetNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:549
SCIP_RETCODE SCIPeventCreateLbChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition: event.c:665
SCIP_DECL_HASHGETKEY(SCIPvarGetHashkey)
Definition: var.c:11984
unsigned int initial
Definition: struct_var.h:265
#define NULL
Definition: lpi_spx1.cpp:155
void SCIPvarGetClosestVub(SCIP_VAR *var, SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *closestvub, int *closestvubidx)
Definition: var.c:14197
SCIP_NEGATE negate
Definition: struct_var.h:224
static SCIP_RETCODE holelistCreate(SCIP_HOLELIST **holelist, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real left, SCIP_Real right)
Definition: var.c:144
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:7633
SCIP_RETCODE SCIPvarSetRelaxSol(SCIP_VAR *var, SCIP_SET *set, SCIP_RELAXATION *relaxation, SCIP_Real solval, SCIP_Bool updateobj)
Definition: var.c:13861
SCIP_HISTORY * glbhistory
Definition: struct_stat.h:172
SCIP_Real SCIPboundchgGetNewbound(SCIP_BOUNDCHG *boundchg)
Definition: var.c:17148
SCIP_Real * SCIPvboundsGetCoefs(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3294
#define REALABS(x)
Definition: def.h:201
int nparentvars
Definition: struct_var.h:252
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition: var.c:18284
SCIP_Real unchangedobj
Definition: struct_var.h:201
SCIP_HOLELIST * SCIPvarGetHolelistGlobal(SCIP_VAR *var)
Definition: var.c:17930
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:9997
SCIP_Longint SCIPvarGetNActiveConflicts(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15267
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:17780
SCIP_Real SCIPvarCalcPscostConfidenceBound(SCIP_VAR *var, SCIP_SET *set, SCIP_BRANCHDIR dir, SCIP_Bool onlycurrentrun, SCIP_CONFIDENCELEVEL clevel)
Definition: var.c:14745
#define SCIP_CALL(x)
Definition: def.h:384
SCIP main data structure.
SCIP_Bool SCIPbdchginfoHasInferenceReason(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18651
SCIP_VBOUNDS * vubs
Definition: struct_var.h:235
SCIP_Real SCIPvarGetLbLazy(SCIP_VAR *var)
Definition: var.c:18048
SCIP_Bool SCIPsetIsFeasGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6686
SCIP_Real * SCIPvarGetVlbConstants(SCIP_VAR *var)
Definition: var.c:18134
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:15446
SCIP_Real SCIPvarGetMultaggrConstant(SCIP_VAR *var)
Definition: var.c:17714
SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
Definition: var.c:17538
int SCIPprobGetNContVars(SCIP_PROB *prob)
Definition: prob.c:2379
SCIP_Real SCIPvarGetPseudocostCount(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14572
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:9716
static SCIP_VAR * varGetActiveVar(SCIP_VAR *var)
Definition: var.c:5794
SCIP_Real * SCIPvboundsGetConstants(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3302
SCIP_Real SCIPvarGetCutoffSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:16178
SCIP_Real * SCIPvarGetVubCoefs(SCIP_VAR *var)
Definition: var.c:18166
Definition: graph_load.c:93
SCIP_Bool SCIPbdchginfoIsRedundant(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18640
int closestvubidx
Definition: struct_var.h:264
internal methods for relaxators
SCIP_Real SCIPvarGetMinPseudocostScore(SCIP_VAR *var, SCIP_STAT *stat, SCIP_SET *set, SCIP_Real solval)
Definition: var.c:14660
SCIP_Real SCIPhistoryGetPseudocostCount(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:468
SCIP_Bool SCIPsetIsEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6222
static SCIP_RETCODE varProcessChgBranchPriority(SCIP_VAR *var, int branchpriority)
Definition: var.c:11630
SCIP_Real vsidsweight
Definition: struct_stat.h:123
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:8093
#define SCIPdebugCheckLbGlobal(scip, var, lb)
Definition: debug.h:267
unsigned int nboundchgs
Definition: struct_var.h:141
SCIP_BDCHGIDX * SCIPbdchginfoGetIdx(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18562
SCIP_Longint SCIPvarGetNActiveConflictsCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15314
SCIP_RETCODE SCIPvarPrint(SCIP_VAR *var, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: var.c:3000
unsigned int branchdirection
Definition: struct_var.h:274
int ubchginfossize
Definition: struct_var.h:259
SCIP_Bool SCIPcliquelistsHaveCommonClique(SCIP_CLIQUELIST *cliquelist1, SCIP_Bool value1, SCIP_CLIQUELIST *cliquelist2, SCIP_Bool value2)
Definition: implics.c:1596
SCIP_Bool SCIPsetIsFeasLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6642
#define SCIPdebugCheckUbGlobal(scip, var, ub)
Definition: debug.h:268
#define SCIP_EVENTTYPE_UBCHANGED
Definition: type_event.h:113
void SCIPvboundsShrink(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem, int newnvbds)
Definition: implics.c:324
void SCIPvarSetBestRootSol(SCIP_VAR *var, SCIP_Real rootsol, SCIP_Real rootredcost, SCIP_Real rootlpobjval)
Definition: var.c:13846
int var_probindex
Definition: struct_lp.h:169
int nlocksdown[NLOCKTYPES]
Definition: struct_var.h:254
void SCIPvarAdjustBd(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real *bd)
Definition: var.c:6547
#define BMSfreeBlockMemory(mem, ptr)
Definition: memory.h:458
internal methods for problem variables
SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
Definition: var.c:17380
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:6225
SCIP_RETCODE SCIPvarChgBranchFactor(SCIP_VAR *var, SCIP_SET *set, SCIP_Real branchfactor)
Definition: var.c:11559
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:5275
#define SCIP_UNKNOWN
Definition: def.h:198
SCIP_Bool SCIPsetIsIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6345
public data structures and miscellaneous methods
unsigned int vartype
Definition: struct_var.h:271
SCIP_BOUNDTYPE * SCIPvarGetImplTypes(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18220
unsigned int boundchgtype
Definition: struct_var.h:91
#define BMSfreeBlockMemorySize(mem, ptr, size)
Definition: memory.h:462
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:15614
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:6682
SCIP_VAR * var
Definition: struct_var.h:90
SCIP_INFERENCEDATA inferencedata
Definition: struct_var.h:88
SCIP_Real SCIPholelistGetRight(SCIP_HOLELIST *holelist)
Definition: var.c:17228
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:8989
#define SCIP_Bool
Definition: def.h:84
void SCIPvarCapture(SCIP_VAR *var)
Definition: var.c:2841
#define BMSreallocBlockMemorySize(mem, ptr, oldsize, newsize)
Definition: memory.h:449
SCIP_BOUNDCHGTYPE SCIPboundchgGetBoundchgtype(SCIP_BOUNDCHG *boundchg)
Definition: var.c:17168
SCIP_Real ub
Definition: struct_var.h:162
unsigned int boundtype
Definition: struct_var.h:92
SCIP_RETCODE SCIPvarAggregate(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR *aggvar, SCIP_Real scalar, SCIP_Real constant, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition: var.c:4725
int SCIPbdchginfoGetPos(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18552
unsigned int deletable
Definition: struct_var.h:267
enum SCIP_Objsense SCIP_OBJSENSE
Definition: type_prob.h:41
SCIP_Bool SCIPvarWasFixedEarlier(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:16950
SCIP_Real SCIPvarGetInferenceSumCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:16023
SCIP_Bool SCIPvarIsInLP(SCIP_VAR *var)
Definition: var.c:17632
SCIP_RETCODE SCIPvarRemove(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_CLIQUETABLE *cliquetable, SCIP_SET *set, SCIP_Bool final)
Definition: var.c:6054
SCIP_RETCODE SCIPconsRelease(SCIP_CONS **cons, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: cons.c:6203
void SCIPvarMarkRelaxationOnly(SCIP_VAR *var)
Definition: var.c:17556
void SCIPvarStoreRootSol(SCIP_VAR *var, SCIP_Bool roothaslp)
Definition: var.c:13268
SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
Definition: var.c:18297
int SCIPvarGetBranchPriority(SCIP_VAR *var)
Definition: var.c:18082
int SCIPgetDepth(SCIP *scip)
Definition: scip_tree.c:661
SCIP_RETCODE SCIPvarFix(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: var.c:3743
SCIP_Real SCIPvarGetLbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16542
SCIP_Bool divingobjchg
Definition: struct_lp.h:371
int SCIPvarGetNImpls(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18188
SCIP_MULTAGGR multaggr
Definition: struct_var.h:223
SCIP_RETCODE SCIPvarChgUbDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newbound)
Definition: var.c:8335
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition: memory.h:460
SCIP_RETCODE SCIPeventCreateGlbChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition: event.c:619
unsigned int deleted
Definition: struct_var.h:268
union SCIP_Var::@21 data
int * SCIPimplicsGetIds(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3349
SCIP_VARDATA * SCIPvarGetData(SCIP_VAR *var)
Definition: var.c:17271
SCIP_RETCODE SCIPcolChgLb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newlb)
Definition: lp.c:3751
int SCIPvarGetNLocksUp(SCIP_VAR *var)
Definition: var.c:3423
#define MAX(x, y)
Definition: tclique_def.h:83
SCIP_Bool SCIPstrToRealValue(const char *str, SCIP_Real *value, char **endptr)
Definition: misc.c:10856
int SCIPimplicsGetNImpls(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3310
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:620
SCIP_VAR * SCIPboundchgGetVar(SCIP_BOUNDCHG *boundchg)
Definition: var.c:17158
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11941
SCIP_Bool * SCIPcliqueGetValues(SCIP_CLIQUE *clique)
Definition: implics.c:3380
SCIP_BOUNDCHG * SCIPdomchgGetBoundchg(SCIP_DOMCHG *domchg, int pos)
Definition: var.c:17206
SCIP_Real SCIPvarGetUnchangedObj(SCIP_VAR *var)
Definition: var.c:17768
public methods for LP management
unsigned int removable
Definition: struct_var.h:266
#define SCIPsetDebugMsg
Definition: set.h:1761
static SCIP_RETCODE varAddParent(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_VAR *parentvar)
Definition: var.c:2637
SCIP_Real SCIPvarGetMultaggrUbGlobal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8628
unsigned int redundant
Definition: struct_var.h:95
SCIP_Real oldbound
Definition: struct_var.h:108
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17758
SCIP_RETCODE SCIPvarAddCliqueToList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:11392
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18502
SCIP_Real SCIPvarGetBestRootRedcost(SCIP_VAR *var)
Definition: var.c:13781
SCIP_VAR * SCIPvarGetAggrVar(SCIP_VAR *var)
Definition: var.c:17642
int closestvlbidx
Definition: struct_var.h:263
#define EPSLE(x, y, eps)
Definition: def.h:204
SCIP_RETCODE SCIPvarFlattenAggregationGraph(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:4408
int nuses
Definition: struct_var.h:253
SCIP_Real SCIPvarGetAvgInferencesCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:16123
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:11178
SCIP_Real SCIPcomputeTwoSampleTTestValue(SCIP_Real meanx, SCIP_Real meany, SCIP_Real variancex, SCIP_Real variancey, SCIP_Real countx, SCIP_Real county)
Definition: misc.c:113
SCIP_RETCODE SCIPvarDelClique(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:11431
#define SCIP_EVENTTYPE_GHOLEADDED
Definition: type_event.h:72
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:127
void SCIPhistoryUpdatePseudocost(SCIP_HISTORY *history, SCIP_SET *set, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition: history.c:162
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition: var.c:17621
int probindex
Definition: struct_var.h:246
static SCIP_RETCODE varProcessAddHoleGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_Real left, SCIP_Real right, SCIP_Bool *added)
Definition: var.c:8741
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:2154
SCIP_Real SCIPvarGetRelaxSol(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:13922
datastructures for problem statistics
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:17678
SCIP_Longint SCIPhistoryGetNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:623
SCIP_Real * SCIPvarGetImplBounds(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18234
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12773
SCIP_Bool SCIPsetIsFeasLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6620
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:2367
static SCIP_Real adjustedLb(SCIP_SET *set, SCIP_VARTYPE vartype, SCIP_Real lb)
Definition: var.c:1560
SCIP_RETCODE SCIPvarAddObj(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_Real addobj)
Definition: var.c:6335
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:15186
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:9508
SCIP_NODE * SCIPgetFocusNode(SCIP *scip)
Definition: scip_tree.c:63
SCIP_RETCODE SCIPcolChgUb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newub)
Definition: lp.c:3796
SCIP_RETCODE SCIPcolFree(SCIP_COL **col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: lp.c:3371
SCIP * scip
Definition: struct_var.h:279
SCIP_EVENTFILTER * eventfilter
Definition: struct_var.h:238
static SCIP_Real SCIPvarGetPseudoSol_rec(SCIP_VAR *var)
Definition: var.c:13189
SCIP_BDCHGINFO * SCIPvarGetLbchgInfo(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16409
SCIP_Bool SCIPprobIsTransformed(SCIP_PROB *prob)
Definition: prob.c:2278
SCIP_BOUNDTYPE SCIPbdchginfoGetInferBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18619
const char * SCIPpropGetName(SCIP_PROP *prop)
Definition: prop.c:932
SCIP_BDCHGINFO * SCIPvarGetUbchgInfo(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16465
int conflictubcount
Definition: struct_var.h:262
int SCIPvboundsGetNVbds(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3278
SCIP_RETCODE SCIPvarGetProbvarBound(SCIP_VAR **var, SCIP_Real *bound, SCIP_BOUNDTYPE *boundtype)
Definition: var.c:12468
static SCIP_RETCODE parseValue(SCIP_SET *set, const char *str, SCIP_Real *value, char **endptr)
Definition: var.c:2267
SCIP_DOM locdom
Definition: struct_var.h:217
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoUb(SCIP_VAR *var, int pos)
Definition: var.c:18330
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:9789
SCIP_BDCHGINFO * SCIPvarGetBdchgInfo(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16521
#define SCIP_REAL_MAX
Definition: def.h:178
SCIP_Bool SCIPsetIsDualfeasPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6930
SCIP_VALUEHISTORY * valuehistory
Definition: struct_var.h:243
static void printBounds(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, FILE *file, SCIP_Real lb, SCIP_Real ub, const char *name)
Definition: var.c:2938
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:471
#define SCIP_DECL_VARDELORIG(x)
Definition: type_var.h:118
SCIP_Real SCIPhistoryGetCutoffSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:662
datastructures for storing and manipulating the main problem
SCIP_RETCODE SCIPvarAddToRow(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *prob, SCIP_LP *lp, SCIP_ROW *row, SCIP_Real val)
Definition: var.c:14269
SCIP_RETCODE SCIPvarLoose(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *prob, SCIP_LP *lp)
Definition: var.c:3607
SCIP_Real newbound
Definition: struct_var.h:84
#define SCIP_REAL_MIN
Definition: def.h:179
static SCIP_RETCODE varEventVarFixed(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, int fixeventtype)
Definition: var.c:3648
methods for sorting joint arrays of various types
SCIP_VAR ** parentvars
Definition: struct_var.h:232
SCIP_BRANCHDIR SCIPbranchdirOpposite(SCIP_BRANCHDIR dir)
Definition: history.c:421
SCIP_VAR ** SCIPvarGetImplVars(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18205
static SCIP_RETCODE varFreeParents(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:2665
SCIP_Real SCIPsetFeasFloor(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6765
SCIP_DOMCHGBOUND domchgbound
Definition: struct_var.h:153
SCIP_VAR ** b
Definition: circlepacking.c:56
SCIP_RETCODE SCIPvarChgBdGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype)
Definition: var.c:7514
#define SCIP_DEFAULT_INFINITY
Definition: def.h:182
static SCIP_RETCODE domchgEnsureHolechgsSize(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: var.c:1267
int SCIPvarGetNLocksDown(SCIP_VAR *var)
Definition: var.c:3410
SCIP_Real SCIPstudentTGetCriticalValue(SCIP_CONFIDENCELEVEL clevel, int df)
Definition: misc.c:96
SCIP_HOLELIST * next
Definition: struct_var.h:52
void SCIPconsCapture(SCIP_CONS *cons)
Definition: cons.c:6191
SCIP_Real SCIPhistoryGetInferenceSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:636
#define BMSallocBlockMemorySize(mem, ptr, size)
Definition: memory.h:446
unsigned int boundtype
Definition: struct_var.h:115
#define SCIPsetFreeCleanBufferArray(set, ptr)
Definition: set.h:1739
void SCIPrelaxationSolObjAdd(SCIP_RELAXATION *relaxation, SCIP_Real val)
Definition: relax.c:834
static const SCIP_Real scalars[]
Definition: lp.c:5736
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:5441
int lpipos
Definition: struct_lp.h:164
SCIP_NODE * SCIPtreeGetRootNode(SCIP_TREE *tree)
Definition: tree.c:8442
int SCIPdomchgGetNBoundchgs(SCIP_DOMCHG *domchg)
Definition: var.c:17198
SCIP_RETCODE SCIPvarColumn(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_LP *lp)
Definition: var.c:3573
SCIP_RETCODE SCIPnodeAddBoundchg(SCIP_NODE *node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype, SCIP_Bool probingchange)
Definition: tree.c:2078
unsigned int donotaggr
Definition: struct_var.h:269
SCIP_Real lazyub
Definition: struct_var.h:215
int SCIPbdchginfoGetDepth(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18542
SCIP_RETCODE SCIPeventfilterFree(SCIP_EVENTFILTER **eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: event.c:1837
#define SCIP_EVENTTYPE_FORMAT
Definition: type_event.h:143
unsigned int redundant
Definition: struct_var.h:117
SCIP_MESSAGEHDLR * messagehdlr
Definition: struct_visual.h:44
SCIP_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:3913
SCIP_Real SCIPnormalCDF(SCIP_Real mean, SCIP_Real variance, SCIP_Real value)
Definition: misc.c:186
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:14860
SCIP_RETCODE SCIPvarMarkDoNotAggr(SCIP_VAR *var)
Definition: var.c:6101
SCIP_DECL_HASHKEYEQ(SCIPvarIsHashkeyEq)
Definition: var.c:11990
SCIP_Real SCIPvarGetBestRootSol(SCIP_VAR *var)
Definition: var.c:13714
SCIP_VAR * var
Definition: struct_var.h:110
public methods for message output
data structures for LP management
int nrootboundchgsrun
Definition: struct_stat.h:214
void SCIPcliquelistCheck(SCIP_CLIQUELIST *cliquelist, SCIP_VAR *var)
Definition: implics.c:3452
SCIP_VAR * a
Definition: circlepacking.c:57
void SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr,...)
Definition: message.c:609
void SCIPvarSetCopyData(SCIP_VAR *var, SCIP_DECL_VARCOPY((*varcopy)))
Definition: var.c:17327
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:9280
SCIP_Real * scalars
Definition: struct_var.h:185
SCIP_IMPLICS * implics
Definition: struct_var.h:236
SCIP_Real SCIPholelistGetLeft(SCIP_HOLELIST *holelist)
Definition: var.c:17218
SCIP_Bool SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6276
datastructures for problem variables
static void holelistFree(SCIP_HOLELIST **holelist, BMS_BLKMEM *blkmem)
Definition: var.c:168
static SCIP_RETCODE varEnsureLbchginfosSize(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: var.c:419
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:17370
SCIP_RETCODE SCIPvarResetBounds(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat)
Definition: var.c:9227
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:216
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:9409
#define SCIP_Real
Definition: def.h:177
internal methods for problem statistics
#define SCIP_EVENTTYPE_VARCHANGED
Definition: type_event.h:121
static SCIP_RETCODE varFree(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:2738
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:1291
SCIP_Longint SCIPvarGetNBranchings(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15698
SCIP_RETCODE SCIPvarsGetProbvarBinary(SCIP_VAR ***vars, SCIP_Bool **negatedarr, int nvars)
Definition: var.c:12277
SCIP_VAR * SCIPbdchginfoGetInferVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18572
SCIP_Bool SCIPsetIsFeasPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6719
SCIP_RETCODE SCIPeventCreateTypeChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_VARTYPE oldtype, SCIP_VARTYPE newtype)
Definition: event.c:824
int parentvarssize
Definition: struct_var.h:251
SCIP_CLIQUELIST * cliquelist
Definition: struct_var.h:237
SCIP_RETCODE SCIPvarSetInitial(SCIP_VAR *var, SCIP_Bool initial)
Definition: var.c:17338
SCIP_VAR ** SCIPprobGetVars(SCIP_PROB *prob)
Definition: prob.c:2388
SCIP_RETCODE SCIPvarGetProbvarHole(SCIP_VAR **var, SCIP_Real *left, SCIP_Real *right)
Definition: var.c:12561
SCIP_RETCODE SCIPlpUpdateVarLoose(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:14287
SCIP_Real SCIPvarGetVSIDS(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:18375
#define SCIP_INVALID
Definition: def.h:197
internal methods for constraints and constraint handlers
SCIP_RETCODE SCIPeventCreateGholeAdded(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real left, SCIP_Real right)
Definition: event.c:717
void SCIPsortPtrReal(void **ptrarray, SCIP_Real *realarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
int SCIPvarGetNUses(SCIP_VAR *var)
Definition: var.c:17261
void SCIPvarsGetProbvar(SCIP_VAR **vars, int nvars)
Definition: var.c:12197
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:2554
static SCIP_RETCODE parseBounds(SCIP_SET *set, const char *str, char *type, SCIP_Real *lb, SCIP_Real *ub, char **endptr)
Definition: var.c:2299
SCIP_VAR ** SCIPvarGetVubVars(SCIP_VAR *var)
Definition: var.c:18156
SCIP_RETCODE SCIPeventCreateVarUnlocked(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition: event.c:575
SCIP_Real branchfactor
Definition: struct_var.h:202
unsigned int donotmultaggr
Definition: struct_var.h:270
#define SCIP_Longint
Definition: def.h:162
SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
Definition: var.c:18022
SCIP_CONS * SCIPbdchginfoGetInferCons(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18584
SCIP_Bool SCIPsetIsDualfeasZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6919
SCIP_Real SCIPvarGetAvgSol(SCIP_VAR *var)
Definition: var.c:14061
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:17590
SCIP_Real nlpsol
Definition: struct_var.h:208
SCIP_VAR * lastbranchvar
Definition: struct_stat.h:174
static SCIP_RETCODE varEnsureParentvarsSize(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: var.c:2613
SCIP_Real SCIPvarGetAvgCutoffs(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:16264
SCIP_Real lb
Definition: struct_var.h:161
SCIP_VAR * var
Definition: struct_lp.h:151
SCIP_Bool SCIPsetIsFeasGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6664
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:9118
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:17416
SCIP_Real SCIPvarGetMultaggrUbLocal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8496
SCIP_RETCODE SCIPvarChgName(SCIP_VAR *var, BMS_BLKMEM *blkmem, const char *name)
Definition: var.c:2907
SCIP_DOM glbdom
Definition: struct_var.h:216
SCIP_Real SCIPsetEpsilon(SCIP_SET *set)
Definition: set.c:6087
SCIP_Real SCIPhistoryGetAvgInferences(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:649
SCIP_STAGE SCIPsetGetStage(SCIP_SET *set)
Definition: set.c:2982
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:6720
SCIP_Bool collectvarhistory
Definition: struct_stat.h:272
SCIP_VAR * negatedvar
Definition: struct_var.h:233
SCIP_Bool SCIPvarIsMarkedDeleteGlobalStructures(SCIP_VAR *var)
Definition: var.c:17518
SCIP_Bool SCIPcliqueIsCleanedUp(SCIP_CLIQUE *clique)
Definition: implics.c:3414
SCIP_Real newbound
Definition: struct_var.h:109
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17976
int SCIPcliqueGetNVars(SCIP_CLIQUE *clique)
Definition: implics.c:3358
SCIP_RETCODE SCIPvarAddHoleOriginal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real left, SCIP_Real right)
Definition: var.c:8689
void SCIPbdchginfoFree(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem)
Definition: var.c:16395
void SCIPvarAdjustUb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *ub)
Definition: var.c:6530
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:17393
static void varIncRootboundchgs(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat)
Definition: var.c:6790
#define BMSallocBlockMemory(mem, ptr)
Definition: memory.h:444
SCIP_HOLELIST * SCIPvarGetHolelistLocal(SCIP_VAR *var)
Definition: var.c:17986
unsigned int delglobalstructs
Definition: struct_var.h:276
SCIP_Bool SCIPsetIsDualfeasNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6941
SCIP_BOUNDTYPE SCIPbdchginfoGetBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18532
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:18417
SCIP_Real rootsol
Definition: struct_var.h:203
SCIP_Bool SCIPeventqueueIsDelayed(SCIP_EVENTQUEUE *eventqueue)
Definition: event.c:2559
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:3096
SCIP_RETCODE SCIPlpUpdateVarColumn(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:14163
SCIP_HISTORY * history
Definition: struct_var.h:241
SCIP_RETCODE SCIPvarSetRemovable(SCIP_VAR *var, SCIP_Bool removable)
Definition: var.c:17354
SCIP_Real SCIPvarGetVSIDS_rec(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15876
int nrootintfixingsrun
Definition: struct_stat.h:216
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:430
SCIP_RETCODE SCIPvarGetProbvarSum(SCIP_VAR **var, SCIP_SET *set, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12646
#define SCIP_EVENTTYPE_GUBCHANGED
Definition: type_event.h:67
#define SCIP_CALL_ABORT(x)
Definition: def.h:363
SCIP_Real SCIPvarGetPseudoSol(SCIP_VAR *var)
Definition: var.c:18362
enum SCIP_BoundchgType SCIP_BOUNDCHGTYPE
Definition: type_var.h:78
SCIP_Real * SCIPimplicsGetBounds(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3337
SCIP_ORIGINAL original
Definition: struct_var.h:220
SCIP_Real SCIPcolGetRedcost(SCIP_COL *col, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:3946
SCIP_VAR * SCIPvarGetTransVar(SCIP_VAR *var)
Definition: var.c:17610
#define SCIP_ALLOC(x)
Definition: def.h:395
#define SCIPABORT()
Definition: def.h:356
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:17442
SCIP_RETCODE SCIPeventCreateGubChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition: event.c:642
void SCIPhistoryFree(SCIP_HISTORY **history, BMS_BLKMEM *blkmem)
Definition: history.c:57
SCIP_Real SCIPvarGetMultaggrLbLocal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8430
const char * SCIPprobGetName(SCIP_PROB *prob)
Definition: prob.c:2334
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9022
unsigned int applied
Definition: struct_var.h:94
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition: var.c:17472
void SCIPvboundsFree(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem)
Definition: implics.c:64
SCIP_RETCODE SCIPvarsAddClique(SCIP_VAR **vars, SCIP_Bool *values, int nvars, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_CLIQUE *clique)
Definition: var.c:11354
void SCIPvarGetImplicVarBounds(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_Real *lb, SCIP_Real *ub)
Definition: var.c:11142
datastructures for global SCIP settings
SCIP_HOLELIST ** ptr
Definition: struct_var.h:58
#define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
Definition: memory.h:451
SCIP_BOUNDCHG * boundchgs
Definition: struct_var.h:143
void SCIPvarMarkDeleted(SCIP_VAR *var)
Definition: var.c:6090
void SCIPvarSetData(SCIP_VAR *var, SCIP_VARDATA *vardata)
Definition: var.c:17281
SCIP_Bool SCIPcolIsInLP(SCIP_COL *col)
Definition: lp.c:17048
SCIP_COL * col
Definition: struct_var.h:221
SCIP_RETCODE SCIPvarNegate(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **negvar)
Definition: var.c:5912
SCIP_Real left
Definition: struct_var.h:44
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9274
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:1414
SCIP_Bool SCIPvarMayRoundUp(SCIP_VAR *var)
Definition: var.c:3445
#define EPSZ(x, eps)
Definition: def.h:207
void SCIPimplicsFree(SCIP_IMPLICS **implics, BMS_BLKMEM *blkmem)
Definition: implics.c:442
static SCIP_RETCODE varProcessChgBranchDirection(SCIP_VAR *var, SCIP_BRANCHDIR branchdirection)
Definition: var.c:11750
SCIP_Bool SCIPvarMayRoundDown(SCIP_VAR *var)
Definition: var.c:3434
SCIP_RETCODE SCIPprobAddVar(SCIP_PROB *prob, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR *var)
Definition: prob.c:928
SCIP callable library.
SCIP_Bool SCIPsetIsFeasNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6730
SCIP_Real SCIPvarGetPseudocostVariance(SCIP_VAR *var, SCIP_BRANCHDIR dir, SCIP_Bool onlycurrentrun)
Definition: var.c:14691
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:17580
SCIP_Real objscale
Definition: struct_prob.h:42
SCIP_BDCHGINFO * lbchginfos
Definition: struct_var.h:239
static SCIP_RETCODE findValuehistoryEntry(SCIP_VAR *var, SCIP_Real value, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HISTORY **history)
Definition: var.c:14995
public methods for propagators
SCIP_RETCODE SCIPcliquelistDel(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: implics.c:1518
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:17406
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:5633
SCIP_Real scalar
Definition: struct_var.h:176
uint64_t SCIP_EVENTTYPE
Definition: type_event.h:142
void SCIPvarMarkDeleteGlobalStructures(SCIP_VAR *var)
Definition: var.c:17508
SCIP_BOUNDCHGTYPE SCIPbdchginfoGetChgtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18522
SCIP_RETCODE SCIPvarDelCliqueFromList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:11414