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-2024 Zuse Institute Berlin (ZIB) */
7 /* */
8 /* Licensed under the Apache License, Version 2.0 (the "License"); */
9 /* you may not use this file except in compliance with the License. */
10 /* You may obtain a copy of the License at */
11 /* */
12 /* http://www.apache.org/licenses/LICENSE-2.0 */
13 /* */
14 /* Unless required by applicable law or agreed to in writing, software */
15 /* distributed under the License is distributed on an "AS IS" BASIS, */
16 /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17 /* See the License for the specific language governing permissions and */
18 /* limitations under the License. */
19 /* */
20 /* You should have received a copy of the Apache-2.0 license */
21 /* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22 /* */
23 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24 
25 /**@file var.c
26  * @ingroup OTHER_CFILES
27  * @brief methods for problem variables
28  * @author Tobias Achterberg
29  * @author Timo Berthold
30  * @author Gerald Gamrath
31  * @author Stefan Heinz
32  * @author Marc Pfetsch
33  * @author Michael Winkler
34  * @author Kati Wolter
35  * @author Stefan Vigerske
36  *
37  * @todo Possibly implement the access of bounds of multi-aggregated variables by accessing the
38  * corresponding linear constraint if it exists. This seems to require some work, since the linear
39  * constraint has to be stored. Moreover, it has even to be created in case the original constraint
40  * was deleted after multi-aggregation, but the bounds of the multi-aggregated variable should be
41  * changed. This has to be done with care in order to not loose the performance gains of
42  * multi-aggregation.
43  */
44 
45 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
46 
47 #include "scip/cons.h"
48 #include "scip/event.h"
49 #include "scip/history.h"
50 #include "scip/implics.h"
51 #include "scip/lp.h"
52 #include "scip/primal.h"
53 #include "scip/prob.h"
54 #include "scip/pub_cons.h"
55 #include "scip/pub_history.h"
56 #include "scip/pub_implics.h"
57 #include "scip/pub_lp.h"
58 #include "scip/pub_message.h"
59 #include "scip/pub_misc.h"
60 #include "scip/pub_misc_sort.h"
61 #include "scip/pub_prop.h"
62 #include "scip/pub_var.h"
63 #include "scip/relax.h"
64 #include "scip/set.h"
65 #include "scip/sol.h"
66 #include "scip/stat.h"
67 #include "scip/struct_event.h"
68 #include "scip/struct_lp.h"
69 #include "scip/struct_prob.h"
70 #include "scip/struct_set.h"
71 #include "scip/struct_stat.h"
72 #include "scip/struct_var.h"
73 #include "scip/tree.h"
74 #include "scip/var.h"
75 #include <string.h>
76 
77 #define MAXIMPLSCLOSURE 100 /**< maximal number of descendants of implied variable for building closure
78  * in implication graph */
79 #define MAXABSVBCOEF 1e+5 /**< maximal absolute coefficient in variable bounds added due to implications */
80 
81 
82 /*
83  * Debugging variable release and capture
84  *
85  * Define DEBUGUSES_VARNAME to the name of the variable for which to print
86  * a backtrace when it is captured and released.
87  * Optionally define DEBUGUSES_PROBNAME to the name of a SCIP problem to consider.
88  * Have DEBUGUSES_NOADDR2LINE defined if you do not have addr2line installed on your system.
89  */
90 /* #define DEBUGUSES_VARNAME "t_t_b7" */
91 /* #define DEBUGUSES_PROBNAME "t_st_e35_rens" */
92 /* #define DEBUGUSES_NOADDR2LINE */
93 
94 #ifdef DEBUGUSES_VARNAME
95 #include <execinfo.h>
96 #include <stdio.h>
97 #include <stdlib.h>
98 #include "scip/struct_scip.h"
99 
100 /** obtains a backtrace and prints it to stdout. */
101 static
102 void print_backtrace(void)
103 {
104  void* array[10];
105  char** strings;
106  int size;
107  int i;
108 
109  size = backtrace(array, 10);
110  strings = backtrace_symbols(array, size);
111  if( strings == NULL )
112  return;
113 
114  /* skip first entry, which is the print_backtrace function */
115  for( i = 1; i < size; ++i )
116  {
117  /* if string is something like
118  * /path/to/scip/bin/../lib/shared/libscip-7.0.1.3.linux.x86_64.gnu.dbg.so(+0x2675dd3)
119  * (that is, no function name because it is a inlined function), then call
120  * addr2line -e <libname> <addr> to get func and code line
121  * dladdr() may be an alternative
122  */
123  char* openpar;
124  char* closepar = NULL;
125 #ifndef DEBUGUSES_NOADDR2LINE
126  openpar = strchr(strings[i], '(');
127  if( openpar != NULL && openpar[1] == '+' )
128  closepar = strchr(openpar+2, ')');
129 #endif
130  if( closepar != NULL )
131  {
132  char cmd[SCIP_MAXSTRLEN];
133  (void) SCIPsnprintf(cmd, SCIP_MAXSTRLEN, "addr2line -f -p -e \"%.*s\" %.*s", openpar - strings[i], strings[i], closepar-openpar-1, openpar+1);
134  printf(" ");
135  fflush(stdout);
136  system(cmd);
137  }
138  else
139  printf(" %s\n", strings[i]);
140  }
141 
142  free(strings);
143 }
144 #endif
145 
146 /*
147  * hole, holelist, and domain methods
148  */
149 
150 /** creates a new holelist element */
151 static
153  SCIP_HOLELIST** holelist, /**< pointer to holelist to create */
154  BMS_BLKMEM* blkmem, /**< block memory for target holelist */
155  SCIP_SET* set, /**< global SCIP settings */
156  SCIP_Real left, /**< left bound of open interval in new hole */
157  SCIP_Real right /**< right bound of open interval in new hole */
158  )
159 {
160  assert(holelist != NULL);
161  assert(blkmem != NULL);
162  assert(SCIPsetIsLT(set, left, right));
163 
164  SCIPsetDebugMsg(set, "create hole list element (%.15g,%.15g) in blkmem %p\n", left, right, (void*)blkmem);
165 
166  SCIP_ALLOC( BMSallocBlockMemory(blkmem, holelist) );
167  (*holelist)->hole.left = left;
168  (*holelist)->hole.right = right;
169  (*holelist)->next = NULL;
170 
171  return SCIP_OKAY;
172 }
173 
174 /** frees all elements in the holelist */
175 static
176 void holelistFree(
177  SCIP_HOLELIST** holelist, /**< pointer to holelist to free */
178  BMS_BLKMEM* blkmem /**< block memory for target holelist */
179  )
180 {
181  assert(holelist != NULL);
182  assert(blkmem != NULL);
183 
184  while( *holelist != NULL )
185  {
186  SCIP_HOLELIST* next;
187 
188  SCIPdebugMessage("free hole list element (%.15g,%.15g) in blkmem %p\n",
189  (*holelist)->hole.left, (*holelist)->hole.right, (void*)blkmem);
190 
191  next = (*holelist)->next;
192  BMSfreeBlockMemory(blkmem, holelist);
193  assert(*holelist == NULL);
194 
195  *holelist = next;
196  }
197  assert(*holelist == NULL);
198 }
199 
200 /** duplicates a list of holes */
201 static
203  SCIP_HOLELIST** target, /**< pointer to target holelist */
204  BMS_BLKMEM* blkmem, /**< block memory for target holelist */
205  SCIP_SET* set, /**< global SCIP settings */
206  SCIP_HOLELIST* source /**< holelist to duplicate */
207  )
208 {
209  assert(target != NULL);
210 
211  while( source != NULL )
212  {
213  assert(source->next == NULL || SCIPsetIsGE(set, source->next->hole.left, source->hole.right));
214  SCIP_CALL( holelistCreate(target, blkmem, set, source->hole.left, source->hole.right) );
215  source = source->next;
216  target = &(*target)->next;
217  }
218 
219  return SCIP_OKAY;
220 }
221 
222 /** adds a hole to the domain */
223 static
225  SCIP_DOM* dom, /**< domain to add hole to */
226  BMS_BLKMEM* blkmem, /**< block memory */
227  SCIP_SET* set, /**< global SCIP settings */
228  SCIP_Real left, /**< left bound of open interval in new hole */
229  SCIP_Real right, /**< right bound of open interval in new hole */
230  SCIP_Bool* added /**< pointer to store whether the hole was added (variable didn't had that hole before), or NULL */
231  )
232 {
233  SCIP_HOLELIST** insertpos;
234  SCIP_HOLELIST* next;
235 
236  assert(dom != NULL);
237  assert(added != NULL);
238 
239  /* search for the position of the new hole */
240  insertpos = &dom->holelist;
241  while( *insertpos != NULL && (*insertpos)->hole.left < left )
242  insertpos = &(*insertpos)->next;
243 
244  /* check if new hole already exists in the hole list or is a sub hole of an existing one */
245  if( *insertpos != NULL && (*insertpos)->hole.left == left && (*insertpos)->hole.right >= right ) /*lint !e777 */
246  {
247  SCIPsetDebugMsg(set, "new hole (%.15g,%.15g) is redundant through known hole (%.15g,%.15g)\n",
248  left, right, (*insertpos)->hole.left, (*insertpos)->hole.right);
249  *added = FALSE;
250  return SCIP_OKAY;
251  }
252 
253  /* add hole */
254  *added = TRUE;
255 
256  next = *insertpos;
257  SCIP_CALL( holelistCreate(insertpos, blkmem, set, left, right) );
258  (*insertpos)->next = next;
259 
260  return SCIP_OKAY;
261 }
262 
263 /** merges overlapping holes into single holes, computes and moves lower and upper bound, respectively */
264 /**@todo the domMerge() method is currently called if a lower or an upper bound locally or globally changed; this could
265  * be more efficient if performed with the knowledge if it was a lower or an upper bound which triggered this
266  * merge */
267 static
268 void domMerge(
269  SCIP_DOM* dom, /**< domain to merge */
270  BMS_BLKMEM* blkmem, /**< block memory */
271  SCIP_SET* set, /**< global SCIP settings */
272  SCIP_Real* newlb, /**< pointer to store new lower bound */
273  SCIP_Real* newub /**< pointer to store new upper bound */
274  )
275 {
276  SCIP_HOLELIST** holelistptr;
277  SCIP_HOLELIST** lastnextptr;
278  SCIP_Real* lastrightptr;
279 
280  assert(dom != NULL);
281  assert(SCIPsetIsLE(set, dom->lb, dom->ub));
282 
283 #ifndef NDEBUG
284  {
285  /* check if the holelist is sorted w.r.t. to the left interval bounds */
286  SCIP_Real lastleft;
287 
288  holelistptr = &dom->holelist;
289 
290  lastleft = -SCIPsetInfinity(set);
291 
292  while( *holelistptr != NULL )
293  {
294  if( (*holelistptr)->next != NULL )
295  {
296  assert( SCIPsetIsLE(set, lastleft, (*holelistptr)->hole.left) );
297  lastleft = (*holelistptr)->hole.left;
298  }
299 
300  holelistptr = &(*holelistptr)->next;
301  }
302  }
303 #endif
304 
305  SCIPsetDebugMsg(set, "merge hole list\n");
306 
307  holelistptr = &dom->holelist;
308  lastrightptr = &dom->lb; /* lower bound is the right bound of the hole (-infinity,lb) */
309  lastnextptr = holelistptr;
310 
311  while( *holelistptr != NULL )
312  {
313  SCIPsetDebugMsg(set, "check hole (%.15g,%.15g) last right interval was <%.15g>\n", (*holelistptr)->hole.left, (*holelistptr)->hole.right, *lastrightptr);
314 
315  /* check that the hole is not empty */
316  assert(SCIPsetIsLT(set, (*holelistptr)->hole.left, (*holelistptr)->hole.right));
317 
318  if( SCIPsetIsGE(set, (*holelistptr)->hole.left, dom->ub) )
319  {
320  /* the remaining holes start behind the upper bound: remove them */
321  SCIPsetDebugMsg(set, "remove remaining hole since upper bound <%.15g> is less then the left hand side of the current hole\n", dom->ub);
322  holelistFree(holelistptr, blkmem);
323  assert(*holelistptr == NULL);
324 
325  /* unlink this hole from the previous hole */
326  *lastnextptr = NULL;
327  }
328  else if( SCIPsetIsGT(set, (*holelistptr)->hole.right, dom->ub) )
329  {
330  /* the hole overlaps the upper bound: decrease upper bound, remove this hole and all remaining holes */
331  SCIPsetDebugMsg(set, "upper bound <%.15g> lays in current hole; store new upper bound and remove this and all remaining holes\n", dom->ub);
332 
333  assert(SCIPsetIsLT(set, (*holelistptr)->hole.left, dom->ub));
334 
335  /* adjust upper bound */
336  dom->ub = (*holelistptr)->hole.left;
337 
338  if(newub != NULL )
339  *newub = (*holelistptr)->hole.left;
340 
341  /* remove remaining hole list */
342  holelistFree(holelistptr, blkmem);
343  assert(*holelistptr == NULL);
344 
345  /* unlink this hole from the previous hole */
346  *lastnextptr = NULL;
347  }
348  else if( SCIPsetIsGT(set, *lastrightptr, (*holelistptr)->hole.left) )
349  {
350  /* the right bound of the last hole is greater than the left bound of this hole: increase the right bound of
351  * the last hole, delete this hole */
352  SCIP_HOLELIST* nextholelist;
353 
354  if( SCIPsetIsEQ(set, *lastrightptr, dom->lb ) )
355  {
356  /* the reason for the overlap results from the lower bound hole (-infinity,lb); therefore, we can increase
357  * the lower bound */
358  SCIPsetDebugMsg(set, "lower bound <%.15g> lays in current hole; store new lower bound and remove hole\n", dom->lb);
359  *lastrightptr = MAX(*lastrightptr, (*holelistptr)->hole.right);
360 
361  /* adjust lower bound */
362  dom->lb = *lastrightptr;
363 
364  if(newlb != NULL )
365  *newlb = *lastrightptr;
366  }
367  else
368  {
369  SCIPsetDebugMsg(set, "current hole overlaps with the previous one (...,%.15g); merge to (...,%.15g)\n",
370  *lastrightptr, MAX(*lastrightptr, (*holelistptr)->hole.right) );
371  *lastrightptr = MAX(*lastrightptr, (*holelistptr)->hole.right);
372  }
373  nextholelist = (*holelistptr)->next;
374  (*holelistptr)->next = NULL;
375  holelistFree(holelistptr, blkmem);
376 
377  /* connect the linked list after removing the hole */
378  *lastnextptr = nextholelist;
379 
380  /* get next hole */
381  *holelistptr = nextholelist;
382  }
383  else
384  {
385  /* the holes do not overlap: update lastholelist and lastrightptr */
386  lastrightptr = &(*holelistptr)->hole.right;
387  lastnextptr = &(*holelistptr)->next;
388 
389  /* get next hole */
390  holelistptr = &(*holelistptr)->next;
391  }
392  }
393 
394 #ifndef NDEBUG
395  {
396  /* check that holes are merged */
397  SCIP_Real lastright;
398 
399  lastright = dom->lb; /* lower bound is the right bound of the hole (-infinity,lb) */
400  holelistptr = &dom->holelist;
401 
402  while( *holelistptr != NULL )
403  {
404  /* check the the last right interval is smaller or equal to the current left interval (none overlapping) */
405  assert( SCIPsetIsLE(set, lastright, (*holelistptr)->hole.left) );
406 
407  /* check the hole property (check that the hole is not empty) */
408  assert( SCIPsetIsLT(set, (*holelistptr)->hole.left, (*holelistptr)->hole.right) );
409  lastright = (*holelistptr)->hole.right;
410 
411  /* get next hole */
412  holelistptr = &(*holelistptr)->next;
413  }
414 
415  /* check the the last right interval is smaller or equal to the upper bound (none overlapping) */
416  assert( SCIPsetIsLE(set, lastright, dom->ub) );
417  }
418 #endif
419 }
420 
421 /*
422  * domain change methods
423  */
424 
425 /** ensures, that bound change info array for lower bound changes can store at least num entries */
426 static
428  SCIP_VAR* var, /**< problem variable */
429  BMS_BLKMEM* blkmem, /**< block memory */
430  SCIP_SET* set, /**< global SCIP settings */
431  int num /**< minimum number of entries to store */
432  )
433 {
434  assert(var != NULL);
435  assert(var->nlbchginfos <= var->lbchginfossize);
436  assert(SCIPvarIsTransformed(var));
437 
438  if( num > var->lbchginfossize )
439  {
440  int newsize;
441 
442  newsize = SCIPsetCalcMemGrowSize(set, num);
443  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->lbchginfos, var->lbchginfossize, newsize) );
444  var->lbchginfossize = newsize;
445  }
446  assert(num <= var->lbchginfossize);
447 
448  return SCIP_OKAY;
449 }
450 
451 /** ensures, that bound change info array for upper bound changes can store at least num entries */
452 static
454  SCIP_VAR* var, /**< problem variable */
455  BMS_BLKMEM* blkmem, /**< block memory */
456  SCIP_SET* set, /**< global SCIP settings */
457  int num /**< minimum number of entries to store */
458  )
459 {
460  assert(var != NULL);
461  assert(var->nubchginfos <= var->ubchginfossize);
462  assert(SCIPvarIsTransformed(var));
463 
464  if( num > var->ubchginfossize )
465  {
466  int newsize;
467 
468  newsize = SCIPsetCalcMemGrowSize(set, num);
469  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->ubchginfos, var->ubchginfossize, newsize) );
470  var->ubchginfossize = newsize;
471  }
472  assert(num <= var->ubchginfossize);
473 
474  return SCIP_OKAY;
475 }
476 
477 /** adds domain change info to the variable's lower bound change info array */
478 static
480  SCIP_VAR* var, /**< problem variable */
481  BMS_BLKMEM* blkmem, /**< block memory */
482  SCIP_SET* set, /**< global SCIP settings */
483  SCIP_Real oldbound, /**< old value for bound */
484  SCIP_Real newbound, /**< new value for bound */
485  int depth, /**< depth in the tree, where the bound change takes place */
486  int pos, /**< position of the bound change in its bound change array */
487  SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself) */
488  SCIP_CONS* infercons, /**< constraint that inferred this bound change, or NULL */
489  SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
490  int inferinfo, /**< user information for inference to help resolving the conflict */
491  SCIP_BOUNDTYPE inferboundtype, /**< type of bound for inference var: lower or upper bound */
492  SCIP_BOUNDCHGTYPE boundchgtype /**< bound change type: branching decision or inferred bound change */
493  )
494 {
495  assert(var != NULL);
496  assert(SCIPsetIsLT(set, oldbound, newbound));
497  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, oldbound));
498  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
499  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, oldbound, 0.0));
500  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, 1.0));
501  assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
502  assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
503  assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
504 
505  SCIPsetDebugMsg(set, "adding lower bound change info to var <%s>[%g,%g]: depth=%d, pos=%d, infer%s=<%s>, inferinfo=%d, %g -> %g\n",
506  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, depth, pos, infercons != NULL ? "cons" : "prop",
507  infercons != NULL ? SCIPconsGetName(infercons) : (inferprop != NULL ? SCIPpropGetName(inferprop) : "-"), inferinfo,
508  oldbound, newbound);
509 
510  SCIP_CALL( varEnsureLbchginfosSize(var, blkmem, set, var->nlbchginfos+1) );
511  var->lbchginfos[var->nlbchginfos].oldbound = oldbound;
512  var->lbchginfos[var->nlbchginfos].newbound = newbound;
513  var->lbchginfos[var->nlbchginfos].var = var;
514  var->lbchginfos[var->nlbchginfos].bdchgidx.depth = depth;
515  var->lbchginfos[var->nlbchginfos].bdchgidx.pos = pos;
516  var->lbchginfos[var->nlbchginfos].pos = var->nlbchginfos; /*lint !e732*/
517  var->lbchginfos[var->nlbchginfos].boundchgtype = boundchgtype; /*lint !e641*/
518  var->lbchginfos[var->nlbchginfos].boundtype = SCIP_BOUNDTYPE_LOWER; /*lint !e641*/
519  var->lbchginfos[var->nlbchginfos].redundant = FALSE;
520  var->lbchginfos[var->nlbchginfos].inferboundtype = inferboundtype; /*lint !e641*/
521  var->lbchginfos[var->nlbchginfos].inferencedata.var = infervar;
522  var->lbchginfos[var->nlbchginfos].inferencedata.info = inferinfo;
523 
524  /**@note The "pos" data member of the bound change info has a size of 27 bits */
525  assert(var->nlbchginfos < 1 << 27);
526 
527  switch( boundchgtype )
528  {
530  break;
532  assert(infercons != NULL);
533  var->lbchginfos[var->nlbchginfos].inferencedata.reason.cons = infercons;
534  break;
536  var->lbchginfos[var->nlbchginfos].inferencedata.reason.prop = inferprop;
537  break;
538  default:
539  SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
540  return SCIP_INVALIDDATA;
541  }
542 
543  var->nlbchginfos++;
544 
545  assert(var->nlbchginfos < 2
547  &var->lbchginfos[var->nlbchginfos-1].bdchgidx));
548 
549  return SCIP_OKAY;
550 }
551 
552 /** adds domain change info to the variable's upper bound change info array */
553 static
555  SCIP_VAR* var, /**< problem variable */
556  BMS_BLKMEM* blkmem, /**< block memory */
557  SCIP_SET* set, /**< global SCIP settings */
558  SCIP_Real oldbound, /**< old value for bound */
559  SCIP_Real newbound, /**< new value for bound */
560  int depth, /**< depth in the tree, where the bound change takes place */
561  int pos, /**< position of the bound change in its bound change array */
562  SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself) */
563  SCIP_CONS* infercons, /**< constraint that inferred this bound change, or NULL */
564  SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
565  int inferinfo, /**< user information for inference to help resolving the conflict */
566  SCIP_BOUNDTYPE inferboundtype, /**< type of bound for inference var: lower or upper bound */
567  SCIP_BOUNDCHGTYPE boundchgtype /**< bound change type: branching decision or inferred bound change */
568  )
569 {
570  assert(var != NULL);
571  assert(SCIPsetIsGT(set, oldbound, newbound));
572  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, oldbound));
573  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
574  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, oldbound, 1.0));
575  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, 0.0));
576  assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
577  assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
578  assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
579 
580  SCIPsetDebugMsg(set, "adding upper bound change info to var <%s>[%g,%g]: depth=%d, pos=%d, infer%s=<%s>, inferinfo=%d, %g -> %g\n",
581  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, depth, pos, infercons != NULL ? "cons" : "prop",
582  infercons != NULL ? SCIPconsGetName(infercons) : (inferprop != NULL ? SCIPpropGetName(inferprop) : "-"), inferinfo,
583  oldbound, newbound);
584 
585  SCIP_CALL( varEnsureUbchginfosSize(var, blkmem, set, var->nubchginfos+1) );
586  var->ubchginfos[var->nubchginfos].oldbound = oldbound;
587  var->ubchginfos[var->nubchginfos].newbound = newbound;
588  var->ubchginfos[var->nubchginfos].var = var;
589  var->ubchginfos[var->nubchginfos].bdchgidx.depth = depth;
590  var->ubchginfos[var->nubchginfos].bdchgidx.pos = pos;
591  var->ubchginfos[var->nubchginfos].pos = var->nubchginfos; /*lint !e732*/
592  var->ubchginfos[var->nubchginfos].boundchgtype = boundchgtype; /*lint !e641*/
593  var->ubchginfos[var->nubchginfos].boundtype = SCIP_BOUNDTYPE_UPPER; /*lint !e641*/
594  var->ubchginfos[var->nubchginfos].redundant = FALSE;
595  var->ubchginfos[var->nubchginfos].inferboundtype = inferboundtype; /*lint !e641*/
596  var->ubchginfos[var->nubchginfos].inferencedata.var = infervar;
597  var->ubchginfos[var->nubchginfos].inferencedata.info = inferinfo;
598 
599  /**@note The "pos" data member of the bound change info has a size of 27 bits */
600  assert(var->nubchginfos < 1 << 27);
601 
602  switch( boundchgtype )
603  {
605  break;
607  assert(infercons != NULL);
608  var->ubchginfos[var->nubchginfos].inferencedata.reason.cons = infercons;
609  break;
611  var->ubchginfos[var->nubchginfos].inferencedata.reason.prop = inferprop;
612  break;
613  default:
614  SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
615  return SCIP_INVALIDDATA;
616  }
617 
618  var->nubchginfos++;
619 
620  assert(var->nubchginfos < 2
622  &var->ubchginfos[var->nubchginfos-1].bdchgidx));
623 
624  return SCIP_OKAY;
625 }
626 
627 /** applies single bound change */
629  SCIP_BOUNDCHG* boundchg, /**< bound change to apply */
630  BMS_BLKMEM* blkmem, /**< block memory */
631  SCIP_SET* set, /**< global SCIP settings */
632  SCIP_STAT* stat, /**< problem statistics */
633  SCIP_LP* lp, /**< current LP data */
634  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
635  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
636  int depth, /**< depth in the tree, where the bound change takes place */
637  int pos, /**< position of the bound change in its bound change array */
638  SCIP_Bool* cutoff /**< pointer to store whether an infeasible bound change was detected */
639  )
640 {
641  SCIP_VAR* var;
642 
643  assert(boundchg != NULL);
644  assert(stat != NULL);
645  assert(depth > 0);
646  assert(pos >= 0);
647  assert(cutoff != NULL);
648 
649  *cutoff = FALSE;
650 
651  /* ignore redundant bound changes */
652  if( boundchg->redundant )
653  return SCIP_OKAY;
654 
655  var = boundchg->var;
656  assert(var != NULL);
658  assert(!SCIPvarIsIntegral(var) || SCIPsetIsFeasIntegral(set, boundchg->newbound));
659 
660  /* apply bound change */
661  switch( boundchg->boundtype )
662  {
664  /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
665  if( SCIPsetIsGT(set, boundchg->newbound, var->locdom.lb) )
666  {
667  if( SCIPsetIsLE(set, boundchg->newbound, var->locdom.ub) )
668  {
669  /* add the bound change info to the variable's bound change info array */
670  switch( boundchg->boundchgtype )
671  {
673  SCIPsetDebugMsg(set, " -> branching: new lower bound of <%s>[%g,%g]: %g\n",
674  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
675  SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
677  stat->lastbranchvar = var;
679  stat->lastbranchvalue = boundchg->newbound;
680  break;
681 
683  assert(boundchg->data.inferencedata.reason.cons != NULL);
684  SCIPsetDebugMsg(set, " -> constraint <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
685  SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
686  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
687  SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
688  boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
689  boundchg->data.inferencedata.info,
691  break;
692 
694  SCIPsetDebugMsg(set, " -> propagator <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
695  boundchg->data.inferencedata.reason.prop != NULL
696  ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
697  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
698  SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
699  boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
700  boundchg->data.inferencedata.info,
702  break;
703 
704  default:
705  SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
706  return SCIP_INVALIDDATA;
707  }
708 
709  /* change local bound of variable */
710  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, boundchg->newbound) );
711  }
712  else
713  {
714  SCIPsetDebugMsg(set, " -> cutoff: new lower bound of <%s>[%g,%g]: %g\n",
715  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
716  *cutoff = TRUE;
717  boundchg->redundant = TRUE; /* bound change has not entered the lbchginfos array of the variable! */
718  }
719  }
720  else
721  {
722  /* mark bound change to be inactive */
723  SCIPsetDebugMsg(set, " -> inactive %s: new lower bound of <%s>[%g,%g]: %g\n",
724  (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
725  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
726  boundchg->redundant = TRUE;
727  }
728  break;
729 
731  /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
732  if( SCIPsetIsLT(set, boundchg->newbound, var->locdom.ub) )
733  {
734  if( SCIPsetIsGE(set, boundchg->newbound, var->locdom.lb) )
735  {
736  /* add the bound change info to the variable's bound change info array */
737  switch( boundchg->boundchgtype )
738  {
740  SCIPsetDebugMsg(set, " -> branching: new upper bound of <%s>[%g,%g]: %g\n",
741  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
742  SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
744  stat->lastbranchvar = var;
746  stat->lastbranchvalue = boundchg->newbound;
747  break;
748 
750  assert(boundchg->data.inferencedata.reason.cons != NULL);
751  SCIPsetDebugMsg(set, " -> constraint <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
752  SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
753  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
754  SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
755  boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
756  boundchg->data.inferencedata.info,
758  break;
759 
761  SCIPsetDebugMsg(set, " -> propagator <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
762  boundchg->data.inferencedata.reason.prop != NULL
763  ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
764  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
765  SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
766  boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
767  boundchg->data.inferencedata.info,
769  break;
770 
771  default:
772  SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
773  return SCIP_INVALIDDATA;
774  }
775 
776  /* change local bound of variable */
777  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, boundchg->newbound) );
778  }
779  else
780  {
781  SCIPsetDebugMsg(set, " -> cutoff: new upper bound of <%s>[%g,%g]: %g\n",
782  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
783  *cutoff = TRUE;
784  boundchg->redundant = TRUE; /* bound change has not entered the ubchginfos array of the variable! */
785  }
786  }
787  else
788  {
789  /* mark bound change to be inactive */
790  SCIPsetDebugMsg(set, " -> inactive %s: new upper bound of <%s>[%g,%g]: %g\n",
791  (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
792  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
793  boundchg->redundant = TRUE;
794  }
795  break;
796 
797  default:
798  SCIPerrorMessage("unknown bound type\n");
799  return SCIP_INVALIDDATA;
800  }
801 
802  /* update the branching and inference history */
803  if( !boundchg->applied && !boundchg->redundant )
804  {
805  assert(var == boundchg->var);
806 
808  {
809  SCIP_CALL( SCIPvarIncNBranchings(var, blkmem, set, stat,
812  }
813  else if( stat->lastbranchvar != NULL )
814  {
815  /**@todo if last branching variable is unknown, retrieve it from the nodes' boundchg arrays */
816  SCIP_CALL( SCIPvarIncInferenceSum(stat->lastbranchvar, blkmem, set, stat, stat->lastbranchdir, stat->lastbranchvalue, 1.0) );
817  }
818  boundchg->applied = TRUE;
819  }
820 
821  return SCIP_OKAY;
822 }
823 
824 /** undoes single bound change */
826  SCIP_BOUNDCHG* boundchg, /**< bound change to remove */
827  BMS_BLKMEM* blkmem, /**< block memory */
828  SCIP_SET* set, /**< global SCIP settings */
829  SCIP_STAT* stat, /**< problem statistics */
830  SCIP_LP* lp, /**< current LP data */
831  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
832  SCIP_EVENTQUEUE* eventqueue /**< event queue */
833  )
834 {
835  SCIP_VAR* var;
836 
837  assert(boundchg != NULL);
838  assert(stat != NULL);
839 
840  /* ignore redundant bound changes */
841  if( boundchg->redundant )
842  return SCIP_OKAY;
843 
844  var = boundchg->var;
845  assert(var != NULL);
847 
848  /* undo bound change: apply the previous bound change of variable */
849  switch( boundchg->boundtype )
850  {
852  var->nlbchginfos--;
853  assert(var->nlbchginfos >= 0);
854  assert(var->lbchginfos != NULL);
855  assert( SCIPsetIsFeasEQ(set, var->lbchginfos[var->nlbchginfos].newbound, var->locdom.lb) ); /*lint !e777*/
856  assert( SCIPsetIsFeasLE(set, boundchg->newbound, var->locdom.lb) ); /* current lb might be larger to intermediate global bound change */
857 
858  SCIPsetDebugMsg(set, "removed lower bound change info of var <%s>[%g,%g]: depth=%d, pos=%d, %g -> %g\n",
859  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub,
862 
863  /* reinstall the previous local bound */
864  SCIP_CALL( SCIPvarChgLbLocal(boundchg->var, blkmem, set, stat, lp, branchcand, eventqueue,
865  var->lbchginfos[var->nlbchginfos].oldbound) );
866 
867  /* in case all bound changes are removed the local bound should match the global bound */
868  assert(var->nlbchginfos > 0 || SCIPsetIsFeasEQ(set, var->locdom.lb, var->glbdom.lb));
869 
870  break;
871 
873  var->nubchginfos--;
874  assert(var->nubchginfos >= 0);
875  assert(var->ubchginfos != NULL);
876  assert( SCIPsetIsFeasEQ(set, var->ubchginfos[var->nubchginfos].newbound, var->locdom.ub) ); /*lint !e777*/
877  assert( SCIPsetIsFeasGE(set, boundchg->newbound, var->locdom.ub) ); /* current ub might be smaller to intermediate global bound change */
878 
879  SCIPsetDebugMsg(set, "removed upper bound change info of var <%s>[%g,%g]: depth=%d, pos=%d, %g -> %g\n",
880  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub,
883 
884  /* reinstall the previous local bound */
885  SCIP_CALL( SCIPvarChgUbLocal(boundchg->var, blkmem, set, stat, lp, branchcand, eventqueue,
886  var->ubchginfos[var->nubchginfos].oldbound) );
887 
888  /* in case all bound changes are removed the local bound should match the global bound */
889  assert(var->nubchginfos > 0 || SCIPsetIsFeasEQ(set, var->locdom.ub, var->glbdom.ub));
890 
891  break;
892 
893  default:
894  SCIPerrorMessage("unknown bound type\n");
895  return SCIP_INVALIDDATA;
896  }
897 
898  /* update last branching variable */
900  {
901  stat->lastbranchvar = NULL;
903  }
904 
905  return SCIP_OKAY;
906 }
907 
908 /** applies single bound change to the global problem by changing the global bound of the corresponding variable */
909 static
911  SCIP_BOUNDCHG* boundchg, /**< bound change to apply */
912  BMS_BLKMEM* blkmem, /**< block memory */
913  SCIP_SET* set, /**< global SCIP settings */
914  SCIP_STAT* stat, /**< problem statistics */
915  SCIP_LP* lp, /**< current LP data */
916  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
917  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
918  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
919  SCIP_Bool* cutoff /**< pointer to store whether an infeasible bound change was detected */
920  )
921 {
922  SCIP_VAR* var;
923  SCIP_Real newbound;
924  SCIP_BOUNDTYPE boundtype;
925 
926  assert(boundchg != NULL);
927  assert(cutoff != NULL);
928 
929  *cutoff = FALSE;
930 
931  /* ignore redundant bound changes */
932  if( boundchg->redundant )
933  return SCIP_OKAY;
934 
935  var = SCIPboundchgGetVar(boundchg);
936  newbound = SCIPboundchgGetNewbound(boundchg);
937  boundtype = SCIPboundchgGetBoundtype(boundchg);
938 
939  /* check if the bound change is redundant which can happen due to a (better) global bound change which was performed
940  * after that bound change was applied
941  *
942  * @note a global bound change is not captured by the redundant member of the bound change data structure
943  */
944  if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasLE(set, newbound, SCIPvarGetLbGlobal(var)))
945  || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasGE(set, newbound, SCIPvarGetUbGlobal(var))) )
946  {
947  return SCIP_OKAY;
948  }
949 
950  SCIPsetDebugMsg(set, "applying global bound change: <%s>[%g,%g] %s %g\n",
952  boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", newbound);
953 
954  /* check for cutoff */
955  if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGT(set, newbound, SCIPvarGetUbGlobal(var)))
956  || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLT(set, newbound, SCIPvarGetLbGlobal(var))) )
957  {
958  *cutoff = TRUE;
959  return SCIP_OKAY;
960  }
961 
962  /* apply bound change */
963  SCIP_CALL( SCIPvarChgBdGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound, boundtype) );
964 
965  return SCIP_OKAY;
966 }
967 
968 /** captures branching and inference data of bound change */
969 static
971  SCIP_BOUNDCHG* boundchg /**< bound change to remove */
972  )
973 {
974  assert(boundchg != NULL);
975 
976  /* capture variable associated with the bound change */
977  assert(boundchg->var != NULL);
978  SCIPvarCapture(boundchg->var);
979 
980  switch( boundchg->boundchgtype )
981  {
984  break;
985 
987  assert(boundchg->data.inferencedata.var != NULL);
988  assert(boundchg->data.inferencedata.reason.cons != NULL);
989  SCIPconsCapture(boundchg->data.inferencedata.reason.cons);
990  break;
991 
992  default:
993  SCIPerrorMessage("invalid bound change type\n");
994  return SCIP_INVALIDDATA;
995  }
996 
997  return SCIP_OKAY;
998 }
999 
1000 /** releases branching and inference data of bound change */
1001 static
1003  SCIP_BOUNDCHG* boundchg, /**< bound change to remove */
1004  BMS_BLKMEM* blkmem, /**< block memory */
1005  SCIP_SET* set, /**< global SCIP settings */
1006  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1007  SCIP_LP* lp /**< current LP data */
1008 
1009  )
1010 {
1011  assert(boundchg != NULL);
1012 
1013  switch( boundchg->boundchgtype )
1014  {
1017  break;
1018 
1020  assert(boundchg->data.inferencedata.var != NULL);
1021  assert(boundchg->data.inferencedata.reason.cons != NULL);
1022  SCIP_CALL( SCIPconsRelease(&boundchg->data.inferencedata.reason.cons, blkmem, set) );
1023  break;
1024 
1025  default:
1026  SCIPerrorMessage("invalid bound change type\n");
1027  return SCIP_INVALIDDATA;
1028  }
1029 
1030  /* release variable */
1031  assert(boundchg->var != NULL);
1032  SCIP_CALL( SCIPvarRelease(&boundchg->var, blkmem, set, eventqueue, lp) );
1033 
1034  return SCIP_OKAY;
1035 }
1036 
1037 /** creates empty domain change data with dynamic arrays */
1038 static
1040  SCIP_DOMCHG** domchg, /**< pointer to domain change data */
1041  BMS_BLKMEM* blkmem /**< block memory */
1042  )
1043 {
1044  assert(domchg != NULL);
1045  assert(blkmem != NULL);
1046 
1047  SCIP_ALLOC( BMSallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN)) );
1048  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1049  (*domchg)->domchgdyn.nboundchgs = 0;
1050  (*domchg)->domchgdyn.boundchgs = NULL;
1051  (*domchg)->domchgdyn.nholechgs = 0;
1052  (*domchg)->domchgdyn.holechgs = NULL;
1053  (*domchg)->domchgdyn.boundchgssize = 0;
1054  (*domchg)->domchgdyn.holechgssize = 0;
1055 
1056  return SCIP_OKAY;
1057 }
1058 
1059 /** frees domain change data */
1061  SCIP_DOMCHG** domchg, /**< pointer to domain change */
1062  BMS_BLKMEM* blkmem, /**< block memory */
1063  SCIP_SET* set, /**< global SCIP settings */
1064  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1065  SCIP_LP* lp /**< current LP data */
1066  )
1067 {
1068  assert(domchg != NULL);
1069  assert(blkmem != NULL);
1070 
1071  if( *domchg != NULL )
1072  {
1073  int i;
1074 
1075  /* release variables, branching and inference data associated with the bound changes */
1076  for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1077  {
1078  SCIP_CALL( boundchgReleaseData(&(*domchg)->domchgbound.boundchgs[i], blkmem, set, eventqueue, lp) );
1079  }
1080 
1081  /* free memory for bound and hole changes */
1082  switch( (*domchg)->domchgdyn.domchgtype )
1083  {
1084  case SCIP_DOMCHGTYPE_BOUND:
1085  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgbound.boundchgs, (*domchg)->domchgbound.nboundchgs);
1086  BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOUND));
1087  break;
1088  case SCIP_DOMCHGTYPE_BOTH:
1089  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgboth.boundchgs, (*domchg)->domchgboth.nboundchgs);
1090  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgboth.holechgs, (*domchg)->domchgboth.nholechgs);
1091  BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH));
1092  break;
1094  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.boundchgs, (*domchg)->domchgdyn.boundchgssize);
1095  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.holechgs, (*domchg)->domchgdyn.holechgssize);
1096  BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN));
1097  break;
1098  default:
1099  SCIPerrorMessage("invalid domain change type\n");
1100  return SCIP_INVALIDDATA;
1101  }
1102  }
1103 
1104  return SCIP_OKAY;
1105 }
1106 
1107 /** converts a static domain change data into a dynamic one */
1108 static
1110  SCIP_DOMCHG** domchg, /**< pointer to domain change data */
1111  BMS_BLKMEM* blkmem /**< block memory */
1112  )
1113 {
1114  assert(domchg != NULL);
1115  assert(blkmem != NULL);
1116 
1117  SCIPdebugMessage("making domain change data %p pointing to %p dynamic\n", (void*)domchg, (void*)*domchg);
1118 
1119  if( *domchg == NULL )
1120  {
1121  SCIP_CALL( domchgCreate(domchg, blkmem) );
1122  }
1123  else
1124  {
1125  switch( (*domchg)->domchgdyn.domchgtype )
1126  {
1127  case SCIP_DOMCHGTYPE_BOUND:
1128  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOUND), sizeof(SCIP_DOMCHGDYN)) );
1129  (*domchg)->domchgdyn.nholechgs = 0;
1130  (*domchg)->domchgdyn.holechgs = NULL;
1131  (*domchg)->domchgdyn.boundchgssize = (int) (*domchg)->domchgdyn.nboundchgs;
1132  (*domchg)->domchgdyn.holechgssize = 0;
1133  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1134  break;
1135  case SCIP_DOMCHGTYPE_BOTH:
1136  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH), sizeof(SCIP_DOMCHGDYN)) );
1137  (*domchg)->domchgdyn.boundchgssize = (int) (*domchg)->domchgdyn.nboundchgs;
1138  (*domchg)->domchgdyn.holechgssize = (*domchg)->domchgdyn.nholechgs;
1139  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1140  break;
1142  break;
1143  default:
1144  SCIPerrorMessage("invalid domain change type\n");
1145  return SCIP_INVALIDDATA;
1146  }
1147  }
1148 #ifndef NDEBUG
1149  {
1150  int i;
1151  for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1152  assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1153  || EPSISINT((*domchg)->domchgbound.boundchgs[i].newbound, 1e-06));
1154  }
1155 #endif
1156 
1157  return SCIP_OKAY;
1158 }
1159 
1160 /** converts a dynamic domain change data into a static one, using less memory than for a dynamic one */
1162  SCIP_DOMCHG** domchg, /**< pointer to domain change data */
1163  BMS_BLKMEM* blkmem, /**< block memory */
1164  SCIP_SET* set, /**< global SCIP settings */
1165  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1166  SCIP_LP* lp /**< current LP data */
1167  )
1168 {
1169  assert(domchg != NULL);
1170  assert(blkmem != NULL);
1171 
1172  SCIPsetDebugMsg(set, "making domain change data %p pointing to %p static\n", (void*)domchg, (void*)*domchg);
1173 
1174  if( *domchg != NULL )
1175  {
1176  switch( (*domchg)->domchgdyn.domchgtype )
1177  {
1178  case SCIP_DOMCHGTYPE_BOUND:
1179  if( (*domchg)->domchgbound.nboundchgs == 0 )
1180  {
1181  SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1182  }
1183  break;
1184  case SCIP_DOMCHGTYPE_BOTH:
1185  if( (*domchg)->domchgboth.nholechgs == 0 )
1186  {
1187  if( (*domchg)->domchgbound.nboundchgs == 0 )
1188  {
1189  SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1190  }
1191  else
1192  {
1193  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH), sizeof(SCIP_DOMCHGBOUND)) );
1194  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOUND; /*lint !e641*/
1195  }
1196  }
1197  break;
1199  if( (*domchg)->domchgboth.nholechgs == 0 )
1200  {
1201  if( (*domchg)->domchgbound.nboundchgs == 0 )
1202  {
1203  SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1204  }
1205  else
1206  {
1207  /* shrink dynamic size arrays to their minimal sizes */
1208  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.boundchgs, \
1209  (*domchg)->domchgdyn.boundchgssize, (*domchg)->domchgdyn.nboundchgs) ); /*lint !e571*/
1210  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.holechgs, (*domchg)->domchgdyn.holechgssize);
1211 
1212  /* convert into static domain change */
1213  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN), sizeof(SCIP_DOMCHGBOUND)) );
1214  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOUND; /*lint !e641*/
1215  }
1216  }
1217  else
1218  {
1219  /* shrink dynamic size arrays to their minimal sizes */
1220  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.boundchgs, \
1221  (*domchg)->domchgdyn.boundchgssize, (*domchg)->domchgdyn.nboundchgs) ); /*lint !e571*/
1222  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.holechgs, \
1223  (*domchg)->domchgdyn.holechgssize, (*domchg)->domchgdyn.nholechgs) );
1224 
1225  /* convert into static domain change */
1226  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN), sizeof(SCIP_DOMCHGBOTH)) );
1227  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOTH; /*lint !e641*/
1228  }
1229  break;
1230  default:
1231  SCIPerrorMessage("invalid domain change type\n");
1232  return SCIP_INVALIDDATA;
1233  }
1234 #ifndef NDEBUG
1235  if( *domchg != NULL )
1236  {
1237  int i;
1238  for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1239  assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1240  || SCIPsetIsFeasIntegral(set, (*domchg)->domchgbound.boundchgs[i].newbound));
1241  }
1242 #endif
1243  }
1244 
1245  return SCIP_OKAY;
1246 }
1247 
1248 /** ensures, that boundchgs array can store at least num entries */
1249 static
1251  SCIP_DOMCHG* domchg, /**< domain change data structure */
1252  BMS_BLKMEM* blkmem, /**< block memory */
1253  SCIP_SET* set, /**< global SCIP settings */
1254  int num /**< minimum number of entries to store */
1255  )
1256 {
1257  assert(domchg != NULL);
1258  assert(domchg->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1259 
1260  if( num > domchg->domchgdyn.boundchgssize )
1261  {
1262  int newsize;
1263 
1264  newsize = SCIPsetCalcMemGrowSize(set, num);
1265  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &domchg->domchgdyn.boundchgs, domchg->domchgdyn.boundchgssize, newsize) );
1266  domchg->domchgdyn.boundchgssize = newsize;
1267  }
1268  assert(num <= domchg->domchgdyn.boundchgssize);
1269 
1270  return SCIP_OKAY;
1271 }
1272 
1273 /** ensures, that holechgs array can store at least num additional entries */
1274 static
1276  SCIP_DOMCHG* domchg, /**< domain change data structure */
1277  BMS_BLKMEM* blkmem, /**< block memory */
1278  SCIP_SET* set, /**< global SCIP settings */
1279  int num /**< minimum number of additional entries to store */
1280  )
1281 {
1282  assert(domchg != NULL);
1283  assert(domchg->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1284 
1285  if( num > domchg->domchgdyn.holechgssize )
1286  {
1287  int newsize;
1288 
1289  newsize = SCIPsetCalcMemGrowSize(set, num);
1290  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &domchg->domchgdyn.holechgs, domchg->domchgdyn.holechgssize, newsize) );
1291  domchg->domchgdyn.holechgssize = newsize;
1292  }
1293  assert(num <= domchg->domchgdyn.holechgssize);
1294 
1295  return SCIP_OKAY;
1296 }
1297 
1298 /** applies domain change */
1300  SCIP_DOMCHG* domchg, /**< domain change to apply */
1301  BMS_BLKMEM* blkmem, /**< block memory */
1302  SCIP_SET* set, /**< global SCIP settings */
1303  SCIP_STAT* stat, /**< problem statistics */
1304  SCIP_LP* lp, /**< current LP data */
1305  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1306  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1307  int depth, /**< depth in the tree, where the domain change takes place */
1308  SCIP_Bool* cutoff /**< pointer to store whether an infeasible domain change was detected */
1309  )
1310 {
1311  int i;
1312 
1313  assert(cutoff != NULL);
1314 
1315  *cutoff = FALSE;
1316 
1317  SCIPsetDebugMsg(set, "applying domain changes at %p in depth %d\n", (void*)domchg, depth);
1318 
1319  if( domchg == NULL )
1320  return SCIP_OKAY;
1321 
1322  /* apply bound changes */
1323  for( i = 0; i < (int)domchg->domchgbound.nboundchgs; ++i )
1324  {
1325  SCIP_CALL( SCIPboundchgApply(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp,
1326  branchcand, eventqueue, depth, i, cutoff) );
1327  if( *cutoff )
1328  break;
1329  }
1330  SCIPsetDebugMsg(set, " -> %u bound changes (cutoff %u)\n", domchg->domchgbound.nboundchgs, *cutoff);
1331 
1332  /* mark all bound changes after a cutoff redundant */
1333  for( ; i < (int)domchg->domchgbound.nboundchgs; ++i )
1334  domchg->domchgbound.boundchgs[i].redundant = TRUE;
1335 
1336  /* apply holelist changes */
1337  if( domchg->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_BOUND ) /*lint !e641*/
1338  {
1339  for( i = 0; i < domchg->domchgboth.nholechgs; ++i )
1340  *(domchg->domchgboth.holechgs[i].ptr) = domchg->domchgboth.holechgs[i].newlist;
1341  SCIPsetDebugMsg(set, " -> %d hole changes\n", domchg->domchgboth.nholechgs);
1342  }
1343 
1344  return SCIP_OKAY;
1345 }
1346 
1347 /** undoes domain change */
1349  SCIP_DOMCHG* domchg, /**< domain change to remove */
1350  BMS_BLKMEM* blkmem, /**< block memory */
1351  SCIP_SET* set, /**< global SCIP settings */
1352  SCIP_STAT* stat, /**< problem statistics */
1353  SCIP_LP* lp, /**< current LP data */
1354  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1355  SCIP_EVENTQUEUE* eventqueue /**< event queue */
1356  )
1357 {
1358  int i;
1359 
1360  SCIPsetDebugMsg(set, "undoing domain changes at %p\n", (void*)domchg);
1361  if( domchg == NULL )
1362  return SCIP_OKAY;
1363 
1364  /* undo holelist changes */
1365  if( domchg->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_BOUND ) /*lint !e641*/
1366  {
1367  for( i = domchg->domchgboth.nholechgs-1; i >= 0; --i )
1368  *(domchg->domchgboth.holechgs[i].ptr) = domchg->domchgboth.holechgs[i].oldlist;
1369  SCIPsetDebugMsg(set, " -> %d hole changes\n", domchg->domchgboth.nholechgs);
1370  }
1371 
1372  /* undo bound changes */
1373  for( i = domchg->domchgbound.nboundchgs-1; i >= 0; --i )
1374  {
1375  SCIP_CALL( SCIPboundchgUndo(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp, branchcand, eventqueue) );
1376  }
1377  SCIPsetDebugMsg(set, " -> %u bound changes\n", domchg->domchgbound.nboundchgs);
1378 
1379  return SCIP_OKAY;
1380 }
1381 
1382 /** applies domain change to the global problem */
1384  SCIP_DOMCHG* domchg, /**< domain change to apply */
1385  BMS_BLKMEM* blkmem, /**< block memory */
1386  SCIP_SET* set, /**< global SCIP settings */
1387  SCIP_STAT* stat, /**< problem statistics */
1388  SCIP_LP* lp, /**< current LP data */
1389  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1390  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1391  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1392  SCIP_Bool* cutoff /**< pointer to store whether an infeasible domain change was detected */
1393  )
1394 {
1395  int i;
1396 
1397  assert(cutoff != NULL);
1398 
1399  *cutoff = FALSE;
1400 
1401  if( domchg == NULL )
1402  return SCIP_OKAY;
1403 
1404  SCIPsetDebugMsg(set, "applying domain changes at %p to the global problem\n", (void*)domchg);
1405 
1406  /* apply bound changes */
1407  for( i = 0; i < (int)domchg->domchgbound.nboundchgs; ++i )
1408  {
1409  SCIP_CALL( boundchgApplyGlobal(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp,
1410  branchcand, eventqueue, cliquetable, cutoff) );
1411  if( *cutoff )
1412  break;
1413  }
1414  SCIPsetDebugMsg(set, " -> %u global bound changes\n", domchg->domchgbound.nboundchgs);
1415 
1416  /**@todo globally apply holelist changes - how can this be done without confusing pointer updates? */
1417 
1418  return SCIP_OKAY;
1419 }
1420 
1421 /** adds bound change to domain changes */
1423  SCIP_DOMCHG** domchg, /**< pointer to domain change data structure */
1424  BMS_BLKMEM* blkmem, /**< block memory */
1425  SCIP_SET* set, /**< global SCIP settings */
1426  SCIP_VAR* var, /**< variable to change the bounds for */
1427  SCIP_Real newbound, /**< new value for bound */
1428  SCIP_BOUNDTYPE boundtype, /**< type of bound for var: lower or upper bound */
1429  SCIP_BOUNDCHGTYPE boundchgtype, /**< type of bound change: branching decision or inference */
1430  SCIP_Real lpsolval, /**< solval of variable in last LP on path to node, or SCIP_INVALID if unknown */
1431  SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself), or NULL */
1432  SCIP_CONS* infercons, /**< constraint that deduced the bound change, or NULL */
1433  SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
1434  int inferinfo, /**< user information for inference to help resolving the conflict */
1435  SCIP_BOUNDTYPE inferboundtype /**< type of bound for inference var: lower or upper bound */
1436  )
1437 {
1438  SCIP_BOUNDCHG* boundchg;
1439 
1440  assert(domchg != NULL);
1441  assert(var != NULL);
1443  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
1444  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, boundtype == SCIP_BOUNDTYPE_LOWER ? 1.0 : 0.0));
1445  assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
1446  assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
1447  assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
1448 
1449  SCIPsetDebugMsg(set, "adding %s bound change <%s: %g> of variable <%s> to domain change at %p pointing to %p\n",
1450  boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
1451  newbound, var->name, (void*)domchg, (void*)*domchg);
1452 
1453  /* if domain change data doesn't exist, create it;
1454  * if domain change is static, convert it into dynamic change
1455  */
1456  if( *domchg == NULL )
1457  {
1458  SCIP_CALL( domchgCreate(domchg, blkmem) );
1459  }
1460  else if( (*domchg)->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_DYNAMIC ) /*lint !e641*/
1461  {
1462  SCIP_CALL( domchgMakeDynamic(domchg, blkmem) );
1463  }
1464  assert(*domchg != NULL && (*domchg)->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1465 
1466  /* get memory for additional bound change */
1467  SCIP_CALL( domchgEnsureBoundchgsSize(*domchg, blkmem, set, (*domchg)->domchgdyn.nboundchgs+1) );
1468 
1469  /* fill in the bound change data */
1470  boundchg = &(*domchg)->domchgdyn.boundchgs[(*domchg)->domchgdyn.nboundchgs];
1471  boundchg->var = var;
1472  switch( boundchgtype )
1473  {
1475  boundchg->data.branchingdata.lpsolval = lpsolval;
1476  break;
1478  assert(infercons != NULL);
1479  boundchg->data.inferencedata.var = infervar;
1480  boundchg->data.inferencedata.reason.cons = infercons;
1481  boundchg->data.inferencedata.info = inferinfo;
1482  break;
1484  boundchg->data.inferencedata.var = infervar;
1485  boundchg->data.inferencedata.reason.prop = inferprop;
1486  boundchg->data.inferencedata.info = inferinfo;
1487  break;
1488  default:
1489  SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
1490  return SCIP_INVALIDDATA;
1491  }
1492 
1493  boundchg->newbound = newbound;
1494  boundchg->boundchgtype = boundchgtype; /*lint !e641*/
1495  boundchg->boundtype = boundtype; /*lint !e641*/
1496  boundchg->inferboundtype = inferboundtype; /*lint !e641*/
1497  boundchg->applied = FALSE;
1498  boundchg->redundant = FALSE;
1499  (*domchg)->domchgdyn.nboundchgs++;
1500 
1501  /* capture branching and inference data associated with the bound changes */
1502  SCIP_CALL( boundchgCaptureData(boundchg) );
1503 
1504 #ifdef SCIP_DISABLED_CODE /* expensive debug check */
1505 #ifdef SCIP_MORE_DEBUG
1506  {
1507  int i;
1508  for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1509  assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1510  || SCIPsetIsFeasIntegral(set, (*domchg)->domchgbound.boundchgs[i].newbound));
1511  }
1512 #endif
1513 #endif
1514 
1515  return SCIP_OKAY;
1516 }
1517 
1518 /** adds hole change to domain changes */
1520  SCIP_DOMCHG** domchg, /**< pointer to domain change data structure */
1521  BMS_BLKMEM* blkmem, /**< block memory */
1522  SCIP_SET* set, /**< global SCIP settings */
1523  SCIP_HOLELIST** ptr, /**< changed list pointer */
1524  SCIP_HOLELIST* newlist, /**< new value of list pointer */
1525  SCIP_HOLELIST* oldlist /**< old value of list pointer */
1526  )
1527 {
1528  SCIP_HOLECHG* holechg;
1529 
1530  assert(domchg != NULL);
1531  assert(ptr != NULL);
1532 
1533  /* if domain change data doesn't exist, create it;
1534  * if domain change is static, convert it into dynamic change
1535  */
1536  if( *domchg == NULL )
1537  {
1538  SCIP_CALL( domchgCreate(domchg, blkmem) );
1539  }
1540  else if( (*domchg)->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_DYNAMIC ) /*lint !e641*/
1541  {
1542  SCIP_CALL( domchgMakeDynamic(domchg, blkmem) );
1543  }
1544  assert(*domchg != NULL && (*domchg)->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1545 
1546  /* get memory for additional hole change */
1547  SCIP_CALL( domchgEnsureHolechgsSize(*domchg, blkmem, set, (*domchg)->domchgdyn.nholechgs+1) );
1548 
1549  /* fill in the hole change data */
1550  holechg = &(*domchg)->domchgdyn.holechgs[(*domchg)->domchgdyn.nholechgs];
1551  holechg->ptr = ptr;
1552  holechg->newlist = newlist;
1553  holechg->oldlist = oldlist;
1554  (*domchg)->domchgdyn.nholechgs++;
1555 
1556  return SCIP_OKAY;
1557 }
1558 
1559 
1560 
1561 
1562 /*
1563  * methods for variables
1564  */
1565 
1566 /** returns adjusted lower bound value, which is rounded for integral variable types */
1567 static
1569  SCIP_SET* set, /**< global SCIP settings */
1570  SCIP_VARTYPE vartype, /**< type of variable */
1571  SCIP_Real lb /**< lower bound to adjust */
1572  )
1573 {
1574  if( lb < 0.0 && SCIPsetIsInfinity(set, -lb) )
1575  return -SCIPsetInfinity(set);
1576  else if( lb > 0.0 && SCIPsetIsInfinity(set, lb) )
1577  return SCIPsetInfinity(set);
1578  else if( vartype != SCIP_VARTYPE_CONTINUOUS )
1579  return SCIPsetFeasCeil(set, lb);
1580  else if( lb > 0.0 && lb < SCIPsetEpsilon(set) )
1581  return 0.0;
1582  else
1583  return lb;
1584 }
1585 
1586 /** returns adjusted upper bound value, which is rounded for integral variable types */
1587 static
1589  SCIP_SET* set, /**< global SCIP settings */
1590  SCIP_VARTYPE vartype, /**< type of variable */
1591  SCIP_Real ub /**< upper bound to adjust */
1592  )
1593 {
1594  if( ub > 0.0 && SCIPsetIsInfinity(set, ub) )
1595  return SCIPsetInfinity(set);
1596  else if( ub < 0.0 && SCIPsetIsInfinity(set, -ub) )
1597  return -SCIPsetInfinity(set);
1598  else if( vartype != SCIP_VARTYPE_CONTINUOUS )
1599  return SCIPsetFeasFloor(set, ub);
1600  else if( ub < 0.0 && ub > -SCIPsetEpsilon(set) )
1601  return 0.0;
1602  else
1603  return ub;
1604 }
1605 
1606 /** removes (redundant) cliques, implications and variable bounds of variable from all other variables' implications and variable
1607  * bounds arrays, and optionally removes them also from the variable itself
1608  */
1610  SCIP_VAR* var, /**< problem variable */
1611  BMS_BLKMEM* blkmem, /**< block memory */
1612  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1613  SCIP_SET* set, /**< global SCIP settings */
1614  SCIP_Bool irrelevantvar, /**< has the variable become irrelevant? */
1615  SCIP_Bool onlyredundant, /**< should only the redundant implications and variable bounds be removed? */
1616  SCIP_Bool removefromvar /**< should the implications and variable bounds be removed from the var itself? */
1617  )
1618 {
1619  SCIP_Real lb;
1620  SCIP_Real ub;
1621 
1622  assert(var != NULL);
1624  assert(SCIPvarIsActive(var) || SCIPvarGetType(var) != SCIP_VARTYPE_BINARY);
1625 
1626  lb = SCIPvarGetLbGlobal(var);
1627  ub = SCIPvarGetUbGlobal(var);
1628 
1629  SCIPsetDebugMsg(set, "removing %s implications and vbounds of %s<%s>[%g,%g]\n",
1630  onlyredundant ? "redundant" : "all", irrelevantvar ? "irrelevant " : "", SCIPvarGetName(var), lb, ub);
1631 
1632  /* remove implications of (fixed) binary variable */
1633  if( var->implics != NULL && (!onlyredundant || lb > 0.5 || ub < 0.5) )
1634  {
1635  SCIP_Bool varfixing;
1636 
1637  assert(SCIPvarIsBinary(var));
1638 
1639  varfixing = FALSE;
1640  do
1641  {
1642  SCIP_VAR** implvars;
1643  SCIP_BOUNDTYPE* impltypes;
1644  int nimpls;
1645  int i;
1646 
1647  nimpls = SCIPimplicsGetNImpls(var->implics, varfixing);
1648  implvars = SCIPimplicsGetVars(var->implics, varfixing);
1649  impltypes = SCIPimplicsGetTypes(var->implics, varfixing);
1650 
1651  for( i = 0; i < nimpls; i++ )
1652  {
1653  SCIP_VAR* implvar;
1654  SCIP_BOUNDTYPE impltype;
1655 
1656  implvar = implvars[i];
1657  impltype = impltypes[i];
1658  assert(implvar != var);
1659 
1660  /* remove for all implications z == 0 / 1 ==> x <= p / x >= p (x not binary)
1661  * the following variable bound from x's variable bounds
1662  * x <= b*z+d (z in vubs of x) , for z == 0 / 1 ==> x <= p
1663  * x >= b*z+d (z in vlbs of x) , for z == 0 / 1 ==> x >= p
1664  */
1665  if( impltype == SCIP_BOUNDTYPE_UPPER )
1666  {
1667  if( implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1668  {
1669  SCIPsetDebugMsg(set, "deleting variable bound: <%s> == %u ==> <%s> <= %g\n",
1670  SCIPvarGetName(var), varfixing, SCIPvarGetName(implvar),
1671  SCIPimplicsGetBounds(var->implics, varfixing)[i]);
1672  SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, varfixing) );
1673  implvar->closestvblpcount = -1;
1674  var->closestvblpcount = -1;
1675  }
1676  }
1677  else
1678  {
1679  if( implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1680  {
1681  SCIPsetDebugMsg(set, "deleting variable bound: <%s> == %u ==> <%s> >= %g\n",
1682  SCIPvarGetName(var), varfixing, SCIPvarGetName(implvar),
1683  SCIPimplicsGetBounds(var->implics, varfixing)[i]);
1684  SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, !varfixing) );
1685  implvar->closestvblpcount = -1;
1686  var->closestvblpcount = -1;
1687  }
1688  }
1689  }
1690  varfixing = !varfixing;
1691  }
1692  while( varfixing == TRUE );
1693 
1694  if( removefromvar )
1695  {
1696  /* free the implications data structures */
1697  SCIPimplicsFree(&var->implics, blkmem);
1698  }
1699  }
1700 
1701  /* remove the (redundant) variable lower bounds */
1702  if( var->vlbs != NULL )
1703  {
1704  SCIP_VAR** vars;
1705  SCIP_Real* coefs;
1706  SCIP_Real* constants;
1707  int nvbds;
1708  int newnvbds;
1709  int i;
1710 
1711  nvbds = SCIPvboundsGetNVbds(var->vlbs);
1712  vars = SCIPvboundsGetVars(var->vlbs);
1713  coefs = SCIPvboundsGetCoefs(var->vlbs);
1714  constants = SCIPvboundsGetConstants(var->vlbs);
1715 
1716  /* remove for all variable bounds x >= b*z+d the following implication from z's implications
1717  * z == ub ==> x >= b*ub + d , if b > 0
1718  * z == lb ==> x >= b*lb + d , if b < 0
1719  */
1720  newnvbds = 0;
1721  for( i = 0; i < nvbds; i++ )
1722  {
1723  SCIP_VAR* implvar;
1724  SCIP_Real coef;
1725 
1726  assert(newnvbds <= i);
1727 
1728  implvar = vars[i];
1729  assert(implvar != NULL);
1730 
1731  coef = coefs[i];
1732  assert(!SCIPsetIsZero(set, coef));
1733 
1734  /* check, if we want to remove the variable bound */
1735  if( onlyredundant )
1736  {
1737  SCIP_Real vbound;
1738 
1739  vbound = MAX(coef * SCIPvarGetUbGlobal(implvar), coef * SCIPvarGetLbGlobal(implvar)) + constants[i]; /*lint !e666*/
1740  if( SCIPsetIsFeasGT(set, vbound, lb) )
1741  {
1742  /* the variable bound is not redundant: keep it */
1743  if( removefromvar )
1744  {
1745  if( newnvbds < i )
1746  {
1747  vars[newnvbds] = implvar;
1748  coefs[newnvbds] = coef;
1749  constants[newnvbds] = constants[i];
1750  }
1751  newnvbds++;
1752  }
1753  continue;
1754  }
1755  }
1756 
1757  /* remove the corresponding implication */
1758  if( implvar->implics != NULL ) /* variable may have been aggregated in the mean time */
1759  {
1760  SCIPsetDebugMsg(set, "deleting implication: <%s> == %d ==> <%s> >= %g\n",
1761  SCIPvarGetName(implvar), (coef > 0.0), SCIPvarGetName(var), MAX(coef, 0.0) + constants[i]);
1762  SCIP_CALL( SCIPimplicsDel(&implvar->implics, blkmem, set, (coef > 0.0), var, SCIP_BOUNDTYPE_LOWER) );
1763  }
1764  if( coef > 0.0 && implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1765  {
1766  SCIPsetDebugMsg(set, "deleting variable upper bound from <%s> involving variable %s\n",
1767  SCIPvarGetName(implvar), SCIPvarGetName(var));
1768  SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, FALSE) );
1769  implvar->closestvblpcount = -1;
1770  var->closestvblpcount = -1;
1771  }
1772  else if( coef < 0.0 && implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1773  {
1774  SCIPsetDebugMsg(set, "deleting variable lower bound from <%s> involving variable %s\n",
1775  SCIPvarGetName(implvar), SCIPvarGetName(var));
1776  SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, TRUE) );
1777  implvar->closestvblpcount = -1;
1778  var->closestvblpcount = -1;
1779  }
1780  }
1781 
1782  if( removefromvar )
1783  {
1784  /* update the number of variable bounds */
1785  SCIPvboundsShrink(&var->vlbs, blkmem, newnvbds);
1786  var->closestvblpcount = -1;
1787  }
1788  }
1789 
1790  /**@todo in general, variable bounds like x >= b*z + d corresponding to an implication like z = ub ==> x >= b*ub + d
1791  * might be missing because we only add variable bounds with reasonably small value of b. thus, we currently
1792  * cannot remove such variables x from z's implications.
1793  */
1794 
1795  /* remove the (redundant) variable upper bounds */
1796  if( var->vubs != NULL )
1797  {
1798  SCIP_VAR** vars;
1799  SCIP_Real* coefs;
1800  SCIP_Real* constants;
1801  int nvbds;
1802  int newnvbds;
1803  int i;
1804 
1805  nvbds = SCIPvboundsGetNVbds(var->vubs);
1806  vars = SCIPvboundsGetVars(var->vubs);
1807  coefs = SCIPvboundsGetCoefs(var->vubs);
1808  constants = SCIPvboundsGetConstants(var->vubs);
1809 
1810  /* remove for all variable bounds x <= b*z+d the following implication from z's implications
1811  * z == lb ==> x <= b*lb + d , if b > 0
1812  * z == ub ==> x <= b*ub + d , if b < 0
1813  */
1814  newnvbds = 0;
1815  for( i = 0; i < nvbds; i++ )
1816  {
1817  SCIP_VAR* implvar;
1818  SCIP_Real coef;
1819 
1820  assert(newnvbds <= i);
1821 
1822  implvar = vars[i];
1823  assert(implvar != NULL);
1824 
1825  coef = coefs[i];
1826  assert(!SCIPsetIsZero(set, coef));
1827 
1828  /* check, if we want to remove the variable bound */
1829  if( onlyredundant )
1830  {
1831  SCIP_Real vbound;
1832 
1833  vbound = MIN(coef * SCIPvarGetUbGlobal(implvar), coef * SCIPvarGetLbGlobal(implvar)) + constants[i]; /*lint !e666*/
1834  if( SCIPsetIsFeasLT(set, vbound, ub) )
1835  {
1836  /* the variable bound is not redundant: keep it */
1837  if( removefromvar )
1838  {
1839  if( newnvbds < i )
1840  {
1841  vars[newnvbds] = implvar;
1842  coefs[newnvbds] = coefs[i];
1843  constants[newnvbds] = constants[i];
1844  }
1845  newnvbds++;
1846  }
1847  continue;
1848  }
1849  }
1850 
1851  /* remove the corresponding implication */
1852  if( implvar->implics != NULL ) /* variable may have been aggregated in the mean time */
1853  {
1854  SCIPsetDebugMsg(set, "deleting implication: <%s> == %d ==> <%s> <= %g\n",
1855  SCIPvarGetName(implvar), (coef < 0.0), SCIPvarGetName(var), MIN(coef, 0.0) + constants[i]);
1856  SCIP_CALL( SCIPimplicsDel(&implvar->implics, blkmem, set, (coef < 0.0), var, SCIP_BOUNDTYPE_UPPER) );
1857  }
1858  if( coef < 0.0 && implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1859  {
1860  SCIPsetDebugMsg(set, "deleting variable upper bound from <%s> involving variable %s\n",
1861  SCIPvarGetName(implvar), SCIPvarGetName(var));
1862  SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, TRUE) );
1863  implvar->closestvblpcount = -1;
1864  var->closestvblpcount = -1;
1865  }
1866  else if( coef > 0.0 && implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1867  {
1868  SCIPsetDebugMsg(set, "deleting variable lower bound from <%s> involving variable %s\n",
1869  SCIPvarGetName(implvar), SCIPvarGetName(var));
1870  SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, FALSE) );
1871  implvar->closestvblpcount = -1;
1872  var->closestvblpcount = -1;
1873  }
1874  }
1875 
1876  if( removefromvar )
1877  {
1878  /* update the number of variable bounds */
1879  SCIPvboundsShrink(&var->vubs, blkmem, newnvbds);
1880  var->closestvblpcount = -1;
1881  }
1882  }
1883 
1884  /* remove the variable from all cliques */
1885  if( SCIPvarIsBinary(var) )
1886  SCIPcliquelistRemoveFromCliques(var->cliquelist, cliquetable, var, irrelevantvar);
1887 
1888  /**@todo variable bounds like x <= b*z + d with z general integer are not removed from x's vbd arrays, because
1889  * z has no link (like in the binary case) to x
1890  */
1891 
1892  return SCIP_OKAY;
1893 }
1894 
1895 /** sets the variable name */
1896 static
1898  SCIP_VAR* var, /**< problem variable */
1899  BMS_BLKMEM* blkmem, /**< block memory */
1900  SCIP_STAT* stat, /**< problem statistics, or NULL */
1901  const char* name /**< name of variable, or NULL for automatic name creation */
1902  )
1903 {
1904  assert(blkmem != NULL);
1905  assert(var != NULL);
1906 
1907  if( name == NULL )
1908  {
1909  char s[SCIP_MAXSTRLEN];
1910 
1911  assert(stat != NULL);
1912 
1913  (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "_var%d_", stat->nvaridx);
1914  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->name, s, strlen(s)+1) );
1915  }
1916  else
1917  {
1918  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->name, name, strlen(name)+1) );
1919  }
1920 
1921  return SCIP_OKAY;
1922 }
1923 
1924 
1925 /** creates variable; if variable is of integral type, fractional bounds are automatically rounded; an integer variable
1926  * with bounds zero and one is automatically converted into a binary variable
1927  */
1928 static
1930  SCIP_VAR** var, /**< pointer to variable data */
1931  BMS_BLKMEM* blkmem, /**< block memory */
1932  SCIP_SET* set, /**< global SCIP settings */
1933  SCIP_STAT* stat, /**< problem statistics */
1934  const char* name, /**< name of variable, or NULL for automatic name creation */
1935  SCIP_Real lb, /**< lower bound of variable */
1936  SCIP_Real ub, /**< upper bound of variable */
1937  SCIP_Real obj, /**< objective function value */
1938  SCIP_VARTYPE vartype, /**< type of variable */
1939  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
1940  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
1941  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
1942  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
1943  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
1944  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
1945  SCIP_VARDATA* vardata /**< user data for this specific variable */
1946  )
1947 {
1948  int i;
1949 
1950  assert(var != NULL);
1951  assert(blkmem != NULL);
1952  assert(stat != NULL);
1953 
1954  /* adjust bounds of variable */
1955  lb = adjustedLb(set, vartype, lb);
1956  ub = adjustedUb(set, vartype, ub);
1957 
1958  /* convert [0,1]-integers into binary variables and check that binary variables have correct bounds */
1959  if( (SCIPsetIsEQ(set, lb, 0.0) || SCIPsetIsEQ(set, lb, 1.0))
1960  && (SCIPsetIsEQ(set, ub, 0.0) || SCIPsetIsEQ(set, ub, 1.0)) )
1961  {
1962  if( vartype == SCIP_VARTYPE_INTEGER )
1963  vartype = SCIP_VARTYPE_BINARY;
1964  }
1965  else
1966  {
1967  if( vartype == SCIP_VARTYPE_BINARY )
1968  {
1969  SCIPerrorMessage("invalid bounds [%.2g,%.2g] for binary variable <%s>\n", lb, ub, name);
1970  return SCIP_INVALIDDATA;
1971  }
1972  }
1973 
1974  assert(vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, lb, 0.0) || SCIPsetIsEQ(set, lb, 1.0));
1975  assert(vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, ub, 0.0) || SCIPsetIsEQ(set, ub, 1.0));
1976 
1977  SCIP_ALLOC( BMSallocBlockMemory(blkmem, var) );
1978 
1979  /* set variable's name */
1980  SCIP_CALL( varSetName(*var, blkmem, stat, name) );
1981 
1982 #ifndef NDEBUG
1983  (*var)->scip = set->scip;
1984 #endif
1985  (*var)->obj = obj;
1986  (*var)->unchangedobj = obj;
1987  (*var)->branchfactor = 1.0;
1988  (*var)->rootsol = 0.0;
1989  (*var)->bestrootsol = 0.0;
1990  (*var)->bestrootredcost = 0.0;
1991  (*var)->bestrootlpobjval = SCIP_INVALID;
1992  (*var)->relaxsol = 0.0;
1993  (*var)->nlpsol = 0.0;
1994  (*var)->primsolavg = 0.5 * (lb + ub);
1995  (*var)->conflictlb = SCIP_REAL_MIN;
1996  (*var)->conflictub = SCIP_REAL_MAX;
1997  (*var)->conflictrelaxedlb = (*var)->conflictlb;
1998  (*var)->conflictrelaxedub = (*var)->conflictub;
1999  (*var)->lazylb = -SCIPsetInfinity(set);
2000  (*var)->lazyub = SCIPsetInfinity(set);
2001  (*var)->glbdom.holelist = NULL;
2002  (*var)->glbdom.lb = lb;
2003  (*var)->glbdom.ub = ub;
2004  (*var)->locdom.holelist = NULL;
2005  (*var)->locdom.lb = lb;
2006  (*var)->locdom.ub = ub;
2007  (*var)->varcopy = varcopy;
2008  (*var)->vardelorig = vardelorig;
2009  (*var)->vartrans = vartrans;
2010  (*var)->vardeltrans = vardeltrans;
2011  (*var)->vardata = vardata;
2012  (*var)->parentvars = NULL;
2013  (*var)->negatedvar = NULL;
2014  (*var)->vlbs = NULL;
2015  (*var)->vubs = NULL;
2016  (*var)->implics = NULL;
2017  (*var)->cliquelist = NULL;
2018  (*var)->eventfilter = NULL;
2019  (*var)->lbchginfos = NULL;
2020  (*var)->ubchginfos = NULL;
2021  (*var)->index = stat->nvaridx;
2022  (*var)->probindex = -1;
2023  (*var)->pseudocandindex = -1;
2024  (*var)->eventqueueindexobj = -1;
2025  (*var)->eventqueueindexlb = -1;
2026  (*var)->eventqueueindexub = -1;
2027  (*var)->parentvarssize = 0;
2028  (*var)->nparentvars = 0;
2029  (*var)->nuses = 0;
2030  (*var)->branchpriority = 0;
2031  (*var)->branchdirection = SCIP_BRANCHDIR_AUTO; /*lint !e641*/
2032  (*var)->lbchginfossize = 0;
2033  (*var)->nlbchginfos = 0;
2034  (*var)->ubchginfossize = 0;
2035  (*var)->nubchginfos = 0;
2036  (*var)->conflictlbcount = 0;
2037  (*var)->conflictubcount = 0;
2038  (*var)->closestvlbidx = -1;
2039  (*var)->closestvubidx = -1;
2040  (*var)->closestvblpcount = -1;
2041  (*var)->initial = initial;
2042  (*var)->removable = removable;
2043  (*var)->deleted = FALSE;
2044  (*var)->donotaggr = FALSE;
2045  (*var)->donotmultaggr = FALSE;
2046  (*var)->vartype = vartype; /*lint !e641*/
2047  (*var)->pseudocostflag = FALSE;
2048  (*var)->eventqueueimpl = FALSE;
2049  (*var)->deletable = FALSE;
2050  (*var)->delglobalstructs = FALSE;
2051  (*var)->relaxationonly = FALSE;
2052 
2053  for( i = 0; i < NLOCKTYPES; i++ )
2054  {
2055  (*var)->nlocksdown[i] = 0;
2056  (*var)->nlocksup[i] = 0;
2057  }
2058 
2059  stat->nvaridx++;
2060 
2061  /* create branching and inference history entries */
2062  SCIP_CALL( SCIPhistoryCreate(&(*var)->history, blkmem) );
2063  SCIP_CALL( SCIPhistoryCreate(&(*var)->historycrun, blkmem) );
2064 
2065  /* the value based history is only created on demand */
2066  (*var)->valuehistory = NULL;
2067 
2068  return SCIP_OKAY;
2069 }
2070 
2071 /** creates and captures an original problem variable; an integer variable with bounds
2072  * zero and one is automatically converted into a binary variable
2073  */
2075  SCIP_VAR** var, /**< pointer to variable data */
2076  BMS_BLKMEM* blkmem, /**< block memory */
2077  SCIP_SET* set, /**< global SCIP settings */
2078  SCIP_STAT* stat, /**< problem statistics */
2079  const char* name, /**< name of variable, or NULL for automatic name creation */
2080  SCIP_Real lb, /**< lower bound of variable */
2081  SCIP_Real ub, /**< upper bound of variable */
2082  SCIP_Real obj, /**< objective function value */
2083  SCIP_VARTYPE vartype, /**< type of variable */
2084  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2085  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2086  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2087  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2088  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2089  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2090  SCIP_VARDATA* vardata /**< user data for this specific variable */
2091  )
2092 {
2093  assert(var != NULL);
2094  assert(blkmem != NULL);
2095  assert(stat != NULL);
2096 
2097  /* create variable */
2098  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2099  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2100 
2101  /* set variable status and data */
2102  (*var)->varstatus = SCIP_VARSTATUS_ORIGINAL; /*lint !e641*/
2103  (*var)->data.original.origdom.holelist = NULL;
2104  (*var)->data.original.origdom.lb = lb;
2105  (*var)->data.original.origdom.ub = ub;
2106  (*var)->data.original.transvar = NULL;
2107 
2108  /* capture variable */
2109  SCIPvarCapture(*var);
2110 
2111  return SCIP_OKAY;
2112 }
2113 
2114 /** creates and captures a loose variable belonging to the transformed problem; an integer variable with bounds
2115  * zero and one is automatically converted into a binary variable
2116  */
2118  SCIP_VAR** var, /**< pointer to variable data */
2119  BMS_BLKMEM* blkmem, /**< block memory */
2120  SCIP_SET* set, /**< global SCIP settings */
2121  SCIP_STAT* stat, /**< problem statistics */
2122  const char* name, /**< name of variable, or NULL for automatic name creation */
2123  SCIP_Real lb, /**< lower bound of variable */
2124  SCIP_Real ub, /**< upper bound of variable */
2125  SCIP_Real obj, /**< objective function value */
2126  SCIP_VARTYPE vartype, /**< type of variable */
2127  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2128  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2129  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2130  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2131  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2132  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2133  SCIP_VARDATA* vardata /**< user data for this specific variable */
2134  )
2135 {
2136  assert(var != NULL);
2137  assert(blkmem != NULL);
2138 
2139  /* create variable */
2140  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2141  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2142 
2143  /* create event filter for transformed variable */
2144  SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
2145 
2146  /* set variable status and data */
2147  (*var)->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
2148 
2149  /* capture variable */
2150  SCIPvarCapture(*var);
2151 
2152  return SCIP_OKAY;
2153 }
2154 
2155 /** copies and captures a variable from source to target SCIP; an integer variable with bounds zero and one is
2156  * automatically converted into a binary variable; in case the variable data cannot be copied the variable is not
2157  * copied at all
2158  */
2160  SCIP_VAR** var, /**< pointer to store the target variable */
2161  BMS_BLKMEM* blkmem, /**< block memory */
2162  SCIP_SET* set, /**< global SCIP settings */
2163  SCIP_STAT* stat, /**< problem statistics */
2164  SCIP* sourcescip, /**< source SCIP data structure */
2165  SCIP_VAR* sourcevar, /**< source variable */
2166  SCIP_HASHMAP* varmap, /**< a hashmap to store the mapping of source variables corresponding
2167  * target variables */
2168  SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
2169  * target constraints */
2170  SCIP_Bool global /**< should global or local bounds be used? */
2171  )
2172 {
2173  SCIP_VARDATA* targetdata;
2174  SCIP_RESULT result;
2175  SCIP_Real lb;
2176  SCIP_Real ub;
2177 
2178  assert(set != NULL);
2179  assert(blkmem != NULL);
2180  assert(stat != NULL);
2181  assert(sourcescip != NULL);
2182  assert(sourcevar != NULL);
2183  assert(var != NULL);
2184  assert(set->stage == SCIP_STAGE_PROBLEM);
2185  assert(varmap != NULL);
2186  assert(consmap != NULL);
2187 
2188  /** @todo copy hole lists */
2189  assert(global || SCIPvarGetHolelistLocal(sourcevar) == NULL);
2190  assert(!global || SCIPvarGetHolelistGlobal(sourcevar) == NULL);
2191 
2192  result = SCIP_DIDNOTRUN;
2193  targetdata = NULL;
2194 
2195  if( SCIPvarGetStatus(sourcevar) == SCIP_VARSTATUS_ORIGINAL )
2196  {
2197  lb = SCIPvarGetLbOriginal(sourcevar);
2198  ub = SCIPvarGetUbOriginal(sourcevar);
2199  }
2200  else
2201  {
2202  lb = global ? SCIPvarGetLbGlobal(sourcevar) : SCIPvarGetLbLocal(sourcevar);
2203  ub = global ? SCIPvarGetUbGlobal(sourcevar) : SCIPvarGetUbLocal(sourcevar);
2204  }
2205 
2206  /* creates and captures the variable in the target SCIP and initialize callback methods and variable data to NULL */
2207  SCIP_CALL( SCIPvarCreateOriginal(var, blkmem, set, stat, SCIPvarGetName(sourcevar),
2208  lb, ub, SCIPvarGetObj(sourcevar), SCIPvarGetType(sourcevar),
2209  SCIPvarIsInitial(sourcevar), SCIPvarIsRemovable(sourcevar),
2210  NULL, NULL, NULL, NULL, NULL) );
2211  assert(*var != NULL);
2212 
2213  /* directly copy donot(mult)aggr flag */
2214  (*var)->donotaggr = sourcevar->donotaggr;
2215  (*var)->donotmultaggr = sourcevar->donotmultaggr;
2216 
2217  /* insert variable into mapping between source SCIP and the target SCIP */
2218  assert(!SCIPhashmapExists(varmap, sourcevar));
2219  SCIP_CALL( SCIPhashmapInsert(varmap, sourcevar, *var) );
2220 
2221  /* in case there exists variable data and the variable data copy callback, try to copy variable data */
2222  if( sourcevar->vardata != NULL && sourcevar->varcopy != NULL )
2223  {
2224  SCIP_CALL( sourcevar->varcopy(set->scip, sourcescip, sourcevar, sourcevar->vardata,
2225  varmap, consmap, (*var), &targetdata, &result) );
2226 
2227  /* evaluate result */
2228  if( result != SCIP_DIDNOTRUN && result != SCIP_SUCCESS )
2229  {
2230  SCIPerrorMessage("variable data copying method returned invalid result <%d>\n", result);
2231  return SCIP_INVALIDRESULT;
2232  }
2233 
2234  assert(targetdata == NULL || result == SCIP_SUCCESS);
2235 
2236  /* if copying was successful, add the created variable data to the variable as well as all callback methods */
2237  if( result == SCIP_SUCCESS )
2238  {
2239  (*var)->varcopy = sourcevar->varcopy;
2240  (*var)->vardelorig = sourcevar->vardelorig;
2241  (*var)->vartrans = sourcevar->vartrans;
2242  (*var)->vardeltrans = sourcevar->vardeltrans;
2243  (*var)->vardata = targetdata;
2244  }
2245  }
2246 
2247  /* we initialize histories of the variables by copying the source variable-information */
2248  if( set->history_allowtransfer )
2249  {
2250  SCIPvarMergeHistories((*var), sourcevar, stat);
2251  }
2252 
2253  /* in case the copying was successfully, add the created variable data to the variable as well as all callback
2254  * methods
2255  */
2256  if( result == SCIP_SUCCESS )
2257  {
2258  (*var)->varcopy = sourcevar->varcopy;
2259  (*var)->vardelorig = sourcevar->vardelorig;
2260  (*var)->vartrans = sourcevar->vartrans;
2261  (*var)->vardeltrans = sourcevar->vardeltrans;
2262  (*var)->vardata = targetdata;
2263  }
2264 
2265  SCIPsetDebugMsg(set, "created copy <%s> of variable <%s>\n", SCIPvarGetName(*var), SCIPvarGetName(sourcevar));
2266 
2267  return SCIP_OKAY;
2268 }
2269 
2270 /** parse given string for a SCIP_Real bound */
2271 static
2273  SCIP_SET* set, /**< global SCIP settings */
2274  const char* str, /**< string to parse */
2275  SCIP_Real* value, /**< pointer to store the parsed value */
2276  char** endptr /**< pointer to store the final string position if successfully parsed */
2277  )
2278 {
2279  /* first check for infinity value */
2280  if( strncmp(str, "+inf", 4) == 0 )
2281  {
2282  *value = SCIPsetInfinity(set);
2283  (*endptr) = (char*)str + 4;
2284  }
2285  else if( strncmp(str, "-inf", 4) == 0 )
2286  {
2287  *value = -SCIPsetInfinity(set);
2288  (*endptr) = (char*)str + 4;
2289  }
2290  else
2291  {
2292  if( !SCIPstrToRealValue(str, value, endptr) )
2293  {
2294  SCIPerrorMessage("expected value: %s.\n", str);
2295  return SCIP_READERROR;
2296  }
2297  }
2298 
2299  return SCIP_OKAY;
2300 }
2301 
2302 /** parse the characters as bounds */
2303 static
2305  SCIP_SET* set, /**< global SCIP settings */
2306  const char* str, /**< string to parse */
2307  char* type, /**< bound type (global, local, or lazy) */
2308  SCIP_Real* lb, /**< pointer to store the lower bound */
2309  SCIP_Real* ub, /**< pointer to store the upper bound */
2310  char** endptr /**< pointer to store the final string position if successfully parsed (or NULL if an error occured) */
2311  )
2312 {
2313  char token[SCIP_MAXSTRLEN];
2314  char* tmpend;
2315 
2316  SCIPsetDebugMsg(set, "parsing bounds: '%s'\n", str);
2317 
2318  /* get bound type */
2319  SCIPstrCopySection(str, ' ', ' ', type, SCIP_MAXSTRLEN, endptr);
2320  if ( *endptr == str
2321  || ( strncmp(type, "original", 8) != 0 && strncmp(type, "global", 6) != 0 && strncmp(type, "local", 5) != 0 && strncmp(type, "lazy", 4) != 0 ) )
2322  {
2323  SCIPsetDebugMsg(set, "unkown bound type\n");
2324  *endptr = NULL;
2325  return SCIP_OKAY;
2326  }
2327 
2328  SCIPsetDebugMsg(set, "parsed bound type <%s>\n", type);
2329 
2330  /* get lower bound */
2331  SCIPstrCopySection(str, '[', ',', token, SCIP_MAXSTRLEN, endptr);
2332  str = *endptr;
2333  SCIP_CALL( parseValue(set, token, lb, &tmpend) );
2334 
2335  /* get upper bound */
2336  SCIP_CALL( parseValue(set, str, ub, endptr) );
2337 
2338  SCIPsetDebugMsg(set, "parsed bounds: [%g,%g]\n", *lb, *ub);
2339 
2340  /* skip end of bounds */
2341  while ( **endptr != '\0' && (**endptr == ']' || **endptr == ',') )
2342  ++(*endptr);
2343 
2344  return SCIP_OKAY;
2345 }
2346 
2347 /** parses a given string for a variable informations */
2348 static
2350  SCIP_SET* set, /**< global SCIP settings */
2351  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2352  const char* str, /**< string to parse */
2353  char* name, /**< pointer to store the variable name */
2354  SCIP_Real* lb, /**< pointer to store the lower bound */
2355  SCIP_Real* ub, /**< pointer to store the upper bound */
2356  SCIP_Real* obj, /**< pointer to store the objective coefficient */
2357  SCIP_VARTYPE* vartype, /**< pointer to store the variable type */
2358  SCIP_Real* lazylb, /**< pointer to store if the lower bound is lazy */
2359  SCIP_Real* lazyub, /**< pointer to store if the upper bound is lazy */
2360  SCIP_Bool local, /**< should the local bound be applied */
2361  char** endptr, /**< pointer to store the final string position if successfully */
2362  SCIP_Bool* success /**< pointer store if the paring process was successful */
2363  )
2364 {
2365  SCIP_Real parsedlb;
2366  SCIP_Real parsedub;
2367  char token[SCIP_MAXSTRLEN];
2368  char* strptr;
2369  int i;
2370 
2371  assert(lb != NULL);
2372  assert(ub != NULL);
2373  assert(obj != NULL);
2374  assert(vartype != NULL);
2375  assert(lazylb != NULL);
2376  assert(lazyub != NULL);
2377  assert(success != NULL);
2378 
2379  (*success) = TRUE;
2380 
2381  /* copy variable type */
2382  SCIPstrCopySection(str, '[', ']', token, SCIP_MAXSTRLEN, endptr);
2383  assert(*endptr != str);
2384  SCIPsetDebugMsg(set, "parsed variable type <%s>\n", token);
2385 
2386  /* get variable type */
2387  if( strncmp(token, "binary", 3) == 0 )
2388  (*vartype) = SCIP_VARTYPE_BINARY;
2389  else if( strncmp(token, "integer", 3) == 0 )
2390  (*vartype) = SCIP_VARTYPE_INTEGER;
2391  else if( strncmp(token, "implicit", 3) == 0 )
2392  (*vartype) = SCIP_VARTYPE_IMPLINT;
2393  else if( strncmp(token, "continuous", 3) == 0 )
2394  (*vartype) = SCIP_VARTYPE_CONTINUOUS;
2395  else
2396  {
2397  SCIPmessagePrintWarning(messagehdlr, "unknown variable type\n");
2398  (*success) = FALSE;
2399  return SCIP_OKAY;
2400  }
2401 
2402  /* move string pointer behind variable type */
2403  str = *endptr;
2404 
2405  /* get variable name */
2406  SCIPstrCopySection(str, '<', '>', name, SCIP_MAXSTRLEN, endptr);
2407  assert(*endptr != str);
2408  SCIPsetDebugMsg(set, "parsed variable name <%s>\n", name);
2409 
2410  /* move string pointer behind variable name */
2411  str = *endptr;
2412 
2413  /* cut out objective coefficient */
2414  SCIPstrCopySection(str, '=', ',', token, SCIP_MAXSTRLEN, endptr);
2415 
2416  /* move string pointer behind objective coefficient */
2417  str = *endptr;
2418 
2419  /* get objective coefficient */
2420  if( !SCIPstrToRealValue(token, obj, endptr) )
2421  {
2422  *endptr = NULL;
2423  return SCIP_READERROR;
2424  }
2425 
2426  SCIPsetDebugMsg(set, "parsed objective coefficient <%g>\n", *obj);
2427 
2428  /* parse global/original bounds */
2429  SCIP_CALL( parseBounds(set, str, token, lb, ub, endptr) );
2430  if ( *endptr == NULL )
2431  {
2432  SCIPerrorMessage("Expected bound type: %s.\n", token);
2433  return SCIP_READERROR;
2434  }
2435  assert(strncmp(token, "global", 6) == 0 || strncmp(token, "original", 8) == 0);
2436 
2437  /* initialize the lazy bound */
2438  *lazylb = -SCIPsetInfinity(set);
2439  *lazyub = SCIPsetInfinity(set);
2440 
2441  /* store pointer */
2442  strptr = *endptr;
2443 
2444  /* possibly parse optional local and lazy bounds */
2445  for( i = 0; i < 2 && *endptr != NULL && **endptr != '\0'; ++i )
2446  {
2447  /* start after previous bounds */
2448  strptr = *endptr;
2449 
2450  /* parse global bounds */
2451  SCIP_CALL( parseBounds(set, strptr, token, &parsedlb, &parsedub, endptr) );
2452 
2453  /* stop if parsing of bounds failed */
2454  if( *endptr == NULL )
2455  break;
2456 
2457  if( strncmp(token, "local", 5) == 0 && local )
2458  {
2459  *lb = parsedlb;
2460  *ub = parsedub;
2461  }
2462  else if( strncmp(token, "lazy", 4) == 0 )
2463  {
2464  *lazylb = parsedlb;
2465  *lazyub = parsedub;
2466  }
2467  }
2468 
2469  /* restore pointer */
2470  if ( *endptr == NULL )
2471  *endptr = strptr;
2472 
2473  /* check bounds for binary variables */
2474  if ( (*vartype) == SCIP_VARTYPE_BINARY )
2475  {
2476  if ( SCIPsetIsLT(set, *lb, 0.0) || SCIPsetIsGT(set, *ub, 1.0) )
2477  {
2478  SCIPerrorMessage("Parsed invalid bounds for binary variable <%s>: [%f, %f].\n", name, *lb, *ub);
2479  return SCIP_READERROR;
2480  }
2481  if ( !SCIPsetIsInfinity(set, -(*lazylb)) && !SCIPsetIsInfinity(set, *lazyub) &&
2482  ( SCIPsetIsLT(set, *lazylb, 0.0) || SCIPsetIsGT(set, *lazyub, 1.0) ) )
2483  {
2484  SCIPerrorMessage("Parsed invalid lazy bounds for binary variable <%s>: [%f, %f].\n", name, *lazylb, *lazyub);
2485  return SCIP_READERROR;
2486  }
2487  }
2488 
2489  return SCIP_OKAY;
2490 }
2491 
2492 /** parses variable information (in cip format) out of a string; if the parsing process was successful an original
2493  * variable is created and captured; if variable is of integral type, fractional bounds are automatically rounded; an
2494  * integer variable with bounds zero and one is automatically converted into a binary variable
2495  */
2497  SCIP_VAR** var, /**< pointer to variable data */
2498  BMS_BLKMEM* blkmem, /**< block memory */
2499  SCIP_SET* set, /**< global SCIP settings */
2500  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2501  SCIP_STAT* stat, /**< problem statistics */
2502  const char* str, /**< string to parse */
2503  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2504  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2505  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2506  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable */
2507  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data */
2508  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable */
2509  SCIP_VARDATA* vardata, /**< user data for this specific variable */
2510  char** endptr, /**< pointer to store the final string position if successfully */
2511  SCIP_Bool* success /**< pointer store if the paring process was successful */
2512  )
2513 {
2514  char name[SCIP_MAXSTRLEN];
2515  SCIP_Real lb;
2516  SCIP_Real ub;
2517  SCIP_Real obj;
2518  SCIP_VARTYPE vartype;
2519  SCIP_Real lazylb;
2520  SCIP_Real lazyub;
2521 
2522  assert(var != NULL);
2523  assert(blkmem != NULL);
2524  assert(stat != NULL);
2525  assert(endptr != NULL);
2526  assert(success != NULL);
2527 
2528  /* parse string in cip format for variable information */
2529  SCIP_CALL( varParse(set, messagehdlr, str, name, &lb, &ub, &obj, &vartype, &lazylb, &lazyub, FALSE, endptr, success) );
2530 
2531  if( *success ) /*lint !e774*/
2532  {
2533  /* create variable */
2534  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2535  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2536 
2537  /* set variable status and data */
2538  (*var)->varstatus = SCIP_VARSTATUS_ORIGINAL; /*lint !e641*/
2539  (*var)->data.original.origdom.holelist = NULL;
2540  (*var)->data.original.origdom.lb = lb;
2541  (*var)->data.original.origdom.ub = ub;
2542  (*var)->data.original.transvar = NULL;
2543 
2544  /* set lazy status of variable bounds */
2545  (*var)->lazylb = lazylb;
2546  (*var)->lazyub = lazyub;
2547 
2548  /* capture variable */
2549  SCIPvarCapture(*var);
2550  }
2551 
2552  return SCIP_OKAY;
2553 }
2554 
2555 /** parses variable information (in cip format) out of a string; if the parsing process was successful a loose variable
2556  * belonging to the transformed problem is created and captured; if variable is of integral type, fractional bounds are
2557  * automatically rounded; an integer variable with bounds zero and one is automatically converted into a binary
2558  * variable
2559  */
2561  SCIP_VAR** var, /**< pointer to variable data */
2562  BMS_BLKMEM* blkmem, /**< block memory */
2563  SCIP_SET* set, /**< global SCIP settings */
2564  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2565  SCIP_STAT* stat, /**< problem statistics */
2566  const char* str, /**< string to parse */
2567  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2568  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2569  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2570  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable */
2571  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data */
2572  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable */
2573  SCIP_VARDATA* vardata, /**< user data for this specific variable */
2574  char** endptr, /**< pointer to store the final string position if successfully */
2575  SCIP_Bool* success /**< pointer store if the paring process was successful */
2576  )
2577 {
2578  char name[SCIP_MAXSTRLEN];
2579  SCIP_Real lb;
2580  SCIP_Real ub;
2581  SCIP_Real obj;
2582  SCIP_VARTYPE vartype;
2583  SCIP_Real lazylb;
2584  SCIP_Real lazyub;
2585 
2586  assert(var != NULL);
2587  assert(blkmem != NULL);
2588  assert(endptr != NULL);
2589  assert(success != NULL);
2590 
2591  /* parse string in cip format for variable information */
2592  SCIP_CALL( varParse(set, messagehdlr, str, name, &lb, &ub, &obj, &vartype, &lazylb, &lazyub, TRUE, endptr, success) );
2593 
2594  if( *success ) /*lint !e774*/
2595  {
2596  /* create variable */
2597  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2598  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2599 
2600  /* create event filter for transformed variable */
2601  SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
2602 
2603  /* set variable status and data */
2604  (*var)->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
2605 
2606  /* set lazy status of variable bounds */
2607  (*var)->lazylb = lazylb;
2608  (*var)->lazyub = lazyub;
2609 
2610  /* capture variable */
2611  SCIPvarCapture(*var);
2612  }
2613 
2614  return SCIP_OKAY;
2615 }
2616 
2617 /** ensures, that parentvars array of var can store at least num entries */
2618 static
2620  SCIP_VAR* var, /**< problem variable */
2621  BMS_BLKMEM* blkmem, /**< block memory */
2622  SCIP_SET* set, /**< global SCIP settings */
2623  int num /**< minimum number of entries to store */
2624  )
2625 {
2626  assert(var->nparentvars <= var->parentvarssize);
2627 
2628  if( num > var->parentvarssize )
2629  {
2630  int newsize;
2631 
2632  newsize = SCIPsetCalcMemGrowSize(set, num);
2633  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->parentvars, var->parentvarssize, newsize) );
2634  var->parentvarssize = newsize;
2635  }
2636  assert(num <= var->parentvarssize);
2637 
2638  return SCIP_OKAY;
2639 }
2640 
2641 /** adds variable to parent list of a variable and captures parent variable */
2642 static
2644  SCIP_VAR* var, /**< variable to add parent to */
2645  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
2646  SCIP_SET* set, /**< global SCIP settings */
2647  SCIP_VAR* parentvar /**< parent variable to add */
2648  )
2649 {
2650  assert(var != NULL);
2651  assert(parentvar != NULL);
2652 
2653  /* the direct original counterpart must be stored as first parent */
2654  assert(var->nparentvars == 0 || SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL);
2655 
2656  SCIPsetDebugMsg(set, "adding parent <%s>[%p] to variable <%s>[%p] in slot %d\n",
2657  parentvar->name, (void*)parentvar, var->name, (void*)var, var->nparentvars);
2658 
2659  SCIP_CALL( varEnsureParentvarsSize(var, blkmem, set, var->nparentvars+1) );
2660 
2661  var->parentvars[var->nparentvars] = parentvar;
2662  var->nparentvars++;
2663 
2664  SCIPvarCapture(parentvar);
2665 
2666  return SCIP_OKAY;
2667 }
2668 
2669 /** deletes and releases all variables from the parent list of a variable, frees the memory of parents array */
2670 static
2672  SCIP_VAR** var, /**< pointer to variable */
2673  BMS_BLKMEM* blkmem, /**< block memory */
2674  SCIP_SET* set, /**< global SCIP settings */
2675  SCIP_EVENTQUEUE* eventqueue, /**< event queue (or NULL, if it's an original variable) */
2676  SCIP_LP* lp /**< current LP data (or NULL, if it's an original variable) */
2677  )
2678 {
2679  SCIP_VAR* parentvar;
2680  int i;
2681 
2682  SCIPsetDebugMsg(set, "free parents of <%s>\n", (*var)->name);
2683 
2684  /* release the parent variables and remove the link from the parent variable to the child */
2685  for( i = 0; i < (*var)->nparentvars; ++i )
2686  {
2687  assert((*var)->parentvars != NULL);
2688  parentvar = (*var)->parentvars[i];
2689  assert(parentvar != NULL);
2690 
2691  switch( SCIPvarGetStatus(parentvar) )
2692  {
2694  assert(parentvar->data.original.transvar == *var);
2695  assert(&parentvar->data.original.transvar != var);
2696  parentvar->data.original.transvar = NULL;
2697  break;
2698 
2700  assert(parentvar->data.aggregate.var == *var);
2701  assert(&parentvar->data.aggregate.var != var);
2702  parentvar->data.aggregate.var = NULL;
2703  break;
2704 
2705 #if 0
2706  /* The following code is unclear: should the current variable be removed from its parents? */
2708  assert(parentvar->data.multaggr.vars != NULL);
2709  for( v = 0; v < parentvar->data.multaggr.nvars && parentvar->data.multaggr.vars[v] != *var; ++v )
2710  {}
2711  assert(v < parentvar->data.multaggr.nvars && parentvar->data.multaggr.vars[v] == *var);
2712  if( v < parentvar->data.multaggr.nvars-1 )
2713  {
2714  parentvar->data.multaggr.vars[v] = parentvar->data.multaggr.vars[parentvar->data.multaggr.nvars-1];
2715  parentvar->data.multaggr.scalars[v] = parentvar->data.multaggr.scalars[parentvar->data.multaggr.nvars-1];
2716  }
2717  parentvar->data.multaggr.nvars--;
2718  break;
2719 #endif
2720 
2722  assert(parentvar->negatedvar == *var);
2723  assert((*var)->negatedvar == parentvar);
2724  parentvar->negatedvar = NULL;
2725  (*var)->negatedvar = NULL;
2726  break;
2727 
2728  default:
2729  SCIPerrorMessage("parent variable is neither ORIGINAL, AGGREGATED nor NEGATED\n");
2730  return SCIP_INVALIDDATA;
2731  } /*lint !e788*/
2732 
2733  SCIP_CALL( SCIPvarRelease(&(*var)->parentvars[i], blkmem, set, eventqueue, lp) );
2734  }
2735 
2736  /* free parentvars array */
2737  BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->parentvars, (*var)->parentvarssize);
2738 
2739  return SCIP_OKAY;
2740 }
2741 
2742 /** frees a variable */
2743 static
2745  SCIP_VAR** var, /**< pointer to variable */
2746  BMS_BLKMEM* blkmem, /**< block memory */
2747  SCIP_SET* set, /**< global SCIP settings */
2748  SCIP_EVENTQUEUE* eventqueue, /**< event queue (may be NULL, if it's not a column variable) */
2749  SCIP_LP* lp /**< current LP data (may be NULL, if it's not a column variable) */
2750  )
2751 {
2752  assert(var != NULL);
2753  assert(*var != NULL);
2754  assert(SCIPvarGetStatus(*var) != SCIP_VARSTATUS_COLUMN || &(*var)->data.col->var != var);
2755  assert((*var)->nuses == 0);
2756  assert((*var)->probindex == -1);
2757  assert((*var)->nlocksup[SCIP_LOCKTYPE_MODEL] == 0);
2758  assert((*var)->nlocksdown[SCIP_LOCKTYPE_MODEL] == 0);
2759 
2760  SCIPsetDebugMsg(set, "free variable <%s> with status=%d\n", (*var)->name, SCIPvarGetStatus(*var));
2761 
2762  switch( SCIPvarGetStatus(*var) )
2763  {
2765  assert((*var)->data.original.transvar == NULL); /* cannot free variable, if transformed variable is still existing */
2766  holelistFree(&(*var)->data.original.origdom.holelist, blkmem);
2767  assert((*var)->data.original.origdom.holelist == NULL);
2768  break;
2769  case SCIP_VARSTATUS_LOOSE:
2770  break;
2771  case SCIP_VARSTATUS_COLUMN:
2772  SCIP_CALL( SCIPcolFree(&(*var)->data.col, blkmem, set, eventqueue, lp) ); /* free corresponding LP column */
2773  break;
2774  case SCIP_VARSTATUS_FIXED:
2776  break;
2778  BMSfreeBlockMemoryArray(blkmem, &(*var)->data.multaggr.vars, (*var)->data.multaggr.varssize);
2779  BMSfreeBlockMemoryArray(blkmem, &(*var)->data.multaggr.scalars, (*var)->data.multaggr.varssize);
2780  break;
2782  break;
2783  default:
2784  SCIPerrorMessage("unknown variable status\n");
2785  return SCIP_INVALIDDATA;
2786  }
2787 
2788  /* release all parent variables and free the parentvars array */
2789  SCIP_CALL( varFreeParents(var, blkmem, set, eventqueue, lp) );
2790 
2791  /* free user data */
2793  {
2794  if( (*var)->vardelorig != NULL )
2795  {
2796  SCIP_CALL( (*var)->vardelorig(set->scip, *var, &(*var)->vardata) );
2797  }
2798  }
2799  else
2800  {
2801  if( (*var)->vardeltrans != NULL )
2802  {
2803  SCIP_CALL( (*var)->vardeltrans(set->scip, *var, &(*var)->vardata) );
2804  }
2805  }
2806 
2807  /* free event filter */
2808  if( (*var)->eventfilter != NULL )
2809  {
2810  SCIP_CALL( SCIPeventfilterFree(&(*var)->eventfilter, blkmem, set) );
2811  }
2812  assert((*var)->eventfilter == NULL);
2813 
2814  /* free hole lists */
2815  holelistFree(&(*var)->glbdom.holelist, blkmem);
2816  holelistFree(&(*var)->locdom.holelist, blkmem);
2817  assert((*var)->glbdom.holelist == NULL);
2818  assert((*var)->locdom.holelist == NULL);
2819 
2820  /* free variable bounds data structures */
2821  SCIPvboundsFree(&(*var)->vlbs, blkmem);
2822  SCIPvboundsFree(&(*var)->vubs, blkmem);
2823 
2824  /* free implications data structures */
2825  SCIPimplicsFree(&(*var)->implics, blkmem);
2826 
2827  /* free clique list data structures */
2828  SCIPcliquelistFree(&(*var)->cliquelist, blkmem);
2829 
2830  /* free bound change information arrays */
2831  BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->lbchginfos, (*var)->lbchginfossize);
2832  BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->ubchginfos, (*var)->ubchginfossize);
2833 
2834  /* free branching and inference history entries */
2835  SCIPhistoryFree(&(*var)->history, blkmem);
2836  SCIPhistoryFree(&(*var)->historycrun, blkmem);
2837  SCIPvaluehistoryFree(&(*var)->valuehistory, blkmem);
2838 
2839  /* free variable data structure */
2840  BMSfreeBlockMemoryArray(blkmem, &(*var)->name, strlen((*var)->name)+1);
2841  BMSfreeBlockMemory(blkmem, var);
2842 
2843  return SCIP_OKAY;
2844 }
2845 
2846 /** increases usage counter of variable */
2847 void SCIPvarCapture(
2848  SCIP_VAR* var /**< variable */
2849  )
2850 {
2851  assert(var != NULL);
2852  assert(var->nuses >= 0);
2853 
2854  SCIPdebugMessage("capture variable <%s> with nuses=%d\n", var->name, var->nuses);
2855  var->nuses++;
2856 
2857 #ifdef DEBUGUSES_VARNAME
2858  if( strcmp(var->name, DEBUGUSES_VARNAME) == 0
2859 #ifdef DEBUGUSES_PROBNAME
2860  && ((var->scip->transprob != NULL && strcmp(SCIPprobGetName(var->scip->transprob), DEBUGUSES_PROBNAME) == 0) ||
2861  strcmp(SCIPprobGetName(var->scip->origprob), DEBUGUSES_PROBNAME) == 0)
2862 #endif
2863  )
2864  {
2865  printf("Captured variable " DEBUGUSES_VARNAME " in SCIP %p, now %d uses; captured at\n", (void*)var->scip, var->nuses);
2866  print_backtrace();
2867  }
2868 #endif
2869 }
2870 
2871 /** decreases usage counter of variable, and frees memory if necessary */
2873  SCIP_VAR** var, /**< pointer to variable */
2874  BMS_BLKMEM* blkmem, /**< block memory */
2875  SCIP_SET* set, /**< global SCIP settings */
2876  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2877  SCIP_LP* lp /**< current LP data (or NULL, if it's an original variable) */
2878  )
2879 {
2880  assert(var != NULL);
2881  assert(*var != NULL);
2882  assert((*var)->nuses >= 1);
2883  assert(blkmem != NULL);
2884  assert((*var)->scip == set->scip);
2885 
2886  SCIPsetDebugMsg(set, "release variable <%s> with nuses=%d\n", (*var)->name, (*var)->nuses);
2887  (*var)->nuses--;
2888 
2889 #ifdef DEBUGUSES_VARNAME
2890  if( strcmp((*var)->name, DEBUGUSES_VARNAME) == 0
2891 #ifdef DEBUGUSES_PROBNAME
2892  && (((*var)->scip->transprob != NULL && strcmp(SCIPprobGetName((*var)->scip->transprob), DEBUGUSES_PROBNAME) == 0) ||
2893  strcmp(SCIPprobGetName((*var)->scip->origprob), DEBUGUSES_PROBNAME) == 0)
2894 #endif
2895  )
2896  {
2897  printf("Released variable " DEBUGUSES_VARNAME " in SCIP %p, now %d uses; released at\n", (void*)(*var)->scip, (*var)->nuses);
2898  print_backtrace();
2899  }
2900 #endif
2901 
2902  if( (*var)->nuses == 0 )
2903  {
2904  SCIP_CALL( varFree(var, blkmem, set, eventqueue, lp) );
2905  }
2906 
2907  *var = NULL;
2908 
2909  return SCIP_OKAY;
2910 }
2911 
2912 /** change variable name */
2914  SCIP_VAR* var, /**< problem variable */
2915  BMS_BLKMEM* blkmem, /**< block memory */
2916  const char* name /**< name of variable */
2917  )
2918 {
2919  assert(name != NULL);
2920 
2921  /* remove old variable name */
2922  BMSfreeBlockMemoryArray(blkmem, &var->name, strlen(var->name)+1);
2923 
2924  /* set new variable name */
2925  SCIP_CALL( varSetName(var, blkmem, NULL, name) );
2926 
2927  return SCIP_OKAY;
2928 }
2929 
2930 /** initializes variable data structure for solving */
2931 void SCIPvarInitSolve(
2932  SCIP_VAR* var /**< problem variable */
2933  )
2934 {
2935  assert(var != NULL);
2936 
2938  var->conflictlbcount = 0;
2939  var->conflictubcount = 0;
2940 }
2941 
2942 /** outputs the given bounds into the file stream */
2943 static
2944 void printBounds(
2945  SCIP_SET* set, /**< global SCIP settings */
2946  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2947  FILE* file, /**< output file (or NULL for standard output) */
2948  SCIP_Real lb, /**< lower bound */
2949  SCIP_Real ub, /**< upper bound */
2950  const char* name /**< bound type name */
2951  )
2952 {
2953  assert(set != NULL);
2954 
2955  SCIPmessageFPrintInfo(messagehdlr, file, ", %s=", name);
2956  if( SCIPsetIsInfinity(set, lb) )
2957  SCIPmessageFPrintInfo(messagehdlr, file, "[+inf,");
2958  else if( SCIPsetIsInfinity(set, -lb) )
2959  SCIPmessageFPrintInfo(messagehdlr, file, "[-inf,");
2960  else
2961  SCIPmessageFPrintInfo(messagehdlr, file, "[%.15g,", lb);
2962  if( SCIPsetIsInfinity(set, ub) )
2963  SCIPmessageFPrintInfo(messagehdlr, file, "+inf]");
2964  else if( SCIPsetIsInfinity(set, -ub) )
2965  SCIPmessageFPrintInfo(messagehdlr, file, "-inf]");
2966  else
2967  SCIPmessageFPrintInfo(messagehdlr, file, "%.15g]", ub);
2968 }
2969 
2970 /** prints hole list to file stream */
2971 static
2972 void printHolelist(
2973  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2974  FILE* file, /**< output file (or NULL for standard output) */
2975  SCIP_HOLELIST* holelist, /**< hole list pointer to hole of interest */
2976  const char* name /**< hole type name */
2977  )
2978 { /*lint --e{715}*/
2979  SCIP_Real left;
2980  SCIP_Real right;
2981 
2982  if( holelist == NULL )
2983  return;
2984 
2985  left = SCIPholelistGetLeft(holelist);
2986  right = SCIPholelistGetRight(holelist);
2987 
2988  /* display first hole */
2989  SCIPmessageFPrintInfo(messagehdlr, file, ", %s=(%g,%g)", name, left, right);
2990  holelist = SCIPholelistGetNext(holelist);
2991 
2992  while(holelist != NULL )
2993  {
2994  left = SCIPholelistGetLeft(holelist);
2995  right = SCIPholelistGetRight(holelist);
2996 
2997  /* display hole */
2998  SCIPmessageFPrintInfo(messagehdlr, file, "(%g,%g)", left, right);
2999 
3000  /* get next hole */
3001  holelist = SCIPholelistGetNext(holelist);
3002  }
3003 }
3004 
3005 /** outputs variable information into file stream */
3007  SCIP_VAR* var, /**< problem variable */
3008  SCIP_SET* set, /**< global SCIP settings */
3009  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3010  FILE* file /**< output file (or NULL for standard output) */
3011  )
3012 {
3013  SCIP_HOLELIST* holelist;
3014  SCIP_Real lb;
3015  SCIP_Real ub;
3016  int i;
3017 
3018  assert(var != NULL);
3019  assert(var->scip == set->scip);
3020 
3021  /* type of variable */
3022  switch( SCIPvarGetType(var) )
3023  {
3024  case SCIP_VARTYPE_BINARY:
3025  SCIPmessageFPrintInfo(messagehdlr, file, " [binary]");
3026  break;
3027  case SCIP_VARTYPE_INTEGER:
3028  SCIPmessageFPrintInfo(messagehdlr, file, " [integer]");
3029  break;
3030  case SCIP_VARTYPE_IMPLINT:
3031  SCIPmessageFPrintInfo(messagehdlr, file, " [implicit]");
3032  break;
3034  SCIPmessageFPrintInfo(messagehdlr, file, " [continuous]");
3035  break;
3036  default:
3037  SCIPerrorMessage("unknown variable type\n");
3038  SCIPABORT();
3039  return SCIP_ERROR; /*lint !e527*/
3040  }
3041 
3042  /* name */
3043  SCIPmessageFPrintInfo(messagehdlr, file, " <%s>:", var->name);
3044 
3045  /* objective value */
3046  SCIPmessageFPrintInfo(messagehdlr, file, " obj=%.15g", var->obj);
3047 
3048  /* bounds (global bounds for transformed variables, original bounds for original variables) */
3049  if( !SCIPvarIsTransformed(var) )
3050  {
3051  /* output original bound */
3052  lb = SCIPvarGetLbOriginal(var);
3053  ub = SCIPvarGetUbOriginal(var);
3054  printBounds(set, messagehdlr, file, lb, ub, "original bounds");
3055 
3056  /* output lazy bound */
3057  lb = SCIPvarGetLbLazy(var);
3058  ub = SCIPvarGetUbLazy(var);
3059 
3060  /* only display the lazy bounds if they are different from [-infinity,infinity] */
3061  if( !SCIPsetIsInfinity(set, -lb) || !SCIPsetIsInfinity(set, ub) )
3062  printBounds(set, messagehdlr, file, lb, ub, "lazy bounds");
3063 
3064  holelist = SCIPvarGetHolelistOriginal(var);
3065  printHolelist(messagehdlr, file, holelist, "original holes");
3066  }
3067  else
3068  {
3069  /* output global bound */
3070  lb = SCIPvarGetLbGlobal(var);
3071  ub = SCIPvarGetUbGlobal(var);
3072  printBounds(set, messagehdlr, file, lb, ub, "global bounds");
3073 
3074  /* output local bound */
3075  lb = SCIPvarGetLbLocal(var);
3076  ub = SCIPvarGetUbLocal(var);
3077  printBounds(set, messagehdlr, file, lb, ub, "local bounds");
3078 
3079  /* output lazy bound */
3080  lb = SCIPvarGetLbLazy(var);
3081  ub = SCIPvarGetUbLazy(var);
3082 
3083  /* only display the lazy bounds if they are different from [-infinity,infinity] */
3084  if( !SCIPsetIsInfinity(set, -lb) || !SCIPsetIsInfinity(set, ub) )
3085  printBounds(set, messagehdlr, file, lb, ub, "lazy bounds");
3086 
3087  /* global hole list */
3088  holelist = SCIPvarGetHolelistGlobal(var);
3089  printHolelist(messagehdlr, file, holelist, "global holes");
3090 
3091  /* local hole list */
3092  holelist = SCIPvarGetHolelistLocal(var);
3093  printHolelist(messagehdlr, file, holelist, "local holes");
3094  }
3095 
3096  /* fixings and aggregations */
3097  switch( SCIPvarGetStatus(var) )
3098  {
3100  case SCIP_VARSTATUS_LOOSE:
3101  case SCIP_VARSTATUS_COLUMN:
3102  break;
3103 
3104  case SCIP_VARSTATUS_FIXED:
3105  SCIPmessageFPrintInfo(messagehdlr, file, ", fixed:");
3106  if( SCIPsetIsInfinity(set, var->glbdom.lb) )
3107  SCIPmessageFPrintInfo(messagehdlr, file, "+inf");
3108  else if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
3109  SCIPmessageFPrintInfo(messagehdlr, file, "-inf");
3110  else
3111  SCIPmessageFPrintInfo(messagehdlr, file, "%.15g", var->glbdom.lb);
3112  break;
3113 
3115  SCIPmessageFPrintInfo(messagehdlr, file, ", aggregated:");
3116  if( !SCIPsetIsZero(set, var->data.aggregate.constant) )
3117  SCIPmessageFPrintInfo(messagehdlr, file, " %.15g", var->data.aggregate.constant);
3118  SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g<%s>", var->data.aggregate.scalar, SCIPvarGetName(var->data.aggregate.var));
3119  break;
3120 
3122  SCIPmessageFPrintInfo(messagehdlr, file, ", aggregated:");
3123  if( var->data.multaggr.nvars == 0 || !SCIPsetIsZero(set, var->data.multaggr.constant) )
3124  SCIPmessageFPrintInfo(messagehdlr, file, " %.15g", var->data.multaggr.constant);
3125  for( i = 0; i < var->data.multaggr.nvars; ++i )
3126  SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g<%s>", var->data.multaggr.scalars[i], SCIPvarGetName(var->data.multaggr.vars[i]));
3127  break;
3128 
3130  SCIPmessageFPrintInfo(messagehdlr, file, ", negated: %.15g - <%s>", var->data.negate.constant, SCIPvarGetName(var->negatedvar));
3131  break;
3132 
3133  default:
3134  SCIPerrorMessage("unknown variable status\n");
3135  SCIPABORT();
3136  return SCIP_ERROR; /*lint !e527*/
3137  }
3138 
3139  SCIPmessageFPrintInfo(messagehdlr, file, "\n");
3140 
3141  return SCIP_OKAY;
3142 }
3143 
3144 /** issues a VARUNLOCKED event on the given variable */
3145 static
3147  SCIP_VAR* var, /**< problem variable to change */
3148  BMS_BLKMEM* blkmem, /**< block memory */
3149  SCIP_SET* set, /**< global SCIP settings */
3150  SCIP_EVENTQUEUE* eventqueue /**< event queue */
3151  )
3152 {
3153  SCIP_EVENT* event;
3154 
3155  assert(var != NULL);
3156  assert(var->nlocksdown[SCIP_LOCKTYPE_MODEL] <= 1 && var->nlocksup[SCIP_LOCKTYPE_MODEL] <= 1);
3157  assert(var->scip == set->scip);
3158 
3159  /* issue VARUNLOCKED event on variable */
3160  SCIP_CALL( SCIPeventCreateVarUnlocked(&event, blkmem, var) );
3161  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
3162 
3163  return SCIP_OKAY;
3164 }
3165 
3166 /** modifies lock numbers for rounding */
3168  SCIP_VAR* var, /**< problem variable */
3169  BMS_BLKMEM* blkmem, /**< block memory */
3170  SCIP_SET* set, /**< global SCIP settings */
3171  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3172  SCIP_LOCKTYPE locktype, /**< type of the variable locks */
3173  int addnlocksdown, /**< increase in number of rounding down locks */
3174  int addnlocksup /**< increase in number of rounding up locks */
3175  )
3176 {
3177  SCIP_VAR* lockvar;
3178 
3179  assert(var != NULL);
3180  assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
3181  assert(var->nlocksup[locktype] >= 0);
3182  assert(var->nlocksdown[locktype] >= 0);
3183  assert(var->scip == set->scip);
3184 
3185  if( addnlocksdown == 0 && addnlocksup == 0 )
3186  return SCIP_OKAY;
3187 
3188 #ifdef SCIP_DEBUG
3189  SCIPsetDebugMsg(set, "add rounding locks %d/%d to variable <%s> (locks=%d/%d, type=%u)\n",
3190  addnlocksdown, addnlocksup, var->name, var->nlocksdown[locktype], var->nlocksup[locktype], locktype);
3191 #endif
3192 
3193  lockvar = var;
3194 
3195  while( TRUE ) /*lint !e716 */
3196  {
3197  assert(lockvar != NULL);
3198 
3199  switch( SCIPvarGetStatus(lockvar) )
3200  {
3202  if( lockvar->data.original.transvar != NULL )
3203  {
3204  lockvar = lockvar->data.original.transvar;
3205  break;
3206  }
3207  else
3208  {
3209  lockvar->nlocksdown[locktype] += addnlocksdown;
3210  lockvar->nlocksup[locktype] += addnlocksup;
3211 
3212  assert(lockvar->nlocksdown[locktype] >= 0);
3213  assert(lockvar->nlocksup[locktype] >= 0);
3214 
3215  return SCIP_OKAY;
3216  }
3217  case SCIP_VARSTATUS_LOOSE:
3218  case SCIP_VARSTATUS_COLUMN:
3219  case SCIP_VARSTATUS_FIXED:
3220  lockvar->nlocksdown[locktype] += addnlocksdown;
3221  lockvar->nlocksup[locktype] += addnlocksup;
3222 
3223  assert(lockvar->nlocksdown[locktype] >= 0);
3224  assert(lockvar->nlocksup[locktype] >= 0);
3225 
3226  if( locktype == SCIP_LOCKTYPE_MODEL && lockvar->nlocksdown[locktype] <= 1
3227  && lockvar->nlocksup[locktype] <= 1 )
3228  {
3229  SCIP_CALL( varEventVarUnlocked(lockvar, blkmem, set, eventqueue) );
3230  }
3231 
3232  return SCIP_OKAY;
3234  assert(!lockvar->donotaggr);
3235 
3236  if( lockvar->data.aggregate.scalar < 0.0 )
3237  {
3238  int tmp = addnlocksup;
3239 
3240  addnlocksup = addnlocksdown;
3241  addnlocksdown = tmp;
3242  }
3243 
3244  lockvar = lockvar->data.aggregate.var;
3245  break;
3247  {
3248  int v;
3249 
3250  assert(!lockvar->donotmultaggr);
3251 
3252  lockvar->nlocksdown[locktype] += addnlocksdown;
3253  lockvar->nlocksup[locktype] += addnlocksup;
3254 
3255  assert(lockvar->nlocksdown[locktype] >= 0);
3256  assert(lockvar->nlocksup[locktype] >= 0);
3257 
3258  for( v = lockvar->data.multaggr.nvars - 1; v >= 0; --v )
3259  {
3260  if( lockvar->data.multaggr.scalars[v] > 0.0 )
3261  {
3262  SCIP_CALL( SCIPvarAddLocks(lockvar->data.multaggr.vars[v], blkmem, set, eventqueue, locktype, addnlocksdown,
3263  addnlocksup) );
3264  }
3265  else
3266  {
3267  SCIP_CALL( SCIPvarAddLocks(lockvar->data.multaggr.vars[v], blkmem, set, eventqueue, locktype, addnlocksup,
3268  addnlocksdown) );
3269  }
3270  }
3271  return SCIP_OKAY;
3272  }
3274  {
3275  int tmp = addnlocksup;
3276 
3277  assert(lockvar->negatedvar != NULL);
3278  assert(SCIPvarGetStatus(lockvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
3279  assert(lockvar->negatedvar->negatedvar == lockvar);
3280 
3281  addnlocksup = addnlocksdown;
3282  addnlocksdown = tmp;
3283 
3284  lockvar = lockvar->negatedvar;
3285  break;
3286  }
3287  default:
3288  SCIPerrorMessage("unknown variable status\n");
3289  return SCIP_INVALIDDATA;
3290  }
3291  }
3292 }
3293 
3294 /** gets number of locks for rounding down of a special type */
3296  SCIP_VAR* var, /**< problem variable */
3297  SCIP_LOCKTYPE locktype /**< type of variable locks */
3298  )
3299 {
3300  int nlocks;
3301  int i;
3302 
3303  assert(var != NULL);
3304  assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
3305  assert(var->nlocksdown[locktype] >= 0);
3306 
3307  switch( SCIPvarGetStatus(var) )
3308  {
3310  if( var->data.original.transvar != NULL )
3311  return SCIPvarGetNLocksDownType(var->data.original.transvar, locktype);
3312  else
3313  return var->nlocksdown[locktype];
3314 
3315  case SCIP_VARSTATUS_LOOSE:
3316  case SCIP_VARSTATUS_COLUMN:
3317  case SCIP_VARSTATUS_FIXED:
3318  return var->nlocksdown[locktype];
3319 
3321  assert(!var->donotaggr);
3322  if( var->data.aggregate.scalar > 0.0 )
3323  return SCIPvarGetNLocksDownType(var->data.aggregate.var, locktype);
3324  else
3325  return SCIPvarGetNLocksUpType(var->data.aggregate.var, locktype);
3326 
3328  assert(!var->donotmultaggr);
3329  nlocks = 0;
3330  for( i = 0; i < var->data.multaggr.nvars; ++i )
3331  {
3332  if( var->data.multaggr.scalars[i] > 0.0 )
3333  nlocks += SCIPvarGetNLocksDownType(var->data.multaggr.vars[i], locktype);
3334  else
3335  nlocks += SCIPvarGetNLocksUpType(var->data.multaggr.vars[i], locktype);
3336  }
3337  return nlocks;
3338 
3340  assert(var->negatedvar != NULL);
3342  assert(var->negatedvar->negatedvar == var);
3343  return SCIPvarGetNLocksUpType(var->negatedvar, locktype);
3344 
3345  default:
3346  SCIPerrorMessage("unknown variable status\n");
3347  SCIPABORT();
3348  return INT_MAX; /*lint !e527*/
3349  }
3350 }
3351 
3352 /** gets number of locks for rounding up of a special type */
3354  SCIP_VAR* var, /**< problem variable */
3355  SCIP_LOCKTYPE locktype /**< type of variable locks */
3356  )
3357 {
3358  int nlocks;
3359  int i;
3360 
3361  assert(var != NULL);
3362  assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
3363  assert(var->nlocksup[locktype] >= 0);
3364 
3365  switch( SCIPvarGetStatus(var) )
3366  {
3368  if( var->data.original.transvar != NULL )
3369  return SCIPvarGetNLocksUpType(var->data.original.transvar, locktype);
3370  else
3371  return var->nlocksup[locktype];
3372 
3373  case SCIP_VARSTATUS_LOOSE:
3374  case SCIP_VARSTATUS_COLUMN:
3375  case SCIP_VARSTATUS_FIXED:
3376  return var->nlocksup[locktype];
3377 
3379  assert(!var->donotaggr);
3380  if( var->data.aggregate.scalar > 0.0 )
3381  return SCIPvarGetNLocksUpType(var->data.aggregate.var, locktype);
3382  else
3383  return SCIPvarGetNLocksDownType(var->data.aggregate.var, locktype);
3384 
3386  assert(!var->donotmultaggr);
3387  nlocks = 0;
3388  for( i = 0; i < var->data.multaggr.nvars; ++i )
3389  {
3390  if( var->data.multaggr.scalars[i] > 0.0 )
3391  nlocks += SCIPvarGetNLocksUpType(var->data.multaggr.vars[i], locktype);
3392  else
3393  nlocks += SCIPvarGetNLocksDownType(var->data.multaggr.vars[i], locktype);
3394  }
3395  return nlocks;
3396 
3398  assert(var->negatedvar != NULL);
3400  assert(var->negatedvar->negatedvar == var);
3401  return SCIPvarGetNLocksDownType(var->negatedvar, locktype);
3402 
3403  default:
3404  SCIPerrorMessage("unknown variable status\n");
3405  SCIPABORT();
3406  return INT_MAX; /*lint !e527*/
3407  }
3408 }
3409 
3410 /** gets number of locks for rounding down
3411  *
3412  * @note This method will always return variable locks of type model
3413  *
3414  * @note It is recommented to use SCIPvarGetNLocksDownType()
3415  */
3417  SCIP_VAR* var /**< problem variable */
3418  )
3419 {
3421 }
3422 
3423 /** gets number of locks for rounding up
3424  *
3425  * @note This method will always return variable locks of type model
3426  *
3427  * @note It is recommented to use SCIPvarGetNLocksUpType()
3428  */
3429 int SCIPvarGetNLocksUp(
3430  SCIP_VAR* var /**< problem variable */
3431  )
3432 {
3434 }
3435 
3436 /** is it possible, to round variable down and stay feasible?
3437  *
3438  * @note This method will always check w.r.t variable locks of type model
3439  */
3441  SCIP_VAR* var /**< problem variable */
3442  )
3443 {
3444  return (SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 0);
3445 }
3446 
3447 /** is it possible, to round variable up and stay feasible?
3448  *
3449  * @note This method will always check w.r.t. variable locks of type model
3450  */
3452  SCIP_VAR* var /**< problem variable */
3453  )
3454 {
3455  return (SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 0);
3456 }
3457 
3458 /** gets and captures transformed variable of a given variable; if the variable is not yet transformed,
3459  * a new transformed variable for this variable is created
3460  */
3462  SCIP_VAR* origvar, /**< original problem variable */
3463  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3464  SCIP_SET* set, /**< global SCIP settings */
3465  SCIP_STAT* stat, /**< problem statistics */
3466  SCIP_OBJSENSE objsense, /**< objective sense of original problem; transformed is always MINIMIZE */
3467  SCIP_VAR** transvar /**< pointer to store the transformed variable */
3468  )
3469 {
3470  char name[SCIP_MAXSTRLEN];
3471 
3472  assert(origvar != NULL);
3473  assert(origvar->scip == set->scip);
3474  assert(SCIPvarGetStatus(origvar) == SCIP_VARSTATUS_ORIGINAL);
3475  assert(SCIPsetIsEQ(set, origvar->glbdom.lb, origvar->locdom.lb));
3476  assert(SCIPsetIsEQ(set, origvar->glbdom.ub, origvar->locdom.ub));
3477  assert(origvar->vlbs == NULL);
3478  assert(origvar->vubs == NULL);
3479  assert(transvar != NULL);
3480 
3481  /* check if variable is already transformed */
3482  if( origvar->data.original.transvar != NULL )
3483  {
3484  *transvar = origvar->data.original.transvar;
3485  SCIPvarCapture(*transvar);
3486  }
3487  else
3488  {
3489  int i;
3490 
3491  /* create transformed variable */
3492  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "t_%s", origvar->name);
3493  SCIP_CALL( SCIPvarCreateTransformed(transvar, blkmem, set, stat, name,
3494  origvar->glbdom.lb, origvar->glbdom.ub, (SCIP_Real)objsense * origvar->obj,
3495  SCIPvarGetType(origvar), origvar->initial, origvar->removable,
3496  origvar->vardelorig, origvar->vartrans, origvar->vardeltrans, origvar->varcopy, NULL) );
3497 
3498  /* copy the branch factor and priority */
3499  (*transvar)->branchfactor = origvar->branchfactor;
3500  (*transvar)->branchpriority = origvar->branchpriority;
3501  (*transvar)->branchdirection = origvar->branchdirection; /*lint !e732*/
3502 
3503  /* duplicate hole lists */
3504  SCIP_CALL( holelistDuplicate(&(*transvar)->glbdom.holelist, blkmem, set, origvar->glbdom.holelist) );
3505  SCIP_CALL( holelistDuplicate(&(*transvar)->locdom.holelist, blkmem, set, origvar->locdom.holelist) );
3506 
3507  /* link original and transformed variable */
3508  origvar->data.original.transvar = *transvar;
3509  SCIP_CALL( varAddParent(*transvar, blkmem, set, origvar) );
3510 
3511  /* copy rounding locks */
3512  for( i = 0; i < NLOCKTYPES; i++ )
3513  {
3514  (*transvar)->nlocksdown[i] = origvar->nlocksdown[i];
3515  (*transvar)->nlocksup[i] = origvar->nlocksup[i];
3516  assert((*transvar)->nlocksdown[i] >= 0);
3517  assert((*transvar)->nlocksup[i] >= 0);
3518  }
3519 
3520  /* copy donot(mult)aggr status */
3521  (*transvar)->donotaggr = origvar->donotaggr;
3522  (*transvar)->donotmultaggr = origvar->donotmultaggr;
3523 
3524  /* copy lazy bounds */
3525  (*transvar)->lazylb = origvar->lazylb;
3526  (*transvar)->lazyub = origvar->lazyub;
3527 
3528  /* transfer eventual variable statistics; do not update global statistics, because this has been done
3529  * when original variable was created
3530  */
3531  SCIPhistoryUnite((*transvar)->history, origvar->history, FALSE);
3532 
3533  /* transform user data */
3534  if( origvar->vartrans != NULL )
3535  {
3536  SCIP_CALL( origvar->vartrans(set->scip, origvar, origvar->vardata, *transvar, &(*transvar)->vardata) );
3537  }
3538  else
3539  (*transvar)->vardata = origvar->vardata;
3540  }
3541 
3542  SCIPsetDebugMsg(set, "transformed variable: <%s>[%p] -> <%s>[%p]\n", origvar->name, (void*)origvar, (*transvar)->name, (void*)*transvar);
3543 
3544  return SCIP_OKAY;
3545 }
3546 
3547 /** gets corresponding transformed variable of an original or negated original variable */
3549  SCIP_VAR* origvar, /**< original problem variable */
3550  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3551  SCIP_SET* set, /**< global SCIP settings */
3552  SCIP_STAT* stat, /**< problem statistics */
3553  SCIP_VAR** transvar /**< pointer to store the transformed variable, or NULL if not existing yet */
3554  )
3555 {
3556  assert(origvar != NULL);
3558  assert(origvar->scip == set->scip);
3559 
3560  if( SCIPvarGetStatus(origvar) == SCIP_VARSTATUS_NEGATED )
3561  {
3562  assert(origvar->negatedvar != NULL);
3564 
3565  if( origvar->negatedvar->data.original.transvar == NULL )
3566  *transvar = NULL;
3567  else
3568  {
3569  SCIP_CALL( SCIPvarNegate(origvar->negatedvar->data.original.transvar, blkmem, set, stat, transvar) );
3570  }
3571  }
3572  else
3573  *transvar = origvar->data.original.transvar;
3574 
3575  return SCIP_OKAY;
3576 }
3577 
3578 /** converts loose transformed variable into column variable, creates LP column */
3580  SCIP_VAR* var, /**< problem variable */
3581  BMS_BLKMEM* blkmem, /**< block memory */
3582  SCIP_SET* set, /**< global SCIP settings */
3583  SCIP_STAT* stat, /**< problem statistics */
3584  SCIP_PROB* prob, /**< problem data */
3585  SCIP_LP* lp /**< current LP data */
3586  )
3587 {
3588  assert(var != NULL);
3589  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
3590  assert(var->scip == set->scip);
3591 
3592  SCIPsetDebugMsg(set, "creating column for variable <%s>\n", var->name);
3593 
3594  /* switch variable status */
3595  var->varstatus = SCIP_VARSTATUS_COLUMN; /*lint !e641*/
3596 
3597  /* create column of variable */
3598  SCIP_CALL( SCIPcolCreate(&var->data.col, blkmem, set, stat, var, 0, NULL, NULL, var->removable) );
3599 
3600  if( var->probindex != -1 )
3601  {
3602  /* inform problem about the variable's status change */
3603  SCIP_CALL( SCIPprobVarChangedStatus(prob, blkmem, set, NULL, NULL, var) );
3604 
3605  /* inform LP, that problem variable is now a column variable and no longer loose */
3606  SCIP_CALL( SCIPlpUpdateVarColumn(lp, set, var) );
3607  }
3608 
3609  return SCIP_OKAY;
3610 }
3611 
3612 /** converts column transformed variable back into loose variable, frees LP column */
3614  SCIP_VAR* var, /**< problem variable */
3615  BMS_BLKMEM* blkmem, /**< block memory */
3616  SCIP_SET* set, /**< global SCIP settings */
3617  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3618  SCIP_PROB* prob, /**< problem data */
3619  SCIP_LP* lp /**< current LP data */
3620  )
3621 {
3622  assert(var != NULL);
3623  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
3624  assert(var->scip == set->scip);
3625  assert(var->data.col != NULL);
3626  assert(var->data.col->lppos == -1);
3627  assert(var->data.col->lpipos == -1);
3628 
3629  SCIPsetDebugMsg(set, "deleting column for variable <%s>\n", var->name);
3630 
3631  /* free column of variable */
3632  SCIP_CALL( SCIPcolFree(&var->data.col, blkmem, set, eventqueue, lp) );
3633 
3634  /* switch variable status */
3635  var->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
3636 
3637  if( var->probindex != -1 )
3638  {
3639  /* inform problem about the variable's status change */
3640  SCIP_CALL( SCIPprobVarChangedStatus(prob, blkmem, set, NULL, NULL, var) );
3641 
3642  /* inform LP, that problem variable is now a loose variable and no longer a column */
3643  SCIP_CALL( SCIPlpUpdateVarLoose(lp, set, var) );
3644  }
3645 
3646  return SCIP_OKAY;
3647 }
3648 
3649 /** issues a VARFIXED event on the given variable and all its parents (except ORIGINAL parents);
3650  * the event issuing on the parents is necessary, because unlike with bound changes, the parent variables
3651  * are not informed about a fixing of an active variable they are pointing to
3652  */
3653 static
3655  SCIP_VAR* var, /**< problem variable to change */
3656  BMS_BLKMEM* blkmem, /**< block memory */
3657  SCIP_SET* set, /**< global SCIP settings */
3658  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3659  int fixeventtype /**< is this event a fixation(0), an aggregation(1), or a
3660  * multi-aggregation(2)
3661  */
3662  )
3663 {
3664  SCIP_EVENT* event;
3665  SCIP_VARSTATUS varstatus;
3666  int i;
3667 
3668  assert(var != NULL);
3669  assert(var->scip == set->scip);
3670  assert(0 <= fixeventtype && fixeventtype <= 2);
3671 
3672  /* issue VARFIXED event on variable */
3673  SCIP_CALL( SCIPeventCreateVarFixed(&event, blkmem, var) );
3674  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
3675 
3676 #ifndef NDEBUG
3677  for( i = var->nparentvars -1; i >= 0; --i )
3678  {
3680  }
3681 #endif
3682 
3683  switch( fixeventtype )
3684  {
3685  case 0:
3686  /* process all parents of a fixed variable */
3687  for( i = var->nparentvars - 1; i >= 0; --i )
3688  {
3689  varstatus = SCIPvarGetStatus(var->parentvars[i]);
3690 
3691  assert(varstatus != SCIP_VARSTATUS_FIXED);
3692 
3693  /* issue event on all not yet fixed parent variables, (that should already issued this event) except the original
3694  * one
3695  */
3696  if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3697  {
3698  SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3699  }
3700  }
3701  break;
3702  case 1:
3703  /* process all parents of a aggregated variable */
3704  for( i = var->nparentvars - 1; i >= 0; --i )
3705  {
3706  varstatus = SCIPvarGetStatus(var->parentvars[i]);
3707 
3708  assert(varstatus != SCIP_VARSTATUS_FIXED);
3709 
3710  /* issue event for not aggregated parent variable, because for these and its parents the var event was already
3711  * issued(, except the original one)
3712  *
3713  * @note that even before an aggregated parent variable, there might be variables, for which the vent was not
3714  * yet issued
3715  */
3716  if( varstatus == SCIP_VARSTATUS_AGGREGATED )
3717  continue;
3718 
3719  if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3720  {
3721  SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3722  }
3723  }
3724  break;
3725  case 2:
3726  /* process all parents of a aggregated variable */
3727  for( i = var->nparentvars - 1; i >= 0; --i )
3728  {
3729  varstatus = SCIPvarGetStatus(var->parentvars[i]);
3730 
3731  assert(varstatus != SCIP_VARSTATUS_FIXED);
3732 
3733  /* issue event on all parent variables except the original one */
3734  if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3735  {
3736  SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3737  }
3738  }
3739  break;
3740  default:
3741  SCIPerrorMessage("unknown variable fixation event origin\n");
3742  return SCIP_INVALIDDATA;
3743  }
3744 
3745  return SCIP_OKAY;
3746 }
3747 
3748 /** converts variable into fixed variable */
3750  SCIP_VAR* var, /**< problem variable */
3751  BMS_BLKMEM* blkmem, /**< block memory */
3752  SCIP_SET* set, /**< global SCIP settings */
3753  SCIP_STAT* stat, /**< problem statistics */
3754  SCIP_PROB* transprob, /**< tranformed problem data */
3755  SCIP_PROB* origprob, /**< original problem data */
3756  SCIP_PRIMAL* primal, /**< primal data */
3757  SCIP_TREE* tree, /**< branch and bound tree */
3758  SCIP_REOPT* reopt, /**< reoptimization data structure */
3759  SCIP_LP* lp, /**< current LP data */
3760  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3761  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
3762  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3763  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
3764  SCIP_Real fixedval, /**< value to fix variable at */
3765  SCIP_Bool* infeasible, /**< pointer to store whether the fixing is infeasible */
3766  SCIP_Bool* fixed /**< pointer to store whether the fixing was performed (variable was unfixed) */
3767  )
3768 {
3769  SCIP_Real obj;
3770  SCIP_Real childfixedval;
3771 
3772  assert(var != NULL);
3773  assert(var->scip == set->scip);
3774  assert(SCIPsetIsEQ(set, var->glbdom.lb, var->locdom.lb));
3775  assert(SCIPsetIsEQ(set, var->glbdom.ub, var->locdom.ub));
3776  assert(infeasible != NULL);
3777  assert(fixed != NULL);
3778 
3779  SCIPsetDebugMsg(set, "fix variable <%s>[%g,%g] to %g\n", var->name, var->glbdom.lb, var->glbdom.ub, fixedval);
3780 
3781  *infeasible = FALSE;
3782  *fixed = FALSE;
3783 
3785  {
3786  *infeasible = !SCIPsetIsFeasEQ(set, fixedval, var->locdom.lb);
3787  SCIPsetDebugMsg(set, " -> variable already fixed to %g (fixedval=%g): infeasible=%u\n", var->locdom.lb, fixedval, *infeasible);
3788  return SCIP_OKAY;
3789  }
3790  else if( (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPsetIsFeasIntegral(set, fixedval))
3791  || SCIPsetIsFeasLT(set, fixedval, var->locdom.lb)
3792  || SCIPsetIsFeasGT(set, fixedval, var->locdom.ub) )
3793  {
3794  SCIPsetDebugMsg(set, " -> fixing infeasible: locdom=[%g,%g], fixedval=%g\n", var->locdom.lb, var->locdom.ub, fixedval);
3795  *infeasible = TRUE;
3796  return SCIP_OKAY;
3797  }
3798 
3799  switch( SCIPvarGetStatus(var) )
3800  {
3802  if( var->data.original.transvar == NULL )
3803  {
3804  SCIPerrorMessage("cannot fix an untransformed original variable\n");
3805  return SCIP_INVALIDDATA;
3806  }
3807  SCIP_CALL( SCIPvarFix(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
3808  lp, branchcand, eventfilter, eventqueue, cliquetable, fixedval, infeasible, fixed) );
3809  break;
3810 
3811  case SCIP_VARSTATUS_LOOSE:
3812  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
3813 
3814  /* set the fixed variable's objective value to 0.0 */
3815  obj = var->obj;
3816  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
3817 
3818  /* since we change the variable type form loose to fixed, we have to adjust the number of loose
3819  * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
3820  * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
3821  * objective of this variable is set to zero
3822  */
3823  SCIPlpDecNLoosevars(lp);
3824 
3825  /* change variable's bounds to fixed value (thereby removing redundant implications and variable bounds) */
3826  holelistFree(&var->glbdom.holelist, blkmem);
3827  holelistFree(&var->locdom.holelist, blkmem);
3828  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, fixedval) );
3829  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, fixedval) );
3830 
3831  if( var->glbdom.lb != var->glbdom.ub ) /*lint !e777*/
3832  {
3833  /* explicitly set variable's bounds if the fixed value was in epsilon range of the old bound (so above call didn't set bound) */
3835  {
3836  /* if not continuous variable, then make sure variable is fixed to integer value */
3837  assert(SCIPsetIsIntegral(set, fixedval));
3838  fixedval = SCIPsetRound(set, fixedval);
3839  }
3840  var->glbdom.lb = fixedval;
3841  var->glbdom.ub = fixedval;
3842  }
3843 
3844  /* ensure local domain is fixed to same value as global domain */
3845  var->locdom.lb = var->glbdom.lb;
3846  var->locdom.ub = var->glbdom.ub;
3847 
3848  /* delete implications and variable bounds information */
3849  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
3850  assert(var->vlbs == NULL);
3851  assert(var->vubs == NULL);
3852  assert(var->implics == NULL);
3853 
3854  /* clear the history of the variable */
3855  SCIPhistoryReset(var->history);
3857 
3858  /* convert variable into fixed variable */
3859  var->varstatus = SCIP_VARSTATUS_FIXED; /*lint !e641*/
3860 
3861  /* inform problem about the variable's status change */
3862  if( var->probindex != -1 )
3863  {
3864  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
3865  }
3866 
3867  /* reset the objective value of the fixed variable, thus adjusting the problem's objective offset */
3868  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventfilter, eventqueue, obj) );
3869 
3870  /* issue VARFIXED event */
3871  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 0) );
3872 
3873  *fixed = TRUE;
3874  break;
3875 
3876  case SCIP_VARSTATUS_COLUMN:
3877  SCIPerrorMessage("cannot fix a column variable\n");
3878  return SCIP_INVALIDDATA;
3879 
3880  case SCIP_VARSTATUS_FIXED:
3881  SCIPerrorMessage("cannot fix a fixed variable again\n"); /*lint !e527*/
3882  SCIPABORT(); /* case is already handled in earlier if condition */
3883  return SCIP_INVALIDDATA; /*lint !e527*/
3884 
3886  /* fix aggregation variable y in x = a*y + c, instead of fixing x directly */
3887  assert(SCIPsetIsZero(set, var->obj));
3888  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
3889  if( SCIPsetIsInfinity(set, fixedval) || SCIPsetIsInfinity(set, -fixedval) )
3890  childfixedval = (var->data.aggregate.scalar < 0.0 ? -fixedval : fixedval);
3891  else
3892  childfixedval = (fixedval - var->data.aggregate.constant)/var->data.aggregate.scalar;
3893  SCIP_CALL( SCIPvarFix(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
3894  branchcand, eventfilter, eventqueue, cliquetable, childfixedval, infeasible, fixed) );
3895  break;
3896 
3898  SCIPerrorMessage("cannot fix a multiple aggregated variable\n");
3899  SCIPABORT();
3900  return SCIP_INVALIDDATA; /*lint !e527*/
3901 
3903  /* fix negation variable x in x' = offset - x, instead of fixing x' directly */
3904  assert(SCIPsetIsZero(set, var->obj));
3905  assert(var->negatedvar != NULL);
3907  assert(var->negatedvar->negatedvar == var);
3908  SCIP_CALL( SCIPvarFix(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
3909  branchcand, eventfilter, eventqueue, cliquetable, var->data.negate.constant - fixedval, infeasible, fixed) );
3910  break;
3911 
3912  default:
3913  SCIPerrorMessage("unknown variable status\n");
3914  return SCIP_INVALIDDATA;
3915  }
3916 
3917  return SCIP_OKAY;
3918 }
3919 
3920 /** transforms given variables, scalars and constant to the corresponding active variables, scalars and constant
3921  *
3922  * If the number of needed active variables is greater than the available slots in the variable array, nothing happens except
3923  * that the required size is stored in the corresponding variable; hence, if afterwards the required size is greater than the
3924  * available slots (varssize), nothing happens; otherwise, the active variable representation is stored in the arrays.
3925  *
3926  * The reason for this approach is that we cannot reallocate memory, since we do not know how the
3927  * memory has been allocated (e.g., by a C++ 'new' or SCIP functions).
3928  */
3930  SCIP_SET* set, /**< global SCIP settings */
3931  SCIP_VAR** vars, /**< variable array to get active variables */
3932  SCIP_Real* scalars, /**< scalars a_1, ..., a_n in linear sum a_1*x_1 + ... + a_n*x_n + c */
3933  int* nvars, /**< pointer to number of variables and values in vars and scalars array */
3934  int varssize, /**< available slots in vars and scalars array */
3935  SCIP_Real* constant, /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c */
3936  int* requiredsize, /**< pointer to store the required array size for the active variables */
3937  SCIP_Bool mergemultiples /**< should multiple occurrences of a var be replaced by a single coeff? */
3938  )
3939 {
3940  SCIP_VAR** activevars;
3941  SCIP_Real* activescalars;
3942  int nactivevars;
3943  SCIP_Real activeconstant;
3944  SCIP_Bool activeconstantinf;
3945  int activevarssize;
3946 
3947  SCIP_VAR* var;
3948  SCIP_Real scalar;
3949  int v;
3950  int k;
3951 
3952  SCIP_VAR** tmpvars;
3953  SCIP_VAR** multvars;
3954  SCIP_Real* tmpscalars;
3955  SCIP_Real* multscalars;
3956  int tmpvarssize;
3957  int ntmpvars;
3958  int nmultvars;
3959 
3960  SCIP_VAR* multvar;
3961  SCIP_Real multscalar;
3962  SCIP_Real multconstant;
3963  int pos;
3964 
3965  int noldtmpvars;
3966 
3967  SCIP_VAR** tmpvars2;
3968  SCIP_Real* tmpscalars2;
3969  int tmpvarssize2;
3970  int ntmpvars2;
3971 
3972  SCIP_Bool sortagain = FALSE;
3973 
3974  assert(set != NULL);
3975  assert(nvars != NULL);
3976  assert(scalars != NULL || *nvars == 0);
3977  assert(constant != NULL);
3978  assert(requiredsize != NULL);
3979  assert(*nvars <= varssize);
3980 
3981  *requiredsize = 0;
3982 
3983  if( *nvars == 0 )
3984  return SCIP_OKAY;
3985 
3986  assert(vars != NULL);
3987 
3988  /* handle the "easy" case of just one variable and avoid memory allocation if the variable is already active */
3989  if( *nvars == 1 && (vars[0]->varstatus == ((int) SCIP_VARSTATUS_COLUMN) || vars[0]->varstatus == ((int) SCIP_VARSTATUS_LOOSE)) )
3990  {
3991  *requiredsize = 1;
3992 
3993  return SCIP_OKAY;
3994  }
3995 
3996  nactivevars = 0;
3997  activeconstant = 0.0;
3998  activeconstantinf = FALSE;
3999  activevarssize = (*nvars) * 2;
4000  ntmpvars = *nvars;
4001  tmpvarssize = *nvars;
4002 
4003  tmpvarssize2 = 1;
4004 
4005  /* allocate temporary memory */
4006  SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpvars2, tmpvarssize2) );
4007  SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpscalars2, tmpvarssize2) );
4008  SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
4009  SCIP_CALL( SCIPsetAllocBufferArray(set, &activescalars, activevarssize) );
4010  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
4011  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpscalars, scalars, ntmpvars) );
4012 
4013  /* to avoid unnecessary expanding of variable arrays while disaggregating several variables multiple times combine same variables
4014  * first, first get all corresponding variables with status loose, column, multaggr or fixed
4015  */
4016  for( v = ntmpvars - 1; v >= 0; --v )
4017  {
4018  var = tmpvars[v];
4019  scalar = tmpscalars[v];
4020 
4021  assert(var != NULL);
4022  /* transforms given variable, scalar and constant to the corresponding active, fixed, or
4023  * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed
4024  * variable, "scalar" will be 0.0 and the value of the sum will be stored in "constant".
4025  */
4026  SCIP_CALL( SCIPvarGetProbvarSum(&var, set, &scalar, &activeconstant) );
4027  assert(var != NULL);
4028 
4029  assert(SCIPsetIsInfinity(set, activeconstant) == (activeconstant == SCIPsetInfinity(set))); /*lint !e777*/
4030  assert(SCIPsetIsInfinity(set, -activeconstant) == (activeconstant == -SCIPsetInfinity(set))); /*lint !e777*/
4031 
4032  activeconstantinf = SCIPsetIsInfinity(set, activeconstant) || SCIPsetIsInfinity(set, -activeconstant);
4033 
4034  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
4035  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
4038 
4039  tmpvars[v] = var;
4040  tmpscalars[v] = scalar;
4041  }
4042  noldtmpvars = ntmpvars;
4043 
4044  /* sort all variables to combine equal variables easily */
4045  SCIPsortPtrReal((void**)tmpvars, tmpscalars, SCIPvarComp, noldtmpvars);
4046  ntmpvars = 0;
4047  for( v = 1; v < noldtmpvars; ++v )
4048  {
4049  /* combine same variables */
4050  if( SCIPvarCompare(tmpvars[v], tmpvars[ntmpvars]) == 0 )
4051  {
4052  tmpscalars[ntmpvars] += tmpscalars[v];
4053  }
4054  else
4055  {
4056  ++ntmpvars;
4057  if( v > ntmpvars )
4058  {
4059  tmpscalars[ntmpvars] = tmpscalars[v];
4060  tmpvars[ntmpvars] = tmpvars[v];
4061  }
4062  }
4063  }
4064  ++ntmpvars;
4065 
4066 #ifdef SCIP_MORE_DEBUG
4067  for( v = 1; v < ntmpvars; ++v )
4068  assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
4069 #endif
4070 
4071  /* collect for each variable the representation in active variables */
4072  while( ntmpvars >= 1 )
4073  {
4074  --ntmpvars;
4075  ntmpvars2 = 0;
4076  var = tmpvars[ntmpvars];
4077  scalar = tmpscalars[ntmpvars];
4078 
4079  assert(var != NULL);
4080 
4081  /* TODO: maybe we should test here on SCIPsetIsZero() instead of 0.0 */
4082  if( scalar == 0.0 )
4083  continue;
4084 
4085  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
4086  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
4089 
4090  switch( SCIPvarGetStatus(var) )
4091  {
4092  case SCIP_VARSTATUS_LOOSE:
4093  case SCIP_VARSTATUS_COLUMN:
4094  /* x = a*y + c */
4095  if( nactivevars >= activevarssize )
4096  {
4097  activevarssize *= 2;
4098  SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
4099  SCIP_CALL( SCIPsetReallocBufferArray(set, &activescalars, activevarssize) );
4100  assert(nactivevars < activevarssize);
4101  }
4102  activevars[nactivevars] = var;
4103  activescalars[nactivevars] = scalar;
4104  nactivevars++;
4105  break;
4106 
4108  /* x = a_1*y_1 + ... + a_n*y_n + c */
4109  nmultvars = var->data.multaggr.nvars;
4110  multvars = var->data.multaggr.vars;
4111  multscalars = var->data.multaggr.scalars;
4112  sortagain = TRUE;
4113 
4114  if( nmultvars + ntmpvars > tmpvarssize )
4115  {
4116  while( nmultvars + ntmpvars > tmpvarssize )
4117  tmpvarssize *= 2;
4118  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
4119  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpscalars, tmpvarssize) );
4120  assert(nmultvars + ntmpvars <= tmpvarssize);
4121  }
4122 
4123  if( nmultvars > tmpvarssize2 )
4124  {
4125  while( nmultvars > tmpvarssize2 )
4126  tmpvarssize2 *= 2;
4127  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars2, tmpvarssize2) );
4128  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpscalars2, tmpvarssize2) );
4129  assert(nmultvars <= tmpvarssize2);
4130  }
4131 
4132  --nmultvars;
4133 
4134  for( ; nmultvars >= 0; --nmultvars )
4135  {
4136  multvar = multvars[nmultvars];
4137  multscalar = multscalars[nmultvars];
4138  multconstant = 0;
4139 
4140  assert(multvar != NULL);
4141  SCIP_CALL( SCIPvarGetProbvarSum(&multvar, set, &multscalar, &multconstant) );
4142  assert(multvar != NULL);
4143 
4144  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
4145  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
4148 
4149  if( !activeconstantinf )
4150  {
4151  assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
4152 
4153  if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) )
4154  {
4155  assert(scalar != 0.0);
4156  if( scalar * multconstant > 0.0 )
4157  {
4158  activeconstant = SCIPsetInfinity(set);
4159  activeconstantinf = TRUE;
4160  }
4161  else
4162  {
4163  activeconstant = -SCIPsetInfinity(set);
4164  activeconstantinf = TRUE;
4165  }
4166  }
4167  else
4168  activeconstant += scalar * multconstant;
4169  }
4170 #ifndef NDEBUG
4171  else
4172  {
4173  assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
4174  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4175  assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
4176  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4177  }
4178 #endif
4179 
4180  if( SCIPsortedvecFindPtr((void**)tmpvars, SCIPvarComp, multvar, ntmpvars, &pos) )
4181  {
4182  assert(SCIPvarCompare(tmpvars[pos], multvar) == 0);
4183  tmpscalars[pos] += scalar * multscalar;
4184  }
4185  else
4186  {
4187  tmpvars2[ntmpvars2] = multvar;
4188  tmpscalars2[ntmpvars2] = scalar * multscalar;
4189  ++(ntmpvars2);
4190  assert(ntmpvars2 <= tmpvarssize2);
4191  }
4192  }
4193 
4194  if( ntmpvars2 > 0 )
4195  {
4196  /* sort all variables to combine equal variables easily */
4197  SCIPsortPtrReal((void**)tmpvars2, tmpscalars2, SCIPvarComp, ntmpvars2);
4198  pos = 0;
4199  for( v = 1; v < ntmpvars2; ++v )
4200  {
4201  /* combine same variables */
4202  if( SCIPvarCompare(tmpvars2[v], tmpvars2[pos]) == 0 )
4203  {
4204  tmpscalars2[pos] += tmpscalars2[v];
4205  }
4206  else
4207  {
4208  ++pos;
4209  if( v > pos )
4210  {
4211  tmpscalars2[pos] = tmpscalars2[v];
4212  tmpvars2[pos] = tmpvars2[v];
4213  }
4214  }
4215  }
4216  ntmpvars2 = pos + 1;
4217 #ifdef SCIP_MORE_DEBUG
4218  for( v = 1; v < ntmpvars2; ++v )
4219  {
4220  assert(SCIPvarCompare(tmpvars2[v], tmpvars2[v-1]) > 0);
4221  }
4222  for( v = 1; v < ntmpvars; ++v )
4223  {
4224  assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
4225  }
4226 #endif
4227  v = ntmpvars - 1;
4228  k = ntmpvars2 - 1;
4229  pos = ntmpvars + ntmpvars2 - 1;
4230  ntmpvars += ntmpvars2;
4231 
4232  while( v >= 0 && k >= 0 )
4233  {
4234  assert(pos >= 0);
4235  assert(SCIPvarCompare(tmpvars[v], tmpvars2[k]) != 0);
4236  if( SCIPvarCompare(tmpvars[v], tmpvars2[k]) >= 0 )
4237  {
4238  tmpvars[pos] = tmpvars[v];
4239  tmpscalars[pos] = tmpscalars[v];
4240  --v;
4241  }
4242  else
4243  {
4244  tmpvars[pos] = tmpvars2[k];
4245  tmpscalars[pos] = tmpscalars2[k];
4246  --k;
4247  }
4248  --pos;
4249  assert(pos >= 0);
4250  }
4251  while( v >= 0 )
4252  {
4253  assert(pos >= 0);
4254  tmpvars[pos] = tmpvars[v];
4255  tmpscalars[pos] = tmpscalars[v];
4256  --v;
4257  --pos;
4258  }
4259  while( k >= 0 )
4260  {
4261  assert(pos >= 0);
4262  tmpvars[pos] = tmpvars2[k];
4263  tmpscalars[pos] = tmpscalars2[k];
4264  --k;
4265  --pos;
4266  }
4267  }
4268 #ifdef SCIP_MORE_DEBUG
4269  for( v = 1; v < ntmpvars; ++v )
4270  {
4271  assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
4272  }
4273 #endif
4274 
4275  if( !activeconstantinf )
4276  {
4277  assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
4278 
4279  multconstant = SCIPvarGetMultaggrConstant(var);
4280 
4281  if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) )
4282  {
4283  assert(scalar != 0.0);
4284  if( scalar * multconstant > 0.0 )
4285  {
4286  activeconstant = SCIPsetInfinity(set);
4287  activeconstantinf = TRUE;
4288  }
4289  else
4290  {
4291  activeconstant = -SCIPsetInfinity(set);
4292  activeconstantinf = TRUE;
4293  }
4294  }
4295  else
4296  activeconstant += scalar * multconstant;
4297  }
4298 #ifndef NDEBUG
4299  else
4300  {
4301  multconstant = SCIPvarGetMultaggrConstant(var);
4302  assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
4303  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4304  assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
4305  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4306  }
4307 #endif
4308  break;
4309 
4310  case SCIP_VARSTATUS_FIXED:
4314  default:
4315  /* case x = c, but actually we should not be here, since SCIPvarGetProbvarSum() returns a scalar of 0.0 for
4316  * fixed variables and is handled already
4317  */
4318  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED);
4319  assert(SCIPsetIsZero(set, var->glbdom.lb) && SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub));
4320  }
4321  }
4322 
4323  if( mergemultiples )
4324  {
4325  if( sortagain )
4326  {
4327  /* sort variable and scalar array by variable index */
4328  SCIPsortPtrReal((void**)activevars, activescalars, SCIPvarComp, nactivevars);
4329 
4330  /* eliminate duplicates and count required size */
4331  v = nactivevars - 1;
4332  while( v > 0 )
4333  {
4334  /* combine both variable since they are the same */
4335  if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
4336  {
4337  if( activescalars[v - 1] + activescalars[v] != 0.0 )
4338  {
4339  activescalars[v - 1] += activescalars[v];
4340  --nactivevars;
4341  activevars[v] = activevars[nactivevars];
4342  activescalars[v] = activescalars[nactivevars];
4343  }
4344  else
4345  {
4346  --nactivevars;
4347  activevars[v] = activevars[nactivevars];
4348  activescalars[v] = activescalars[nactivevars];
4349  --nactivevars;
4350  --v;
4351  activevars[v] = activevars[nactivevars];
4352  activescalars[v] = activescalars[nactivevars];
4353  }
4354  }
4355  --v;
4356  }
4357  }
4358  /* the variables were added in reverse order, we revert the order now;
4359  * this should not be necessary, but not doing this changes the behavior sometimes
4360  */
4361  else
4362  {
4363  SCIP_VAR* tmpvar;
4364  SCIP_Real tmpscalar;
4365 
4366  for( v = 0; v < nactivevars / 2; ++v )
4367  {
4368  tmpvar = activevars[v];
4369  tmpscalar = activescalars[v];
4370  activevars[v] = activevars[nactivevars - 1 - v];
4371  activescalars[v] = activescalars[nactivevars - 1 - v];
4372  activevars[nactivevars - 1 - v] = tmpvar;
4373  activescalars[nactivevars - 1 - v] = tmpscalar;
4374  }
4375  }
4376  }
4377  *requiredsize = nactivevars;
4378 
4379  if( varssize >= *requiredsize )
4380  {
4381  assert(vars != NULL);
4382 
4383  *nvars = *requiredsize;
4384 
4385  if( !SCIPsetIsInfinity(set, *constant) && !SCIPsetIsInfinity(set, -(*constant)) )
4386  {
4387  /* if the activeconstant is infinite, the constant pointer gets the same value, otherwise add the value */
4388  if( activeconstantinf )
4389  (*constant) = activeconstant;
4390  else
4391  (*constant) += activeconstant;
4392  }
4393 #ifndef NDEBUG
4394  else
4395  {
4396  assert(!SCIPsetIsInfinity(set, (*constant)) || !SCIPsetIsInfinity(set, -activeconstant));
4397  assert(!SCIPsetIsInfinity(set, -(*constant)) || !SCIPsetIsInfinity(set, activeconstant));
4398  }
4399 #endif
4400 
4401  /* copy active variable and scalar array to the given arrays */
4402  for( v = 0; v < *nvars; ++v )
4403  {
4404  vars[v] = activevars[v];
4405  scalars[v] = activescalars[v]; /*lint !e613*/
4406  }
4407  }
4408 
4409  assert(SCIPsetIsInfinity(set, *constant) == ((*constant) == SCIPsetInfinity(set))); /*lint !e777*/
4410  assert(SCIPsetIsInfinity(set, -(*constant)) == ((*constant) == -SCIPsetInfinity(set))); /*lint !e777*/
4411 
4412  SCIPsetFreeBufferArray(set, &tmpscalars);
4413  SCIPsetFreeBufferArray(set, &tmpvars);
4414  SCIPsetFreeBufferArray(set, &activescalars);
4415  SCIPsetFreeBufferArray(set, &activevars);
4416  SCIPsetFreeBufferArray(set, &tmpscalars2);
4417  SCIPsetFreeBufferArray(set, &tmpvars2);
4418 
4419  return SCIP_OKAY;
4420 }
4421 
4422 
4423 /** flattens aggregation graph of multi-aggregated variable in order to avoid exponential recursion later on */
4425  SCIP_VAR* var, /**< problem variable */
4426  BMS_BLKMEM* blkmem, /**< block memory */
4427  SCIP_SET* set, /**< global SCIP settings */
4428  SCIP_EVENTQUEUE* eventqueue /**< event queue */
4429  )
4430 {
4431  int nlocksup[NLOCKTYPES];
4432  int nlocksdown[NLOCKTYPES];
4433  SCIP_Real multconstant;
4434  int multvarssize;
4435  int nmultvars;
4436  int multrequiredsize;
4437  int i;
4438 
4439  assert( var != NULL );
4440  assert( SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR );
4441  assert(var->scip == set->scip);
4442 
4443  /* in order to update the locks on the active representation of the multi-aggregated variable, we remove all locks
4444  * on the current representation now and re-add the locks once the variable graph has been flattened, which
4445  * may lead to duplicate occurences of the same variable being merged
4446  *
4447  * Here is an example. Assume we have the multi-aggregation z = x + y.
4448  * z occures with positive coefficient in a <= constraint c1, so it has an uplock from there.
4449  * When the multi-aggregation is performed, all locks are added to the active representation,
4450  * so x and y both get an uplock from c1. However, z was not yet replaced by x + y in c1.
4451  * Next, a negation y = 1 - x is identified. Again, locks are moved, so that the uplock of y originating
4452  * from c1 is added to x as a downlock. Thus, x has both an up- and downlock from c1.
4453  * The multi-aggregation changes to z = x + 1 - x, which corresponds to the locks.
4454  * However, before z is replaced by that sum, SCIPvarFlattenAggregationGraph() is called
4455  * which changes z = x + y = x + 1 - x = 1, since it merges multiple occurences of the same variable.
4456  * The up- and downlock of x, however, is not removed when replacing z in c1 by its active representation,
4457  * because it is just 1 now. Therefore, we need to update locks when flattening the aggregation graph.
4458  * For this, the multi-aggregated variable knows its locks in addition to adding them to the active
4459  * representation, which corresponds to the locks from constraints where the variable was not replaced yet.
4460  * By removing the locks here, based on the old representation and adding them again after flattening,
4461  * we ensure that the locks are correct afterwards if coefficients were merged.
4462  */
4463  for( i = 0; i < NLOCKTYPES; ++i )
4464  {
4465  nlocksup[i] = var->nlocksup[i];
4466  nlocksdown[i] = var->nlocksdown[i];
4467 
4468  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, -nlocksdown[i], -nlocksup[i]) );
4469  }
4470 
4471  multconstant = var->data.multaggr.constant;
4472  nmultvars = var->data.multaggr.nvars;
4473  multvarssize = var->data.multaggr.varssize;
4474 
4475  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize, TRUE) );
4476 
4477  if( multrequiredsize > multvarssize )
4478  {
4479  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.vars), multvarssize, multrequiredsize) );
4480  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.scalars), multvarssize, multrequiredsize) );
4481  multvarssize = multrequiredsize;
4482  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize, TRUE) );
4483  assert( multrequiredsize <= multvarssize );
4484  }
4485  /**@note After the flattening the multi aggregation might resolve to be in fact an aggregation (or even a fixing?).
4486  * This issue is not resolved right now, since var->data.multaggr.nvars < 2 should not cause troubles. However, one
4487  * may loose performance hereby, since aggregated variables are easier to handle.
4488  *
4489  * Note, that there are two cases where SCIPvarFlattenAggregationGraph() is called: The easier one is that it is
4490  * called while installing the multi-aggregation. in principle, the described issue could be handled straightforward
4491  * in this case by aggregating or fixing the variable instead. The more complicated case is the one, when the
4492  * multi-aggregation is used, e.g., in linear presolving (and the variable is already declared to be multi-aggregated).
4493  *
4494  * By now, it is not allowed to fix or aggregate multi-aggregated variables which would be necessary in this case.
4495  *
4496  * The same issue appears in the SCIPvarGetProbvar...() methods.
4497  */
4498 
4499  var->data.multaggr.constant = multconstant;
4500  var->data.multaggr.nvars = nmultvars;
4501  var->data.multaggr.varssize = multvarssize;
4502 
4503  for( i = 0; i < NLOCKTYPES; ++i )
4504  {
4505  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
4506  }
4507 
4508  return SCIP_OKAY;
4509 }
4510 
4511 /** merge two variable histories together; a typical use case is that \p othervar is an image of the target variable
4512  * in a SCIP copy. Method should be applied with care, especially because no internal checks are performed whether
4513  * the history merge is reasonable
4514  *
4515  * @note Do not use this method if the two variables originate from two SCIP's with different objective functions, since
4516  * this corrupts the variable pseudo costs
4517  * @note Apply with care; no internal checks are performed if the two variables should be merged
4518  */
4520  SCIP_VAR* targetvar, /**< the variable that should contain both histories afterwards */
4521  SCIP_VAR* othervar, /**< the variable whose history is to be merged with that of the target variable */
4522  SCIP_STAT* stat /**< problem statistics */
4523  )
4524 {
4525  /* merge only the history of the current run into the target history */
4526  SCIPhistoryUnite(targetvar->history, othervar->historycrun, FALSE);
4527 
4528  /* apply the changes also to the global history */
4529  SCIPhistoryUnite(stat->glbhistory, othervar->historycrun, FALSE);
4530 }
4531 
4532 /** sets the history of a variable; this method is typically used within reoptimization to keep and update the variable
4533  * history over several iterations
4534  */
4535 void SCIPvarSetHistory(
4536  SCIP_VAR* var, /**< variable */
4537  SCIP_HISTORY* history, /**< the history which is to set */
4538  SCIP_STAT* stat /**< problem statistics */
4539  )
4540 {
4541  /* merge only the history of the current run into the target history */
4542  SCIPhistoryUnite(var->history, history, FALSE);
4543 
4544  /* apply the changes also to the global history */
4545  SCIPhistoryUnite(stat->glbhistory, history, FALSE);
4546 }
4547 
4548 /** tightens the bounds of both variables in aggregation x = a*y + c */
4549 static
4551  SCIP_VAR* var, /**< problem variable */
4552  BMS_BLKMEM* blkmem, /**< block memory */
4553  SCIP_SET* set, /**< global SCIP settings */
4554  SCIP_STAT* stat, /**< problem statistics */
4555  SCIP_PROB* transprob, /**< tranformed problem data */
4556  SCIP_PROB* origprob, /**< original problem data */
4557  SCIP_PRIMAL* primal, /**< primal data */
4558  SCIP_TREE* tree, /**< branch and bound tree */
4559  SCIP_REOPT* reopt, /**< reoptimization data structure */
4560  SCIP_LP* lp, /**< current LP data */
4561  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4562  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4563  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4564  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4565  SCIP_VAR* aggvar, /**< variable y in aggregation x = a*y + c */
4566  SCIP_Real scalar, /**< multiplier a in aggregation x = a*y + c */
4567  SCIP_Real constant, /**< constant shift c in aggregation x = a*y + c */
4568  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4569  SCIP_Bool* fixed /**< pointer to store whether the variables were fixed */
4570  )
4571 {
4572  SCIP_Real varlb;
4573  SCIP_Real varub;
4574  SCIP_Real aggvarlb;
4575  SCIP_Real aggvarub;
4576  SCIP_Bool aggvarbdschanged;
4577 
4578  assert(var != NULL);
4579  assert(var->scip == set->scip);
4580  assert(aggvar != NULL);
4581  assert(!SCIPsetIsZero(set, scalar));
4582  assert(infeasible != NULL);
4583  assert(fixed != NULL);
4584 
4585  *infeasible = FALSE;
4586  *fixed = FALSE;
4587 
4588  SCIPsetDebugMsg(set, "updating bounds of variables in aggregation <%s> == %g*<%s> %+g\n", var->name, scalar, aggvar->name, constant);
4589  SCIPsetDebugMsg(set, " old bounds: <%s> [%g,%g] <%s> [%g,%g]\n",
4590  var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
4591 
4592  /* loop as long additional changes may be found */
4593  do
4594  {
4595  aggvarbdschanged = FALSE;
4596 
4597  /* update the bounds of the aggregated variable x in x = a*y + c */
4598  if( scalar > 0.0 )
4599  {
4600  if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
4601  varlb = -SCIPsetInfinity(set);
4602  else
4603  varlb = aggvar->glbdom.lb * scalar + constant;
4604  if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
4605  varub = SCIPsetInfinity(set);
4606  else
4607  varub = aggvar->glbdom.ub * scalar + constant;
4608  }
4609  else
4610  {
4611  if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
4612  varub = SCIPsetInfinity(set);
4613  else
4614  varub = aggvar->glbdom.lb * scalar + constant;
4615  if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
4616  varlb = -SCIPsetInfinity(set);
4617  else
4618  varlb = aggvar->glbdom.ub * scalar + constant;
4619  }
4620  varlb = MAX(varlb, var->glbdom.lb);
4621  varub = MIN(varub, var->glbdom.ub);
4622  SCIPvarAdjustLb(var, set, &varlb);
4623  SCIPvarAdjustUb(var, set, &varub);
4624 
4625  /* check the new bounds */
4626  if( SCIPsetIsGT(set, varlb, varub) )
4627  {
4628  /* the aggregation is infeasible */
4629  *infeasible = TRUE;
4630  return SCIP_OKAY;
4631  }
4632  else if( SCIPsetIsEQ(set, varlb, varub) )
4633  {
4634  /* the aggregated variable is fixed -> fix both variables */
4635  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4636  eventfilter, eventqueue, cliquetable, varlb, infeasible, fixed) );
4637  if( !(*infeasible) )
4638  {
4639  SCIP_Bool aggfixed;
4640 
4641  SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4642  eventfilter, eventqueue, cliquetable, (varlb-constant)/scalar, infeasible, &aggfixed) );
4643  assert(*fixed == aggfixed);
4644  }
4645  return SCIP_OKAY;
4646  }
4647  else
4648  {
4649  if( SCIPsetIsGT(set, varlb, var->glbdom.lb) )
4650  {
4651  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, varlb) );
4652  }
4653  if( SCIPsetIsLT(set, varub, var->glbdom.ub) )
4654  {
4655  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, varub) );
4656  }
4657 
4658  /* update the hole list of the aggregation variable */
4659  /**@todo update hole list of aggregation variable */
4660  }
4661 
4662  /* update the bounds of the aggregation variable y in x = a*y + c -> y = (x-c)/a */
4663  if( scalar > 0.0 )
4664  {
4665  if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
4666  aggvarlb = -SCIPsetInfinity(set);
4667  else
4668  aggvarlb = (var->glbdom.lb - constant) / scalar;
4669  if( SCIPsetIsInfinity(set, var->glbdom.ub) )
4670  aggvarub = SCIPsetInfinity(set);
4671  else
4672  aggvarub = (var->glbdom.ub - constant) / scalar;
4673  }
4674  else
4675  {
4676  if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
4677  aggvarub = SCIPsetInfinity(set);
4678  else
4679  aggvarub = (var->glbdom.lb - constant) / scalar;
4680  if( SCIPsetIsInfinity(set, var->glbdom.ub) )
4681  aggvarlb = -SCIPsetInfinity(set);
4682  else
4683  aggvarlb = (var->glbdom.ub - constant) / scalar;
4684  }
4685  aggvarlb = MAX(aggvarlb, aggvar->glbdom.lb);
4686  aggvarub = MIN(aggvarub, aggvar->glbdom.ub);
4687  SCIPvarAdjustLb(aggvar, set, &aggvarlb);
4688  SCIPvarAdjustUb(aggvar, set, &aggvarub);
4689 
4690  /* check the new bounds */
4691  if( SCIPsetIsGT(set, aggvarlb, aggvarub) )
4692  {
4693  /* the aggregation is infeasible */
4694  *infeasible = TRUE;
4695  return SCIP_OKAY;
4696  }
4697  else if( SCIPsetIsEQ(set, aggvarlb, aggvarub) )
4698  {
4699  /* the aggregation variable is fixed -> fix both variables */
4700  SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4701  eventfilter, eventqueue, cliquetable, aggvarlb, infeasible, fixed) );
4702  if( !(*infeasible) )
4703  {
4704  SCIP_Bool varfixed;
4705 
4706  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4707  eventfilter, eventqueue, cliquetable, aggvarlb * scalar + constant, infeasible, &varfixed) );
4708  assert(*fixed == varfixed);
4709  }
4710  return SCIP_OKAY;
4711  }
4712  else
4713  {
4714  SCIP_Real oldbd;
4715  if( SCIPsetIsGT(set, aggvarlb, aggvar->glbdom.lb) )
4716  {
4717  oldbd = aggvar->glbdom.lb;
4718  SCIP_CALL( SCIPvarChgLbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, aggvarlb) );
4719  aggvarbdschanged = !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.lb);
4720  }
4721  if( SCIPsetIsLT(set, aggvarub, aggvar->glbdom.ub) )
4722  {
4723  oldbd = aggvar->glbdom.ub;
4724  SCIP_CALL( SCIPvarChgUbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, aggvarub) );
4725  aggvarbdschanged = aggvarbdschanged || !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.ub);
4726  }
4727 
4728  /* update the hole list of the aggregation variable */
4729  /**@todo update hole list of aggregation variable */
4730  }
4731  }
4732  while( aggvarbdschanged );
4733 
4734  SCIPsetDebugMsg(set, " new bounds: <%s> [%g,%g] <%s> [%g,%g]\n",
4735  var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
4736 
4737  return SCIP_OKAY;
4738 }
4739 
4740 /** converts loose variable into aggregated variable */
4742  SCIP_VAR* var, /**< loose problem variable */
4743  BMS_BLKMEM* blkmem, /**< block memory */
4744  SCIP_SET* set, /**< global SCIP settings */
4745  SCIP_STAT* stat, /**< problem statistics */
4746  SCIP_PROB* transprob, /**< tranformed problem data */
4747  SCIP_PROB* origprob, /**< original problem data */
4748  SCIP_PRIMAL* primal, /**< primal data */
4749  SCIP_TREE* tree, /**< branch and bound tree */
4750  SCIP_REOPT* reopt, /**< reoptimization data structure */
4751  SCIP_LP* lp, /**< current LP data */
4752  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4753  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4754  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4755  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4756  SCIP_VAR* aggvar, /**< loose variable y in aggregation x = a*y + c */
4757  SCIP_Real scalar, /**< multiplier a in aggregation x = a*y + c */
4758  SCIP_Real constant, /**< constant shift c in aggregation x = a*y + c */
4759  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4760  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
4761  )
4762 {
4763  SCIP_VAR** vars;
4764  SCIP_Real* coefs;
4765  SCIP_Real* constants;
4766  SCIP_Real obj;
4767  SCIP_Real branchfactor;
4768  SCIP_Bool fixed;
4769  int branchpriority;
4770  int nlocksdown[NLOCKTYPES];
4771  int nlocksup[NLOCKTYPES];
4772  int nvbds;
4773  int i;
4774  int j;
4775 
4776  assert(var != NULL);
4777  assert(aggvar != NULL);
4778  assert(var->scip == set->scip);
4779  assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
4780  assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
4781  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
4782  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
4783  assert(infeasible != NULL);
4784  assert(aggregated != NULL);
4785 
4786  *infeasible = FALSE;
4787  *aggregated = FALSE;
4788 
4789  /* get active problem variable of aggregation variable */
4790  SCIP_CALL( SCIPvarGetProbvarSum(&aggvar, set, &scalar, &constant) );
4791 
4792  /* aggregation is a fixing, if the scalar is zero */
4793  if( SCIPsetIsZero(set, scalar) )
4794  {
4795  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventfilter,
4796  eventqueue, cliquetable, constant, infeasible, aggregated) );
4797  goto TERMINATE;
4798  }
4799 
4800  /* don't perform the aggregation if the aggregation variable is multi-aggregated itself */
4801  if( SCIPvarGetStatus(aggvar) == SCIP_VARSTATUS_MULTAGGR )
4802  return SCIP_OKAY;
4803 
4804  /**@todo currently we don't perform the aggregation if the aggregation variable has a non-empty hole list; this
4805  * should be changed in the future
4806  */
4807  if( SCIPvarGetHolelistGlobal(var) != NULL )
4808  return SCIP_OKAY;
4809 
4810  /* if the variable is not allowed to be aggregated */
4811  if( SCIPvarDoNotAggr(var) )
4812  {
4813  SCIPsetDebugMsg(set, "variable is not allowed to be aggregated.\n");
4814  return SCIP_OKAY;
4815  }
4816 
4817  assert(aggvar->glbdom.lb == aggvar->locdom.lb); /*lint !e777*/
4818  assert(aggvar->glbdom.ub == aggvar->locdom.ub); /*lint !e777*/
4819  assert(SCIPvarGetStatus(aggvar) == SCIP_VARSTATUS_LOOSE);
4820 
4821  SCIPsetDebugMsg(set, "aggregate variable <%s>[%g,%g] == %g*<%s>[%g,%g] %+g\n", var->name, var->glbdom.lb, var->glbdom.ub,
4822  scalar, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub, constant);
4823 
4824  /* if variable and aggregation variable are equal, the variable can be fixed: x == a*x + c => x == c/(1-a) */
4825  if( var == aggvar )
4826  {
4827  if( SCIPsetIsEQ(set, scalar, 1.0) )
4828  *infeasible = !SCIPsetIsZero(set, constant);
4829  else
4830  {
4831  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4832  eventfilter, eventqueue, cliquetable, constant/(1.0-scalar), infeasible, aggregated) );
4833  }
4834  goto TERMINATE;
4835  }
4836 
4837  /* tighten the bounds of aggregated and aggregation variable */
4838  SCIP_CALL( varUpdateAggregationBounds(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
4839  branchcand, eventfilter, eventqueue, cliquetable, aggvar, scalar, constant, infeasible, &fixed) );
4840  if( *infeasible || fixed )
4841  {
4842  *aggregated = fixed;
4843  goto TERMINATE;
4844  }
4845 
4846  /* delete implications and variable bounds of the aggregated variable from other variables, but keep them in the
4847  * aggregated variable
4848  */
4849  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, FALSE) );
4850 
4851  /* set the aggregated variable's objective value to 0.0 */
4852  obj = var->obj;
4853  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
4854 
4855  /* unlock all locks */
4856  for( i = 0; i < NLOCKTYPES; i++ )
4857  {
4858  nlocksdown[i] = var->nlocksdown[i];
4859  nlocksup[i] = var->nlocksup[i];
4860 
4861  var->nlocksdown[i] = 0;
4862  var->nlocksup[i] = 0;
4863  }
4864 
4865  /* check, if variable should be used as NEGATED variable of the aggregation variable */
4866  if( SCIPvarIsBinary(var) && SCIPvarIsBinary(aggvar)
4867  && var->negatedvar == NULL && aggvar->negatedvar == NULL
4868  && SCIPsetIsEQ(set, scalar, -1.0) && SCIPsetIsEQ(set, constant, 1.0) )
4869  {
4870  /* link both variables as negation pair */
4871  var->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
4872  var->data.negate.constant = 1.0;
4873  var->negatedvar = aggvar;
4874  aggvar->negatedvar = var;
4875 
4876  /* copy donot(mult)aggr status */
4877  aggvar->donotaggr |= var->donotaggr;
4878  aggvar->donotmultaggr |= var->donotmultaggr;
4879 
4880  /* mark both variables to be non-deletable */
4882  SCIPvarMarkNotDeletable(aggvar);
4883  }
4884  else
4885  {
4886  /* convert variable into aggregated variable */
4887  var->varstatus = SCIP_VARSTATUS_AGGREGATED; /*lint !e641*/
4888  var->data.aggregate.var = aggvar;
4889  var->data.aggregate.scalar = scalar;
4890  var->data.aggregate.constant = constant;
4891 
4892  /* copy donot(mult)aggr status */
4893  aggvar->donotaggr |= var->donotaggr;
4894  aggvar->donotmultaggr |= var->donotmultaggr;
4895 
4896  /* mark both variables to be non-deletable */
4898  SCIPvarMarkNotDeletable(aggvar);
4899  }
4900 
4901  /* make aggregated variable a parent of the aggregation variable */
4902  SCIP_CALL( varAddParent(aggvar, blkmem, set, var) );
4903 
4904  /* relock the variable, thus increasing the locks of the aggregation variable */
4905  for( i = 0; i < NLOCKTYPES; i++ )
4906  {
4907  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
4908  }
4909 
4910  /* move the variable bounds to the aggregation variable:
4911  * - add all variable bounds again to the variable, thus adding it to the aggregation variable
4912  * - free the variable bounds data structures
4913  */
4914  if( var->vlbs != NULL )
4915  {
4916  nvbds = SCIPvboundsGetNVbds(var->vlbs);
4917  vars = SCIPvboundsGetVars(var->vlbs);
4918  coefs = SCIPvboundsGetCoefs(var->vlbs);
4919  constants = SCIPvboundsGetConstants(var->vlbs);
4920  for( i = 0; i < nvbds && !(*infeasible); ++i )
4921  {
4922  SCIP_CALL( SCIPvarAddVlb(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
4923  eventqueue, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
4924  }
4925  }
4926  if( var->vubs != NULL )
4927  {
4928  nvbds = SCIPvboundsGetNVbds(var->vubs);
4929  vars = SCIPvboundsGetVars(var->vubs);
4930  coefs = SCIPvboundsGetCoefs(var->vubs);
4931  constants = SCIPvboundsGetConstants(var->vubs);
4932  for( i = 0; i < nvbds && !(*infeasible); ++i )
4933  {
4934  SCIP_CALL( SCIPvarAddVub(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
4935  eventqueue, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
4936  }
4937  }
4938  SCIPvboundsFree(&var->vlbs, blkmem);
4939  SCIPvboundsFree(&var->vubs, blkmem);
4940 
4941  /* move the implications to the aggregation variable:
4942  * - add all implications again to the variable, thus adding it to the aggregation variable
4943  * - free the implications data structures
4944  */
4945  if( var->implics != NULL && SCIPvarGetType(aggvar) == SCIP_VARTYPE_BINARY )
4946  {
4947  assert(SCIPvarIsBinary(var));
4948  for( i = 0; i < 2; ++i )
4949  {
4950  SCIP_VAR** implvars;
4951  SCIP_BOUNDTYPE* impltypes;
4952  SCIP_Real* implbounds;
4953  int nimpls;
4954 
4955  nimpls = SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i);
4956  implvars = SCIPimplicsGetVars(var->implics, (SCIP_Bool)i);
4957  impltypes = SCIPimplicsGetTypes(var->implics, (SCIP_Bool)i);
4958  implbounds = SCIPimplicsGetBounds(var->implics, (SCIP_Bool)i);
4959 
4960  for( j = 0; j < nimpls && !(*infeasible); ++j )
4961  {
4962  /* @todo can't we omit transitive closure, because it should already have been done when adding the
4963  * implication to the aggregated variable?
4964  */
4965  SCIP_CALL( SCIPvarAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
4966  branchcand, eventqueue, (SCIP_Bool)i, implvars[j], impltypes[j], implbounds[j], FALSE, infeasible,
4967  NULL) );
4968  assert(nimpls == SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i));
4969  }
4970  }
4971  }
4972  SCIPimplicsFree(&var->implics, blkmem);
4973 
4974  /* add the history entries to the aggregation variable and clear the history of the aggregated variable */
4975  SCIPhistoryUnite(aggvar->history, var->history, scalar < 0.0);
4976  SCIPhistoryUnite(aggvar->historycrun, var->historycrun, scalar < 0.0);
4977  SCIPhistoryReset(var->history);
4979 
4980  /* update flags of aggregation variable */
4981  aggvar->removable &= var->removable;
4982 
4983  /* update branching factors and priorities of both variables to be the maximum of both variables */
4984  branchfactor = MAX(aggvar->branchfactor, var->branchfactor);
4985  branchpriority = MAX(aggvar->branchpriority, var->branchpriority);
4986  SCIP_CALL( SCIPvarChgBranchFactor(aggvar, set, branchfactor) );
4987  SCIP_CALL( SCIPvarChgBranchPriority(aggvar, branchpriority) );
4988  SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
4989  SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
4990 
4991  /* update branching direction of both variables to agree to a single direction */
4992  if( scalar >= 0.0 )
4993  {
4995  {
4997  }
4998  else if( (SCIP_BRANCHDIR)aggvar->branchdirection == SCIP_BRANCHDIR_AUTO )
4999  {
5001  }
5002  else if( var->branchdirection != aggvar->branchdirection )
5003  {
5005  }
5006  }
5007  else
5008  {
5010  {
5012  }
5013  else if( (SCIP_BRANCHDIR)aggvar->branchdirection == SCIP_BRANCHDIR_AUTO )
5014  {
5016  }
5017  else if( var->branchdirection != aggvar->branchdirection )
5018  {
5020  }
5021  }
5022 
5023  if( var->probindex != -1 )
5024  {
5025  /* inform problem about the variable's status change */
5026  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
5027  }
5028 
5029  /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
5030  * variable and the problem's objective offset
5031  */
5032  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventfilter, eventqueue, obj) );
5033 
5034  /* issue VARFIXED event */
5035  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 1) );
5036 
5037  *aggregated = TRUE;
5038 
5039 TERMINATE:
5040  /* check aggregation on debugging solution */
5041  if( *infeasible || *aggregated )
5042  SCIP_CALL( SCIPdebugCheckAggregation(set, var, &aggvar, &scalar, constant, 1) ); /*lint !e506 !e774*/
5043 
5044  return SCIP_OKAY;
5045 }
5046 
5047 /** Tries to aggregate an equality a*x + b*y == c consisting of two (implicit) integral active problem variables x and
5048  * y. An integer aggregation (i.e. integral coefficients a' and b', such that a'*x + b'*y == c') is searched.
5049  *
5050  * This can lead to the detection of infeasibility (e.g. if c' is fractional), or to a rejection of the aggregation
5051  * (denoted by aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
5052  */
5053 static
5055  SCIP_SET* set, /**< global SCIP settings */
5056  BMS_BLKMEM* blkmem, /**< block memory */
5057  SCIP_STAT* stat, /**< problem statistics */
5058  SCIP_PROB* transprob, /**< tranformed problem data */
5059  SCIP_PROB* origprob, /**< original problem data */
5060  SCIP_PRIMAL* primal, /**< primal data */
5061  SCIP_TREE* tree, /**< branch and bound tree */
5062  SCIP_REOPT* reopt, /**< reoptimization data structure */
5063  SCIP_LP* lp, /**< current LP data */
5064  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5065  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5066  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
5067  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5068  SCIP_VAR* varx, /**< integral variable x in equality a*x + b*y == c */
5069  SCIP_VAR* vary, /**< integral variable y in equality a*x + b*y == c */
5070  SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
5071  SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
5072  SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
5073  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
5074  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
5075  )
5076 {
5077  SCIP_VAR* aggvar;
5078  char aggvarname[SCIP_MAXSTRLEN];
5079  SCIP_Longint scalarxn = 0;
5080  SCIP_Longint scalarxd = 0;
5081  SCIP_Longint scalaryn = 0;
5082  SCIP_Longint scalaryd = 0;
5083  SCIP_Longint a;
5084  SCIP_Longint b;
5085  SCIP_Longint c;
5086  SCIP_Longint scm;
5087  SCIP_Longint gcd;
5088  SCIP_Longint currentclass;
5089  SCIP_Longint classstep;
5090  SCIP_Longint xsol;
5091  SCIP_Longint ysol;
5092  SCIP_Bool success;
5093  SCIP_VARTYPE vartype;
5094 
5095 #define MAXDNOM 1000000LL
5096 
5097  assert(set != NULL);
5098  assert(blkmem != NULL);
5099  assert(stat != NULL);
5100  assert(transprob != NULL);
5101  assert(origprob != NULL);
5102  assert(tree != NULL);
5103  assert(lp != NULL);
5104  assert(cliquetable != NULL);
5105  assert(branchcand != NULL);
5106  assert(eventqueue != NULL);
5107  assert(varx != NULL);
5108  assert(vary != NULL);
5109  assert(varx != vary);
5110  assert(infeasible != NULL);
5111  assert(aggregated != NULL);
5112  assert(SCIPsetGetStage(set) == SCIP_STAGE_PRESOLVING);
5113  assert(SCIPvarGetStatus(varx) == SCIP_VARSTATUS_LOOSE);
5115  assert(SCIPvarGetStatus(vary) == SCIP_VARSTATUS_LOOSE);
5117  assert(!SCIPsetIsZero(set, scalarx));
5118  assert(!SCIPsetIsZero(set, scalary));
5119 
5120  *infeasible = FALSE;
5121  *aggregated = FALSE;
5122 
5123  /* if the variable is not allowed to be aggregated */
5124  if( SCIPvarDoNotAggr(varx) )
5125  {
5126  SCIPsetDebugMsg(set, "variable is not allowed to be aggregated.\n");
5127  return SCIP_OKAY;
5128  }
5129 
5130  /* get rational representation of coefficients */
5131  success = SCIPrealToRational(scalarx, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalarxn, &scalarxd);
5132  if( success )
5133  success = SCIPrealToRational(scalary, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalaryn, &scalaryd);
5134  if( !success )
5135  return SCIP_OKAY;
5136  assert(scalarxd >= 1);
5137  assert(scalaryd >= 1);
5138 
5139  /* multiply equality with smallest common denominator */
5140  scm = SCIPcalcSmaComMul(scalarxd, scalaryd);
5141  a = (scm/scalarxd)*scalarxn;
5142  b = (scm/scalaryd)*scalaryn;
5143  rhs *= scm;
5144 
5145  /* divide equality by the greatest common divisor of a and b */
5146  gcd = SCIPcalcGreComDiv(ABS(a), ABS(b));
5147  a /= gcd;
5148  b /= gcd;
5149  rhs /= gcd;
5150  assert(a != 0);
5151  assert(b != 0);
5152 
5153  /* check, if right hand side is integral */
5154  if( !SCIPsetIsFeasIntegral(set, rhs) )
5155  {
5156  *infeasible = TRUE;
5157  return SCIP_OKAY;
5158  }
5159  c = (SCIP_Longint)(SCIPsetFeasFloor(set, rhs));
5160 
5161  /* check that the scalar and constant in the aggregation are not too large to avoid numerical problems */
5162  if( REALABS((SCIP_Real)(c/a)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) /*lint !e653*/
5163  || REALABS((SCIP_Real)(b)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) /*lint !e653*/
5164  || REALABS((SCIP_Real)(a)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
5165  {
5166  return SCIP_OKAY;
5167  }
5168 
5169  /* check, if we are in an easy case with either |a| = 1 or |b| = 1 */
5170  if( (a == 1 || a == -1) && SCIPvarGetType(vary) == SCIP_VARTYPE_INTEGER )
5171  {
5172  /* aggregate x = - b/a*y + c/a */
5173  /*lint --e{653}*/
5174  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5175  branchcand, eventfilter, eventqueue, vary, (SCIP_Real)(-b/a), (SCIP_Real)(c/a), infeasible, aggregated) );
5176  assert(*aggregated);
5177  return SCIP_OKAY;
5178  }
5179  if( (b == 1 || b == -1) && SCIPvarGetType(varx) == SCIP_VARTYPE_INTEGER )
5180  {
5181  /* aggregate y = - a/b*x + c/b */
5182  /*lint --e{653}*/
5183  SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5184  branchcand, eventfilter, eventqueue, varx, (SCIP_Real)(-a/b), (SCIP_Real)(c/b), infeasible, aggregated) );
5185  assert(*aggregated);
5186  return SCIP_OKAY;
5187  }
5188 
5189  /* Both variables are integers, their coefficients are not multiples of each other, and they don't have any
5190  * common divisor. Let (x',y') be a solution of the equality
5191  * a*x + b*y == c -> a*x == c - b*y
5192  * Then x = -b*z + x', y = a*z + y' with z integral gives all solutions to the equality.
5193  */
5194 
5195  /* find initial solution (x',y'):
5196  * - find y' such that c - b*y' is a multiple of a
5197  * - start in equivalence class c%a
5198  * - step through classes, where each step increases class number by (-b)%a, until class 0 is visited
5199  * - if equivalence class 0 is visited, we are done: y' equals the number of steps taken
5200  * - 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
5201  * - calculate x' with x' = (c - b*y')/a (which must be integral)
5202  *
5203  * Algorithm works for a > 0 only.
5204  */
5205  if( a < 0 )
5206  {
5207  a = -a;
5208  b = -b;
5209  c = -c;
5210  }
5211  assert(a > 0);
5212 
5213  /* search upwards from ysol = 0 */
5214  ysol = 0;
5215  currentclass = c % a;
5216  if( currentclass < 0 )
5217  currentclass += a;
5218  assert(0 <= currentclass && currentclass < a);
5219 
5220  classstep = (-b) % a;
5221 
5222  if( classstep < 0 )
5223  classstep += a;
5224  assert(0 <= classstep && classstep < a);
5225 
5226  while( currentclass != 0 )
5227  {
5228  assert(0 <= currentclass && currentclass < a);
5229  currentclass += classstep;
5230  if( currentclass >= a )
5231  currentclass -= a;
5232  ysol++;
5233  }
5234  assert(ysol < a);
5235  assert(((c - b*ysol) % a) == 0);
5236 
5237  xsol = (c - b*ysol)/a;
5238 
5239  /* determine variable type for new artificial variable:
5240  *
5241  * if both variables are implicit integer the new variable can be implicit too, because the integer implication on
5242  * these both variables should be enforced by some other variables, otherwise the new variable needs to be of
5243  * integral type
5244  */
5247 
5248  /* feasible solutions are (x,y) = (x',y') + z*(-b,a)
5249  * - create new integer variable z with infinite bounds
5250  * - aggregate variable x = -b*z + x'
5251  * - aggregate variable y = a*z + y'
5252  * - the bounds of z are calculated automatically during aggregation
5253  */
5254  (void) SCIPsnprintf(aggvarname, SCIP_MAXSTRLEN, "agg%d", stat->nvaridx);
5255  SCIP_CALL( SCIPvarCreateTransformed(&aggvar, blkmem, set, stat,
5256  aggvarname, -SCIPsetInfinity(set), SCIPsetInfinity(set), 0.0, vartype,
5258  NULL, NULL, NULL, NULL, NULL) );
5259 
5260  SCIP_CALL( SCIPprobAddVar(transprob, blkmem, set, lp, branchcand, eventfilter, eventqueue, aggvar) );
5261 
5262  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5263  branchcand, eventfilter, eventqueue, aggvar, (SCIP_Real)(-b), (SCIP_Real)xsol, infeasible, aggregated) );
5264  assert(*aggregated || *infeasible);
5265 
5266  if( !(*infeasible) )
5267  {
5268  SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5269  branchcand, eventfilter, eventqueue, aggvar, (SCIP_Real)a, (SCIP_Real)ysol, infeasible, aggregated) );
5270  assert(*aggregated || *infeasible);
5271  }
5272 
5273  /* release z */
5274  SCIP_CALL( SCIPvarRelease(&aggvar, blkmem, set, eventqueue, lp) );
5275 
5276  return SCIP_OKAY; /*lint !e438*/
5277 }
5278 
5279 /** performs second step of SCIPaggregateVars():
5280  * the variable to be aggregated is chosen among active problem variables x' and y', preferring a less strict variable
5281  * type as aggregation variable (i.e. continuous variables are preferred over implicit integers, implicit integers
5282  * or integers over binaries). If none of the variables is continuous, it is tried to find an integer
5283  * aggregation (i.e. integral coefficients a'' and b'', such that a''*x' + b''*y' == c''). This can lead to
5284  * the detection of infeasibility (e.g. if c'' is fractional), or to a rejection of the aggregation (denoted by
5285  * aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
5286  *
5287  * @todo check for fixings, infeasibility, bound changes, or domain holes:
5288  * a) if there is no easy aggregation and we have one binary variable and another integer/implicit/binary variable
5289  * b) for implicit integer variables with fractional aggregation scalar (we cannot (for technical reasons) and do
5290  * not want to aggregate implicit integer variables, since we loose the corresponding divisibility property)
5291  */
5293  SCIP_SET* set, /**< global SCIP settings */
5294  BMS_BLKMEM* blkmem, /**< block memory */
5295  SCIP_STAT* stat, /**< problem statistics */
5296  SCIP_PROB* transprob, /**< tranformed problem data */
5297  SCIP_PROB* origprob, /**< original problem data */
5298  SCIP_PRIMAL* primal, /**< primal data */
5299  SCIP_TREE* tree, /**< branch and bound tree */
5300  SCIP_REOPT* reopt, /**< reoptimization data structure */
5301  SCIP_LP* lp, /**< current LP data */
5302  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5303  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5304  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
5305  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5306  SCIP_VAR* varx, /**< variable x in equality a*x + b*y == c */
5307  SCIP_VAR* vary, /**< variable y in equality a*x + b*y == c */
5308  SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
5309  SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
5310  SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
5311  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
5312  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
5313  )
5314 {
5315  SCIP_Bool easyaggr;
5316 
5317  assert(set != NULL);
5318  assert(blkmem != NULL);
5319  assert(stat != NULL);
5320  assert(transprob != NULL);
5321  assert(origprob != NULL);
5322  assert(tree != NULL);
5323  assert(lp != NULL);
5324  assert(cliquetable != NULL);
5325  assert(branchcand != NULL);
5326  assert(eventqueue != NULL);
5327  assert(varx != NULL);
5328  assert(vary != NULL);
5329  assert(varx != vary);
5330  assert(infeasible != NULL);
5331  assert(aggregated != NULL);
5332  assert(SCIPsetGetStage(set) == SCIP_STAGE_PRESOLVING);
5333  assert(SCIPvarGetStatus(varx) == SCIP_VARSTATUS_LOOSE);
5334  assert(SCIPvarGetStatus(vary) == SCIP_VARSTATUS_LOOSE);
5335  assert(!SCIPsetIsZero(set, scalarx));
5336  assert(!SCIPsetIsZero(set, scalary));
5337 
5338  *infeasible = FALSE;
5339  *aggregated = FALSE;
5340 
5341  if( SCIPsetIsZero(set, scalarx / scalary) || SCIPsetIsZero(set, scalary / scalarx) )
5342  return SCIP_OKAY;
5343 
5344  /* prefer aggregating the variable of more general type (preferred aggregation variable is varx) */
5345  if( SCIPvarGetType(vary) > SCIPvarGetType(varx) ||
5346  (SCIPvarGetType(vary) == SCIPvarGetType(varx) && !SCIPvarIsBinary(vary) && SCIPvarIsBinary(varx)) )
5347  {
5348  SCIP_VAR* var;
5349  SCIP_Real scalar;
5350 
5351  /* switch the variables, such that varx is the variable of more general type (cont > implint > int > bin) */
5352  var = vary;
5353  vary = varx;
5354  varx = var;
5355  scalar = scalary;
5356  scalary = scalarx;
5357  scalarx = scalar;
5358  }
5359 
5360  /* don't aggregate if the aggregation would lead to a binary variable aggregated to a non-binary variable */
5361  if( SCIPvarIsBinary(varx) && !SCIPvarIsBinary(vary) )
5362  return SCIP_OKAY;
5363 
5364  assert(SCIPvarGetType(varx) >= SCIPvarGetType(vary));
5365 
5366  /* figure out, which variable should be aggregated */
5367  easyaggr = FALSE;
5368 
5369  /* check if it is an easy aggregation */
5371  {
5372  easyaggr = TRUE;
5373  }
5374  else if( SCIPsetIsFeasIntegral(set, scalary/scalarx) )
5375  {
5376  easyaggr = TRUE;
5377  }
5378  else if( SCIPsetIsFeasIntegral(set, scalarx/scalary) && SCIPvarGetType(vary) == SCIPvarGetType(varx) )
5379  {
5380  /* we have an easy aggregation if we flip the variables x and y */
5381  SCIP_VAR* var;
5382  SCIP_Real scalar;
5383 
5384  /* switch the variables, such that varx is the aggregated variable */
5385  var = vary;
5386  vary = varx;
5387  varx = var;
5388  scalar = scalary;
5389  scalary = scalarx;
5390  scalarx = scalar;
5391  easyaggr = TRUE;
5392  }
5393  else if( SCIPvarGetType(varx) == SCIP_VARTYPE_CONTINUOUS )
5394  {
5395  /* the aggregation is still easy if both variables are continuous */
5396  assert(SCIPvarGetType(vary) == SCIP_VARTYPE_CONTINUOUS); /* otherwise we are in the first case */
5397  easyaggr = TRUE;
5398  }
5399 
5400  /* did we find an "easy" aggregation? */
5401  if( easyaggr )
5402  {
5403  SCIP_Real scalar;
5404  SCIP_Real constant;
5405 
5406  assert(SCIPvarGetType(varx) >= SCIPvarGetType(vary));
5407 
5408  /* calculate aggregation scalar and constant: a*x + b*y == c => x == -b/a * y + c/a */
5409  scalar = -scalary/scalarx;
5410  constant = rhs/scalarx;
5411 
5412  if( REALABS(constant) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
5413  return SCIP_OKAY;
5414 
5415  /* check aggregation for integer feasibility */
5418  && SCIPsetIsFeasIntegral(set, scalar) && !SCIPsetIsFeasIntegral(set, constant) )
5419  {
5420  *infeasible = TRUE;
5421  return SCIP_OKAY;
5422  }
5423 
5424  /* if the aggregation scalar is fractional, we cannot (for technical reasons) and do not want to aggregate implicit integer variables,
5425  * since then we would loose the corresponding divisibility property
5426  */
5427  assert(SCIPvarGetType(varx) != SCIP_VARTYPE_IMPLINT || SCIPsetIsFeasIntegral(set, scalar));
5428 
5429  /* aggregate the variable */
5430  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5431  branchcand, eventfilter, eventqueue, vary, scalar, constant, infeasible, aggregated) );
5432  assert(*aggregated || *infeasible || SCIPvarDoNotAggr(varx));
5433  }
5436  {
5437  /* the variables are both integral: we have to try to find an integer aggregation */
5438  SCIP_CALL( tryAggregateIntVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5439  branchcand, eventfilter, eventqueue, varx, vary, scalarx, scalary, rhs, infeasible, aggregated) );
5440  }
5441 
5442  return SCIP_OKAY;
5443 }
5444 
5445 /** converts variable into multi-aggregated variable */
5447  SCIP_VAR* var, /**< problem variable */
5448  BMS_BLKMEM* blkmem, /**< block memory */
5449  SCIP_SET* set, /**< global SCIP settings */
5450  SCIP_STAT* stat, /**< problem statistics */
5451  SCIP_PROB* transprob, /**< tranformed problem data */
5452  SCIP_PROB* origprob, /**< original problem data */
5453  SCIP_PRIMAL* primal, /**< primal data */
5454  SCIP_TREE* tree, /**< branch and bound tree */
5455  SCIP_REOPT* reopt, /**< reoptimization data structure */
5456  SCIP_LP* lp, /**< current LP data */
5457  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5458  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5459  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
5460  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5461  int naggvars, /**< number n of variables in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5462  SCIP_VAR** aggvars, /**< variables y_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5463  SCIP_Real* scalars, /**< multipliers a_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5464  SCIP_Real constant, /**< constant shift c in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5465  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
5466  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
5467  )
5468 {
5469  SCIP_VAR** tmpvars;
5470  SCIP_Real* tmpscalars;
5471  SCIP_Real obj;
5472  SCIP_Real branchfactor;
5473  int branchpriority;
5474  SCIP_BRANCHDIR branchdirection;
5475  int nlocksdown[NLOCKTYPES];
5476  int nlocksup[NLOCKTYPES];
5477  int v;
5478  SCIP_Real tmpconstant;
5479  SCIP_Real tmpscalar;
5480  int ntmpvars;
5481  int tmpvarssize;
5482  int tmprequiredsize;
5483  int i;
5484 
5485  assert(var != NULL);
5486  assert(var->scip == set->scip);
5487  assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
5488  assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
5489  assert(naggvars == 0 || aggvars != NULL);
5490  assert(naggvars == 0 || scalars != NULL);
5491  assert(infeasible != NULL);
5492  assert(aggregated != NULL);
5493 
5494  SCIPsetDebugMsg(set, "trying multi-aggregating variable <%s> == ...%d vars... %+g\n", var->name, naggvars, constant);
5495 
5496  *infeasible = FALSE;
5497  *aggregated = FALSE;
5498 
5499  switch( SCIPvarGetStatus(var) )
5500  {
5502  if( var->data.original.transvar == NULL )
5503  {
5504  SCIPerrorMessage("cannot multi-aggregate an untransformed original variable\n");
5505  return SCIP_INVALIDDATA;
5506  }
5507  SCIP_CALL( SCIPvarMultiaggregate(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
5508  reopt, lp, cliquetable, branchcand, eventfilter, eventqueue, naggvars, aggvars, scalars, constant, infeasible, aggregated) );
5509  break;
5510 
5511  case SCIP_VARSTATUS_LOOSE:
5512  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
5513 
5514  /* check if we would create a self-reference */
5515  ntmpvars = naggvars;
5516  tmpvarssize = naggvars;
5517  tmpconstant = constant;
5518  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpvars, aggvars, ntmpvars) );
5519  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpscalars, scalars, ntmpvars) );
5520 
5521  /* get all active variables for multi-aggregation */
5522  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize, FALSE) );
5523  if( tmprequiredsize > tmpvarssize )
5524  {
5525  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpvars, tmpvarssize, tmprequiredsize) );
5526  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize, tmprequiredsize) );
5527  tmpvarssize = tmprequiredsize;
5528  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize, FALSE) );
5529  assert( tmprequiredsize <= tmpvarssize );
5530  }
5531 
5532  tmpscalar = 0.0;
5533 
5534  /* iterate over all active variables of the multi-aggregation and filter all variables which are equal to the
5535  * possible multi-aggregated variable
5536  */
5537  for( v = ntmpvars - 1; v >= 0; --v )
5538  {
5539  assert(tmpvars[v] != NULL);
5540  assert(SCIPvarGetStatus(tmpvars[v]) == SCIP_VARSTATUS_LOOSE);
5541 
5542  if( tmpvars[v]->index == var->index )
5543  {
5544  tmpscalar += tmpscalars[v];
5545  tmpvars[v] = tmpvars[ntmpvars - 1];
5546  tmpscalars[v] = tmpscalars[ntmpvars - 1];
5547  --ntmpvars;
5548  }
5549  }
5550 
5551  /* this means that x = x + a_1*y_1 + ... + a_n*y_n + c */
5552  if( SCIPsetIsEQ(set, tmpscalar, 1.0) )
5553  {
5554  if( ntmpvars == 0 )
5555  {
5556  if( SCIPsetIsZero(set, tmpconstant) ) /* x = x */
5557  {
5558  SCIPsetDebugMsg(set, "Possible multi-aggregation was completely resolved and detected to be redundant.\n");
5559  goto TERMINATE;
5560  }
5561  else /* 0 = c and c != 0 */
5562  {
5563  SCIPsetDebugMsg(set, "Multi-aggregation was completely resolved and led to infeasibility.\n");
5564  *infeasible = TRUE;
5565  goto TERMINATE;
5566  }
5567  }
5568  else if( ntmpvars == 1 ) /* 0 = a*y + c => y = -c/a */
5569  {
5570  assert(tmpscalars[0] != 0.0);
5571  assert(tmpvars[0] != NULL);
5572 
5573  SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(tmpvars[0]), -constant/tmpscalars[0]);
5574  SCIP_CALL( SCIPvarFix(tmpvars[0], blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5575  branchcand, eventfilter, eventqueue, cliquetable, -constant/tmpscalars[0], infeasible, aggregated) );
5576  goto TERMINATE;
5577  }
5578  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 */
5579  {
5580  /* both variables are different active problem variables, and both scalars are non-zero: try to aggregate them */
5581  SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
5582  SCIPvarGetName(tmpvars[0]), SCIPvarGetName(tmpvars[1]), tmpscalars[0], tmpscalars[1], -tmpconstant);
5583 
5584  SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
5585  cliquetable, branchcand, eventfilter, eventqueue, tmpvars[0], tmpvars[1], tmpscalars[0],
5586  tmpscalars[1], -tmpconstant, infeasible, aggregated) );
5587 
5588  goto TERMINATE;
5589  }
5590  else
5591  /* @todo: it is possible to multi-aggregate another variable, does it make sense?,
5592  * rest looks like 0 = a_1*y_1 + ... + a_n*y_n + c and has at least three variables
5593  */
5594  goto TERMINATE;
5595  }
5596  /* this means that x = b*x + a_1*y_1 + ... + a_n*y_n + c */
5597  else if( !SCIPsetIsZero(set, tmpscalar) )
5598  {
5599  tmpscalar = 1 - tmpscalar;
5600  tmpconstant /= tmpscalar;
5601  for( v = ntmpvars - 1; v >= 0; --v )
5602  tmpscalars[v] /= tmpscalar;
5603  }
5604 
5605  /* check, if we are in one of the simple cases */
5606  if( ntmpvars == 0 )
5607  {
5608  SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(var), tmpconstant);
5609  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
5610  eventfilter, eventqueue, cliquetable, tmpconstant, infeasible, aggregated) );
5611  goto TERMINATE;
5612  }
5613 
5614  /* if only one aggregation variable is left, we perform a normal aggregation instead of a multi-aggregation */
5615  if( ntmpvars == 1 )
5616  {
5617  SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
5618  SCIPvarGetName(var), SCIPvarGetName(tmpvars[0]), 1.0, -tmpscalars[0], tmpconstant);
5619 
5620  SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
5621  cliquetable, branchcand, eventfilter, eventqueue, var, tmpvars[0], 1.0, -tmpscalars[0], tmpconstant,
5622  infeasible, aggregated) );
5623 
5624  goto TERMINATE;
5625  }
5626 
5627  /**@todo currently we don't perform the multi aggregation if the multi aggregation variable has a non
5628  * empty hole list; this should be changed in the future */
5629  if( SCIPvarGetHolelistGlobal(var) != NULL )
5630  goto TERMINATE;
5631 
5632  /* if the variable is not allowed to be multi-aggregated */
5633  if( SCIPvarDoNotMultaggr(var) )
5634  {
5635  SCIPsetDebugMsg(set, "variable is not allowed to be multi-aggregated.\n");
5636  goto TERMINATE;
5637  }
5638 
5639  /* if the variable to be multi-aggregated has implications or variable bounds (i.e. is the implied variable or
5640  * variable bound variable of another variable), we have to remove it from the other variables implications or
5641  * variable bounds
5642  */
5643  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
5644  assert(var->vlbs == NULL);
5645  assert(var->vubs == NULL);
5646  assert(var->implics == NULL);
5647 
5648  /* set the aggregated variable's objective value to 0.0 */
5649  obj = var->obj;
5650  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
5651 
5652  /* since we change the variable type form loose to multi aggregated, we have to adjust the number of loose
5653  * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
5654  * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
5655  * objective of this variable is set to zero
5656  */
5657  SCIPlpDecNLoosevars(lp);
5658 
5659  /* unlock all rounding locks */
5660  for( i = 0; i < NLOCKTYPES; i++ )
5661  {
5662  nlocksdown[i] = var->nlocksdown[i];
5663  nlocksup[i] = var->nlocksup[i];
5664 
5665  var->nlocksdown[i] = 0;
5666  var->nlocksup[i] = 0;
5667  }
5668 
5669  /* convert variable into multi-aggregated variable */
5670  var->varstatus = SCIP_VARSTATUS_MULTAGGR; /*lint !e641*/
5671  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.vars, tmpvars, ntmpvars) );
5672  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.scalars, tmpscalars, ntmpvars) );
5673  var->data.multaggr.constant = tmpconstant;
5674  var->data.multaggr.nvars = ntmpvars;
5675  var->data.multaggr.varssize = ntmpvars;
5676 
5677  /* mark variable to be non-deletable */
5679 
5680  /* relock the variable, thus increasing the locks of the aggregation variables */
5681  for( i = 0; i < NLOCKTYPES; i++ )
5682  {
5683  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
5684  }
5685 
5686  /* update flags and branching factors and priorities of aggregation variables;
5687  * update preferred branching direction of all aggregation variables that don't have a preferred direction yet
5688  */
5689  branchfactor = var->branchfactor;
5690  branchpriority = var->branchpriority;
5691  branchdirection = (SCIP_BRANCHDIR)var->branchdirection;
5692 
5693  for( v = 0; v < ntmpvars; ++v )
5694  {
5695  assert(tmpvars[v] != NULL);
5696  tmpvars[v]->removable &= var->removable;
5697  branchfactor = MAX(tmpvars[v]->branchfactor, branchfactor);
5698  branchpriority = MAX(tmpvars[v]->branchpriority, branchpriority);
5699 
5700  /* mark variable to be non-deletable */
5701  SCIPvarMarkNotDeletable(tmpvars[v]);
5702  }
5703  for( v = 0; v < ntmpvars; ++v )
5704  {
5705  SCIP_CALL( SCIPvarChgBranchFactor(tmpvars[v], set, branchfactor) );
5706  SCIP_CALL( SCIPvarChgBranchPriority(tmpvars[v], branchpriority) );
5707  if( (SCIP_BRANCHDIR)tmpvars[v]->branchdirection == SCIP_BRANCHDIR_AUTO )
5708  {
5709  if( tmpscalars[v] >= 0.0 )
5710  {
5711  SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], branchdirection) );
5712  }
5713  else
5714  {
5715  SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], SCIPbranchdirOpposite(branchdirection)) );
5716  }
5717  }
5718  }
5719  SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
5720  SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
5721 
5722  if( var->probindex != -1 )
5723  {
5724  /* inform problem about the variable's status change */
5725  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
5726  }
5727 
5728  /* issue VARFIXED event */
5729  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 2) );
5730 
5731  /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
5732  * variables and the problem's objective offset
5733  */
5734  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventfilter, eventqueue, obj) );
5735 
5736  *aggregated = TRUE;
5737 
5738  TERMINATE:
5739  BMSfreeBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize);
5740  BMSfreeBlockMemoryArray(blkmem, &tmpvars, tmpvarssize);
5741 
5742  break;
5743 
5744  case SCIP_VARSTATUS_COLUMN:
5745  SCIPerrorMessage("cannot multi-aggregate a column variable\n");
5746  return SCIP_INVALIDDATA;
5747 
5748  case SCIP_VARSTATUS_FIXED:
5749  SCIPerrorMessage("cannot multi-aggregate a fixed variable\n");
5750  return SCIP_INVALIDDATA;
5751 
5753  SCIPerrorMessage("cannot multi-aggregate an aggregated variable\n");
5754  return SCIP_INVALIDDATA;
5755 
5757  SCIPerrorMessage("cannot multi-aggregate a multiple aggregated variable again\n");
5758  return SCIP_INVALIDDATA;
5759 
5761  /* aggregate negation variable x in x' = offset - x, instead of aggregating x' directly:
5762  * x' = a_1*y_1 + ... + a_n*y_n + c -> x = offset - x' = offset - a_1*y_1 - ... - a_n*y_n - c
5763  */
5764  assert(SCIPsetIsZero(set, var->obj));
5765  assert(var->negatedvar != NULL);
5767  assert(var->negatedvar->negatedvar == var);
5768 
5769  /* switch the signs of the aggregation scalars */
5770  for( v = 0; v < naggvars; ++v )
5771  scalars[v] *= -1.0;
5772 
5773  /* perform the multi aggregation on the negation variable */
5774  SCIP_CALL( SCIPvarMultiaggregate(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5775  cliquetable, branchcand, eventfilter, eventqueue, naggvars, aggvars, scalars,
5776  var->data.negate.constant - constant, infeasible, aggregated) );
5777 
5778  /* switch the signs of the aggregation scalars again, to reset them to their original values */
5779  for( v = 0; v < naggvars; ++v )
5780  scalars[v] *= -1.0;
5781  break;
5782 
5783  default:
5784  SCIPerrorMessage("unknown variable status\n");
5785  return SCIP_INVALIDDATA;
5786  }
5787 
5788  /* check multi-aggregation on debugging solution */
5789  if( *infeasible || *aggregated )
5790  SCIP_CALL( SCIPdebugCheckAggregation(set, var, aggvars, scalars, constant, naggvars) ); /*lint !e506 !e774*/
5791 
5792  return SCIP_OKAY;
5793 }
5794 
5795 /** transformed variables are resolved to their active, fixed, or multi-aggregated problem variable of a variable,
5796  * or for original variables the same variable is returned
5797  */
5798 static
5800  SCIP_VAR* var /**< problem variable */
5801  )
5802 {
5803  SCIP_VAR* retvar;
5804 
5805  assert(var != NULL);
5806 
5807  retvar = var;
5808 
5809  SCIPdebugMessage("get active variable of <%s>\n", var->name);
5810 
5811  while( TRUE ) /*lint !e716 */
5812  {
5813  assert(retvar != NULL);
5814 
5815  switch( SCIPvarGetStatus(retvar) )
5816  {
5818  case SCIP_VARSTATUS_LOOSE:
5819  case SCIP_VARSTATUS_COLUMN:
5820  case SCIP_VARSTATUS_FIXED:
5821  return retvar;
5822 
5824  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
5825  if ( retvar->data.multaggr.nvars == 1 )
5826  retvar = retvar->data.multaggr.vars[0];
5827  else
5828  return retvar;
5829  break;
5830 
5832  retvar = retvar->data.aggregate.var;
5833  break;
5834 
5836  retvar = retvar->negatedvar;
5837  break;
5838 
5839  default:
5840  SCIPerrorMessage("unknown variable status\n");
5841  SCIPABORT();
5842  return NULL; /*lint !e527*/
5843  }
5844  }
5845 }
5846 
5847 /** returns whether variable is not allowed to be aggregated */
5849  SCIP_VAR* var /**< problem variable */
5850  )
5851 {
5852  SCIP_VAR* retvar;
5853 
5854  assert(var != NULL);
5855 
5856  retvar = varGetActiveVar(var);
5857  assert(retvar != NULL);
5858 
5859  switch( SCIPvarGetStatus(retvar) )
5860  {
5862  case SCIP_VARSTATUS_LOOSE:
5863  case SCIP_VARSTATUS_COLUMN:
5864  case SCIP_VARSTATUS_FIXED:
5865  return retvar->donotaggr;
5866 
5868  return FALSE;
5869 
5872  default:
5873  /* aggregated and negated variables should be resolved by varGetActiveVar() */
5874  SCIPerrorMessage("wrong variable status\n");
5875  SCIPABORT();
5876  return FALSE; /*lint !e527 */
5877  }
5878 }
5879 
5880 /** returns whether variable is not allowed to be multi-aggregated */
5882  SCIP_VAR* var /**< problem variable */
5883  )
5884 {
5885  SCIP_VAR* retvar;
5886 
5887  assert(var != NULL);
5888 
5889  retvar = varGetActiveVar(var);
5890  assert(retvar != NULL);
5891 
5892  switch( SCIPvarGetStatus(retvar) )
5893  {
5895  case SCIP_VARSTATUS_LOOSE:
5896  case SCIP_VARSTATUS_COLUMN:
5897  case SCIP_VARSTATUS_FIXED:
5898  return retvar->donotmultaggr;
5899 
5901  return FALSE;
5902 
5905  default:
5906  /* aggregated and negated variables should be resolved by varGetActiveVar() */
5907  SCIPerrorMessage("wrong variable status\n");
5908  SCIPABORT();
5909  return FALSE; /*lint !e527 */
5910  }
5911 }
5912 
5913 /** gets negated variable x' = offset - x of problem variable x; the negated variable is created if not yet existing;
5914  * the negation offset of binary variables is always 1, the offset of other variables is fixed to lb + ub when the
5915  * negated variable is created
5916  */
5918  SCIP_VAR* var, /**< problem variable to negate */
5919  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
5920  SCIP_SET* set, /**< global SCIP settings */
5921  SCIP_STAT* stat, /**< problem statistics */
5922  SCIP_VAR** negvar /**< pointer to store the negated variable */
5923  )
5924 {
5925  assert(var != NULL);
5926  assert(var->scip == set->scip);
5927  assert(negvar != NULL);
5928 
5929  /* check, if we already created the negated variable */
5930  if( var->negatedvar == NULL )
5931  {
5932  char negvarname[SCIP_MAXSTRLEN];
5933 
5934  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED);
5935 
5936  SCIPsetDebugMsg(set, "creating negated variable of <%s>\n", var->name);
5937 
5938  /* negation is only possible for bounded variables */
5939  if( SCIPsetIsInfinity(set, -var->glbdom.lb) || SCIPsetIsInfinity(set, var->glbdom.ub) )
5940  {
5941  SCIPerrorMessage("cannot negate unbounded variable\n");
5942  return SCIP_INVALIDDATA;
5943  }
5944 
5945  (void) SCIPsnprintf(negvarname, SCIP_MAXSTRLEN, "%s_neg", var->name);
5946 
5947  /* create negated variable */
5948  SCIP_CALL( varCreate(negvar, blkmem, set, stat, negvarname, var->glbdom.lb, var->glbdom.ub, 0.0,
5949  SCIPvarGetType(var), var->initial, var->removable, NULL, NULL, NULL, NULL, NULL) );
5950  (*negvar)->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
5951  if( SCIPvarIsBinary(var) )
5952  (*negvar)->data.negate.constant = 1.0;
5953  else
5954  (*negvar)->data.negate.constant = var->glbdom.lb + var->glbdom.ub;
5955 
5956  /* create event filter for transformed variable */
5957  if( SCIPvarIsTransformed(var) )
5958  {
5959  SCIP_CALL( SCIPeventfilterCreate(&(*negvar)->eventfilter, blkmem) );
5960  }
5961 
5962  /* set the bounds corresponding to the negation variable */
5963  (*negvar)->glbdom.lb = (*negvar)->data.negate.constant - var->glbdom.ub;
5964  (*negvar)->glbdom.ub = (*negvar)->data.negate.constant - var->glbdom.lb;
5965  (*negvar)->locdom.lb = (*negvar)->data.negate.constant - var->locdom.ub;
5966  (*negvar)->locdom.ub = (*negvar)->data.negate.constant - var->locdom.lb;
5967  /**@todo create holes in the negated variable corresponding to the holes of the negation variable */
5968 
5969  /* link the variables together */
5970  var->negatedvar = *negvar;
5971  (*negvar)->negatedvar = var;
5972 
5973  /* mark both variables to be non-deletable */
5975  SCIPvarMarkNotDeletable(*negvar);
5976 
5977  /* copy the branch factor and priority, and use the negative preferred branching direction */
5978  (*negvar)->branchfactor = var->branchfactor;
5979  (*negvar)->branchpriority = var->branchpriority;
5980  (*negvar)->branchdirection = SCIPbranchdirOpposite((SCIP_BRANCHDIR)var->branchdirection); /*lint !e641*/
5981 
5982  /* copy donot(mult)aggr status */
5983  (*negvar)->donotaggr = var->donotaggr;
5984  (*negvar)->donotmultaggr = var->donotmultaggr;
5985 
5986  /* copy lazy bounds (they have to be flipped) */
5987  (*negvar)->lazylb = (*negvar)->data.negate.constant - var->lazyub;
5988  (*negvar)->lazyub = (*negvar)->data.negate.constant - var->lazylb;
5989 
5990  /* make negated variable a parent of the negation variable (negated variable is captured as a parent) */
5991  SCIP_CALL( varAddParent(var, blkmem, set, *negvar) );
5992  assert((*negvar)->nuses == 1);
5993  }
5994  assert(var->negatedvar != NULL);
5995 
5996  /* return the negated variable */
5997  *negvar = var->negatedvar;
5998 
5999  /* exactly one variable of the negation pair has to be marked as negated variable */
6001 
6002  return SCIP_OKAY;
6003 }
6004 
6005 /** informs variable that its position in problem's vars array changed */
6006 static
6007 void varSetProbindex(
6008  SCIP_VAR* var, /**< problem variable */
6009  int probindex /**< new problem index of variable (-1 for removal) */
6010  )
6011 {
6012  assert(var != NULL);
6013  assert(probindex >= 0 || var->vlbs == NULL);
6014  assert(probindex >= 0 || var->vubs == NULL);
6015  assert(probindex >= 0 || var->implics == NULL);
6016 
6017  var->probindex = probindex;
6019  {
6020  assert(var->data.col != NULL);
6021  var->data.col->var_probindex = probindex;
6022  }
6023 }
6024 
6025 /** informs variable that its position in problem's vars array changed */
6026 void SCIPvarSetProbindex(
6027  SCIP_VAR* var, /**< problem variable */
6028  int probindex /**< new problem index of variable */
6029  )
6030 {
6031  assert(var != NULL);
6032  assert(probindex >= 0);
6033 
6034  varSetProbindex(var, probindex);
6035 }
6036 
6037 /** gives the variable a new name
6038  *
6039  * @note the old pointer is overwritten, which might result in a memory leakage
6040  */
6042  SCIP_VAR* var, /**< problem variable */
6043  const char* name /**< new name of variable */
6044  )
6045 {
6046  assert(var != NULL);
6047  assert(name != NULL);
6048 
6049  var->name = (char*)name;
6050 }
6051 
6052 /** informs variable that it will be removed from the problem; adjusts probindex and removes variable from the
6053  * implication graph;
6054  * If 'final' is TRUE, the thorough implication graph removal is not performed. Instead, only the
6055  * variable bounds and implication data structures of the variable are freed. Since in the final removal
6056  * of all variables from the transformed problem, this deletes the implication graph completely and is faster
6057  * than removing the variables one by one, each time updating all lists of the other variables.
6058  */
6060  SCIP_VAR* var, /**< problem variable */
6061  BMS_BLKMEM* blkmem, /**< block memory buffer */
6062  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6063  SCIP_SET* set, /**< global SCIP settings */
6064  SCIP_Bool final /**< is this the final removal of all problem variables? */
6065  )
6066 {
6067  assert(SCIPvarGetProbindex(var) >= 0);
6068  assert(var->scip == set->scip);
6069 
6070  /* if the variable is active in the transformed problem, remove it from the implication graph */
6071  if( SCIPvarIsTransformed(var)
6073  {
6074  if( final )
6075  {
6076  /* just destroy the data structures */
6077  SCIPvboundsFree(&var->vlbs, blkmem);
6078  SCIPvboundsFree(&var->vubs, blkmem);
6079  SCIPimplicsFree(&var->implics, blkmem);
6080  }
6081  else
6082  {
6083  /* unlink the variable from all other variables' lists and free the data structures */
6084  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
6085  }
6086  }
6087 
6088  /* mark the variable to be no longer a member of the problem */
6089  varSetProbindex(var, -1);
6090 
6091  return SCIP_OKAY;
6092 }
6093 
6094 /** marks the variable to be deleted from the problem */
6095 void SCIPvarMarkDeleted(
6096  SCIP_VAR* var /**< problem variable */
6097  )
6098 {
6099  assert(var != NULL);
6100  assert(var->probindex != -1);
6101 
6102  var->deleted = TRUE;
6103 }
6104 
6105 /** marks the variable to not to be aggregated */
6107  SCIP_VAR* var /**< problem variable */
6108  )
6109 {
6110  SCIP_VAR* retvar;
6111 
6112  assert(var != NULL);
6113 
6114  retvar = varGetActiveVar(var);
6115  assert(retvar != NULL);
6116 
6117  switch( SCIPvarGetStatus(retvar) )
6118  {
6120  case SCIP_VARSTATUS_LOOSE:
6121  case SCIP_VARSTATUS_COLUMN:
6122  case SCIP_VARSTATUS_FIXED:
6123  retvar->donotaggr = TRUE;
6124  break;
6125 
6127  SCIPerrorMessage("cannot mark a multi-aggregated variable to not be aggregated.\n");
6128  return SCIP_INVALIDDATA;
6129 
6132  default:
6133  /* aggregated and negated variables should be resolved by varGetActiveVar() */
6134  SCIPerrorMessage("wrong variable status\n");
6135  return SCIP_INVALIDDATA;
6136  }
6137 
6138  return SCIP_OKAY;
6139 }
6140 
6141 /** marks the variable to not to be multi-aggregated */
6143  SCIP_VAR* var /**< problem variable */
6144  )
6145 {
6146  SCIP_VAR* retvar;
6147 
6148  assert(var != NULL);
6149 
6150  retvar = varGetActiveVar(var);
6151  assert(retvar != NULL);
6152 
6153  switch( SCIPvarGetStatus(retvar) )
6154  {
6156  case SCIP_VARSTATUS_LOOSE:
6157  case SCIP_VARSTATUS_COLUMN:
6158  case SCIP_VARSTATUS_FIXED:
6159  retvar->donotmultaggr = TRUE;
6160  break;
6161 
6163  SCIPerrorMessage("cannot mark a multi-aggregated variable to not be multi-aggregated.\n");
6164  return SCIP_INVALIDDATA;
6165 
6168  default:
6169  /* aggregated and negated variables should be resolved by varGetActiveVar() */
6170  SCIPerrorMessage("wrong variable status\n");
6171  return SCIP_INVALIDDATA;
6172  }
6173 
6174  return SCIP_OKAY;
6175 }
6176 
6177 /** changes type of variable; cannot be called, if var belongs to a problem */
6179  SCIP_VAR* var, /**< problem variable to change */
6180  BMS_BLKMEM* blkmem, /**< block memory */
6181  SCIP_SET* set, /**< global SCIP settings */
6182  SCIP_PRIMAL* primal, /**< primal data */
6183  SCIP_LP* lp, /**< current LP data */
6184  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6185  SCIP_VARTYPE vartype /**< new type of variable */
6186  )
6187 {
6188  SCIP_EVENT* event;
6189  SCIP_VARTYPE oldtype;
6190 
6191  assert(var != NULL);
6192 
6193  SCIPdebugMessage("change type of <%s> from %d to %d\n", var->name, SCIPvarGetType(var), vartype);
6194 
6195  if( var->probindex >= 0 )
6196  {
6197  SCIPerrorMessage("cannot change type of variable already in the problem\n");
6198  return SCIP_INVALIDDATA;
6199  }
6200 
6201  oldtype = (SCIP_VARTYPE)var->vartype;
6202  var->vartype = vartype; /*lint !e641*/
6203 
6205  {
6206  SCIP_CALL( SCIPeventCreateTypeChanged(&event, blkmem, var, oldtype, vartype) );
6207  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
6208  }
6209 
6210  if( var->negatedvar != NULL )
6211  {
6212  assert(oldtype == (SCIP_VARTYPE)var->negatedvar->vartype
6213  || SCIPvarIsBinary(var) == SCIPvarIsBinary(var->negatedvar));
6214 
6215  var->negatedvar->vartype = vartype; /*lint !e641*/
6216 
6218  {
6219  SCIP_CALL( SCIPeventCreateTypeChanged(&event, blkmem, var->negatedvar, oldtype, vartype) );
6220  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
6221  }
6222  }
6223 
6224  return SCIP_OKAY;
6225 }
6226 
6227 /** appends OBJCHANGED event to the event queue */
6228 static
6230  SCIP_VAR* var, /**< problem variable to change */
6231  BMS_BLKMEM* blkmem, /**< block memory */
6232  SCIP_SET* set, /**< global SCIP settings */
6233  SCIP_PRIMAL* primal, /**< primal data */
6234  SCIP_LP* lp, /**< current LP data */
6235  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6236  SCIP_Real oldobj, /**< old objective value for variable */
6237  SCIP_Real newobj /**< new objective value for variable */
6238  )
6239 {
6240  SCIP_EVENT* event;
6241 
6242  assert(var != NULL);
6243  assert(var->scip == set->scip);
6244  assert(var->eventfilter != NULL);
6246  assert(SCIPvarIsTransformed(var));
6247 
6248  /* In the case where the objcetive value of a variable is very close to epsilon, and it is aggregated
6249  * into a variable with a big objective value, round-off errors might make the assert oldobj != newobj fail.
6250  * Hence, we relax it by letting it pass if the variables are percieved the same and we use very large values
6251  * that make comparison with values close to epsilon inaccurate.
6252  */
6253  assert(!SCIPsetIsEQ(set, oldobj, newobj) ||
6254  (SCIPsetIsEQ(set, oldobj, newobj) && REALABS(newobj) > 1e+15 * SCIPsetEpsilon(set))
6255  );
6256 
6257  SCIP_CALL( SCIPeventCreateObjChanged(&event, blkmem, var, oldobj, newobj) );
6258  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
6259 
6260  return SCIP_OKAY;
6261 }
6262 
6263 /** changes objective value of variable */
6265  SCIP_VAR* var, /**< variable to change */
6266  BMS_BLKMEM* blkmem, /**< block memory */
6267  SCIP_SET* set, /**< global SCIP settings */
6268  SCIP_PROB* prob, /**< problem data */
6269  SCIP_PRIMAL* primal, /**< primal data */
6270  SCIP_LP* lp, /**< current LP data */
6271  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6272  SCIP_Real newobj /**< new objective value for variable */
6273  )
6274 {
6275  SCIP_Real oldobj;
6276 
6277  assert(var != NULL);
6278  assert(set != NULL);
6279  assert(var->scip == set->scip);
6280 
6281  SCIPsetDebugMsg(set, "changing objective value of <%s> from %g to %g\n", var->name, var->obj, newobj);
6282 
6283  if( !SCIPsetIsEQ(set, var->obj, newobj) )
6284  {
6285  switch( SCIPvarGetStatus(var) )
6286  {
6288  if( var->data.original.transvar != NULL )
6289  {
6290  assert(SCIPprobIsTransformed(prob));
6291 
6292  SCIP_CALL( SCIPvarChgObj(var->data.original.transvar, blkmem, set, prob, primal, lp, eventqueue,
6293  (SCIP_Real) prob->objsense * newobj/prob->objscale) );
6294  }
6295  else
6296  assert(set->stage == SCIP_STAGE_PROBLEM);
6297 
6298  var->obj = newobj;
6299  var->unchangedobj = newobj;
6300 
6301  break;
6302 
6303  case SCIP_VARSTATUS_LOOSE:
6304  case SCIP_VARSTATUS_COLUMN:
6305  oldobj = var->obj;
6306  var->obj = newobj;
6307 
6308  /* update unchanged objective value of variable */
6309  if( !lp->divingobjchg )
6310  var->unchangedobj = newobj;
6311 
6312  /* update the number of variables with non-zero objective coefficient;
6313  * we only want to do the update, if the variable is added to the problem;
6314  * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
6315  */
6316  if( SCIPvarIsActive(var) )
6317  SCIPprobUpdateNObjVars(prob, set, oldobj, var->obj);
6318 
6319  SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
6320  break;
6321 
6322  case SCIP_VARSTATUS_FIXED:
6326  SCIPerrorMessage("cannot change objective value of a fixed, aggregated, multi-aggregated, or negated variable\n");
6327  return SCIP_INVALIDDATA;
6328 
6329  default:
6330  SCIPerrorMessage("unknown variable status\n");
6331  return SCIP_INVALIDDATA;
6332  }
6333  }
6334 
6335  return SCIP_OKAY;
6336 }
6337 
6338 /** adds value to objective value of variable */
6340  SCIP_VAR* var, /**< variable to change */
6341  BMS_BLKMEM* blkmem, /**< block memory */
6342  SCIP_SET* set, /**< global SCIP settings */
6343  SCIP_STAT* stat, /**< problem statistics */
6344  SCIP_PROB* transprob, /**< transformed problem data */
6345  SCIP_PROB* origprob, /**< original problem data */
6346  SCIP_PRIMAL* primal, /**< primal data */
6347  SCIP_TREE* tree, /**< branch and bound tree */
6348  SCIP_REOPT* reopt, /**< reoptimization data structure */
6349  SCIP_LP* lp, /**< current LP data */
6350  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
6351  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6352  SCIP_Real addobj /**< additional objective value for variable */
6353  )
6354 {
6355  assert(var != NULL);
6356  assert(set != NULL);
6357  assert(var->scip == set->scip);
6358  assert(set->stage < SCIP_STAGE_INITSOLVE);
6359 
6360  SCIPsetDebugMsg(set, "adding %g to objective value %g of <%s>\n", addobj, var->obj, var->name);
6361 
6362  if( !SCIPsetIsZero(set, addobj) )
6363  {
6364  SCIP_Real oldobj;
6365  int i;
6366 
6367  switch( SCIPvarGetStatus(var) )
6368  {
6370  if( var->data.original.transvar != NULL )
6371  {
6372  SCIP_CALL( SCIPvarAddObj(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
6373  reopt, lp, eventfilter, eventqueue, (SCIP_Real) transprob->objsense * addobj/transprob->objscale) );
6374  }
6375  else
6376  assert(set->stage == SCIP_STAGE_PROBLEM);
6377 
6378  var->obj += addobj;
6379  var->unchangedobj += addobj;
6380  assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
6381 
6382  break;
6383 
6384  case SCIP_VARSTATUS_LOOSE:
6385  case SCIP_VARSTATUS_COLUMN:
6386  oldobj = var->obj;
6387  var->obj += addobj;
6388 
6389  /* update unchanged objective value of variable */
6390  if( !lp->divingobjchg )
6391  {
6392  var->unchangedobj += addobj;
6393  assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
6394  }
6395 
6396  /* update the number of variables with non-zero objective coefficient;
6397  * we only want to do the update, if the variable is added to the problem;
6398  * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
6399  */
6400  if( SCIPvarIsActive(var) )
6401  SCIPprobUpdateNObjVars(transprob, set, oldobj, var->obj);
6402 
6403  SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
6404  break;
6405 
6406  case SCIP_VARSTATUS_FIXED:
6407  assert(SCIPsetIsEQ(set, var->locdom.lb, var->locdom.ub));
6408  SCIPprobAddObjoffset(transprob, var->locdom.lb * addobj);
6409  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6410  break;
6411 
6413  assert(!var->donotaggr);
6414  /* x = a*y + c -> add a*addobj to obj. val. of y, and c*addobj to obj. offset of problem */
6415  SCIPprobAddObjoffset(transprob, var->data.aggregate.constant * addobj);
6416  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6417  SCIP_CALL( SCIPvarAddObj(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
6418  lp, eventfilter, eventqueue, var->data.aggregate.scalar * addobj) );
6419  break;
6420 
6422  assert(!var->donotmultaggr);
6423  /* 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 */
6424  SCIPprobAddObjoffset(transprob, var->data.multaggr.constant * addobj);
6425  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6426  for( i = 0; i < var->data.multaggr.nvars; ++i )
6427  {
6428  SCIP_CALL( SCIPvarAddObj(var->data.multaggr.vars[i], blkmem, set, stat, transprob, origprob, primal, tree,
6429  reopt, lp, eventfilter, eventqueue, var->data.multaggr.scalars[i] * addobj) );
6430  }
6431  break;
6432 
6434  /* x' = offset - x -> add -addobj to obj. val. of x and offset*addobj to obj. offset of problem */
6435  assert(var->negatedvar != NULL);
6437  assert(var->negatedvar->negatedvar == var);
6438  SCIPprobAddObjoffset(transprob, var->data.negate.constant * addobj);
6439  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6440  SCIP_CALL( SCIPvarAddObj(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
6441  eventfilter, eventqueue, -addobj) );
6442  break;
6443 
6444  default:
6445  SCIPerrorMessage("unknown variable status\n");
6446  return SCIP_INVALIDDATA;
6447  }
6448  }
6449 
6450  return SCIP_OKAY;
6451 }
6452 
6453 /** changes objective value of variable in current dive */
6455  SCIP_VAR* var, /**< problem variable to change */
6456  SCIP_SET* set, /**< global SCIP settings */
6457  SCIP_LP* lp, /**< current LP data */
6458  SCIP_Real newobj /**< new objective value for variable */
6459  )
6460 {
6461  assert(var != NULL);
6462  assert(set != NULL);
6463  assert(var->scip == set->scip);
6464  assert(lp != NULL);
6465 
6466  SCIPsetDebugMsg(set, "changing objective of <%s> to %g in current dive\n", var->name, newobj);
6467 
6468  if( SCIPsetIsZero(set, newobj) )
6469  newobj = 0.0;
6470 
6471  /* change objective value of attached variables */
6472  switch( SCIPvarGetStatus(var) )
6473  {
6475  assert(var->data.original.transvar != NULL);
6476  SCIP_CALL( SCIPvarChgObjDive(var->data.original.transvar, set, lp, newobj) );
6477  break;
6478 
6479  case SCIP_VARSTATUS_COLUMN:
6480  assert(var->data.col != NULL);
6481  SCIP_CALL( SCIPcolChgObj(var->data.col, set, lp, newobj) );
6482  break;
6483 
6484  case SCIP_VARSTATUS_LOOSE:
6485  case SCIP_VARSTATUS_FIXED:
6486  /* nothing to do here: only the constant shift in objective function would change */
6487  break;
6488 
6489  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6490  assert(var->data.aggregate.var != NULL);
6491  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
6492  SCIP_CALL( SCIPvarChgObjDive(var->data.aggregate.var, set, lp, newobj / var->data.aggregate.scalar) );
6493  /* the constant can be ignored, because it would only affect the objective shift */
6494  break;
6495 
6497  SCIPerrorMessage("cannot change diving objective value of a multi-aggregated variable\n");
6498  return SCIP_INVALIDDATA;
6499 
6500  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6501  assert(var->negatedvar != NULL);
6503  assert(var->negatedvar->negatedvar == var);
6504  SCIP_CALL( SCIPvarChgObjDive(var->negatedvar, set, lp, -newobj) );
6505  /* the offset can be ignored, because it would only affect the objective shift */
6506  break;
6507 
6508  default:
6509  SCIPerrorMessage("unknown variable status\n");
6510  return SCIP_INVALIDDATA;
6511  }
6512 
6513  return SCIP_OKAY;
6514 }
6515 
6516 /** adjust lower bound to integral value, if variable is integral */
6517 void SCIPvarAdjustLb(
6518  SCIP_VAR* var, /**< problem variable */
6519  SCIP_SET* set, /**< global SCIP settings */
6520  SCIP_Real* lb /**< pointer to lower bound to adjust */
6521  )
6522 {
6523  assert(var != NULL);
6524  assert(set != NULL);
6525  assert(var->scip == set->scip);
6526  assert(lb != NULL);
6527 
6528  SCIPsetDebugMsg(set, "adjust lower bound %g of <%s>\n", *lb, var->name);
6529 
6530  *lb = adjustedLb(set, SCIPvarGetType(var), *lb);
6531 }
6532 
6533 /** adjust upper bound to integral value, if variable is integral */
6534 void SCIPvarAdjustUb(
6535  SCIP_VAR* var, /**< problem variable */
6536  SCIP_SET* set, /**< global SCIP settings */
6537  SCIP_Real* ub /**< pointer to upper bound to adjust */
6538  )
6539 {
6540  assert(var != NULL);
6541  assert(set != NULL);
6542  assert(var->scip == set->scip);
6543  assert(ub != NULL);
6544 
6545  SCIPsetDebugMsg(set, "adjust upper bound %g of <%s>\n", *ub, var->name);
6546 
6547  *ub = adjustedUb(set, SCIPvarGetType(var), *ub);
6548 }
6549 
6550 /** adjust lower or upper bound to integral value, if variable is integral */
6551 void SCIPvarAdjustBd(
6552  SCIP_VAR* var, /**< problem variable */
6553  SCIP_SET* set, /**< global SCIP settings */
6554  SCIP_BOUNDTYPE boundtype, /**< type of bound to adjust */
6555  SCIP_Real* bd /**< pointer to bound to adjust */
6556  )
6557 {
6558  assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
6559 
6560  if( boundtype == SCIP_BOUNDTYPE_LOWER )
6561  SCIPvarAdjustLb(var, set, bd);
6562  else
6563  SCIPvarAdjustUb(var, set, bd);
6564 }
6565 
6566 /** changes lower bound of original variable in original problem */
6568  SCIP_VAR* var, /**< problem variable to change */
6569  SCIP_SET* set, /**< global SCIP settings */
6570  SCIP_Real newbound /**< new bound for variable */
6571  )
6572 {
6573  int i;
6574 
6575  assert(var != NULL);
6576  assert(!SCIPvarIsTransformed(var));
6578  assert(set != NULL);
6579  assert(var->scip == set->scip);
6580  assert(set->stage == SCIP_STAGE_PROBLEM);
6581 
6582  /* check that the bound is feasible */
6583  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsLE(set, newbound, SCIPvarGetUbOriginal(var)));
6584  /* adjust bound to integral value if variable is of integral type */
6585  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6586 
6587  if( SCIPsetIsZero(set, newbound) )
6588  newbound = 0.0;
6589 
6590  /* original domains are only stored for ORIGINAL variables, not for NEGATED */
6592  {
6593  SCIPsetDebugMsg(set, "changing original lower bound of <%s> from %g to %g\n",
6594  var->name, var->data.original.origdom.lb, newbound);
6595 
6596  if( SCIPsetIsEQ(set, var->data.original.origdom.lb, newbound) )
6597  return SCIP_OKAY;
6598 
6599  /* change the bound */
6600  var->data.original.origdom.lb = newbound;
6601  }
6602  else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
6603  {
6604  assert( var->negatedvar != NULL );
6605  SCIP_CALL( SCIPvarChgUbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
6606  }
6607 
6608  /* process parent variables */
6609  for( i = 0; i < var->nparentvars; ++i )
6610  {
6611  SCIP_VAR* parentvar;
6612 
6613  parentvar = var->parentvars[i];
6614  assert(parentvar != NULL);
6615  assert(SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_NEGATED);
6616  assert(parentvar->negatedvar == var);
6617  assert(var->negatedvar == parentvar);
6618 
6619  SCIP_CALL( SCIPvarChgUbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
6620  }
6621 
6622  return SCIP_OKAY;
6623 }
6624 
6625 /** changes upper bound of original variable in original problem */
6627  SCIP_VAR* var, /**< problem variable to change */
6628  SCIP_SET* set, /**< global SCIP settings */
6629  SCIP_Real newbound /**< new bound for variable */
6630  )
6631 {
6632  int i;
6633 
6634  assert(var != NULL);
6635  assert(!SCIPvarIsTransformed(var));
6637  assert(set != NULL);
6638  assert(var->scip == set->scip);
6639  assert(set->stage == SCIP_STAGE_PROBLEM);
6640 
6641  /* check that the bound is feasible */
6642  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsGE(set, newbound, SCIPvarGetLbOriginal(var)));
6643  /* adjust bound to integral value if variable is of integral type */
6644  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
6645 
6646  if( SCIPsetIsZero(set, newbound) )
6647  newbound = 0.0;
6648 
6649  /* original domains are only stored for ORIGINAL variables, not for NEGATED */
6651  {
6652  SCIPsetDebugMsg(set, "changing original upper bound of <%s> from %g to %g\n",
6653  var->name, var->data.original.origdom.ub, newbound);
6654 
6655  if( SCIPsetIsEQ(set, var->data.original.origdom.ub, newbound) )
6656  return SCIP_OKAY;
6657 
6658  /* change the bound */
6659  var->data.original.origdom.ub = newbound;
6660  }
6661  else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
6662  {
6663  assert( var->negatedvar != NULL );
6664  SCIP_CALL( SCIPvarChgLbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
6665  }
6666 
6667  /* process parent variables */
6668  for( i = 0; i < var->nparentvars; ++i )
6669  {
6670  SCIP_VAR* parentvar;
6671 
6672  parentvar = var->parentvars[i];
6673  assert(parentvar != NULL);
6674  assert(SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_NEGATED);
6675  assert(parentvar->negatedvar == var);
6676  assert(var->negatedvar == parentvar);
6677 
6678  SCIP_CALL( SCIPvarChgLbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
6679  }
6680 
6681  return SCIP_OKAY;
6682 }
6683 
6684 /** appends GLBCHANGED event to the event queue */
6685 static
6687  SCIP_VAR* var, /**< problem variable to change */
6688  BMS_BLKMEM* blkmem, /**< block memory */
6689  SCIP_SET* set, /**< global SCIP settings */
6690  SCIP_LP* lp, /**< current LP data */
6691  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6692  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6693  SCIP_Real oldbound, /**< old lower bound for variable */
6694  SCIP_Real newbound /**< new lower bound for variable */
6695  )
6696 {
6697  assert(var != NULL);
6698  assert(var->eventfilter != NULL);
6699  assert(SCIPvarIsTransformed(var));
6700  assert(!SCIPsetIsEQ(set, oldbound, newbound) || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
6701  assert(set != NULL);
6702  assert(var->scip == set->scip);
6703 
6704  /* check, if the variable is being tracked for bound changes
6705  * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
6706  */
6707  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GLBCHANGED) != 0)
6710  {
6711  SCIP_EVENT* event;
6712 
6713  SCIPsetDebugMsg(set, "issue GLBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
6714 
6715  SCIP_CALL( SCIPeventCreateGlbChanged(&event, blkmem, var, oldbound, newbound) );
6716  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
6717  }
6718 
6719  return SCIP_OKAY;
6720 }
6721 
6722 /** appends GUBCHANGED event to the event queue */
6723 static
6725  SCIP_VAR* var, /**< problem variable to change */
6726  BMS_BLKMEM* blkmem, /**< block memory */
6727  SCIP_SET* set, /**< global SCIP settings */
6728  SCIP_LP* lp, /**< current LP data */
6729  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6730  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6731  SCIP_Real oldbound, /**< old lower bound for variable */
6732  SCIP_Real newbound /**< new lower bound for variable */
6733  )
6734 {
6735  assert(var != NULL);
6736  assert(var->eventfilter != NULL);
6737  assert(SCIPvarIsTransformed(var));
6738  assert(!SCIPsetIsEQ(set, oldbound, newbound) || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
6739  assert(set != NULL);
6740  assert(var->scip == set->scip);
6741 
6742  /* check, if the variable is being tracked for bound changes
6743  * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
6744  */
6745  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GUBCHANGED) != 0)
6748  {
6749  SCIP_EVENT* event;
6750 
6751  SCIPsetDebugMsg(set, "issue GUBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
6752 
6753  SCIP_CALL( SCIPeventCreateGubChanged(&event, blkmem, var, oldbound, newbound) );
6754  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
6755  }
6756 
6757  return SCIP_OKAY;
6758 }
6759 
6760 /** appends GHOLEADDED event to the event queue */
6761 static
6763  SCIP_VAR* var, /**< problem variable to change */
6764  BMS_BLKMEM* blkmem, /**< block memory */
6765  SCIP_SET* set, /**< global SCIP settings */
6766  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6767  SCIP_Real left, /**< left bound of open interval in new hole */
6768  SCIP_Real right /**< right bound of open interval in new hole */
6769  )
6770 {
6771  assert(var != NULL);
6772  assert(var->eventfilter != NULL);
6773  assert(SCIPvarIsTransformed(var));
6774  assert(set != NULL);
6775  assert(var->scip == set->scip);
6776  assert(SCIPsetIsLT(set, left, right));
6777 
6778  /* check, if the variable is being tracked for bound changes */
6779  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GHOLEADDED) != 0) )
6780  {
6781  SCIP_EVENT* event;
6782 
6783  SCIPsetDebugMsg(set, "issue GHOLEADDED event for variable <%s>: (%.15g,%.15g)\n", var->name, left, right);
6784 
6785  SCIP_CALL( SCIPeventCreateGholeAdded(&event, blkmem, var, left, right) );
6786  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
6787  }
6788 
6789  return SCIP_OKAY;
6790 }
6791 
6792 /** increases root bound change statistics after a global bound change */
6793 static
6794 void varIncRootboundchgs(
6795  SCIP_VAR* var, /**< problem variable to change */
6796  SCIP_SET* set, /**< global SCIP settings */
6797  SCIP_STAT* stat /**< problem statistics */
6798  )
6799 {
6800  assert(var != NULL);
6801  assert(set != NULL);
6802  assert(var->scip == set->scip);
6803  assert(stat != NULL);
6804 
6805  if( SCIPvarIsActive(var) && SCIPvarIsTransformed(var) && set->stage == SCIP_STAGE_SOLVING )
6806  {
6807  stat->nrootboundchgs++;
6808  stat->nrootboundchgsrun++;
6809  if( SCIPvarIsIntegral(var) && SCIPvarGetLbGlobal(var) + 0.5 > SCIPvarGetUbGlobal(var) )
6810  {
6811  stat->nrootintfixings++;
6812  stat->nrootintfixingsrun++;
6813  }
6814  }
6815 }
6816 
6817 /* forward declaration, because both methods call each other recursively */
6818 
6819 /* performs the current change in upper bound, changes all parents accordingly */
6820 static
6822  SCIP_VAR* var, /**< problem variable to change */
6823  BMS_BLKMEM* blkmem, /**< block memory */
6824  SCIP_SET* set, /**< global SCIP settings */
6825  SCIP_STAT* stat, /**< problem statistics */
6826  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6827  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6828  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6829  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6830  SCIP_Real newbound /**< new bound for variable */
6831  );
6832 
6833 /** performs the current change in lower bound, changes all parents accordingly */
6834 static
6836  SCIP_VAR* var, /**< problem variable to change */
6837  BMS_BLKMEM* blkmem, /**< block memory */
6838  SCIP_SET* set, /**< global SCIP settings */
6839  SCIP_STAT* stat, /**< problem statistics */
6840  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6841  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6842  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6843  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6844  SCIP_Real newbound /**< new bound for variable */
6845  )
6846 {
6847  SCIP_VAR* parentvar;
6848  SCIP_Real oldbound;
6849  int i;
6850 
6851  assert(var != NULL);
6852  /* local domains can violate global bounds but not more than feasibility epsilon */
6853  assert(SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb));
6854  assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
6855  assert(blkmem != NULL);
6856  assert(set != NULL);
6857  assert(var->scip == set->scip);
6858  assert(stat != NULL);
6859 
6860  /* adjust bound to integral value if variable is of integral type */
6861  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6862 
6863  /* check that the bound is feasible */
6864  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound > var->glbdom.ub )
6865  {
6866  /* due to numerics we only want to be feasible in feasibility tolerance */
6867  assert(SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
6868  newbound = var->glbdom.ub;
6869  }
6870  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6871 
6872  assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
6873 
6874  SCIPsetDebugMsg(set, "process changing global lower bound of <%s> from %f to %f\n", var->name, var->glbdom.lb, newbound);
6875 
6876  if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) && !(newbound != var->glbdom.lb && newbound * var->glbdom.lb <= 0.0) ) /*lint !e777*/
6877  return SCIP_OKAY;
6878 
6879  /* check bound on debugging solution */
6880  SCIP_CALL( SCIPdebugCheckLbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
6881 
6882  /* change the bound */
6883  oldbound = var->glbdom.lb;
6884  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
6885  var->glbdom.lb = newbound;
6886  assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
6887  assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
6888 
6889  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6890  {
6891  /* merges overlapping holes into single holes, moves bounds respectively */
6892  domMerge(&var->glbdom, blkmem, set, &newbound, NULL);
6893  }
6894 
6895  /* update the root bound changes counters */
6896  varIncRootboundchgs(var, set, stat);
6897 
6898  /* update the lbchginfos array by replacing worse local bounds with the new global bound and changing the
6899  * redundant bound changes to be branching decisions
6900  */
6901  for( i = 0; i < var->nlbchginfos; ++i )
6902  {
6903  assert(var->lbchginfos[i].var == var);
6904 
6905  if( var->lbchginfos[i].oldbound < var->glbdom.lb )
6906  {
6907  SCIPsetDebugMsg(set, " -> adjust lower bound change <%s>: %g -> %g due to new global lower bound %g\n",
6908  SCIPvarGetName(var), var->lbchginfos[i].oldbound, var->lbchginfos[i].newbound, var->glbdom.lb);
6909  var->lbchginfos[i].oldbound = var->glbdom.lb;
6910  if( SCIPsetIsLE(set, var->lbchginfos[i].newbound, var->glbdom.lb) )
6911  {
6912  /* this bound change is redundant due to the new global bound */
6913  var->lbchginfos[i].newbound = var->glbdom.lb;
6914  var->lbchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
6915  var->lbchginfos[i].redundant = TRUE;
6916  }
6917  else
6918  break; /* from now on, the remaining local bound changes are not redundant */
6919  }
6920  else
6921  break; /* from now on, the remaining local bound changes are not redundant */
6922  }
6923 
6924  /* remove redundant implications and variable bounds */
6926  && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
6927  {
6928  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
6929  }
6930 
6931  /* issue bound change event */
6932  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
6933  if( var->eventfilter != NULL )
6934  {
6935  SCIP_CALL( varEventGlbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
6936  }
6937 
6938  /* process parent variables */
6939  for( i = 0; i < var->nparentvars; ++i )
6940  {
6941  parentvar = var->parentvars[i];
6942  assert(parentvar != NULL);
6943 
6944  switch( SCIPvarGetStatus(parentvar) )
6945  {
6947  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6948  break;
6949 
6950  case SCIP_VARSTATUS_COLUMN:
6951  case SCIP_VARSTATUS_LOOSE:
6952  case SCIP_VARSTATUS_FIXED:
6954  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
6955  return SCIP_INVALIDDATA;
6956 
6957  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6958  assert(parentvar->data.aggregate.var == var);
6959  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
6960  {
6961  SCIP_Real parentnewbound;
6962 
6963  /* a > 0 -> change lower bound of y */
6964  assert(SCIPsetIsInfinity(set, -parentvar->glbdom.lb) || SCIPsetIsInfinity(set, -oldbound)
6965  || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
6966  || (SCIPsetIsZero(set, parentvar->glbdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
6967 
6968  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6969  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6970  else
6971  parentnewbound = newbound;
6972  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6973  }
6974  else
6975  {
6976  SCIP_Real parentnewbound;
6977 
6978  /* a < 0 -> change upper bound of y */
6979  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
6980  assert(SCIPsetIsInfinity(set, parentvar->glbdom.ub) || SCIPsetIsInfinity(set, -oldbound)
6981  || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
6982  || (SCIPsetIsZero(set, parentvar->glbdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
6983 
6984  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6985  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6986  else
6987  parentnewbound = -newbound;
6988  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6989  }
6990  break;
6991 
6992  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6993  assert(parentvar->negatedvar != NULL);
6994  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
6995  assert(parentvar->negatedvar->negatedvar == parentvar);
6996  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6997  parentvar->data.negate.constant - newbound) );
6998  break;
6999 
7000  default:
7001  SCIPerrorMessage("unknown variable status\n");
7002  return SCIP_INVALIDDATA;
7003  }
7004  }
7005 
7006  return SCIP_OKAY;
7007 }
7008 
7009 /** performs the current change in upper bound, changes all parents accordingly */
7010 static
7012  SCIP_VAR* var, /**< problem variable to change */
7013  BMS_BLKMEM* blkmem, /**< block memory */
7014  SCIP_SET* set, /**< global SCIP settings */
7015  SCIP_STAT* stat, /**< problem statistics */
7016  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7017  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7018  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7019  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7020  SCIP_Real newbound /**< new bound for variable */
7021  )
7022 {
7023  SCIP_VAR* parentvar;
7024  SCIP_Real oldbound;
7025  int i;
7026 
7027  assert(var != NULL);
7028  /* local domains can violate global bounds but not more than feasibility epsilon */
7029  assert(SCIPsetIsFeasLE(set, var->glbdom.lb , var->locdom.lb));
7030  assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
7031  assert(blkmem != NULL);
7032  assert(set != NULL);
7033  assert(var->scip == set->scip);
7034  assert(stat != NULL);
7035 
7036  /* adjust bound to integral value if variable is of integral type */
7037  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7038 
7039  /* check that the bound is feasible */
7040  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound < var->glbdom.lb )
7041  {
7042  /* due to numerics we only want to be feasible in feasibility tolerance */
7043  assert(SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
7044  newbound = var->glbdom.lb;
7045  }
7046  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7047 
7048  assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
7049 
7050  SCIPsetDebugMsg(set, "process changing global upper bound of <%s> from %f to %f\n", var->name, var->glbdom.ub, newbound);
7051 
7052  if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) && !(newbound != var->glbdom.ub && newbound * var->glbdom.ub <= 0.0) ) /*lint !e777*/
7053  return SCIP_OKAY;
7054 
7055  /* check bound on debugging solution */
7056  SCIP_CALL( SCIPdebugCheckUbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
7057 
7058  /* change the bound */
7059  oldbound = var->glbdom.ub;
7060  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
7061  var->glbdom.ub = newbound;
7062  assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
7063  assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
7064 
7065  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7066  {
7067  /* merges overlapping holes into single holes, moves bounds respectively */
7068  domMerge(&var->glbdom, blkmem, set, NULL, &newbound);
7069  }
7070 
7071  /* update the root bound changes counters */
7072  varIncRootboundchgs(var, set, stat);
7073 
7074  /* update the ubchginfos array by replacing worse local bounds with the new global bound and changing the
7075  * redundant bound changes to be branching decisions
7076  */
7077  for( i = 0; i < var->nubchginfos; ++i )
7078  {
7079  assert(var->ubchginfos[i].var == var);
7080  if( var->ubchginfos[i].oldbound > var->glbdom.ub )
7081  {
7082  SCIPsetDebugMsg(set, " -> adjust upper bound change <%s>: %g -> %g due to new global upper bound %g\n",
7083  SCIPvarGetName(var), var->ubchginfos[i].oldbound, var->ubchginfos[i].newbound, var->glbdom.ub);
7084  var->ubchginfos[i].oldbound = var->glbdom.ub;
7085  if( SCIPsetIsGE(set, var->ubchginfos[i].newbound, var->glbdom.ub) )
7086  {
7087  /* this bound change is redundant due to the new global bound */
7088  var->ubchginfos[i].newbound = var->glbdom.ub;
7089  var->ubchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
7090  var->ubchginfos[i].redundant = TRUE;
7091  }
7092  else
7093  break; /* from now on, the remaining local bound changes are not redundant */
7094  }
7095  else
7096  break; /* from now on, the remaining local bound changes are not redundant */
7097  }
7098 
7099  /* remove redundant implications and variable bounds */
7101  && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
7102  {
7103  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
7104  }
7105 
7106  /* issue bound change event */
7107  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7108  if( var->eventfilter != NULL )
7109  {
7110  SCIP_CALL( varEventGubChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7111  }
7112 
7113  /* process parent variables */
7114  for( i = 0; i < var->nparentvars; ++i )
7115  {
7116  parentvar = var->parentvars[i];
7117  assert(parentvar != NULL);
7118 
7119  switch( SCIPvarGetStatus(parentvar) )
7120  {
7122  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7123  break;
7124 
7125  case SCIP_VARSTATUS_COLUMN:
7126  case SCIP_VARSTATUS_LOOSE:
7127  case SCIP_VARSTATUS_FIXED:
7129  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7130  return SCIP_INVALIDDATA;
7131 
7132  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7133  assert(parentvar->data.aggregate.var == var);
7134  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7135  {
7136  SCIP_Real parentnewbound;
7137 
7138  /* a > 0 -> change upper bound of y */
7139  assert(SCIPsetIsInfinity(set, parentvar->glbdom.ub) || SCIPsetIsInfinity(set, oldbound)
7140  || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub,
7141  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7142  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7143  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7144  else
7145  parentnewbound = newbound;
7146  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
7147  }
7148  else
7149  {
7150  SCIP_Real parentnewbound;
7151 
7152  /* a < 0 -> change lower bound of y */
7153  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7154  assert(SCIPsetIsInfinity(set, -parentvar->glbdom.lb) || SCIPsetIsInfinity(set, oldbound)
7155  || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb,
7156  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7157  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7158  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7159  else
7160  parentnewbound = -newbound;
7161  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
7162  }
7163  break;
7164 
7165  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7166  assert(parentvar->negatedvar != NULL);
7167  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7168  assert(parentvar->negatedvar->negatedvar == parentvar);
7169  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7170  parentvar->data.negate.constant - newbound) );
7171  break;
7172 
7173  default:
7174  SCIPerrorMessage("unknown variable status\n");
7175  return SCIP_INVALIDDATA;
7176  }
7177  }
7178 
7179  return SCIP_OKAY;
7180 }
7181 
7182 /** changes global lower bound of variable; if possible, adjusts bound to integral value;
7183  * updates local lower bound if the global bound is tighter
7184  */
7186  SCIP_VAR* var, /**< problem variable to change */
7187  BMS_BLKMEM* blkmem, /**< block memory */
7188  SCIP_SET* set, /**< global SCIP settings */
7189  SCIP_STAT* stat, /**< problem statistics */
7190  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7191  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7192  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7193  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7194  SCIP_Real newbound /**< new bound for variable */
7195  )
7196 {
7197  assert(var != NULL);
7198  assert(blkmem != NULL);
7199  assert(set != NULL);
7200  assert(var->scip == set->scip);
7201 
7202  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7203  * of the domain within feastol
7204  */
7205  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
7206 
7207  /* adjust bound to integral value if variable is of integral type */
7208  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7209 
7210  /* check that the adjusted bound is feasible
7211  * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
7212  * here because we reset bounds to their original value!
7213  */
7214  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
7215 
7216  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7217  {
7218  /* we do not want to exceed the upperbound, which could have happened due to numerics */
7219  newbound = MIN(newbound, var->glbdom.ub);
7220  }
7221  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7222 
7223  /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
7224  * SCIPvarFix() allows fixings that are outside of the domain within feastol
7225  */
7226  assert(lp == NULL || SCIPsetIsFeasLE(set, var->glbdom.lb, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
7227 
7228  SCIPsetDebugMsg(set, "changing global lower bound of <%s> from %g to %g\n", var->name, var->glbdom.lb, newbound);
7229 
7230  if( SCIPsetIsEQ(set, var->glbdom.lb, newbound) && !(newbound != var->glbdom.lb && newbound * var->glbdom.lb <= 0.0) ) /*lint !e777*/
7231  return SCIP_OKAY;
7232 
7233  /* change bounds of attached variables */
7234  switch( SCIPvarGetStatus(var) )
7235  {
7237  if( var->data.original.transvar != NULL )
7238  {
7239  SCIP_CALL( SCIPvarChgLbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
7240  cliquetable, newbound) );
7241  }
7242  else
7243  {
7244  assert(set->stage == SCIP_STAGE_PROBLEM);
7245  if( newbound > SCIPvarGetLbLocal(var) )
7246  {
7247  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7248  }
7249  SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7250  }
7251  break;
7252 
7253  case SCIP_VARSTATUS_COLUMN:
7254  case SCIP_VARSTATUS_LOOSE:
7255  if( newbound > SCIPvarGetLbLocal(var) )
7256  {
7257  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7258  }
7259  SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7260  break;
7261 
7262  case SCIP_VARSTATUS_FIXED:
7263  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7264  return SCIP_INVALIDDATA;
7265 
7266  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7267  assert(var->data.aggregate.var != NULL);
7268  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7269  {
7270  SCIP_Real childnewbound;
7271 
7272  /* a > 0 -> change lower bound of y */
7273  assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, -var->data.aggregate.var->glbdom.lb))
7274  || SCIPsetIsFeasEQ(set, var->glbdom.lb,
7276  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7277  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7278  else
7279  childnewbound = newbound;
7280  SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7281  childnewbound) );
7282  }
7283  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7284  {
7285  SCIP_Real childnewbound;
7286 
7287  /* a < 0 -> change upper bound of y */
7288  assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
7289  || SCIPsetIsFeasEQ(set, var->glbdom.lb,
7291  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7292  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7293  else
7294  childnewbound = -newbound;
7295  SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7296  childnewbound) );
7297  }
7298  else
7299  {
7300  SCIPerrorMessage("scalar is zero in aggregation\n");
7301  return SCIP_INVALIDDATA;
7302  }
7303  break;
7304 
7306  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7307  return SCIP_INVALIDDATA;
7308 
7309  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7310  assert(var->negatedvar != NULL);
7312  assert(var->negatedvar->negatedvar == var);
7313  SCIP_CALL( SCIPvarChgUbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7314  var->data.negate.constant - newbound) );
7315  break;
7316 
7317  default:
7318  SCIPerrorMessage("unknown variable status\n");
7319  return SCIP_INVALIDDATA;
7320  }
7321 
7322  return SCIP_OKAY;
7323 }
7324 
7325 /** changes global upper bound of variable; if possible, adjusts bound to integral value;
7326  * updates local upper bound if the global bound is tighter
7327  */
7329  SCIP_VAR* var, /**< problem variable to change */
7330  BMS_BLKMEM* blkmem, /**< block memory */
7331  SCIP_SET* set, /**< global SCIP settings */
7332  SCIP_STAT* stat, /**< problem statistics */
7333  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7334  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7335  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7336  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7337  SCIP_Real newbound /**< new bound for variable */
7338  )
7339 {
7340  assert(var != NULL);
7341  assert(blkmem != NULL);
7342  assert(set != NULL);
7343  assert(var->scip == set->scip);
7344 
7345  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7346  * of the domain within feastol
7347  */
7348  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
7349 
7350  /* adjust bound to integral value if variable is of integral type */
7351  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7352 
7353  /* check that the adjusted bound is feasible
7354  * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
7355  * here because we reset bounds to their original value!
7356  */
7357  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
7358 
7359  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7360  {
7361  /* we do not want to undercut the lowerbound, which could have happened due to numerics */
7362  newbound = MAX(newbound, var->glbdom.lb);
7363  }
7364  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7365 
7366  /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
7367  * SCIPvarFix() allows fixings that are outside of the domain within feastol
7368  */
7369  assert(lp == NULL || SCIPsetIsFeasGE(set, var->glbdom.ub, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
7370 
7371  SCIPsetDebugMsg(set, "changing global upper bound of <%s> from %g to %g\n", var->name, var->glbdom.ub, newbound);
7372 
7373  if( SCIPsetIsEQ(set, var->glbdom.ub, newbound) && !(newbound != var->glbdom.ub && newbound * var->glbdom.ub <= 0.0) ) /*lint !e777*/
7374  return SCIP_OKAY;
7375 
7376  /* change bounds of attached variables */
7377  switch( SCIPvarGetStatus(var) )
7378  {
7380  if( var->data.original.transvar != NULL )
7381  {
7382  SCIP_CALL( SCIPvarChgUbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7383  newbound) );
7384  }
7385  else
7386  {
7387  assert(set->stage == SCIP_STAGE_PROBLEM);
7388  if( newbound < SCIPvarGetUbLocal(var) )
7389  {
7390  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7391  }
7392  SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7393  }
7394  break;
7395 
7396  case SCIP_VARSTATUS_COLUMN:
7397  case SCIP_VARSTATUS_LOOSE:
7398  if( newbound < SCIPvarGetUbLocal(var) )
7399  {
7400  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7401  }
7402  SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7403  break;
7404 
7405  case SCIP_VARSTATUS_FIXED:
7406  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7407  return SCIP_INVALIDDATA;
7408 
7409  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7410  assert(var->data.aggregate.var != NULL);
7411  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7412  {
7413  SCIP_Real childnewbound;
7414 
7415  /* a > 0 -> change lower bound of y */
7416  assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
7417  || SCIPsetIsFeasEQ(set, var->glbdom.ub,
7419  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7420  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7421  else
7422  childnewbound = newbound;
7423  SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7424  childnewbound) );
7425  }
7426  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7427  {
7428  SCIP_Real childnewbound;
7429 
7430  /* a < 0 -> change upper bound of y */
7431  assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, -var->data.aggregate.var->glbdom.lb))
7432  || SCIPsetIsFeasEQ(set, var->glbdom.ub,
7434  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7435  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7436  else
7437  childnewbound = -newbound;
7438  SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7439  childnewbound) );
7440  }
7441  else
7442  {
7443  SCIPerrorMessage("scalar is zero in aggregation\n");
7444  return SCIP_INVALIDDATA;
7445  }
7446  break;
7447 
7449  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7450  return SCIP_INVALIDDATA;
7451 
7452  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7453  assert(var->negatedvar != NULL);
7455  assert(var->negatedvar->negatedvar == var);
7456  SCIP_CALL( SCIPvarChgLbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7457  var->data.negate.constant - newbound) );
7458  break;
7459 
7460  default:
7461  SCIPerrorMessage("unknown variable status\n");
7462  return SCIP_INVALIDDATA;
7463  }
7464 
7465  return SCIP_OKAY;
7466 }
7467 
7468 /** changes lazy lower bound of the variable, this is only possible if the variable is not in the LP yet */
7470  SCIP_VAR* var, /**< problem variable */
7471  SCIP_SET* set, /**< global SCIP settings */
7472  SCIP_Real lazylb /**< the lazy lower bound to be set */
7473  )
7474 {
7475  assert(var != NULL);
7476  assert(var->probindex != -1);
7477  assert(SCIPsetIsFeasGE(set, var->glbdom.ub, lazylb));
7478  assert(SCIPsetIsFeasGE(set, var->lazyub, lazylb));
7479  assert(set != NULL);
7480  assert(var->scip == set->scip);
7481 
7482  /* variable should not be in the LP */
7484  return SCIP_INVALIDCALL;
7485 
7486  var->lazylb = lazylb;
7487 
7488  return SCIP_OKAY;
7489 }
7490 
7491 /** changes lazy upper bound of the variable, this is only possible if the variable is not in the LP yet */
7493  SCIP_VAR* var, /**< problem variable */
7494  SCIP_SET* set, /**< global SCIP settings */
7495  SCIP_Real lazyub /**< the lazy lower bound to be set */
7496  )
7497 {
7498  assert(var != NULL);
7499  assert(var->probindex != -1);
7500  assert(SCIPsetIsFeasGE(set, lazyub, var->glbdom.lb));
7501  assert(SCIPsetIsFeasGE(set, lazyub, var->lazylb));
7502  assert(set != NULL);
7503  assert(var->scip == set->scip);
7504 
7505  /* variable should not be in the LP */
7507  return SCIP_INVALIDCALL;
7508 
7509  var->lazyub = lazyub;
7510 
7511  return SCIP_OKAY;
7512 }
7513 
7514 
7515 /** changes global bound of variable; if possible, adjusts bound to integral value;
7516  * updates local bound if the global bound is tighter
7517  */
7519  SCIP_VAR* var, /**< problem variable to change */
7520  BMS_BLKMEM* blkmem, /**< block memory */
7521  SCIP_SET* set, /**< global SCIP settings */
7522  SCIP_STAT* stat, /**< problem statistics */
7523  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7524  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7525  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7526  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7527  SCIP_Real newbound, /**< new bound for variable */
7528  SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
7529  )
7530 {
7531  /* apply bound change to the LP data */
7532  switch( boundtype )
7533  {
7534  case SCIP_BOUNDTYPE_LOWER:
7535  return SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
7536  case SCIP_BOUNDTYPE_UPPER:
7537  return SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
7538  default:
7539  SCIPerrorMessage("unknown bound type\n");
7540  return SCIP_INVALIDDATA;
7541  }
7542 }
7543 
7544 /** appends LBTIGHTENED or LBRELAXED event to the event queue */
7545 static
7547  SCIP_VAR* var, /**< problem variable to change */
7548  BMS_BLKMEM* blkmem, /**< block memory */
7549  SCIP_SET* set, /**< global SCIP settings */
7550  SCIP_LP* lp, /**< current LP data */
7551  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7552  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7553  SCIP_Real oldbound, /**< old lower bound for variable */
7554  SCIP_Real newbound /**< new lower bound for variable */
7555  )
7556 {
7557  assert(var != NULL);
7558  assert(var->eventfilter != NULL);
7559  assert(SCIPvarIsTransformed(var));
7560  assert(!SCIPsetIsEQ(set, oldbound, newbound) || newbound == var->glbdom.lb || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
7561  assert(set != NULL);
7562  assert(var->scip == set->scip);
7563 
7564  /* check, if the variable is being tracked for bound changes
7565  * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
7566  */
7567  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_LBCHANGED) != 0)
7570  {
7571  SCIP_EVENT* event;
7572 
7573  SCIPsetDebugMsg(set, "issue LBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
7574 
7575  SCIP_CALL( SCIPeventCreateLbChanged(&event, blkmem, var, oldbound, newbound) );
7576  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
7577  }
7578 
7579  return SCIP_OKAY;
7580 }
7581 
7582 /** appends UBTIGHTENED or UBRELAXED event to the event queue */
7583 static
7585  SCIP_VAR* var, /**< problem variable to change */
7586  BMS_BLKMEM* blkmem, /**< block memory */
7587  SCIP_SET* set, /**< global SCIP settings */
7588  SCIP_LP* lp, /**< current LP data */
7589  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7590  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7591  SCIP_Real oldbound, /**< old upper bound for variable */
7592  SCIP_Real newbound /**< new upper bound for variable */
7593  )
7594 {
7595  assert(var != NULL);
7596  assert(var->eventfilter != NULL);
7597  assert(SCIPvarIsTransformed(var));
7598  assert(!SCIPsetIsEQ(set, oldbound, newbound) || newbound == var->glbdom.ub || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
7599  assert(set != NULL);
7600  assert(var->scip == set->scip);
7601 
7602  /* check, if the variable is being tracked for bound changes
7603  * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
7604  */
7605  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_UBCHANGED) != 0)
7608  {
7609  SCIP_EVENT* event;
7610 
7611  SCIPsetDebugMsg(set, "issue UBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
7612 
7613  SCIP_CALL( SCIPeventCreateUbChanged(&event, blkmem, var, oldbound, newbound) );
7614  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
7615  }
7616 
7617  return SCIP_OKAY;
7618 }
7619 
7620 /* forward declaration, because both methods call each other recursively */
7621 
7622 /* performs the current change in upper bound, changes all parents accordingly */
7623 static
7625  SCIP_VAR* var, /**< problem variable to change */
7626  BMS_BLKMEM* blkmem, /**< block memory */
7627  SCIP_SET* set, /**< global SCIP settings */
7628  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7629  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7630  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7631  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7632  SCIP_Real newbound /**< new bound for variable */
7633  );
7634 
7635 /** performs the current change in lower bound, changes all parents accordingly */
7636 static
7638  SCIP_VAR* var, /**< problem variable to change */
7639  BMS_BLKMEM* blkmem, /**< block memory */
7640  SCIP_SET* set, /**< global SCIP settings */
7641  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7642  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7643  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7644  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7645  SCIP_Real newbound /**< new bound for variable */
7646  )
7647 {
7648  SCIP_VAR* parentvar;
7649  SCIP_Real oldbound;
7650  int i;
7651 
7652  assert(var != NULL);
7653  assert(set != NULL);
7654  assert(var->scip == set->scip);
7655  assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)
7656  || SCIPsetIsEQ(set, newbound, var->locdom.ub)))
7657  || (SCIPvarGetType(var) < SCIP_VARTYPE_CONTINUOUS && (SCIPsetIsIntegral(set, newbound)
7658  || SCIPsetIsEQ(set, newbound, var->locdom.ub)))
7660 
7661  /* check that the bound is feasible */
7662  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsLE(set, newbound, var->glbdom.ub));
7663  /* adjust bound to integral value if variable is of integral type */
7664  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7665 
7666  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7667  {
7668  /* we do not want to exceed the upper bound, which could have happened due to numerics */
7669  newbound = MIN(newbound, var->locdom.ub);
7670 
7671  /* we do not want to undercut the global lower bound, which could have happened due to numerics */
7672  newbound = MAX(newbound, var->glbdom.lb);
7673  }
7674  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7675 
7676  SCIPsetDebugMsg(set, "process changing lower bound of <%s> from %g to %g\n", var->name, var->locdom.lb, newbound);
7677 
7678  if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) && var->glbdom.lb != var->locdom.lb ) /*lint !e777*/
7679  newbound = var->glbdom.lb;
7680  else if( SCIPsetIsEQ(set, newbound, var->locdom.lb) && !(newbound != var->locdom.lb && newbound * var->locdom.lb <= 0.0) ) /*lint !e777*/
7681  return SCIP_OKAY;
7682 
7683  /* change the bound */
7684  oldbound = var->locdom.lb;
7685  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->locdom.ub));
7686  var->locdom.lb = newbound;
7687 
7688  /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
7689  * once update the statistic
7690  */
7691  if( stat != NULL )
7692  SCIPstatIncrement(stat, set, domchgcount);
7693 
7694  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7695  {
7696  /* merges overlapping holes into single holes, moves bounds respectively */
7697  domMerge(&var->locdom, blkmem, set, &newbound, NULL);
7698  }
7699 
7700  /* issue bound change event */
7701  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7702  if( var->eventfilter != NULL )
7703  {
7704  SCIP_CALL( varEventLbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7705  }
7706 
7707  /* process parent variables */
7708  for( i = 0; i < var->nparentvars; ++i )
7709  {
7710  parentvar = var->parentvars[i];
7711  assert(parentvar != NULL);
7712 
7713  switch( SCIPvarGetStatus(parentvar) )
7714  {
7716  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
7717  break;
7718 
7719  case SCIP_VARSTATUS_COLUMN:
7720  case SCIP_VARSTATUS_LOOSE:
7721  case SCIP_VARSTATUS_FIXED:
7723  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7724  return SCIP_INVALIDDATA;
7725 
7726  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7727  assert(parentvar->data.aggregate.var == var);
7728  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7729  {
7730  SCIP_Real parentnewbound;
7731 
7732  /* a > 0 -> change lower bound of y */
7733  assert(SCIPsetIsInfinity(set, -parentvar->locdom.lb) || SCIPsetIsInfinity(set, -oldbound)
7734  || SCIPsetIsFeasEQ(set, parentvar->locdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
7735  || (SCIPsetIsZero(set, parentvar->locdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
7736 
7737  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7738  {
7739  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7740  /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
7741  * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
7742  * as a result, the parent's lower bound is set to it's upper bound, and not above
7743  */
7744  if( parentnewbound > parentvar->glbdom.ub )
7745  {
7746  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7747  assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
7748  parentnewbound = parentvar->glbdom.ub;
7749  }
7750  }
7751  else
7752  parentnewbound = newbound;
7753  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7754  }
7755  else
7756  {
7757  SCIP_Real parentnewbound;
7758 
7759  /* a < 0 -> change upper bound of y */
7760  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7761  assert(SCIPsetIsInfinity(set, parentvar->locdom.ub) || SCIPsetIsInfinity(set, -oldbound)
7762  || SCIPsetIsFeasEQ(set, parentvar->locdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
7763  || (SCIPsetIsZero(set, parentvar->locdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
7764 
7765  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7766  {
7767  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7768  /* 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
7769  * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
7770  * as a result, the parent's upper bound is set to it's lower bound, and not below
7771  */
7772  if( parentnewbound < parentvar->glbdom.lb )
7773  {
7774  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7775  assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
7776  parentnewbound = parentvar->glbdom.lb;
7777  }
7778  }
7779  else
7780  parentnewbound = -newbound;
7781  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7782  }
7783  break;
7784 
7785  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
7786  assert(parentvar->negatedvar != NULL);
7787  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7788  assert(parentvar->negatedvar->negatedvar == parentvar);
7789  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
7790  parentvar->data.negate.constant - newbound) );
7791  break;
7792 
7793  default:
7794  SCIPerrorMessage("unknown variable status\n");
7795  return SCIP_INVALIDDATA;
7796  }
7797  }
7798 
7799  return SCIP_OKAY;
7800 }
7801 
7802 /** performs the current change in upper bound, changes all parents accordingly */
7803 static
7805  SCIP_VAR* var, /**< problem variable to change */
7806  BMS_BLKMEM* blkmem, /**< block memory */
7807  SCIP_SET* set, /**< global SCIP settings */
7808  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7809  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7810  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7811  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7812  SCIP_Real newbound /**< new bound for variable */
7813  )
7814 {
7815  SCIP_VAR* parentvar;
7816  SCIP_Real oldbound;
7817  int i;
7818 
7819  assert(var != NULL);
7820  assert(set != NULL);
7821  assert(var->scip == set->scip);
7822  assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)
7823  || SCIPsetIsEQ(set, newbound, var->locdom.lb)))
7824  || (SCIPvarGetType(var) < SCIP_VARTYPE_CONTINUOUS && (SCIPsetIsIntegral(set, newbound)
7825  || SCIPsetIsEQ(set, newbound, var->locdom.lb)))
7827 
7828  /* check that the bound is feasible */
7829  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsGE(set, newbound, var->glbdom.lb));
7830  /* adjust bound to integral value if variable is of integral type */
7831  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7832 
7833  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7834  {
7835  /* we do not want to undercut the lower bound, which could have happened due to numerics */
7836  newbound = MAX(newbound, var->locdom.lb);
7837 
7838  /* we do not want to exceed the global upper bound, which could have happened due to numerics */
7839  newbound = MIN(newbound, var->glbdom.ub);
7840  }
7841  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7842 
7843  SCIPsetDebugMsg(set, "process changing upper bound of <%s> from %g to %g\n", var->name, var->locdom.ub, newbound);
7844 
7845  if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) && var->glbdom.ub != var->locdom.ub ) /*lint !e777*/
7846  newbound = var->glbdom.ub;
7847  else if( SCIPsetIsEQ(set, newbound, var->locdom.ub) && !(newbound != var->locdom.ub && newbound * var->locdom.ub <= 0.0) ) /*lint !e777*/
7848  return SCIP_OKAY;
7849 
7850  /* change the bound */
7851  oldbound = var->locdom.ub;
7852  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->locdom.lb));
7853  var->locdom.ub = newbound;
7854 
7855  /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
7856  * once update the statistic
7857  */
7858  if( stat != NULL )
7859  SCIPstatIncrement(stat, set, domchgcount);
7860 
7861  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7862  {
7863  /* merges overlapping holes into single holes, moves bounds respectively */
7864  domMerge(&var->locdom, blkmem, set, NULL, &newbound);
7865  }
7866 
7867  /* issue bound change event */
7868  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7869  if( var->eventfilter != NULL )
7870  {
7871  SCIP_CALL( varEventUbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7872  }
7873 
7874  /* process parent variables */
7875  for( i = 0; i < var->nparentvars; ++i )
7876  {
7877  parentvar = var->parentvars[i];
7878  assert(parentvar != NULL);
7879 
7880  switch( SCIPvarGetStatus(parentvar) )
7881  {
7883  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
7884  break;
7885 
7886  case SCIP_VARSTATUS_COLUMN:
7887  case SCIP_VARSTATUS_LOOSE:
7888  case SCIP_VARSTATUS_FIXED:
7890  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7891  return SCIP_INVALIDDATA;
7892 
7893  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7894  assert(parentvar->data.aggregate.var == var);
7895  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7896  {
7897  SCIP_Real parentnewbound;
7898 
7899  /* a > 0 -> change upper bound of x */
7900  assert(SCIPsetIsInfinity(set, parentvar->locdom.ub) || SCIPsetIsInfinity(set, oldbound)
7901  || SCIPsetIsFeasEQ(set, parentvar->locdom.ub,
7902  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7903  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7904  {
7905  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7906  /* 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
7907  * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
7908  * as a result, the parent's upper bound is set to it's lower bound, and not below
7909  */
7910  if( parentnewbound < parentvar->glbdom.lb )
7911  {
7912  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7913  assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
7914  parentnewbound = parentvar->glbdom.lb;
7915  }
7916  }
7917  else
7918  parentnewbound = newbound;
7919  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7920  }
7921  else
7922  {
7923  SCIP_Real parentnewbound;
7924 
7925  /* a < 0 -> change lower bound of x */
7926  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7927  assert(SCIPsetIsInfinity(set, -parentvar->locdom.lb) || SCIPsetIsInfinity(set, oldbound)
7928  || SCIPsetIsFeasEQ(set, parentvar->locdom.lb,
7929  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7930  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7931  {
7932  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7933  /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
7934  * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
7935  * as a result, the parent's lower bound is set to it's upper bound, and not above
7936  */
7937  if( parentnewbound > parentvar->glbdom.ub )
7938  {
7939  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7940  assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
7941  parentnewbound = parentvar->glbdom.ub;
7942  }
7943  }
7944  else
7945  parentnewbound = -newbound;
7946  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7947  }
7948  break;
7949 
7950  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
7951  assert(parentvar->negatedvar != NULL);
7952  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7953  assert(parentvar->negatedvar->negatedvar == parentvar);
7954  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
7955  parentvar->data.negate.constant - newbound) );
7956  break;
7957 
7958  default:
7959  SCIPerrorMessage("unknown variable status\n");
7960  return SCIP_INVALIDDATA;
7961  }
7962  }
7963 
7964  return SCIP_OKAY;
7965 }
7966 
7967 /** changes current local lower bound of variable; if possible, adjusts bound to integral value; stores inference
7968  * information in variable
7969  */
7971  SCIP_VAR* var, /**< problem variable to change */
7972  BMS_BLKMEM* blkmem, /**< block memory */
7973  SCIP_SET* set, /**< global SCIP settings */
7974  SCIP_STAT* stat, /**< problem statistics */
7975  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7976  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7977  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7978  SCIP_Real newbound /**< new bound for variable */
7979  )
7980 {
7981  assert(var != NULL);
7982  assert(blkmem != NULL);
7983  assert(set != NULL);
7984  assert(var->scip == set->scip);
7985 
7986  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7987  * of the domain within feastol
7988  */
7989  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
7990 
7991  /* adjust bound to integral value if variable is of integral type */
7992  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7993 
7994  /* check that the adjusted bound is feasible */
7995  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
7996 
7997  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7998  {
7999  /* we do not want to exceed the upperbound, which could have happened due to numerics */
8000  newbound = MIN(newbound, var->locdom.ub);
8001  }
8002  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
8003 
8004  SCIPsetDebugMsg(set, "changing lower bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
8005 
8006  if( SCIPsetIsEQ(set, var->locdom.lb, newbound) && (!SCIPsetIsEQ(set, var->glbdom.lb, newbound) || var->locdom.lb == newbound) /*lint !e777*/
8007  && !(newbound != var->locdom.lb && newbound * var->locdom.lb <= 0.0) ) /*lint !e777*/
8008  return SCIP_OKAY;
8009 
8010  /* change bounds of attached variables */
8011  switch( SCIPvarGetStatus(var) )
8012  {
8014  if( var->data.original.transvar != NULL )
8015  {
8016  SCIP_CALL( SCIPvarChgLbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
8017  newbound) );
8018  }
8019  else
8020  {
8021  assert(set->stage == SCIP_STAGE_PROBLEM);
8022  SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8023  }
8024  break;
8025 
8026  case SCIP_VARSTATUS_COLUMN:
8027  case SCIP_VARSTATUS_LOOSE:
8028  SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8029  break;
8030 
8031  case SCIP_VARSTATUS_FIXED:
8032  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8033  return SCIP_INVALIDDATA;
8034 
8035  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8036  assert(var->data.aggregate.var != NULL);
8037  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8038  {
8039  SCIP_Real childnewbound;
8040 
8041  /* a > 0 -> change lower bound of y */
8042  assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, -var->data.aggregate.var->locdom.lb))
8043  || SCIPsetIsFeasEQ(set, var->locdom.lb,
8045  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8046  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8047  else
8048  childnewbound = newbound;
8049  SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
8050  childnewbound) );
8051  }
8052  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8053  {
8054  SCIP_Real childnewbound;
8055 
8056  /* a < 0 -> change upper bound of y */
8057  assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->locdom.ub))
8058  || SCIPsetIsFeasEQ(set, var->locdom.lb,
8060  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8061  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8062  else
8063  childnewbound = -newbound;
8064  SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
8065  childnewbound) );
8066  }
8067  else
8068  {
8069  SCIPerrorMessage("scalar is zero in aggregation\n");
8070  return SCIP_INVALIDDATA;
8071  }
8072  break;
8073 
8075  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8076  return SCIP_INVALIDDATA;
8077 
8078  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8079  assert(var->negatedvar != NULL);
8081  assert(var->negatedvar->negatedvar == var);
8082  SCIP_CALL( SCIPvarChgUbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
8083  var->data.negate.constant - newbound) );
8084  break;
8085 
8086  default:
8087  SCIPerrorMessage("unknown variable status\n");
8088  return SCIP_INVALIDDATA;
8089  }
8090 
8091  return SCIP_OKAY;
8092 }
8093 
8094 /** changes current local upper bound of variable; if possible, adjusts bound to integral value; stores inference
8095  * information in variable
8096  */
8098  SCIP_VAR* var, /**< problem variable to change */
8099  BMS_BLKMEM* blkmem, /**< block memory */
8100  SCIP_SET* set, /**< global SCIP settings */
8101  SCIP_STAT* stat, /**< problem statistics */
8102  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
8103  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
8104  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8105  SCIP_Real newbound /**< new bound for variable */
8106  )
8107 {
8108  assert(var != NULL);
8109  assert(blkmem != NULL);
8110  assert(set != NULL);
8111  assert(var->scip == set->scip);
8112 
8113  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
8114  * of the domain within feastol
8115  */
8116  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
8117 
8118  /* adjust bound to integral value if variable is of integral type */
8119  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
8120 
8121  /* check that the adjusted bound is feasible */
8122  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
8123 
8124  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
8125  {
8126  /* we do not want to undercut the lowerbound, which could have happened due to numerics */
8127  newbound = MAX(newbound, var->locdom.lb);
8128  }
8129  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
8130 
8131  SCIPsetDebugMsg(set, "changing upper bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
8132 
8133  if( SCIPsetIsEQ(set, var->locdom.ub, newbound) && (!SCIPsetIsEQ(set, var->glbdom.ub, newbound) || var->locdom.ub == newbound) /*lint !e777*/
8134  && !(newbound != var->locdom.ub && newbound * var->locdom.ub <= 0.0) ) /*lint !e777*/
8135  return SCIP_OKAY;
8136 
8137  /* change bounds of attached variables */
8138  switch( SCIPvarGetStatus(var) )
8139  {
8141  if( var->data.original.transvar != NULL )
8142  {
8143  SCIP_CALL( SCIPvarChgUbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8144  }
8145  else
8146  {
8147  assert(set->stage == SCIP_STAGE_PROBLEM);
8148  SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8149  }
8150  break;
8151 
8152  case SCIP_VARSTATUS_COLUMN:
8153  case SCIP_VARSTATUS_LOOSE:
8154  SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8155  break;
8156 
8157  case SCIP_VARSTATUS_FIXED:
8158  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8159  return SCIP_INVALIDDATA;
8160 
8161  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8162  assert(var->data.aggregate.var != NULL);
8163  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8164  {
8165  SCIP_Real childnewbound;
8166 
8167  /* a > 0 -> change upper bound of y */
8168  assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, var->data.aggregate.var->locdom.ub))
8169  || SCIPsetIsFeasEQ(set, var->locdom.ub,
8171  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8172  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8173  else
8174  childnewbound = newbound;
8175  SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
8176  childnewbound) );
8177  }
8178  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8179  {
8180  SCIP_Real childnewbound;
8181 
8182  /* a < 0 -> change lower bound of y */
8183  assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, -var->data.aggregate.var->locdom.lb))
8184  || SCIPsetIsFeasEQ(set, var->locdom.ub,
8186  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8187  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8188  else
8189  childnewbound = -newbound;
8190  SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
8191  childnewbound) );
8192  }
8193  else
8194  {
8195  SCIPerrorMessage("scalar is zero in aggregation\n");
8196  return SCIP_INVALIDDATA;
8197  }
8198  break;
8199 
8201  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8202  return SCIP_INVALIDDATA;
8203 
8204  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8205  assert(var->negatedvar != NULL);
8207  assert(var->negatedvar->negatedvar == var);
8208  SCIP_CALL( SCIPvarChgLbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
8209  var->data.negate.constant - newbound) );
8210  break;
8211 
8212  default:
8213  SCIPerrorMessage("unknown variable status\n");
8214  return SCIP_INVALIDDATA;
8215  }
8216 
8217  return SCIP_OKAY;
8218 }
8219 
8220 /** changes current local bound of variable; if possible, adjusts bound to integral value; stores inference
8221  * information in variable
8222  */
8224  SCIP_VAR* var, /**< problem variable to change */
8225  BMS_BLKMEM* blkmem, /**< block memory */
8226  SCIP_SET* set, /**< global SCIP settings */
8227  SCIP_STAT* stat, /**< problem statistics */
8228  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
8229  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
8230  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8231  SCIP_Real newbound, /**< new bound for variable */
8232  SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
8233  )
8234 {
8235  /* apply bound change to the LP data */
8236  switch( boundtype )
8237  {
8238  case SCIP_BOUNDTYPE_LOWER:
8239  return SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
8240  case SCIP_BOUNDTYPE_UPPER:
8241  return SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
8242  default:
8243  SCIPerrorMessage("unknown bound type\n");
8244  return SCIP_INVALIDDATA;
8245  }
8246 }
8247 
8248 /** changes lower bound of variable in current dive; if possible, adjusts bound to integral value */
8250  SCIP_VAR* var, /**< problem variable to change */
8251  SCIP_SET* set, /**< global SCIP settings */
8252  SCIP_LP* lp, /**< current LP data */
8253  SCIP_Real newbound /**< new bound for variable */
8254  )
8255 {
8256  assert(var != NULL);
8257  assert(set != NULL);
8258  assert(var->scip == set->scip);
8259  assert(lp != NULL);
8260  assert(SCIPlpDiving(lp));
8261 
8262  /* adjust bound for integral variables */
8263  SCIPvarAdjustLb(var, set, &newbound);
8264 
8265  SCIPsetDebugMsg(set, "changing lower bound of <%s> to %g in current dive\n", var->name, newbound);
8266 
8267  /* change bounds of attached variables */
8268  switch( SCIPvarGetStatus(var) )
8269  {
8271  assert(var->data.original.transvar != NULL);
8272  SCIP_CALL( SCIPvarChgLbDive(var->data.original.transvar, set, lp, newbound) );
8273  break;
8274 
8275  case SCIP_VARSTATUS_COLUMN:
8276  assert(var->data.col != NULL);
8277  SCIP_CALL( SCIPcolChgLb(var->data.col, set, lp, newbound) );
8278  break;
8279 
8280  case SCIP_VARSTATUS_LOOSE:
8281  SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
8282  return SCIP_INVALIDDATA;
8283 
8284  case SCIP_VARSTATUS_FIXED:
8285  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8286  return SCIP_INVALIDDATA;
8287 
8288  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8289  assert(var->data.aggregate.var != NULL);
8290  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8291  {
8292  SCIP_Real childnewbound;
8293 
8294  /* a > 0 -> change lower bound of y */
8295  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8296  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8297  else
8298  childnewbound = newbound;
8299  SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
8300  }
8301  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8302  {
8303  SCIP_Real childnewbound;
8304 
8305  /* a < 0 -> change upper bound of y */
8306  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8307  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8308  else
8309  childnewbound = -newbound;
8310  SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
8311  }
8312  else
8313  {
8314  SCIPerrorMessage("scalar is zero in aggregation\n");
8315  return SCIP_INVALIDDATA;
8316  }
8317  break;
8318 
8320  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8321  return SCIP_INVALIDDATA;
8322 
8323  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8324  assert(var->negatedvar != NULL);
8326  assert(var->negatedvar->negatedvar == var);
8327  SCIP_CALL( SCIPvarChgUbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
8328  break;
8329 
8330  default:
8331  SCIPerrorMessage("unknown variable status\n");
8332  return SCIP_INVALIDDATA;
8333  }
8334 
8335  return SCIP_OKAY;
8336 }
8337 
8338 /** changes upper bound of variable in current dive; if possible, adjusts bound to integral value */
8340  SCIP_VAR* var, /**< problem variable to change */
8341  SCIP_SET* set, /**< global SCIP settings */
8342  SCIP_LP* lp, /**< current LP data */
8343  SCIP_Real newbound /**< new bound for variable */
8344  )
8345 {
8346  assert(var != NULL);
8347  assert(set != NULL);
8348  assert(var->scip == set->scip);
8349  assert(lp != NULL);
8350  assert(SCIPlpDiving(lp));
8351 
8352  /* adjust bound for integral variables */
8353  SCIPvarAdjustUb(var, set, &newbound);
8354 
8355  SCIPsetDebugMsg(set, "changing upper bound of <%s> to %g in current dive\n", var->name, newbound);
8356 
8357  /* change bounds of attached variables */
8358  switch( SCIPvarGetStatus(var) )
8359  {
8361  assert(var->data.original.transvar != NULL);
8362  SCIP_CALL( SCIPvarChgUbDive(var->data.original.transvar, set, lp, newbound) );
8363  break;
8364 
8365  case SCIP_VARSTATUS_COLUMN:
8366  assert(var->data.col != NULL);
8367  SCIP_CALL( SCIPcolChgUb(var->data.col, set, lp, newbound) );
8368  break;
8369 
8370  case SCIP_VARSTATUS_LOOSE:
8371  SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
8372  return SCIP_INVALIDDATA;
8373 
8374  case SCIP_VARSTATUS_FIXED:
8375  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8376  return SCIP_INVALIDDATA;
8377 
8378  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8379  assert(var->data.aggregate.var != NULL);
8380  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8381  {
8382  SCIP_Real childnewbound;
8383 
8384  /* a > 0 -> change upper bound of y */
8385  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8386  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8387  else
8388  childnewbound = newbound;
8389  SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
8390  }
8391  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8392  {
8393  SCIP_Real childnewbound;
8394 
8395  /* a < 0 -> change lower bound of y */
8396  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8397  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8398  else
8399  childnewbound = -newbound;
8400  SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
8401  }
8402  else
8403  {
8404  SCIPerrorMessage("scalar is zero in aggregation\n");
8405  return SCIP_INVALIDDATA;
8406  }
8407  break;
8408 
8410  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8411  return SCIP_INVALIDDATA;
8412 
8413  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8414  assert(var->negatedvar != NULL);
8416  assert(var->negatedvar->negatedvar == var);
8417  SCIP_CALL( SCIPvarChgLbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
8418  break;
8419 
8420  default:
8421  SCIPerrorMessage("unknown variable status\n");
8422  return SCIP_INVALIDDATA;
8423  }
8424 
8425  return SCIP_OKAY;
8426 }
8427 
8428 /** for a multi-aggregated variable, gives the local lower bound computed by adding the local bounds from all
8429  * aggregation variables, this lower bound may be tighter than the one given by SCIPvarGetLbLocal, since the latter is
8430  * not updated if bounds of aggregation variables are changing
8431  *
8432  * calling this function for a non-multi-aggregated variable is not allowed
8433  */
8435  SCIP_VAR* var, /**< problem variable */
8436  SCIP_SET* set /**< global SCIP settings */
8437  )
8438 {
8439  int i;
8440  SCIP_Real lb;
8441  SCIP_Real bnd;
8442  SCIP_VAR* aggrvar;
8443  SCIP_Bool posinf;
8444  SCIP_Bool neginf;
8445 
8446  assert(var != NULL);
8447  assert(set != NULL);
8448  assert(var->scip == set->scip);
8450 
8451  posinf = FALSE;
8452  neginf = FALSE;
8453  lb = var->data.multaggr.constant;
8454  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8455  {
8456  aggrvar = var->data.multaggr.vars[i];
8457  if( var->data.multaggr.scalars[i] > 0.0 )
8458  {
8459  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbLocal(aggrvar, set) : SCIPvarGetLbLocal(aggrvar);
8460 
8461  if( SCIPsetIsInfinity(set, bnd) )
8462  posinf = TRUE;
8463  else if( SCIPsetIsInfinity(set, -bnd) )
8464  neginf = TRUE;
8465  else
8466  lb += var->data.multaggr.scalars[i] * bnd;
8467  }
8468  else
8469  {
8470  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbLocal(aggrvar, set) : SCIPvarGetUbLocal(aggrvar);
8471 
8472  if( SCIPsetIsInfinity(set, -bnd) )
8473  posinf = TRUE;
8474  else if( SCIPsetIsInfinity(set, bnd) )
8475  neginf = TRUE;
8476  else
8477  lb += var->data.multaggr.scalars[i] * bnd;
8478  }
8479 
8480  /* stop if two diffrent infinities (or a -infinity) were found and return local lower bound of multi aggregated
8481  * variable
8482  */
8483  if( neginf )
8484  return SCIPvarGetLbLocal(var);
8485  }
8486 
8487  /* if positive infinity flag was set to true return infinity */
8488  if( posinf )
8489  return SCIPsetInfinity(set);
8490 
8491  return (MAX(lb, SCIPvarGetLbLocal(var))); /*lint !e666*/
8492 }
8493 
8494 /** for a multi-aggregated variable, gives the local upper bound computed by adding the local bounds from all
8495  * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbLocal, since the latter is
8496  * not updated if bounds of aggregation variables are changing
8497  *
8498  * calling this function for a non-multi-aggregated variable is not allowed
8499  */
8501  SCIP_VAR* var, /**< problem variable */
8502  SCIP_SET* set /**< global SCIP settings */
8503  )
8504 {
8505  int i;
8506  SCIP_Real ub;
8507  SCIP_Real bnd;
8508  SCIP_VAR* aggrvar;
8509  SCIP_Bool posinf;
8510  SCIP_Bool neginf;
8511 
8512  assert(var != NULL);
8513  assert(set != NULL);
8514  assert(var->scip == set->scip);
8516 
8517  posinf = FALSE;
8518  neginf = FALSE;
8519  ub = var->data.multaggr.constant;
8520  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8521  {
8522  aggrvar = var->data.multaggr.vars[i];
8523  if( var->data.multaggr.scalars[i] > 0.0 )
8524  {
8525  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbLocal(aggrvar, set) : SCIPvarGetUbLocal(aggrvar);
8526 
8527  if( SCIPsetIsInfinity(set, bnd) )
8528  posinf = TRUE;
8529  else if( SCIPsetIsInfinity(set, -bnd) )
8530  neginf = TRUE;
8531  else
8532  ub += var->data.multaggr.scalars[i] * bnd;
8533  }
8534  else
8535  {
8536  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbLocal(aggrvar, set) : SCIPvarGetLbLocal(aggrvar);
8537 
8538  if( SCIPsetIsInfinity(set, -bnd) )
8539  posinf = TRUE;
8540  else if( SCIPsetIsInfinity(set, bnd) )
8541  neginf = TRUE;
8542  else
8543  ub += var->data.multaggr.scalars[i] * bnd;
8544  }
8545 
8546  /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
8547  * variable
8548  */
8549  if( posinf )
8550  return SCIPvarGetUbLocal(var);
8551  }
8552 
8553  /* if negative infinity flag was set to true return -infinity */
8554  if( neginf )
8555  return -SCIPsetInfinity(set);
8556 
8557  return (MIN(ub, SCIPvarGetUbLocal(var))); /*lint !e666*/
8558 }
8559 
8560 /** for a multi-aggregated variable, gives the global lower bound computed by adding the global bounds from all
8561  * aggregation variables, this global bound may be tighter than the one given by SCIPvarGetLbGlobal, since the latter is
8562  * not updated if bounds of aggregation variables are changing
8563  *
8564  * calling this function for a non-multi-aggregated variable is not allowed
8565  */
8567  SCIP_VAR* var, /**< problem variable */
8568  SCIP_SET* set /**< global SCIP settings */
8569  )
8570 {
8571  int i;
8572  SCIP_Real lb;
8573  SCIP_Real bnd;
8574  SCIP_VAR* aggrvar;
8575  SCIP_Bool posinf;
8576  SCIP_Bool neginf;
8577 
8578  assert(var != NULL);
8579  assert(set != NULL);
8580  assert(var->scip == set->scip);
8582 
8583  posinf = FALSE;
8584  neginf = FALSE;
8585  lb = var->data.multaggr.constant;
8586  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8587  {
8588  aggrvar = var->data.multaggr.vars[i];
8589  if( var->data.multaggr.scalars[i] > 0.0 )
8590  {
8591  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbGlobal(aggrvar, set) : SCIPvarGetLbGlobal(aggrvar);
8592 
8593  if( SCIPsetIsInfinity(set, bnd) )
8594  posinf = TRUE;
8595  else if( SCIPsetIsInfinity(set, -bnd) )
8596  neginf = TRUE;
8597  else
8598  lb += var->data.multaggr.scalars[i] * bnd;
8599  }
8600  else
8601  {
8602  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbGlobal(aggrvar, set) : SCIPvarGetUbGlobal(aggrvar);
8603 
8604  if( SCIPsetIsInfinity(set, -bnd) )
8605  posinf = TRUE;
8606  else if( SCIPsetIsInfinity(set, bnd) )
8607  neginf = TRUE;
8608  else
8609  lb += var->data.multaggr.scalars[i] * bnd;
8610  }
8611 
8612  /* stop if two diffrent infinities (or a -infinity) were found and return global lower bound of multi aggregated
8613  * variable
8614  */
8615  if( neginf )
8616  return SCIPvarGetLbGlobal(var);
8617  }
8618 
8619  /* if positive infinity flag was set to true return infinity */
8620  if( posinf )
8621  return SCIPsetInfinity(set);
8622 
8623  return (MAX(lb, SCIPvarGetLbGlobal(var))); /*lint !e666*/
8624 }
8625 
8626 /** for a multi-aggregated variable, gives the global upper bound computed by adding the global bounds from all
8627  * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbGlobal, since the latter is
8628  * not updated if bounds of aggregation variables are changing
8629  *
8630  * calling this function for a non-multi-aggregated variable is not allowed
8631  */
8633  SCIP_VAR* var, /**< problem variable */
8634  SCIP_SET* set /**< global SCIP settings */
8635  )
8636 {
8637  int i;
8638  SCIP_Real ub;
8639  SCIP_Real bnd;
8640  SCIP_VAR* aggrvar;
8641  SCIP_Bool posinf;
8642  SCIP_Bool neginf;
8643 
8644  assert(var != NULL);
8645  assert(set != NULL);
8646  assert(var->scip == set->scip);
8648 
8649  posinf = FALSE;
8650  neginf = FALSE;
8651  ub = var->data.multaggr.constant;
8652  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8653  {
8654  aggrvar = var->data.multaggr.vars[i];
8655  if( var->data.multaggr.scalars[i] > 0.0 )
8656  {
8657  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbGlobal(aggrvar, set) : SCIPvarGetUbGlobal(aggrvar);
8658 
8659  if( SCIPsetIsInfinity(set, bnd) )
8660  posinf = TRUE;
8661  else if( SCIPsetIsInfinity(set, -bnd) )
8662  neginf = TRUE;
8663  else
8664  ub += var->data.multaggr.scalars[i] * bnd;
8665  }
8666  else
8667  {
8668  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbGlobal(aggrvar, set) : SCIPvarGetLbGlobal(aggrvar);
8669 
8670  if( SCIPsetIsInfinity(set, -bnd) )
8671  posinf = TRUE;
8672  else if( SCIPsetIsInfinity(set, bnd) )
8673  neginf = TRUE;
8674  else
8675  ub += var->data.multaggr.scalars[i] * bnd;
8676  }
8677 
8678  /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
8679  * variable
8680  */
8681  if( posinf )
8682  return SCIPvarGetUbGlobal(var);
8683  }
8684 
8685  /* if negative infinity flag was set to true return -infinity */
8686  if( neginf )
8687  return -SCIPsetInfinity(set);
8688 
8689  return (MIN(ub, SCIPvarGetUbGlobal(var))); /*lint !e666*/
8690 }
8691 
8692 /** adds a hole to the original domain of the variable */
8694  SCIP_VAR* var, /**< problem variable */
8695  BMS_BLKMEM* blkmem, /**< block memory */
8696  SCIP_SET* set, /**< global SCIP settings */
8697  SCIP_Real left, /**< left bound of open interval in new hole */
8698  SCIP_Real right /**< right bound of open interval in new hole */
8699  )
8700 {
8701  SCIP_Bool added;
8702 
8703  assert(var != NULL);
8704  assert(!SCIPvarIsTransformed(var));
8706  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8707  assert(set != NULL);
8708  assert(var->scip == set->scip);
8709  assert(set->stage == SCIP_STAGE_PROBLEM);
8710 
8711  SCIPsetDebugMsg(set, "adding original hole (%g,%g) to <%s>\n", left, right, var->name);
8712 
8713  if( SCIPsetIsEQ(set, left, right) )
8714  return SCIP_OKAY;
8715 
8716  /* the interval should not be empty */
8717  assert(SCIPsetIsLT(set, left, right));
8718 
8719  /* the the interval bound should already be adjusted */
8720  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8721  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8722 
8723  /* the the interval should lay between the lower and upper bound */
8724  assert(SCIPsetIsGE(set, left, SCIPvarGetLbOriginal(var)));
8725  assert(SCIPsetIsLE(set, right, SCIPvarGetUbOriginal(var)));
8726 
8727  /* add domain hole */
8728  SCIP_CALL( domAddHole(&var->data.original.origdom, blkmem, set, left, right, &added) );
8729 
8730  /* merges overlapping holes into single holes, moves bounds respectively if hole was added */
8731  if( added )
8732  {
8733  domMerge(&var->data.original.origdom, blkmem, set, NULL, NULL);
8734  }
8735 
8736  /**@todo add hole in parent and child variables (just like with bound changes);
8737  * warning! original vars' holes are in original blkmem, transformed vars' holes in transformed blkmem
8738  */
8739 
8740  return SCIP_OKAY;
8741 }
8742 
8743 /** performs the current add of domain, changes all parents accordingly */
8744 static
8746  SCIP_VAR* var, /**< problem variable */
8747  BMS_BLKMEM* blkmem, /**< block memory */
8748  SCIP_SET* set, /**< global SCIP settings */
8749  SCIP_STAT* stat, /**< problem statistics */
8750  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8751  SCIP_Real left, /**< left bound of open interval in new hole */
8752  SCIP_Real right, /**< right bound of open interval in new hole */
8753  SCIP_Bool* added /**< pointer to store whether the hole was added */
8754  )
8755 {
8756  SCIP_VAR* parentvar;
8757  SCIP_Real newlb;
8758  SCIP_Real newub;
8759  int i;
8760 
8761  assert(var != NULL);
8762  assert(added != NULL);
8763  assert(blkmem != NULL);
8764 
8765  /* the interval should not be empty */
8766  assert(SCIPsetIsLT(set, left, right));
8767 
8768  /* the interval bound should already be adjusted */
8769  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8770  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8771 
8772  /* the interval should lay between the lower and upper bound */
8773  assert(SCIPsetIsGE(set, left, SCIPvarGetLbGlobal(var)));
8774  assert(SCIPsetIsLE(set, right, SCIPvarGetUbGlobal(var)));
8775 
8776  /* @todo add debugging mechanism for holes when using a debugging solution */
8777 
8778  /* add hole to hole list */
8779  SCIP_CALL( domAddHole(&var->glbdom, blkmem, set, left, right, added) );
8780 
8781  /* check if the hole is redundant */
8782  if( !(*added) )
8783  return SCIP_OKAY;
8784 
8785  /* current bounds */
8786  newlb = var->glbdom.lb;
8787  newub = var->glbdom.ub;
8788 
8789  /* merge domain holes */
8790  domMerge(&var->glbdom, blkmem, set, &newlb, &newub);
8791 
8792  /* the bound should not be changed */
8793  assert(SCIPsetIsEQ(set, newlb, var->glbdom.lb));
8794  assert(SCIPsetIsEQ(set, newub, var->glbdom.ub));
8795 
8796  /* issue bound change event */
8797  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
8798  if( var->eventfilter != NULL )
8799  {
8800  SCIP_CALL( varEventGholeAdded(var, blkmem, set, eventqueue, left, right) );
8801  }
8802 
8803  /* process parent variables */
8804  for( i = 0; i < var->nparentvars; ++i )
8805  {
8806  SCIP_Real parentnewleft;
8807  SCIP_Real parentnewright;
8808  SCIP_Bool localadded;
8809 
8810  parentvar = var->parentvars[i];
8811  assert(parentvar != NULL);
8812 
8813  switch( SCIPvarGetStatus(parentvar) )
8814  {
8816  parentnewleft = left;
8817  parentnewright = right;
8818  break;
8819 
8820  case SCIP_VARSTATUS_COLUMN:
8821  case SCIP_VARSTATUS_LOOSE:
8822  case SCIP_VARSTATUS_FIXED:
8824  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
8825  return SCIP_INVALIDDATA;
8826 
8827  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8828  assert(parentvar->data.aggregate.var == var);
8829 
8830  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
8831  {
8832  /* a > 0 -> change upper bound of x */
8833  parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8834  parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8835  }
8836  else
8837  {
8838  /* a < 0 -> change lower bound of x */
8839  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
8840 
8841  parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8842  parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8843  }
8844  break;
8845 
8846  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
8847  assert(parentvar->negatedvar != NULL);
8848  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
8849  assert(parentvar->negatedvar->negatedvar == parentvar);
8850 
8851  parentnewright = -left + parentvar->data.negate.constant;
8852  parentnewleft = -right + parentvar->data.negate.constant;
8853  break;
8854 
8855  default:
8856  SCIPerrorMessage("unknown variable status\n");
8857  return SCIP_INVALIDDATA;
8858  }
8859 
8860  SCIPsetDebugMsg(set, "add global hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
8861 
8862  /* perform hole added for parent variable */
8863  assert(blkmem != NULL);
8864  assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
8865  SCIP_CALL( varProcessAddHoleGlobal(parentvar, blkmem, set, stat, eventqueue,
8866  parentnewleft, parentnewright, &localadded) );
8867  assert(localadded);
8868  }
8869 
8870  return SCIP_OKAY;
8871 }
8872 
8873 /** adds a hole to the variable's global and local domain */
8875  SCIP_VAR* var, /**< problem variable */
8876  BMS_BLKMEM* blkmem, /**< block memory */
8877  SCIP_SET* set, /**< global SCIP settings */
8878  SCIP_STAT* stat, /**< problem statistics */
8879  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8880  SCIP_Real left, /**< left bound of open interval in new hole */
8881  SCIP_Real right, /**< right bound of open interval in new hole */
8882  SCIP_Bool* added /**< pointer to store whether the hole was added */
8883  )
8884 {
8885  SCIP_Real childnewleft;
8886  SCIP_Real childnewright;
8887 
8888  assert(var != NULL);
8889  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8890  assert(blkmem != NULL);
8891  assert(added != NULL);
8892 
8893  SCIPsetDebugMsg(set, "adding global hole (%g,%g) to <%s>\n", left, right, var->name);
8894 
8895  /* the interval should not be empty */
8896  assert(SCIPsetIsLT(set, left, right));
8897 
8898  /* the the interval bound should already be adjusted */
8899  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8900  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8901 
8902  /* the the interval should lay between the lower and upper bound */
8903  assert(SCIPsetIsGE(set, left, SCIPvarGetLbGlobal(var)));
8904  assert(SCIPsetIsLE(set, right, SCIPvarGetUbGlobal(var)));
8905 
8906  /* change bounds of attached variables */
8907  switch( SCIPvarGetStatus(var) )
8908  {
8910  if( var->data.original.transvar != NULL )
8911  {
8912  SCIP_CALL( SCIPvarAddHoleGlobal(var->data.original.transvar, blkmem, set, stat, eventqueue,
8913  left, right, added) );
8914  }
8915  else
8916  {
8917  assert(set->stage == SCIP_STAGE_PROBLEM);
8918 
8919  SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
8920  if( *added )
8921  {
8922  SCIP_Bool localadded;
8923 
8924  SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
8925  }
8926  }
8927  break;
8928 
8929  case SCIP_VARSTATUS_COLUMN:
8930  case SCIP_VARSTATUS_LOOSE:
8931  SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
8932  if( *added )
8933  {
8934  SCIP_Bool localadded;
8935 
8936  SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
8937  }
8938  break;
8939 
8940  case SCIP_VARSTATUS_FIXED:
8941  SCIPerrorMessage("cannot add hole of a fixed variable\n");
8942  return SCIP_INVALIDDATA;
8943 
8944  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8945  assert(var->data.aggregate.var != NULL);
8946 
8947  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8948  {
8949  /* a > 0 -> change lower bound of y */
8950  childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8951  childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8952  }
8953  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8954  {
8955  childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8956  childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8957  }
8958  else
8959  {
8960  SCIPerrorMessage("scalar is zero in aggregation\n");
8961  return SCIP_INVALIDDATA;
8962  }
8963  SCIP_CALL( SCIPvarAddHoleGlobal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
8964  childnewleft, childnewright, added) );
8965  break;
8966 
8968  SCIPerrorMessage("cannot add a hole of a multi-aggregated variable.\n");
8969  return SCIP_INVALIDDATA;
8970 
8971  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8972  assert(var->negatedvar != NULL);
8974  assert(var->negatedvar->negatedvar == var);
8975 
8976  childnewright = -left + var->data.negate.constant;
8977  childnewleft = -right + var->data.negate.constant;
8978 
8979  SCIP_CALL( SCIPvarAddHoleGlobal(var->negatedvar, blkmem, set, stat, eventqueue,
8980  childnewleft, childnewright, added) );
8981  break;
8982 
8983  default:
8984  SCIPerrorMessage("unknown variable status\n");
8985  return SCIP_INVALIDDATA;
8986  }
8987 
8988  return SCIP_OKAY;
8989 }
8990 
8991 /** performs the current add of domain, changes all parents accordingly */
8992 static
8994  SCIP_VAR* var, /**< problem variable */
8995  BMS_BLKMEM* blkmem, /**< block memory */
8996  SCIP_SET* set, /**< global SCIP settings */
8997  SCIP_STAT* stat, /**< problem statistics */
8998  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8999  SCIP_Real left, /**< left bound of open interval in new hole */
9000  SCIP_Real right, /**< right bound of open interval in new hole */
9001  SCIP_Bool* added /**< pointer to store whether the hole was added, or NULL */
9002  )
9003 {
9004  SCIP_VAR* parentvar;
9005  SCIP_Real newlb;
9006  SCIP_Real newub;
9007  int i;
9008 
9009  assert(var != NULL);
9010  assert(added != NULL);
9011  assert(blkmem != NULL);
9012 
9013  /* the interval should not be empty */
9014  assert(SCIPsetIsLT(set, left, right));
9015 
9016  /* the the interval bound should already be adjusted */
9017  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
9018  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
9019 
9020  /* the the interval should lay between the lower and upper bound */
9021  assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
9022  assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
9023 
9024  /* add hole to hole list */
9025  SCIP_CALL( domAddHole(&var->locdom, blkmem, set, left, right, added) );
9026 
9027  /* check if the hole is redundant */
9028  if( !(*added) )
9029  return SCIP_OKAY;
9030 
9031  /* current bounds */
9032  newlb = var->locdom.lb;
9033  newub = var->locdom.ub;
9034 
9035  /* merge domain holes */
9036  domMerge(&var->locdom, blkmem, set, &newlb, &newub);
9037 
9038  /* the bound should not be changed */
9039  assert(SCIPsetIsEQ(set, newlb, var->locdom.lb));
9040  assert(SCIPsetIsEQ(set, newub, var->locdom.ub));
9041 
9042 #if 0
9043  /* issue bound change event */
9044  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
9045  if( var->eventfilter != NULL )
9046  {
9047  SCIP_CALL( varEventLholeAdded(var, blkmem, set, lp, branchcand, eventqueue, left, right) );
9048  }
9049 #endif
9050 
9051  /* process parent variables */
9052  for( i = 0; i < var->nparentvars; ++i )
9053  {
9054  SCIP_Real parentnewleft;
9055  SCIP_Real parentnewright;
9056  SCIP_Bool localadded;
9057 
9058  parentvar = var->parentvars[i];
9059  assert(parentvar != NULL);
9060 
9061  switch( SCIPvarGetStatus(parentvar) )
9062  {
9064  parentnewleft = left;
9065  parentnewright = right;
9066  break;
9067 
9068  case SCIP_VARSTATUS_COLUMN:
9069  case SCIP_VARSTATUS_LOOSE:
9070  case SCIP_VARSTATUS_FIXED:
9072  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
9073  return SCIP_INVALIDDATA;
9074 
9075  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
9076  assert(parentvar->data.aggregate.var == var);
9077 
9078  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
9079  {
9080  /* a > 0 -> change upper bound of x */
9081  parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
9082  parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
9083  }
9084  else
9085  {
9086  /* a < 0 -> change lower bound of x */
9087  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
9088 
9089  parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
9090  parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
9091  }
9092  break;
9093 
9094  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
9095  assert(parentvar->negatedvar != NULL);
9096  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
9097  assert(parentvar->negatedvar->negatedvar == parentvar);
9098 
9099  parentnewright = -left + parentvar->data.negate.constant;
9100  parentnewleft = -right + parentvar->data.negate.constant;
9101  break;
9102 
9103  default:
9104  SCIPerrorMessage("unknown variable status\n");
9105  return SCIP_INVALIDDATA;
9106  }
9107 
9108  SCIPsetDebugMsg(set, "add local hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
9109 
9110  /* perform hole added for parent variable */
9111  assert(blkmem != NULL);
9112  assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
9113  SCIP_CALL( varProcessAddHoleLocal(parentvar, blkmem, set, stat, eventqueue,
9114  parentnewleft, parentnewright, &localadded) );
9115  assert(localadded);
9116  }
9117 
9118  return SCIP_OKAY;
9119 }
9120 
9121 /** adds a hole to the variable's current local domain */
9123  SCIP_VAR* var, /**< problem variable */
9124  BMS_BLKMEM* blkmem, /**< block memory */
9125  SCIP_SET* set, /**< global SCIP settings */
9126  SCIP_STAT* stat, /**< problem statistics */
9127  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
9128  SCIP_Real left, /**< left bound of open interval in new hole */
9129  SCIP_Real right, /**< right bound of open interval in new hole */
9130  SCIP_Bool* added /**< pointer to store whether the hole was added */
9131  )
9132 {
9133  SCIP_Real childnewleft;
9134  SCIP_Real childnewright;
9135 
9136  assert(var != NULL);
9137 
9138  SCIPsetDebugMsg(set, "adding local hole (%g,%g) to <%s>\n", left, right, var->name);
9139 
9140  assert(set != NULL);
9141  assert(var->scip == set->scip);
9142  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
9143  assert(blkmem != NULL);
9144  assert(added != NULL);
9145 
9146  /* the interval should not be empty */
9147  assert(SCIPsetIsLT(set, left, right));
9148 
9149  /* the the interval bound should already be adjusted */
9150  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
9151  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
9152 
9153  /* the the interval should lay between the lower and upper bound */
9154  assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
9155  assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
9156 
9157  /* change bounds of attached variables */
9158  switch( SCIPvarGetStatus(var) )
9159  {
9161  if( var->data.original.transvar != NULL )
9162  {
9163  SCIP_CALL( SCIPvarAddHoleLocal(var->data.original.transvar, blkmem, set, stat, eventqueue,
9164  left, right, added) );
9165  }
9166  else
9167  {
9168  assert(set->stage == SCIP_STAGE_PROBLEM);
9169  SCIPstatIncrement(stat, set, domchgcount);
9170  SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
9171  }
9172  break;
9173 
9174  case SCIP_VARSTATUS_COLUMN:
9175  case SCIP_VARSTATUS_LOOSE:
9176  SCIPstatIncrement(stat, set, domchgcount);
9177  SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
9178  break;
9179 
9180  case SCIP_VARSTATUS_FIXED:
9181  SCIPerrorMessage("cannot add domain hole to a fixed variable\n");
9182  return SCIP_INVALIDDATA;
9183 
9184  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
9185  assert(var->data.aggregate.var != NULL);
9186 
9187  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
9188  {
9189  /* a > 0 -> change lower bound of y */
9190  childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
9191  childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
9192  }
9193  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
9194  {
9195  childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
9196  childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
9197  }
9198  else
9199  {
9200  SCIPerrorMessage("scalar is zero in aggregation\n");
9201  return SCIP_INVALIDDATA;
9202  }
9203  SCIP_CALL( SCIPvarAddHoleLocal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
9204  childnewleft, childnewright, added) );
9205  break;
9206 
9208  SCIPerrorMessage("cannot add domain hole to a multi-aggregated variable.\n");
9209  return SCIP_INVALIDDATA;
9210 
9211  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
9212  assert(var->negatedvar != NULL);
9214  assert(var->negatedvar->negatedvar == var);
9215 
9216  childnewright = -left + var->data.negate.constant;
9217  childnewleft = -right + var->data.negate.constant;
9218 
9219  SCIP_CALL( SCIPvarAddHoleLocal(var->negatedvar, blkmem, set, stat, eventqueue, childnewleft, childnewright, added) );
9220  break;
9221 
9222  default:
9223  SCIPerrorMessage("unknown variable status\n");
9224  return SCIP_INVALIDDATA;
9225  }
9226 
9227  return SCIP_OKAY;
9228 }
9229 
9230 /** resets the global and local bounds of original variable to their original values */
9232  SCIP_VAR* var, /**< problem variable */
9233  BMS_BLKMEM* blkmem, /**< block memory */
9234  SCIP_SET* set, /**< global SCIP settings */
9235  SCIP_STAT* stat /**< problem statistics */
9236  )
9237 {
9238  assert(var != NULL);
9239  assert(set != NULL);
9240  assert(var->scip == set->scip);
9241  assert(SCIPvarIsOriginal(var));
9242  /* resetting of bounds on original variables which have a transformed counterpart easily fails if, e.g.,
9243  * the transformed variable has been fixed */
9244  assert(SCIPvarGetTransVar(var) == NULL);
9245 
9246  /* copy the original bounds back to the global and local bounds */
9247  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.lb) );
9248  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.ub) );
9249  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.lb) );
9250  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.ub) );
9251 
9252  /* free the global and local holelists and duplicate the original ones */
9253  /**@todo this has also to be called recursively with methods similar to SCIPvarChgLbGlobal() */
9254  holelistFree(&var->glbdom.holelist, blkmem);
9255  holelistFree(&var->locdom.holelist, blkmem);
9256  SCIP_CALL( holelistDuplicate(&var->glbdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
9257  SCIP_CALL( holelistDuplicate(&var->locdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
9258 
9259  return SCIP_OKAY;
9260 }
9261 
9262 /** issues a IMPLADDED event on the given variable */
9263 static
9265  SCIP_VAR* var, /**< problem variable to change */
9266  BMS_BLKMEM* blkmem, /**< block memory */
9267  SCIP_SET* set, /**< global SCIP settings */
9268  SCIP_EVENTQUEUE* eventqueue /**< event queue */
9269  )
9270 {
9271  SCIP_EVENT* event;
9272 
9273  assert(var != NULL);
9274 
9275  /* issue IMPLADDED event on variable */
9276  SCIP_CALL( SCIPeventCreateImplAdded(&event, blkmem, var) );
9277  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
9278 
9279  return SCIP_OKAY;
9280 }
9281 
9282 /** actually performs the addition of a variable bound to the variable's vbound arrays */
9283 static
9285  SCIP_VAR* var, /**< problem variable x in x <= b*z + d or x >= b*z + d */
9286  BMS_BLKMEM* blkmem, /**< block memory */
9287  SCIP_SET* set, /**< global SCIP settings */
9288  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9289  SCIP_BOUNDTYPE vbtype, /**< type of variable bound (LOWER or UPPER) */
9290  SCIP_VAR* vbvar, /**< variable z in x <= b*z + d or x >= b*z + d */
9291  SCIP_Real vbcoef, /**< coefficient b in x <= b*z + d or x >= b*z + d */
9292  SCIP_Real vbconstant /**< constant d in x <= b*z + d or x >= b*z + d */
9293  )
9294 {
9295  SCIP_Bool added;
9296 
9297  /* It can happen that the variable "var" and the variable "vbvar" are the same variable. For example if a variable
9298  * gets aggregated, the variable bounds (vbound) of that variable are copied to the other variable. A variable bound
9299  * variable of the aggregated variable might be the same as the one its gets aggregated too.
9300  *
9301  * If the variable "var" and the variable "vbvar" are the same, the variable bound which should be added here has to
9302  * be redundant. This is the case since an infeasibility should have be detected in the previous methods. As well as
9303  * the bounds of the variable which should be also already be tightened in the previous methods. Therefore, the
9304  * variable bound can be ignored.
9305  *
9306  * From the way the the variable bound system is implemented (detecting infeasibility, tighten bounds), the
9307  * equivalence of the variables should be checked here.
9308  */
9309  if( var == vbvar )
9310  {
9311  /* in this case the variable bound has to be redundant, this means for possible assignments to this variable; this
9312  * can be checked via the global bounds of the variable */
9313 #ifndef NDEBUG
9314  SCIP_Real lb;
9315  SCIP_Real ub;
9316 
9317  lb = SCIPvarGetLbGlobal(var);
9318  ub = SCIPvarGetUbGlobal(var);
9319 
9320  if(vbtype == SCIP_BOUNDTYPE_LOWER)
9321  {
9322  if( vbcoef > 0.0 )
9323  {
9324  assert(SCIPsetIsGE(set, lb, lb * vbcoef + vbconstant) );
9325  assert(SCIPsetIsGE(set, ub, ub * vbcoef + vbconstant) );
9326  }
9327  else
9328  {
9329  assert(SCIPsetIsGE(set, lb, ub * vbcoef + vbconstant) );
9330  assert(SCIPsetIsGE(set, ub, lb * vbcoef + vbconstant) );
9331  }
9332  }
9333  else
9334  {
9335  assert(vbtype == SCIP_BOUNDTYPE_UPPER);
9336  if( vbcoef > 0.0 )
9337  {
9338  assert(SCIPsetIsLE(set, lb, lb * vbcoef + vbconstant) );
9339  assert(SCIPsetIsLE(set, ub, ub * vbcoef + vbconstant) );
9340  }
9341  else
9342  {
9343  assert(SCIPsetIsLE(set, lb, ub * vbcoef + vbconstant) );
9344  assert(SCIPsetIsLE(set, ub, lb * vbcoef + vbconstant) );
9345  }
9346  }
9347 #endif
9348  SCIPsetDebugMsg(set, "redundant variable bound: <%s> %s %g<%s> %+g\n",
9349  SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
9350 
9351  return SCIP_OKAY;
9352  }
9353 
9354  SCIPsetDebugMsg(set, "adding variable bound: <%s> %s %g<%s> %+g\n",
9355  SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
9356 
9357  /* check variable bound on debugging solution */
9358  SCIP_CALL( SCIPdebugCheckVbound(set, var, vbtype, vbvar, vbcoef, vbconstant) ); /*lint !e506 !e774*/
9359 
9360  /* perform the addition */
9361  if( vbtype == SCIP_BOUNDTYPE_LOWER )
9362  {
9363  SCIP_CALL( SCIPvboundsAdd(&var->vlbs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
9364  }
9365  else
9366  {
9367  SCIP_CALL( SCIPvboundsAdd(&var->vubs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
9368  }
9369  var->closestvblpcount = -1;
9370 
9371  if( added )
9372  {
9373  /* issue IMPLADDED event */
9374  SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
9375  }
9376 
9377  return SCIP_OKAY;
9378 }
9379 
9380 /** checks whether the given implication is redundant or infeasible w.r.t. the implied variables global bounds */
9381 static
9382 void checkImplic(
9383  SCIP_SET* set, /**< global SCIP settings */
9384  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9385  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9386  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9387  SCIP_Bool* redundant, /**< pointer to store whether the implication is redundant */
9388  SCIP_Bool* infeasible /**< pointer to store whether the implication is infeasible */
9389  )
9390 {
9391  SCIP_Real impllb;
9392  SCIP_Real implub;
9393 
9394  assert(redundant != NULL);
9395  assert(infeasible != NULL);
9396 
9397  impllb = SCIPvarGetLbGlobal(implvar);
9398  implub = SCIPvarGetUbGlobal(implvar);
9399  if( impltype == SCIP_BOUNDTYPE_LOWER )
9400  {
9401  *infeasible = SCIPsetIsFeasGT(set, implbound, implub);
9402  *redundant = SCIPsetIsFeasLE(set, implbound, impllb);
9403  }
9404  else
9405  {
9406  *infeasible = SCIPsetIsFeasLT(set, implbound, impllb);
9407  *redundant = SCIPsetIsFeasGE(set, implbound, implub);
9408  }
9409 }
9410 
9411 /** applies the given implication, if it is not redundant */
9412 static
9414  BMS_BLKMEM* blkmem, /**< block memory */
9415  SCIP_SET* set, /**< global SCIP settings */
9416  SCIP_STAT* stat, /**< problem statistics */
9417  SCIP_PROB* transprob, /**< transformed problem */
9418  SCIP_PROB* origprob, /**< original problem */
9419  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9420  SCIP_REOPT* reopt, /**< reoptimization data structure */
9421  SCIP_LP* lp, /**< current LP data */
9422  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9423  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9424  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9425  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9426  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9427  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9428  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9429  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9430  )
9431 {
9432  SCIP_Real implub;
9433  SCIP_Real impllb;
9434 
9435  assert(infeasible != NULL);
9436 
9437  *infeasible = FALSE;
9438 
9439  implub = SCIPvarGetUbGlobal(implvar);
9440  impllb = SCIPvarGetLbGlobal(implvar);
9441  if( impltype == SCIP_BOUNDTYPE_LOWER )
9442  {
9443  if( SCIPsetIsFeasGT(set, implbound, implub) )
9444  {
9445  /* the implication produces a conflict: the problem is infeasible */
9446  *infeasible = TRUE;
9447  }
9448  else if( SCIPsetIsFeasGT(set, implbound, impllb) )
9449  {
9450  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9451  * with the local bound, in this case we need to store the bound change as pending bound change
9452  */
9453  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9454  {
9455  assert(tree != NULL);
9456  assert(transprob != NULL);
9457  assert(SCIPprobIsTransformed(transprob));
9458 
9459  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9460  tree, reopt, lp, branchcand, eventqueue, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
9461  }
9462  else
9463  {
9464  SCIP_CALL( SCIPvarChgLbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
9465  }
9466 
9467  if( nbdchgs != NULL )
9468  (*nbdchgs)++;
9469  }
9470  }
9471  else
9472  {
9473  if( SCIPsetIsFeasLT(set, implbound, impllb) )
9474  {
9475  /* the implication produces a conflict: the problem is infeasible */
9476  *infeasible = TRUE;
9477  }
9478  else if( SCIPsetIsFeasLT(set, implbound, implub) )
9479  {
9480  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9481  * with the local bound, in this case we need to store the bound change as pending bound change
9482  */
9483  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9484  {
9485  assert(tree != NULL);
9486  assert(transprob != NULL);
9487  assert(SCIPprobIsTransformed(transprob));
9488 
9489  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9490  tree, reopt, lp, branchcand, eventqueue, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
9491  }
9492  else
9493  {
9494  SCIP_CALL( SCIPvarChgUbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
9495  }
9496 
9497  if( nbdchgs != NULL )
9498  (*nbdchgs)++;
9499  }
9500  }
9501 
9502  return SCIP_OKAY;
9503 }
9504 
9505 /** actually performs the addition of an implication to the variable's implication arrays,
9506  * and adds the corresponding implication or variable bound to the implied variable;
9507  * if the implication is conflicting, the variable is fixed to the opposite value;
9508  * if the variable is already fixed to the given value, the implication is performed immediately;
9509  * if the implication is redundant with respect to the variables' global bounds, it is ignored
9510  */
9511 static
9513  SCIP_VAR* var, /**< problem variable */
9514  BMS_BLKMEM* blkmem, /**< block memory */
9515  SCIP_SET* set, /**< global SCIP settings */
9516  SCIP_STAT* stat, /**< problem statistics */
9517  SCIP_PROB* transprob, /**< transformed problem */
9518  SCIP_PROB* origprob, /**< original problem */
9519  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9520  SCIP_REOPT* reopt, /**< reoptimization data structure */
9521  SCIP_LP* lp, /**< current LP data */
9522  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9523  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9524  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9525  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9526  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9527  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9528  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9529  SCIP_Bool isshortcut, /**< is the implication a shortcut, i.e., added as part of the transitive closure of another implication? */
9530  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9531  int* nbdchgs, /**< pointer to count the number of performed bound changes, or NULL */
9532  SCIP_Bool* added /**< pointer to store whether an implication was added */
9533  )
9534 {
9535  SCIP_Bool redundant;
9536  SCIP_Bool conflict;
9537 
9538  assert(var != NULL);
9539  assert(SCIPvarIsActive(var));
9541  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
9542  assert(SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED);
9543  assert(infeasible != NULL);
9544  assert(added != NULL);
9545 
9546  /* check implication on debugging solution */
9547  SCIP_CALL( SCIPdebugCheckImplic(set, var, varfixing, implvar, impltype, implbound) ); /*lint !e506 !e774*/
9548 
9549  *infeasible = FALSE;
9550  *added = FALSE;
9551 
9552  /* check, if the implication is redundant or infeasible */
9553  checkImplic(set, implvar, impltype, implbound, &redundant, &conflict);
9554  assert(!redundant || !conflict);
9555  if( redundant )
9556  return SCIP_OKAY;
9557 
9558  if( var == implvar )
9559  {
9560  /* special cases appear were a bound to a variable implies itself to be outside the bounds:
9561  * x == varfixing => x < 0 or x > 1
9562  */
9563  if( SCIPsetIsLT(set, implbound, 0.0) || SCIPsetIsGT(set, implbound, 1.0) )
9564  conflict = TRUE;
9565  else
9566  {
9567  /* variable implies itself: x == varfixing => x == (impltype == SCIP_BOUNDTYPE_LOWER) */
9568  assert(SCIPsetIsZero(set, implbound) || SCIPsetIsEQ(set, implbound, 1.0));
9569  assert(SCIPsetIsZero(set, implbound) == (impltype == SCIP_BOUNDTYPE_UPPER));
9570  assert(SCIPsetIsEQ(set, implbound, 1.0) == (impltype == SCIP_BOUNDTYPE_LOWER));
9571  conflict = conflict || ((varfixing == TRUE) == (impltype == SCIP_BOUNDTYPE_UPPER));
9572  if( !conflict )
9573  return SCIP_OKAY;
9574  }
9575  }
9576 
9577  /* check, if the variable is already fixed */
9578  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
9579  {
9580  /* if the variable is fixed to the given value, perform the implication; otherwise, ignore the implication */
9581  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
9582  {
9583  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
9584  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
9585  }
9586  return SCIP_OKAY;
9587  }
9588 
9589  assert((impltype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, implbound, SCIPvarGetLbGlobal(implvar)))
9590  || (impltype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, implbound, SCIPvarGetUbGlobal(implvar))));
9591 
9592  if( !conflict )
9593  {
9594  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9595 
9596  if( SCIPvarIsBinary(implvar) )
9597  {
9598  SCIP_VAR* vars[2];
9599  SCIP_Bool vals[2];
9600 
9601  assert(SCIPsetIsFeasEQ(set, implbound, 1.0) || SCIPsetIsFeasZero(set, implbound));
9602  assert((impltype == SCIP_BOUNDTYPE_UPPER) == SCIPsetIsFeasZero(set, implbound));
9603 
9604  vars[0] = var;
9605  vars[1] = implvar;
9606  vals[0] = varfixing;
9607  vals[1] = (impltype == SCIP_BOUNDTYPE_UPPER);
9608 
9609  /* add the clique to the clique table */
9610  SCIP_CALL( SCIPcliquetableAdd(cliquetable, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
9611  eventqueue, vars, vals, 2, FALSE, &conflict, nbdchgs) );
9612 
9613  if( !conflict )
9614  return SCIP_OKAY;
9615  }
9616  else
9617  {
9618  /* add implication x == 0/1 -> y <= b / y >= b to the implications list of x */
9619  SCIPsetDebugMsg(set, "adding implication: <%s> == %u ==> <%s> %s %g\n",
9620  SCIPvarGetName(var), varfixing,
9621  SCIPvarGetName(implvar), impltype == SCIP_BOUNDTYPE_UPPER ? "<=" : ">=", implbound);
9622  SCIP_CALL( SCIPimplicsAdd(&var->implics, blkmem, set, stat, varfixing, implvar, impltype, implbound,
9623  isshortcut, &conflict, added) );
9624  }
9625  }
9626  assert(!conflict || !(*added));
9627 
9628  /* on conflict, fix the variable to the opposite value */
9629  if( conflict )
9630  {
9631  SCIPsetDebugMsg(set, " -> implication yields a conflict: fix <%s> == %d\n", SCIPvarGetName(var), !varfixing);
9632 
9633  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9634  * with the local bound, in this case we need to store the bound change as pending bound change
9635  */
9636  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9637  {
9638  assert(tree != NULL);
9639  assert(transprob != NULL);
9640  assert(SCIPprobIsTransformed(transprob));
9641 
9642  if( varfixing )
9643  {
9644  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9645  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
9646  }
9647  else
9648  {
9649  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9650  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
9651  }
9652  }
9653  else
9654  {
9655  if( varfixing )
9656  {
9657  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
9658  }
9659  else
9660  {
9661  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
9662  }
9663  }
9664  if( nbdchgs != NULL )
9665  (*nbdchgs)++;
9666 
9667  return SCIP_OKAY;
9668  }
9669  else if( *added )
9670  {
9671  /* issue IMPLADDED event */
9672  SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
9673  }
9674  else
9675  {
9676  /* the implication was redundant: the inverse is also redundant */
9677  return SCIP_OKAY;
9678  }
9679 
9680  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9681 
9682  /* check, whether implied variable is binary */
9683  if( !SCIPvarIsBinary(implvar) )
9684  {
9685  SCIP_Real lb;
9686  SCIP_Real ub;
9687 
9688  /* add inverse variable bound to the variable bounds of y with global bounds y \in [lb,ub]:
9689  * x == 0 -> y <= b <-> y <= (ub - b)*x + b
9690  * x == 1 -> y <= b <-> y <= (b - ub)*x + ub
9691  * x == 0 -> y >= b <-> y >= (lb - b)*x + b
9692  * x == 1 -> y >= b <-> y >= (b - lb)*x + lb
9693  * for numerical reasons, ignore variable bounds with large absolute coefficient
9694  */
9695  lb = SCIPvarGetLbGlobal(implvar);
9696  ub = SCIPvarGetUbGlobal(implvar);
9697  if( impltype == SCIP_BOUNDTYPE_UPPER )
9698  {
9699  if( REALABS(implbound - ub) <= MAXABSVBCOEF )
9700  {
9701  SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, var,
9702  varfixing ? implbound - ub : ub - implbound, varfixing ? ub : implbound) );
9703  }
9704  }
9705  else
9706  {
9707  if( REALABS(implbound - lb) <= MAXABSVBCOEF )
9708  {
9709  SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, var,
9710  varfixing ? implbound - lb : lb - implbound, varfixing ? lb : implbound) );
9711  }
9712  }
9713  }
9714 
9715  return SCIP_OKAY;
9716 }
9717 
9718 /** adds transitive closure for binary implication x = a -> y = b */
9719 static
9721  SCIP_VAR* var, /**< problem variable */
9722  BMS_BLKMEM* blkmem, /**< block memory */
9723  SCIP_SET* set, /**< global SCIP settings */
9724  SCIP_STAT* stat, /**< problem statistics */
9725  SCIP_PROB* transprob, /**< transformed problem */
9726  SCIP_PROB* origprob, /**< original problem */
9727  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9728  SCIP_REOPT* reopt, /**< reoptimization data structure */
9729  SCIP_LP* lp, /**< current LP data */
9730  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9731  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9732  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9733  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9734  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9735  SCIP_Bool implvarfixing, /**< fixing b in implication */
9736  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9737  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9738  )
9739 {
9740  SCIP_VAR** implvars;
9741  SCIP_BOUNDTYPE* impltypes;
9742  SCIP_Real* implbounds;
9743  int nimpls;
9744  int i;
9745 
9746  *infeasible = FALSE;
9747 
9748  /* binary variable: implications of implvar */
9749  nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
9750  implvars = SCIPimplicsGetVars(implvar->implics, implvarfixing);
9751  impltypes = SCIPimplicsGetTypes(implvar->implics, implvarfixing);
9752  implbounds = SCIPimplicsGetBounds(implvar->implics, implvarfixing);
9753 
9754  /* if variable has too many implications, the implication graph may become too dense */
9755  i = MIN(nimpls, MAXIMPLSCLOSURE) - 1;
9756 
9757  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9758  * implvars[i] is fixed, s.t. the implication y == varfixing -> z <= b / z >= b is deleted; this affects the
9759  * array over which we currently iterate; the only thing that can happen, is that elements of the array are
9760  * deleted; in this case, the subsequent elements are moved to the front; if we iterate from back to front, the
9761  * only thing that can happen is that we add the same implication twice - this does no harm
9762  */
9763  while ( i >= 0 && !(*infeasible) )
9764  {
9765  SCIP_Bool added;
9766 
9767  assert(implvars[i] != implvar);
9768 
9769  /* we have x == varfixing -> y == implvarfixing -> z <= b / z >= b:
9770  * add implication x == varfixing -> z <= b / z >= b to the implications list of x
9771  */
9772  if( SCIPvarIsActive(implvars[i]) )
9773  {
9774  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
9775  eventqueue, varfixing, implvars[i], impltypes[i], implbounds[i], TRUE, infeasible, nbdchgs, &added) );
9776  assert(SCIPimplicsGetNImpls(implvar->implics, implvarfixing) <= nimpls);
9777  nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
9778  i = MIN(i, nimpls); /* some elements from the array could have been removed */
9779  }
9780  --i;
9781  }
9782 
9783  return SCIP_OKAY;
9784 }
9785 
9786 /** adds given implication to the variable's implication list, and adds all implications directly implied by this
9787  * implication to the variable's implication list;
9788  * if the implication is conflicting, the variable is fixed to the opposite value;
9789  * if the variable is already fixed to the given value, the implication is performed immediately;
9790  * if the implication is redundant with respect to the variables' global bounds, it is ignored
9791  */
9792 static
9794  SCIP_VAR* var, /**< problem variable */
9795  BMS_BLKMEM* blkmem, /**< block memory */
9796  SCIP_SET* set, /**< global SCIP settings */
9797  SCIP_STAT* stat, /**< problem statistics */
9798  SCIP_PROB* transprob, /**< transformed problem */
9799  SCIP_PROB* origprob, /**< original problem */
9800  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9801  SCIP_REOPT* reopt, /**< reoptimization data structure */
9802  SCIP_LP* lp, /**< current LP data */
9803  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9804  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9805  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9806  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9807  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9808  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9809  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9810  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
9811  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9812  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9813  )
9814 {
9815  SCIP_Bool added;
9816 
9817  assert(var != NULL);
9818  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
9819  assert(SCIPvarIsActive(var));
9820  assert(implvar != NULL);
9821  assert(SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED);
9822  assert(infeasible != NULL);
9823 
9824  /* add implication x == varfixing -> y <= b / y >= b to the implications list of x */
9825  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
9826  eventqueue, varfixing, implvar, impltype, implbound, FALSE, infeasible, nbdchgs, &added) );
9827 
9828  if( *infeasible || var == implvar || !transitive || !added )
9829  return SCIP_OKAY;
9830 
9831  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9832 
9833  /* add transitive closure */
9834  if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
9835  {
9836  SCIP_Bool implvarfixing;
9837 
9838  implvarfixing = (impltype == SCIP_BOUNDTYPE_LOWER);
9839 
9840  /* binary variable: implications of implvar */
9841  SCIP_CALL( varAddTransitiveBinaryClosureImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9842  cliquetable, branchcand, eventqueue, varfixing, implvar, implvarfixing, infeasible, nbdchgs) );
9843 
9844  /* inverse implication */
9845  if( !(*infeasible) )
9846  {
9847  SCIP_CALL( varAddTransitiveBinaryClosureImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9848  cliquetable, branchcand, eventqueue, !implvarfixing, var, !varfixing, infeasible, nbdchgs) );
9849  }
9850  }
9851  else
9852  {
9853  /* non-binary variable: variable lower bounds of implvar */
9854  if( impltype == SCIP_BOUNDTYPE_UPPER && implvar->vlbs != NULL )
9855  {
9856  SCIP_VAR** vlbvars;
9857  SCIP_Real* vlbcoefs;
9858  SCIP_Real* vlbconstants;
9859  int nvlbvars;
9860  int i;
9861 
9862  nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
9863  vlbvars = SCIPvboundsGetVars(implvar->vlbs);
9864  vlbcoefs = SCIPvboundsGetCoefs(implvar->vlbs);
9865  vlbconstants = SCIPvboundsGetConstants(implvar->vlbs);
9866 
9867  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9868  * vlbvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
9869  * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
9870  * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
9871  * is that we add the same implication twice - this does no harm
9872  */
9873  i = nvlbvars-1;
9874  while ( i >= 0 && !(*infeasible) )
9875  {
9876  assert(vlbvars[i] != implvar);
9877  assert(!SCIPsetIsZero(set, vlbcoefs[i]));
9878 
9879  /* we have x == varfixing -> y <= b and y >= c*z + d:
9880  * c > 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
9881  * c < 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
9882  *
9883  * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
9884  * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
9885  * aggregation variable (the one which will stay active);
9886  *
9887  * W.l.o.g. we consider the variable upper bounds for now. Let "vubvar" be a variable upper bound of
9888  * the aggregated variable "aggvar"; During that copying of that variable upper bound variable
9889  * "vubvar" the variable lower and upper bounds of this variable "vubvar" are also considered; note
9890  * that the "aggvar" can be a variable lower bound variable of the variable "vubvar"; Due to that
9891  * situation it can happen that we reach that code place where "vlbvars[i] == aggvar". In particular
9892  * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
9893  * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
9894  * have to explicitly check that the active variable has not a variable status
9895  * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
9896  */
9897  if( SCIPvarIsActive(vlbvars[i]) && SCIPvarGetStatus(vlbvars[i]) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(vlbvars[i]) != SCIP_VARSTATUS_NEGATED )
9898  {
9899  SCIP_Real vbimplbound;
9900 
9901  vbimplbound = (implbound - vlbconstants[i])/vlbcoefs[i];
9902  if( vlbcoefs[i] >= 0.0 )
9903  {
9904  vbimplbound = adjustedUb(set, SCIPvarGetType(vlbvars[i]), vbimplbound);
9905  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9906  branchcand, eventqueue, varfixing, vlbvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
9907  infeasible, nbdchgs, &added) );
9908  }
9909  else
9910  {
9911  vbimplbound = adjustedLb(set, SCIPvarGetType(vlbvars[i]), vbimplbound);
9912  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9913  branchcand, eventqueue, varfixing, vlbvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
9914  infeasible, nbdchgs, &added) );
9915  }
9916  nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
9917  i = MIN(i, nvlbvars); /* some elements from the array could have been removed */
9918  }
9919  --i;
9920  }
9921  }
9922 
9923  /* non-binary variable: variable upper bounds of implvar */
9924  if( impltype == SCIP_BOUNDTYPE_LOWER && implvar->vubs != NULL )
9925  {
9926  SCIP_VAR** vubvars;
9927  SCIP_Real* vubcoefs;
9928  SCIP_Real* vubconstants;
9929  int nvubvars;
9930  int i;
9931 
9932  nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
9933  vubvars = SCIPvboundsGetVars(implvar->vubs);
9934  vubcoefs = SCIPvboundsGetCoefs(implvar->vubs);
9935  vubconstants = SCIPvboundsGetConstants(implvar->vubs);
9936 
9937  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9938  * vubvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
9939  * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
9940  * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
9941  * is that we add the same implication twice - this does no harm
9942  */
9943  i = nvubvars-1;
9944  while ( i >= 0 && !(*infeasible) )
9945  {
9946  assert(vubvars[i] != implvar);
9947  assert(!SCIPsetIsZero(set, vubcoefs[i]));
9948 
9949  /* we have x == varfixing -> y >= b and y <= c*z + d:
9950  * c > 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
9951  * c < 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
9952  *
9953  * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
9954  * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
9955  * aggregation variable (the one which will stay active);
9956  *
9957  * W.l.o.g. we consider the variable lower bounds for now. Let "vlbvar" be a variable lower bound of
9958  * the aggregated variable "aggvar"; During that copying of that variable lower bound variable
9959  * "vlbvar" the variable lower and upper bounds of this variable "vlbvar" are also considered; note
9960  * that the "aggvar" can be a variable upper bound variable of the variable "vlbvar"; Due to that
9961  * situation it can happen that we reach that code place where "vubvars[i] == aggvar". In particular
9962  * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
9963  * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
9964  * have to explicitly check that the active variable has not a variable status
9965  * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
9966  */
9967  if( SCIPvarIsActive(vubvars[i]) && SCIPvarGetStatus(vubvars[i]) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(vubvars[i]) != SCIP_VARSTATUS_NEGATED )
9968  {
9969  SCIP_Real vbimplbound;
9970 
9971  vbimplbound = (implbound - vubconstants[i])/vubcoefs[i];
9972  if( vubcoefs[i] >= 0.0 )
9973  {
9974  vbimplbound = adjustedLb(set, SCIPvarGetType(vubvars[i]), vbimplbound);
9975  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9976  branchcand, eventqueue, varfixing, vubvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
9977  infeasible, nbdchgs, &added) );
9978  }
9979  else
9980  {
9981  vbimplbound = adjustedUb(set, SCIPvarGetType(vubvars[i]), vbimplbound);
9982  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9983  branchcand, eventqueue, varfixing, vubvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
9984  infeasible, nbdchgs, &added) );
9985  }
9986  nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
9987  i = MIN(i, nvubvars); /* some elements from the array could have been removed */
9988  }
9989  --i;
9990  }
9991  }
9992  }
9993 
9994  return SCIP_OKAY;
9995 }
9996 
9997 /** informs variable x about a globally valid variable lower bound x >= b*z + d with integer variable z;
9998  * if z is binary, the corresponding valid implication for z is also added;
9999  * improves the global bounds of the variable and the vlb variable if possible
10000  */
10002  SCIP_VAR* var, /**< problem variable */
10003  BMS_BLKMEM* blkmem, /**< block memory */
10004  SCIP_SET* set, /**< global SCIP settings */
10005  SCIP_STAT* stat, /**< problem statistics */
10006  SCIP_PROB* transprob, /**< transformed problem */
10007  SCIP_PROB* origprob, /**< original problem */
10008  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10009  SCIP_REOPT* reopt, /**< reoptimization data structure */
10010  SCIP_LP* lp, /**< current LP data */
10011  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10012  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10013  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10014  SCIP_VAR* vlbvar, /**< variable z in x >= b*z + d */
10015  SCIP_Real vlbcoef, /**< coefficient b in x >= b*z + d */
10016  SCIP_Real vlbconstant, /**< constant d in x >= b*z + d */
10017  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
10018  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10019  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
10020  )
10021 {
10022  assert(var != NULL);
10023  assert(set != NULL);
10024  assert(var->scip == set->scip);
10025  assert(SCIPvarGetType(vlbvar) != SCIP_VARTYPE_CONTINUOUS);
10026  assert(infeasible != NULL);
10027 
10028  SCIPsetDebugMsg(set, "adding variable lower bound <%s> >= %g<%s> + %g\n", SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
10029 
10030  *infeasible = FALSE;
10031  if( nbdchgs != NULL )
10032  *nbdchgs = 0;
10033 
10034  switch( SCIPvarGetStatus(var) )
10035  {
10037  assert(var->data.original.transvar != NULL);
10038  SCIP_CALL( SCIPvarAddVlb(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10039  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef, vlbconstant, transitive, infeasible, nbdchgs) );
10040  break;
10041 
10042  case SCIP_VARSTATUS_COLUMN:
10043  case SCIP_VARSTATUS_LOOSE:
10044  case SCIP_VARSTATUS_FIXED:
10045  /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
10046  SCIP_CALL( SCIPvarGetProbvarSum(&vlbvar, set, &vlbcoef, &vlbconstant) );
10047  SCIPsetDebugMsg(set, " -> transformed to variable lower bound <%s> >= %g<%s> + %g\n", SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
10048 
10049  /* if the vlb coefficient is zero, just update the lower bound of the variable */
10050  if( SCIPsetIsZero(set, vlbcoef) )
10051  {
10052  if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetUbGlobal(var)) )
10053  *infeasible = TRUE;
10054  else if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetLbGlobal(var)) )
10055  {
10056  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10057  * with the local bound, in this case we need to store the bound change as pending bound change
10058  */
10059  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10060  {
10061  assert(tree != NULL);
10062  assert(transprob != NULL);
10063  assert(SCIPprobIsTransformed(transprob));
10064 
10065  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10066  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vlbconstant, SCIP_BOUNDTYPE_LOWER, FALSE) );
10067  }
10068  else
10069  {
10070  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vlbconstant) );
10071  }
10072 
10073  if( nbdchgs != NULL )
10074  (*nbdchgs)++;
10075  }
10076  }
10077  else if( var == vlbvar )
10078  {
10079  /* the variables cancels out, the variable bound constraint is either redundant or proves global infeasibility */
10080  if( SCIPsetIsEQ(set, vlbcoef, 1.0) )
10081  {
10082  if( SCIPsetIsPositive(set, vlbconstant) )
10083  *infeasible = TRUE;
10084  return SCIP_OKAY;
10085  }
10086  else
10087  {
10088  SCIP_Real lb = SCIPvarGetLbGlobal(var);
10089  SCIP_Real ub = SCIPvarGetUbGlobal(var);
10090 
10091  /* the variable bound constraint defines a new upper bound */
10092  if( SCIPsetIsGT(set, vlbcoef, 1.0) )
10093  {
10094  SCIP_Real newub = vlbconstant / (1.0 - vlbcoef);
10095 
10096  if( SCIPsetIsFeasLT(set, newub, lb) )
10097  {
10098  *infeasible = TRUE;
10099  return SCIP_OKAY;
10100  }
10101  else if( SCIPsetIsFeasLT(set, newub, ub) )
10102  {
10103  /* bound might be adjusted due to integrality condition */
10104  newub = adjustedUb(set, SCIPvarGetType(var), newub);
10105 
10106  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10107  * with the local bound, in this case we need to store the bound change as pending bound change
10108  */
10109  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10110  {
10111  assert(tree != NULL);
10112  assert(transprob != NULL);
10113  assert(SCIPprobIsTransformed(transprob));
10114 
10115  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10116  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10117  }
10118  else
10119  {
10120  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newub) );
10121  }
10122 
10123  if( nbdchgs != NULL )
10124  (*nbdchgs)++;
10125  }
10126  }
10127  /* the variable bound constraint defines a new lower bound */
10128  else
10129  {
10130  SCIP_Real newlb;
10131 
10132  assert(SCIPsetIsLT(set, vlbcoef, 1.0));
10133 
10134  newlb = vlbconstant / (1.0 - vlbcoef);
10135 
10136  if( SCIPsetIsFeasGT(set, newlb, ub) )
10137  {
10138  *infeasible = TRUE;
10139  return SCIP_OKAY;
10140  }
10141  else if( SCIPsetIsFeasGT(set, newlb, lb) )
10142  {
10143  /* bound might be adjusted due to integrality condition */
10144  newlb = adjustedLb(set, SCIPvarGetType(var), newlb);
10145 
10146  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10147  * with the local bound, in this case we need to store the bound change as pending bound change
10148  */
10149  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10150  {
10151  assert(tree != NULL);
10152  assert(transprob != NULL);
10153  assert(SCIPprobIsTransformed(transprob));
10154 
10155  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10156  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10157  }
10158  else
10159  {
10160  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newlb) );
10161  }
10162 
10163  if( nbdchgs != NULL )
10164  (*nbdchgs)++;
10165  }
10166  }
10167  }
10168  }
10169  else if( SCIPvarIsActive(vlbvar) )
10170  {
10171  SCIP_Real xlb;
10172  SCIP_Real xub;
10173  SCIP_Real zlb;
10174  SCIP_Real zub;
10175  SCIP_Real minvlb;
10176  SCIP_Real maxvlb;
10177 
10179  assert(vlbcoef != 0.0);
10180 
10181  minvlb = -SCIPsetInfinity(set);
10182  maxvlb = SCIPsetInfinity(set);
10183 
10184  xlb = SCIPvarGetLbGlobal(var);
10185  xub = SCIPvarGetUbGlobal(var);
10186  zlb = SCIPvarGetLbGlobal(vlbvar);
10187  zub = SCIPvarGetUbGlobal(vlbvar);
10188 
10189  /* improve global bounds of vlb variable, and calculate minimal and maximal value of variable bound */
10190  if( vlbcoef >= 0.0 )
10191  {
10192  SCIP_Real newzub;
10193 
10194  if( !SCIPsetIsInfinity(set, xub) )
10195  {
10196  /* x >= b*z + d -> z <= (x-d)/b */
10197  newzub = (xub - vlbconstant)/vlbcoef;
10198 
10199  /* return if the new bound is less than -infinity */
10200  if( SCIPsetIsInfinity(set, REALABS(newzub)) )
10201  return SCIP_OKAY;
10202 
10203  if( SCIPsetIsFeasLT(set, newzub, zlb) )
10204  {
10205  *infeasible = TRUE;
10206  return SCIP_OKAY;
10207  }
10208  if( SCIPsetIsFeasLT(set, newzub, zub) )
10209  {
10210  /* bound might be adjusted due to integrality condition */
10211  newzub = adjustedUb(set, SCIPvarGetType(vlbvar), newzub);
10212 
10213  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10214  * with the local bound, in this case we need to store the bound change as pending bound change
10215  */
10216  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10217  {
10218  assert(tree != NULL);
10219  assert(transprob != NULL);
10220  assert(SCIPprobIsTransformed(transprob));
10221 
10222  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10223  tree, reopt, lp, branchcand, eventqueue, cliquetable, vlbvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10224  }
10225  else
10226  {
10227  SCIP_CALL( SCIPvarChgUbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
10228  }
10229  zub = newzub;
10230 
10231  if( nbdchgs != NULL )
10232  (*nbdchgs)++;
10233  }
10234  maxvlb = vlbcoef * zub + vlbconstant;
10235  if( !SCIPsetIsInfinity(set, -zlb) )
10236  minvlb = vlbcoef * zlb + vlbconstant;
10237  }
10238  else
10239  {
10240  if( !SCIPsetIsInfinity(set, zub) )
10241  maxvlb = vlbcoef * zub + vlbconstant;
10242  if( !SCIPsetIsInfinity(set, -zlb) )
10243  minvlb = vlbcoef * zlb + vlbconstant;
10244  }
10245  }
10246  else
10247  {
10248  SCIP_Real newzlb;
10249 
10250  if( !SCIPsetIsInfinity(set, xub) )
10251  {
10252  /* x >= b*z + d -> z >= (x-d)/b */
10253  newzlb = (xub - vlbconstant)/vlbcoef;
10254 
10255  /* return if the new bound is larger than infinity */
10256  if( SCIPsetIsInfinity(set, REALABS(newzlb)) )
10257  return SCIP_OKAY;
10258 
10259  if( SCIPsetIsFeasGT(set, newzlb, zub) )
10260  {
10261  *infeasible = TRUE;
10262  return SCIP_OKAY;
10263  }
10264  if( SCIPsetIsFeasGT(set, newzlb, zlb) )
10265  {
10266  /* bound might be adjusted due to integrality condition */
10267  newzlb = adjustedLb(set, SCIPvarGetType(vlbvar), newzlb);
10268 
10269  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10270  * with the local bound, in this case we need to store the bound change as pending bound change
10271  */
10272  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10273  {
10274  assert(tree != NULL);
10275  assert(transprob != NULL);
10276  assert(SCIPprobIsTransformed(transprob));
10277 
10278  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10279  tree, reopt, lp, branchcand, eventqueue, cliquetable, vlbvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10280  }
10281  else
10282  {
10283  SCIP_CALL( SCIPvarChgLbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
10284  }
10285  zlb = newzlb;
10286 
10287  if( nbdchgs != NULL )
10288  (*nbdchgs)++;
10289  }
10290  maxvlb = vlbcoef * zlb + vlbconstant;
10291  if( !SCIPsetIsInfinity(set, zub) )
10292  minvlb = vlbcoef * zub + vlbconstant;
10293  }
10294  else
10295  {
10296  if( !SCIPsetIsInfinity(set, -zlb) )
10297  maxvlb = vlbcoef * zlb + vlbconstant;
10298  if( !SCIPsetIsInfinity(set, zub) )
10299  minvlb = vlbcoef * zub + vlbconstant;
10300  }
10301  }
10302  if( maxvlb < minvlb )
10303  maxvlb = minvlb;
10304 
10305  /* adjust bounds due to integrality of variable */
10306  minvlb = adjustedLb(set, SCIPvarGetType(var), minvlb);
10307  maxvlb = adjustedLb(set, SCIPvarGetType(var), maxvlb);
10308 
10309  /* check bounds for feasibility */
10310  if( SCIPsetIsFeasGT(set, minvlb, xub) || (var == vlbvar && SCIPsetIsEQ(set, vlbcoef, 1.0) && SCIPsetIsFeasPositive(set, vlbconstant)) )
10311  {
10312  *infeasible = TRUE;
10313  return SCIP_OKAY;
10314  }
10315  /* improve global lower bound of variable */
10316  if( SCIPsetIsFeasGT(set, minvlb, xlb) )
10317  {
10318  /* bound might be adjusted due to integrality condition */
10319  minvlb = adjustedLb(set, SCIPvarGetType(var), minvlb);
10320 
10321  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10322  * with the local bound, in this case we need to store the bound change as pending bound change
10323  */
10324  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10325  {
10326  assert(tree != NULL);
10327  assert(transprob != NULL);
10328  assert(SCIPprobIsTransformed(transprob));
10329 
10330  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10331  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, minvlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10332  }
10333  else
10334  {
10335  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, minvlb) );
10336  }
10337  xlb = minvlb;
10338 
10339  if( nbdchgs != NULL )
10340  (*nbdchgs)++;
10341  }
10342  minvlb = xlb;
10343 
10344  /* improve variable bound for binary z by moving the variable's global bound to the vlb constant */
10345  if( SCIPvarGetType(vlbvar) == SCIP_VARTYPE_BINARY )
10346  {
10347  /* b > 0: x >= (maxvlb - minvlb) * z + minvlb
10348  * b < 0: x >= (minvlb - maxvlb) * z + maxvlb
10349  */
10350 
10351  assert(!SCIPsetIsInfinity(set, maxvlb) && !SCIPsetIsInfinity(set, -minvlb));
10352 
10353  if( vlbcoef >= 0.0 )
10354  {
10355  vlbcoef = maxvlb - minvlb;
10356  vlbconstant = minvlb;
10357  }
10358  else
10359  {
10360  vlbcoef = minvlb - maxvlb;
10361  vlbconstant = maxvlb;
10362  }
10363  }
10364 
10365  /* add variable bound to the variable bounds list */
10366  if( SCIPsetIsFeasGT(set, maxvlb, xlb) )
10367  {
10368  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED);
10369  assert(!SCIPsetIsZero(set, vlbcoef));
10370 
10371  /* if one of the variables is binary, add the corresponding implication to the variable's implication
10372  * list, thereby also adding the variable bound (or implication) to the other variable
10373  */
10374  if( SCIPvarGetType(vlbvar) == SCIP_VARTYPE_BINARY )
10375  {
10376  /* add corresponding implication:
10377  * b > 0, x >= b*z + d <-> z == 1 -> x >= b+d
10378  * b < 0, x >= b*z + d <-> z == 0 -> x >= d
10379  */
10380  SCIP_CALL( varAddTransitiveImplic(vlbvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10381  cliquetable, branchcand, eventqueue, (vlbcoef >= 0.0), var, SCIP_BOUNDTYPE_LOWER, maxvlb, transitive,
10382  infeasible, nbdchgs) );
10383  }
10384  else if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
10385  {
10386  /* add corresponding implication:
10387  * b > 0, x >= b*z + d <-> x == 0 -> z <= -d/b
10388  * b < 0, x >= b*z + d <-> x == 0 -> z >= -d/b
10389  */
10390  SCIP_Real implbound;
10391  implbound = -vlbconstant/vlbcoef;
10392 
10393  /* tighten the implication bound if the variable is integer */
10394  if( SCIPvarIsIntegral(vlbvar) )
10395  {
10396  if( vlbcoef >= 0 )
10397  implbound = SCIPsetFloor(set, implbound);
10398  else
10399  implbound = SCIPsetCeil(set, implbound);
10400  }
10401  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10402  cliquetable, branchcand, eventqueue, FALSE, vlbvar, (vlbcoef >= 0.0 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER),
10403  implbound, transitive, infeasible, nbdchgs) );
10404  }
10405  else
10406  {
10407  SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, vlbvar, vlbcoef, vlbconstant) );
10408  }
10409  }
10410  }
10411  break;
10412 
10414  /* x = a*y + c: x >= b*z + d <=> a*y + c >= b*z + d <=> y >= b/a * z + (d-c)/a, if a > 0
10415  * y <= b/a * z + (d-c)/a, if a < 0
10416  */
10417  assert(var->data.aggregate.var != NULL);
10418  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
10419  {
10420  /* a > 0 -> add variable lower bound */
10421  SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10422  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef/var->data.aggregate.scalar,
10423  (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10424  }
10425  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
10426  {
10427  /* a < 0 -> add variable upper bound */
10428  SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10429  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef/var->data.aggregate.scalar,
10430  (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10431  }
10432  else
10433  {
10434  SCIPerrorMessage("scalar is zero in aggregation\n");
10435  return SCIP_INVALIDDATA;
10436  }
10437  break;
10438 
10440  /* nothing to do here */
10441  break;
10442 
10444  /* x = offset - x': x >= b*z + d <=> offset - x' >= b*z + d <=> x' <= -b*z + (offset-d) */
10445  assert(var->negatedvar != NULL);
10447  assert(var->negatedvar->negatedvar == var);
10448  SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10449  branchcand, eventqueue, vlbvar, -vlbcoef, var->data.negate.constant - vlbconstant, transitive, infeasible,
10450  nbdchgs) );
10451  break;
10452 
10453  default:
10454  SCIPerrorMessage("unknown variable status\n");
10455  return SCIP_INVALIDDATA;
10456  }
10457 
10458  return SCIP_OKAY;
10459 }
10460 
10461 /** informs variable x about a globally valid variable upper bound x <= b*z + d with integer variable z;
10462  * if z is binary, the corresponding valid implication for z is also added;
10463  * updates the global bounds of the variable and the vub variable correspondingly
10464  */
10466  SCIP_VAR* var, /**< problem variable */
10467  BMS_BLKMEM* blkmem, /**< block memory */
10468  SCIP_SET* set, /**< global SCIP settings */
10469  SCIP_STAT* stat, /**< problem statistics */
10470  SCIP_PROB* transprob, /**< transformed problem */
10471  SCIP_PROB* origprob, /**< original problem */
10472  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10473  SCIP_REOPT* reopt, /**< reoptimization data structure */
10474  SCIP_LP* lp, /**< current LP data */
10475  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10476  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10477  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10478  SCIP_VAR* vubvar, /**< variable z in x <= b*z + d */
10479  SCIP_Real vubcoef, /**< coefficient b in x <= b*z + d */
10480  SCIP_Real vubconstant, /**< constant d in x <= b*z + d */
10481  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
10482  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10483  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
10484  )
10485 {
10486  assert(var != NULL);
10487  assert(set != NULL);
10488  assert(var->scip == set->scip);
10489  assert(SCIPvarGetType(vubvar) != SCIP_VARTYPE_CONTINUOUS);
10490  assert(infeasible != NULL);
10491 
10492  SCIPsetDebugMsg(set, "adding variable upper bound <%s> <= %g<%s> + %g\n", SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
10493 
10494  *infeasible = FALSE;
10495  if( nbdchgs != NULL )
10496  *nbdchgs = 0;
10497 
10498  switch( SCIPvarGetStatus(var) )
10499  {
10501  assert(var->data.original.transvar != NULL);
10502  SCIP_CALL( SCIPvarAddVub(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10503  cliquetable, branchcand, eventqueue, vubvar, vubcoef, vubconstant, transitive, infeasible, nbdchgs) );
10504  break;
10505 
10506  case SCIP_VARSTATUS_COLUMN:
10507  case SCIP_VARSTATUS_LOOSE:
10508  case SCIP_VARSTATUS_FIXED:
10509  /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
10510  SCIP_CALL( SCIPvarGetProbvarSum(&vubvar, set, &vubcoef, &vubconstant) );
10511  SCIPsetDebugMsg(set, " -> transformed to variable upper bound <%s> <= %g<%s> + %g\n",
10512  SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
10513 
10514  /* if the vub coefficient is zero, just update the upper bound of the variable */
10515  if( SCIPsetIsZero(set, vubcoef) )
10516  {
10517  if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetLbGlobal(var)) )
10518  *infeasible = TRUE;
10519  else if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetUbGlobal(var)) )
10520  {
10521  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10522  * with the local bound, in this case we need to store the bound change as pending bound change
10523  */
10524  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10525  {
10526  assert(tree != NULL);
10527  assert(transprob != NULL);
10528  assert(SCIPprobIsTransformed(transprob));
10529 
10530  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10531  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vubconstant, SCIP_BOUNDTYPE_UPPER, FALSE) );
10532  }
10533  else
10534  {
10535  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vubconstant) );
10536  }
10537 
10538  if( nbdchgs != NULL )
10539  (*nbdchgs)++;
10540  }
10541  }
10542  else if( var == vubvar )
10543  {
10544  /* the variables cancels out, the variable bound constraint is either redundant or proves global infeasibility */
10545  if( SCIPsetIsEQ(set, vubcoef, 1.0) )
10546  {
10547  if( SCIPsetIsNegative(set, vubconstant) )
10548  *infeasible = TRUE;
10549  return SCIP_OKAY;
10550  }
10551  else
10552  {
10553  SCIP_Real lb = SCIPvarGetLbGlobal(var);
10554  SCIP_Real ub = SCIPvarGetUbGlobal(var);
10555 
10556  /* the variable bound constraint defines a new lower bound */
10557  if( SCIPsetIsGT(set, vubcoef, 1.0) )
10558  {
10559  SCIP_Real newlb = vubconstant / (1.0 - vubcoef);
10560 
10561  if( SCIPsetIsFeasGT(set, newlb, ub) )
10562  {
10563  *infeasible = TRUE;
10564  return SCIP_OKAY;
10565  }
10566  else if( SCIPsetIsFeasGT(set, newlb, lb) )
10567  {
10568  /* bound might be adjusted due to integrality condition */
10569  newlb = adjustedLb(set, SCIPvarGetType(var), newlb);
10570 
10571  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10572  * with the local bound, in this case we need to store the bound change as pending bound change
10573  */
10574  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10575  {
10576  assert(tree != NULL);
10577  assert(transprob != NULL);
10578  assert(SCIPprobIsTransformed(transprob));
10579 
10580  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10581  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10582  }
10583  else
10584  {
10585  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newlb) );
10586  }
10587 
10588  if( nbdchgs != NULL )
10589  (*nbdchgs)++;
10590  }
10591  }
10592  /* the variable bound constraint defines a new upper bound */
10593  else
10594  {
10595  SCIP_Real newub;
10596 
10597  assert(SCIPsetIsLT(set, vubcoef, 1.0));
10598 
10599  newub = vubconstant / (1.0 - vubcoef);
10600 
10601  if( SCIPsetIsFeasLT(set, newub, lb) )
10602  {
10603  *infeasible = TRUE;
10604  return SCIP_OKAY;
10605  }
10606  else if( SCIPsetIsFeasLT(set, newub, ub) )
10607  {
10608  /* bound might be adjusted due to integrality condition */
10609  newub = adjustedUb(set, SCIPvarGetType(var), newub);
10610 
10611  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10612  * with the local bound, in this case we need to store the bound change as pending bound change
10613  */
10614  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10615  {
10616  assert(tree != NULL);
10617  assert(transprob != NULL);
10618  assert(SCIPprobIsTransformed(transprob));
10619 
10620  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10621  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10622  }
10623  else
10624  {
10625  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newub) );
10626  }
10627 
10628  if( nbdchgs != NULL )
10629  (*nbdchgs)++;
10630  }
10631  }
10632  }
10633  }
10634  else if( SCIPvarIsActive(vubvar) )
10635  {
10636  SCIP_Real xlb;
10637  SCIP_Real xub;
10638  SCIP_Real zlb;
10639  SCIP_Real zub;
10640  SCIP_Real minvub;
10641  SCIP_Real maxvub;
10642 
10644  assert(vubcoef != 0.0);
10645 
10646  minvub = -SCIPsetInfinity(set);
10647  maxvub = SCIPsetInfinity(set);
10648 
10649  xlb = SCIPvarGetLbGlobal(var);
10650  xub = SCIPvarGetUbGlobal(var);
10651  zlb = SCIPvarGetLbGlobal(vubvar);
10652  zub = SCIPvarGetUbGlobal(vubvar);
10653 
10654  /* improve global bounds of vub variable, and calculate minimal and maximal value of variable bound */
10655  if( vubcoef >= 0.0 )
10656  {
10657  SCIP_Real newzlb;
10658 
10659  if( !SCIPsetIsInfinity(set, -xlb) )
10660  {
10661  /* x <= b*z + d -> z >= (x-d)/b */
10662  newzlb = (xlb - vubconstant)/vubcoef;
10663  if( SCIPsetIsFeasGT(set, newzlb, zub) )
10664  {
10665  *infeasible = TRUE;
10666  return SCIP_OKAY;
10667  }
10668  if( SCIPsetIsFeasGT(set, newzlb, zlb) )
10669  {
10670  /* bound might be adjusted due to integrality condition */
10671  newzlb = adjustedLb(set, SCIPvarGetType(vubvar), newzlb);
10672 
10673  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10674  * with the local bound, in this case we need to store the bound change as pending bound change
10675  */
10676  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10677  {
10678  assert(tree != NULL);
10679  assert(transprob != NULL);
10680  assert(SCIPprobIsTransformed(transprob));
10681 
10682  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10683  tree, reopt, lp, branchcand, eventqueue, cliquetable, vubvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10684  }
10685  else
10686  {
10687  SCIP_CALL( SCIPvarChgLbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
10688  }
10689  zlb = newzlb;
10690 
10691  if( nbdchgs != NULL )
10692  (*nbdchgs)++;
10693  }
10694  minvub = vubcoef * zlb + vubconstant;
10695  if( !SCIPsetIsInfinity(set, zub) )
10696  maxvub = vubcoef * zub + vubconstant;
10697  }
10698  else
10699  {
10700  if( !SCIPsetIsInfinity(set, zub) )
10701  maxvub = vubcoef * zub + vubconstant;
10702  if( !SCIPsetIsInfinity(set, -zlb) )
10703  minvub = vubcoef * zlb + vubconstant;
10704  }
10705  }
10706  else
10707  {
10708  SCIP_Real newzub;
10709 
10710  if( !SCIPsetIsInfinity(set, -xlb) )
10711  {
10712  /* x <= b*z + d -> z <= (x-d)/b */
10713  newzub = (xlb - vubconstant)/vubcoef;
10714  if( SCIPsetIsFeasLT(set, newzub, zlb) )
10715  {
10716  *infeasible = TRUE;
10717  return SCIP_OKAY;
10718  }
10719  if( SCIPsetIsFeasLT(set, newzub, zub) )
10720  {
10721  /* bound might be adjusted due to integrality condition */
10722  newzub = adjustedUb(set, SCIPvarGetType(vubvar), newzub);
10723 
10724  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10725  * with the local bound, in this case we need to store the bound change as pending bound change
10726  */
10727  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10728  {
10729  assert(tree != NULL);
10730  assert(transprob != NULL);
10731  assert(SCIPprobIsTransformed(transprob));
10732 
10733  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10734  tree, reopt, lp, branchcand, eventqueue, cliquetable, vubvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10735  }
10736  else
10737  {
10738  SCIP_CALL( SCIPvarChgUbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
10739  }
10740  zub = newzub;
10741 
10742  if( nbdchgs != NULL )
10743  (*nbdchgs)++;
10744  }
10745  minvub = vubcoef * zub + vubconstant;
10746  if( !SCIPsetIsInfinity(set, -zlb) )
10747  maxvub = vubcoef * zlb + vubconstant;
10748  }
10749  else
10750  {
10751  if( !SCIPsetIsInfinity(set, zub) )
10752  minvub = vubcoef * zub + vubconstant;
10753  if( !SCIPsetIsInfinity(set, -zlb) )
10754  maxvub = vubcoef * zlb + vubconstant;
10755  }
10756  }
10757  if( minvub > maxvub )
10758  minvub = maxvub;
10759 
10760  /* adjust bounds due to integrality of vub variable */
10761  minvub = adjustedUb(set, SCIPvarGetType(var), minvub);
10762  maxvub = adjustedUb(set, SCIPvarGetType(var), maxvub);
10763 
10764  /* check bounds for feasibility */
10765  if( SCIPsetIsFeasLT(set, maxvub, xlb) || (var == vubvar && SCIPsetIsEQ(set, vubcoef, 1.0) && SCIPsetIsFeasNegative(set, vubconstant)) )
10766  {
10767  *infeasible = TRUE;
10768  return SCIP_OKAY;
10769  }
10770 
10771  /* improve global upper bound of variable */
10772  if( SCIPsetIsFeasLT(set, maxvub, xub) )
10773  {
10774  /* bound might be adjusted due to integrality condition */
10775  maxvub = adjustedUb(set, SCIPvarGetType(var), maxvub);
10776 
10777  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10778  * with the local bound, in this case we need to store the bound change as pending bound change
10779  */
10780  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10781  {
10782  assert(tree != NULL);
10783  assert(transprob != NULL);
10784  assert(SCIPprobIsTransformed(transprob));
10785 
10786  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10787  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, maxvub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10788  }
10789  else
10790  {
10791  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, maxvub) );
10792  }
10793  xub = maxvub;
10794 
10795  if( nbdchgs != NULL )
10796  (*nbdchgs)++;
10797  }
10798  maxvub = xub;
10799 
10800  /* improve variable bound for binary z by moving the variable's global bound to the vub constant */
10801  if( SCIPvarIsBinary(vubvar) )
10802  {
10803  /* b > 0: x <= (maxvub - minvub) * z + minvub
10804  * b < 0: x <= (minvub - maxvub) * z + maxvub
10805  */
10806 
10807  assert(!SCIPsetIsInfinity(set, maxvub) && !SCIPsetIsInfinity(set, -minvub));
10808 
10809  if( vubcoef >= 0.0 )
10810  {
10811  vubcoef = maxvub - minvub;
10812  vubconstant = minvub;
10813  }
10814  else
10815  {
10816  vubcoef = minvub - maxvub;
10817  vubconstant = maxvub;
10818  }
10819  }
10820 
10821  /* add variable bound to the variable bounds list */
10822  if( SCIPsetIsFeasLT(set, minvub, xub) )
10823  {
10824  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED);
10825  assert(!SCIPsetIsZero(set, vubcoef));
10826 
10827  /* if one of the variables is binary, add the corresponding implication to the variable's implication
10828  * list, thereby also adding the variable bound (or implication) to the other variable
10829  */
10830  if( SCIPvarGetType(vubvar) == SCIP_VARTYPE_BINARY )
10831  {
10832  /* add corresponding implication:
10833  * b > 0, x <= b*z + d <-> z == 0 -> x <= d
10834  * b < 0, x <= b*z + d <-> z == 1 -> x <= b+d
10835  */
10836  SCIP_CALL( varAddTransitiveImplic(vubvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10837  cliquetable, branchcand, eventqueue, (vubcoef < 0.0), var, SCIP_BOUNDTYPE_UPPER, minvub, transitive,
10838  infeasible, nbdchgs) );
10839  }
10840  else if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
10841  {
10842  /* add corresponding implication:
10843  * b > 0, x <= b*z + d <-> x == 1 -> z >= (1-d)/b
10844  * b < 0, x <= b*z + d <-> x == 1 -> z <= (1-d)/b
10845  */
10846  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10847  cliquetable, branchcand, eventqueue, TRUE, vubvar, (vubcoef >= 0.0 ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER),
10848  (1.0-vubconstant)/vubcoef, transitive, infeasible, nbdchgs) );
10849  }
10850  else
10851  {
10852  SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, vubvar, vubcoef, vubconstant) );
10853  }
10854  }
10855  }
10856  break;
10857 
10859  /* x = a*y + c: x <= b*z + d <=> a*y + c <= b*z + d <=> y <= b/a * z + (d-c)/a, if a > 0
10860  * y >= b/a * z + (d-c)/a, if a < 0
10861  */
10862  assert(var->data.aggregate.var != NULL);
10863  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
10864  {
10865  /* a > 0 -> add variable upper bound */
10866  SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10867  cliquetable, branchcand, eventqueue, vubvar, vubcoef/var->data.aggregate.scalar,
10868  (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10869  }
10870  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
10871  {
10872  /* a < 0 -> add variable lower bound */
10873  SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10874  cliquetable, branchcand, eventqueue, vubvar, vubcoef/var->data.aggregate.scalar,
10875  (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10876  }
10877  else
10878  {
10879  SCIPerrorMessage("scalar is zero in aggregation\n");
10880  return SCIP_INVALIDDATA;
10881  }
10882  break;
10883 
10885  /* nothing to do here */
10886  break;
10887 
10889  /* x = offset - x': x <= b*z + d <=> offset - x' <= b*z + d <=> x' >= -b*z + (offset-d) */
10890  assert(var->negatedvar != NULL);
10892  assert(var->negatedvar->negatedvar == var);
10893  SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10894  branchcand, eventqueue, vubvar, -vubcoef, var->data.negate.constant - vubconstant, transitive, infeasible,
10895  nbdchgs) );
10896  break;
10897 
10898  default:
10899  SCIPerrorMessage("unknown variable status\n");
10900  return SCIP_INVALIDDATA;
10901  }
10902 
10903  return SCIP_OKAY;
10904 }
10905 
10906 /** informs binary variable x about a globally valid implication: x == 0 or x == 1 ==> y <= b or y >= b;
10907  * also adds the corresponding implication or variable bound to the implied variable;
10908  * if the implication is conflicting, the variable is fixed to the opposite value;
10909  * if the variable is already fixed to the given value, the implication is performed immediately;
10910  * if the implication is redundant with respect to the variables' global bounds, it is ignored
10911  */
10913  SCIP_VAR* var, /**< problem variable */
10914  BMS_BLKMEM* blkmem, /**< block memory */
10915  SCIP_SET* set, /**< global SCIP settings */
10916  SCIP_STAT* stat, /**< problem statistics */
10917  SCIP_PROB* transprob, /**< transformed problem */
10918  SCIP_PROB* origprob, /**< original problem */
10919  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10920  SCIP_REOPT* reopt, /**< reoptimization data structure */
10921  SCIP_LP* lp, /**< current LP data */
10922  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10923  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10924  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10925  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
10926  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
10927  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
10928  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
10929  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
10930  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10931  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
10932  )
10933 {
10934  assert(var != NULL);
10935  assert(set != NULL);
10936  assert(var->scip == set->scip);
10937  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
10938  assert(infeasible != NULL);
10939 
10940  *infeasible = FALSE;
10941  if( nbdchgs != NULL )
10942  *nbdchgs = 0;
10943 
10944  switch( SCIPvarGetStatus(var) )
10945  {
10947  assert(var->data.original.transvar != NULL);
10948  SCIP_CALL( SCIPvarAddImplic(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10949  cliquetable, branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible,
10950  nbdchgs) );
10951  break;
10952 
10953  case SCIP_VARSTATUS_COLUMN:
10954  case SCIP_VARSTATUS_LOOSE:
10955  /* if the variable is fixed (although it has no FIXED status), and varfixing corresponds to the fixed value of
10956  * the variable, the implication can be applied directly;
10957  * otherwise, add implication to the implications list (and add inverse of implication to the implied variable)
10958  */
10959  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
10960  {
10961  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
10962  {
10963  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
10964  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
10965  }
10966  }
10967  else
10968  {
10969  SCIP_CALL( SCIPvarGetProbvarBound(&implvar, &implbound, &impltype) );
10970  SCIPvarAdjustBd(implvar, set, impltype, &implbound);
10971  if( SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED )
10972  {
10973  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10974  branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
10975  }
10976  }
10977  break;
10978 
10979  case SCIP_VARSTATUS_FIXED:
10980  /* if varfixing corresponds to the fixed value of the variable, the implication can be applied directly */
10981  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
10982  {
10983  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
10984  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
10985  }
10986  break;
10987 
10989  /* implication added for x == 1:
10990  * x == 1 && x = 1*z + 0 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10991  * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10992  * implication added for x == 0:
10993  * x == 0 && x = 1*z + 0 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10994  * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10995  *
10996  * use only binary variables z
10997  */
10998  assert(var->data.aggregate.var != NULL);
10999  if( SCIPvarIsBinary(var->data.aggregate.var) )
11000  {
11001  assert( (SCIPsetIsEQ(set, var->data.aggregate.scalar, 1.0) && SCIPsetIsZero(set, var->data.aggregate.constant))
11002  || (SCIPsetIsEQ(set, var->data.aggregate.scalar, -1.0) && SCIPsetIsEQ(set, var->data.aggregate.constant, 1.0)) );
11003 
11004  if( var->data.aggregate.scalar > 0 )
11005  {
11006  SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11007  cliquetable, branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible,
11008  nbdchgs) );
11009  }
11010  else
11011  {
11012  SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11013  cliquetable, branchcand, eventqueue, !varfixing, implvar, impltype, implbound, transitive, infeasible,
11014  nbdchgs) );
11015  }
11016  }
11017  break;
11018 
11020  /* nothing to do here */
11021  break;
11022 
11024  /* implication added for x == 1:
11025  * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
11026  * implication added for x == 0:
11027  * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
11028  */
11029  assert(var->negatedvar != NULL);
11031  assert(var->negatedvar->negatedvar == var);
11032  assert(SCIPvarIsBinary(var->negatedvar));
11033 
11035  {
11036  SCIP_CALL( SCIPvarAddImplic(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11037  cliquetable, branchcand, eventqueue, !varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
11038  }
11039  /* in case one both variables are not of binary type we have to add the implication as variable bounds */
11040  else
11041  {
11042  /* if the implied variable is of binary type exchange the variables */
11043  if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
11044  {
11045  SCIP_CALL( SCIPvarAddImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
11046  branchcand, eventqueue, (impltype == SCIP_BOUNDTYPE_UPPER) ? TRUE : FALSE, var->negatedvar,
11047  varfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER, varfixing ? 1.0 : 0.0, transitive,
11048  infeasible, nbdchgs) );
11049  }
11050  else
11051  {
11052  /* both variables are not of binary type but are implicit binary; in that case we can only add this
11053  * implication as variable bounds
11054  */
11055 
11056  /* add variable lower bound on the negation of var */
11057  if( varfixing )
11058  {
11059  /* (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
11060  * as variable lower bound
11061  */
11062  SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11063  cliquetable, branchcand, eventqueue, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : -1.0,
11064  (impltype == SCIP_BOUNDTYPE_UPPER) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
11065  }
11066  else
11067  {
11068  /* (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
11069  * as variable upper bound
11070  */
11071  SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11072  cliquetable, branchcand, eventqueue, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? -1.0 : 1.0,
11073  (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : 0.0, transitive, infeasible, nbdchgs) );
11074  }
11075 
11076  /* add variable bound on implvar */
11077  if( impltype == SCIP_BOUNDTYPE_UPPER )
11078  {
11079  /* (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
11080  * as variable upper bound
11081  */
11082  SCIP_CALL( SCIPvarAddVub(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
11083  branchcand, eventqueue, var->negatedvar, (varfixing) ? 1.0 : -1.0,
11084  (varfixing) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
11085  }
11086  else
11087  {
11088  /* (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
11089  * as variable upper bound
11090  */
11091  SCIP_CALL( SCIPvarAddVlb(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
11092  branchcand, eventqueue, var->negatedvar, (varfixing) ? -1.0 : 1.0, (varfixing) ? 1.0 : 0.0,
11093  transitive, infeasible, nbdchgs) );
11094  }
11095  }
11096  }
11097  break;
11098 
11099  default:
11100  SCIPerrorMessage("unknown variable status\n");
11101  return SCIP_INVALIDDATA;
11102  }
11103 
11104  return SCIP_OKAY;
11105 }
11106 
11107 /** returns whether there is an implication x == varfixing -> y <= b or y >= b in the implication graph;
11108  * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
11109  * both variables must be active, variable x must be binary
11110  */
11112  SCIP_VAR* var, /**< problem variable x */
11113  SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
11114  SCIP_VAR* implvar, /**< variable y to search for */
11115  SCIP_BOUNDTYPE impltype /**< type of implication y <=/>= b to search for */
11116  )
11117 {
11118  assert(var != NULL);
11119  assert(implvar != NULL);
11120  assert(SCIPvarIsActive(var));
11121  assert(SCIPvarIsActive(implvar));
11122  assert(SCIPvarIsBinary(var));
11123 
11124  return var->implics != NULL && SCIPimplicsContainsImpl(var->implics, varfixing, implvar, impltype);
11125 }
11126 
11127 /** returns whether there is an implication x == varfixing -> y == implvarfixing in the implication graph;
11128  * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
11129  * both variables must be active binary variables
11130  */
11132  SCIP_VAR* var, /**< problem variable x */
11133  SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
11134  SCIP_VAR* implvar, /**< variable y to search for */
11135  SCIP_Bool implvarfixing /**< value of the implied variable to search for */
11136  )
11137 {
11138  assert(SCIPvarIsBinary(implvar));
11139 
11140  return SCIPvarHasImplic(var, varfixing, implvar, implvarfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER);
11141 }
11142 
11143 /** gets the values of b in implications x == varfixing -> y <= b or y >= b in the implication graph;
11144  * the values are set to SCIP_INVALID if there is no implied bound
11145  */
11147  SCIP_VAR* var, /**< problem variable x */
11148  SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
11149  SCIP_VAR* implvar, /**< variable y to search for */
11150  SCIP_Real* lb, /**< buffer to store the value of the implied lower bound */
11151  SCIP_Real* ub /**< buffer to store the value of the implied upper bound */
11152  )
11153 {
11154  int lowerpos;
11155  int upperpos;
11156  SCIP_Real* bounds;
11157 
11158  assert(lb != NULL);
11159  assert(ub != NULL);
11160 
11161  *lb = SCIP_INVALID;
11162  *ub = SCIP_INVALID;
11163 
11164  if( var->implics == NULL )
11165  return;
11166 
11167  SCIPimplicsGetVarImplicPoss(var->implics, varfixing, implvar, &lowerpos, &upperpos);
11168  bounds = SCIPvarGetImplBounds(var, varfixing);
11169 
11170  if( bounds == NULL )
11171  return;
11172 
11173  if( lowerpos >= 0 )
11174  *lb = bounds[lowerpos];
11175 
11176  if( upperpos >= 0 )
11177  *ub = bounds[upperpos];
11178 }
11179 
11180 
11181 /** fixes the bounds of a binary variable to the given value, counting bound changes and detecting infeasibility */
11183  SCIP_VAR* var, /**< problem variable */
11184  BMS_BLKMEM* blkmem, /**< block memory */
11185  SCIP_SET* set, /**< global SCIP settings */
11186  SCIP_STAT* stat, /**< problem statistics */
11187  SCIP_PROB* transprob, /**< transformed problem */
11188  SCIP_PROB* origprob, /**< original problem */
11189  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
11190  SCIP_REOPT* reopt, /**< reoptimization data structure */
11191  SCIP_LP* lp, /**< current LP data */
11192  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
11193  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
11194  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11195  SCIP_Bool value, /**< value to fix variable to */
11196  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
11197  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
11198  )
11199 {
11200  assert(var != NULL);
11201  assert(set != NULL);
11202  assert(var->scip == set->scip);
11203  assert(infeasible != NULL);
11204 
11205  *infeasible = FALSE;
11206 
11207  if( value == FALSE )
11208  {
11209  if( var->glbdom.lb > 0.5 )
11210  *infeasible = TRUE;
11211  else if( var->glbdom.ub > 0.5 )
11212  {
11213  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
11214  * with the local bound, in this case we need to store the bound change as pending bound change
11215  */
11216  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
11217  {
11218  assert(tree != NULL);
11219  assert(transprob != NULL);
11220  assert(SCIPprobIsTransformed(transprob));
11221 
11222  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
11223  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
11224  }
11225  else
11226  {
11227  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
11228  }
11229 
11230  if( nbdchgs != NULL )
11231  (*nbdchgs)++;
11232  }
11233  }
11234  else
11235  {
11236  if( var->glbdom.ub < 0.5 )
11237  *infeasible = TRUE;
11238  else if( var->glbdom.lb < 0.5 )
11239  {
11240  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
11241  * with the local bound, in this case we need to store the bound change as pending bound change
11242  */
11243  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
11244  {
11245  assert(tree != NULL);
11246  assert(transprob != NULL);
11247  assert(SCIPprobIsTransformed(transprob));
11248 
11249  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
11250  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
11251  }
11252  else
11253  {
11254  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
11255  }
11256 
11257  if( nbdchgs != NULL )
11258  (*nbdchgs)++;
11259  }
11260  }
11261 
11262  return SCIP_OKAY;
11263 }
11264 
11265 /** adds the variable to the given clique and updates the list of cliques the binary variable is member of;
11266  * if the variable now appears twice in the clique with the same value, it is fixed to the opposite value;
11267  * if the variable now appears twice in the clique with opposite values, all other variables are fixed to
11268  * the opposite of the value they take in the clique
11269  */
11271  SCIP_VAR* var, /**< problem variable */
11272  BMS_BLKMEM* blkmem, /**< block memory */
11273  SCIP_SET* set, /**< global SCIP settings */
11274  SCIP_STAT* stat, /**< problem statistics */
11275  SCIP_PROB* transprob, /**< transformed problem */
11276  SCIP_PROB* origprob, /**< original problem */
11277  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
11278  SCIP_REOPT* reopt, /**< reoptimization data structure */
11279  SCIP_LP* lp, /**< current LP data */
11280  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
11281  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
11282  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11283  SCIP_Bool value, /**< value of the variable in the clique */
11284  SCIP_CLIQUE* clique, /**< clique the variable should be added to */
11285  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
11286  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
11287  )
11288 {
11289  assert(var != NULL);
11290  assert(set != NULL);
11291  assert(var->scip == set->scip);
11292  assert(SCIPvarIsBinary(var));
11293  assert(infeasible != NULL);
11294 
11295  *infeasible = FALSE;
11296 
11297  /* get corresponding active problem variable */
11298  SCIP_CALL( SCIPvarGetProbvarBinary(&var, &value) );
11303  assert(SCIPvarIsBinary(var));
11304 
11305  /* only column and loose variables may be member of a clique */
11307  {
11308  SCIP_Bool doubleentry;
11309  SCIP_Bool oppositeentry;
11310 
11311  /* add variable to clique */
11312  SCIP_CALL( SCIPcliqueAddVar(clique, blkmem, set, var, value, &doubleentry, &oppositeentry) );
11313 
11314  /* add clique to variable's clique list */
11315  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
11316 
11317  /* check consistency of cliquelist */
11318  SCIPcliquelistCheck(var->cliquelist, var);
11319 
11320  /* if the variable now appears twice with the same value in the clique, it can be fixed to the opposite value */
11321  if( doubleentry )
11322  {
11323  SCIP_CALL( SCIPvarFixBinary(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
11324  eventqueue, cliquetable, !value, infeasible, nbdchgs) );
11325  }
11326 
11327  /* if the variable appears with both values in the clique, all other variables of the clique can be fixed
11328  * to the opposite of the value they take in the clique
11329  */
11330  if( oppositeentry )
11331  {
11332  SCIP_VAR** vars;
11333  SCIP_Bool* values;
11334  int nvars;
11335  int i;
11336 
11337  nvars = SCIPcliqueGetNVars(clique);
11338  vars = SCIPcliqueGetVars(clique);
11339  values = SCIPcliqueGetValues(clique);
11340  for( i = 0; i < nvars && !(*infeasible); ++i )
11341  {
11342  if( vars[i] == var )
11343  continue;
11344 
11345  SCIP_CALL( SCIPvarFixBinary(vars[i], blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
11346  eventqueue, cliquetable, !values[i], infeasible, nbdchgs) );
11347  }
11348  }
11349  }
11350 
11351  return SCIP_OKAY;
11352 }
11353 
11354 /** adds a filled clique to the cliquelists of all corresponding variables */
11356  SCIP_VAR** vars, /**< problem variables */
11357  SCIP_Bool* values, /**< values of the variables in the clique */
11358  int nvars, /**< number of problem variables */
11359  BMS_BLKMEM* blkmem, /**< block memory */
11360  SCIP_SET* set, /**< global SCIP settings */
11361  SCIP_CLIQUE* clique /**< clique that contains all given variables and values */
11362  )
11363 {
11364  SCIP_VAR* var;
11365  int v;
11366 
11367  assert(vars != NULL);
11368  assert(values != NULL);
11369  assert(nvars > 0);
11370  assert(set != NULL);
11371  assert(blkmem != NULL);
11372  assert(clique != NULL);
11373 
11374  for( v = nvars - 1; v >= 0; --v )
11375  {
11376  var = vars[v];
11377  assert(SCIPvarIsBinary(var));
11379 
11380  /* add clique to variable's clique list */
11381  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, values[v], clique) );
11382 
11383  /* check consistency of cliquelist */
11384  SCIPcliquelistCheck(var->cliquelist, var);
11385  }
11386 
11387  return SCIP_OKAY;
11388 }
11389 
11390 /** adds a clique to the list of cliques of the given binary variable, but does not change the clique
11391  * itself
11392  */
11394  SCIP_VAR* var, /**< problem variable */
11395  BMS_BLKMEM* blkmem, /**< block memory */
11396  SCIP_SET* set, /**< global SCIP settings */
11397  SCIP_Bool value, /**< value of the variable in the clique */
11398  SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
11399  )
11400 {
11401  assert(var != NULL);
11402  assert(SCIPvarIsBinary(var));
11404 
11405  /* add clique to variable's clique list */
11406  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
11407 
11408  return SCIP_OKAY;
11409 }
11410 
11411 
11412 /** deletes a clique from the list of cliques the binary variable is member of, but does not change the clique
11413  * itself
11414  */
11416  SCIP_VAR* var, /**< problem variable */
11417  BMS_BLKMEM* blkmem, /**< block memory */
11418  SCIP_Bool value, /**< value of the variable in the clique */
11419  SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
11420  )
11421 {
11422  assert(var != NULL);
11423  assert(SCIPvarIsBinary(var));
11424 
11425  /* delete clique from variable's clique list */
11426  SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
11427 
11428  return SCIP_OKAY;
11429 }
11430 
11431 /** deletes the variable from the given clique and updates the list of cliques the binary variable is member of */
11433  SCIP_VAR* var, /**< problem variable */
11434  BMS_BLKMEM* blkmem, /**< block memory */
11435  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11436  SCIP_Bool value, /**< value of the variable in the clique */
11437  SCIP_CLIQUE* clique /**< clique the variable should be removed from */
11438  )
11439 {
11440  assert(var != NULL);
11441  assert(SCIPvarIsBinary(var));
11442 
11443  /* get corresponding active problem variable */
11444  SCIP_CALL( SCIPvarGetProbvarBinary(&var, &value) );
11449  assert(SCIPvarIsBinary(var));
11450 
11451  /* only column and loose variables may be member of a clique */
11453  {
11454  /* delete clique from variable's clique list */
11455  SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
11456 
11457  /* delete variable from clique */
11458  SCIPcliqueDelVar(clique, cliquetable, var, value);
11459 
11460  /* check consistency of cliquelist */
11461  SCIPcliquelistCheck(var->cliquelist, var);
11462  }
11463 
11464  return SCIP_OKAY;
11465 }
11466 
11467 /** returns whether there is a clique that contains both given variable/value pairs;
11468  * the variables must be active binary variables;
11469  * if regardimplics is FALSE, only the cliques in the clique table are looked at;
11470  * if regardimplics is TRUE, both the cliques and the implications of the implication graph are regarded
11471  *
11472  * @note a variable with it's negated variable are NOT! in a clique
11473  * @note a variable with itself are in a clique
11474  */
11476  SCIP_VAR* var1, /**< first variable */
11477  SCIP_Bool value1, /**< value of first variable */
11478  SCIP_VAR* var2, /**< second variable */
11479  SCIP_Bool value2, /**< value of second variable */
11480  SCIP_Bool regardimplics /**< should the implication graph also be searched for a clique? */
11481  )
11482 {
11483  assert(var1 != NULL);
11484  assert(var2 != NULL);
11485  assert(SCIPvarIsActive(var1));
11486  assert(SCIPvarIsActive(var2));
11487  assert(SCIPvarIsBinary(var1));
11488  assert(SCIPvarIsBinary(var2));
11489 
11490  return (SCIPcliquelistsHaveCommonClique(var1->cliquelist, value1, var2->cliquelist, value2)
11491  || (regardimplics && SCIPvarHasImplic(var1, value1, var2, value2 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER)));
11492 }
11493 
11494 /** actually changes the branch factor of the variable and of all parent variables */
11495 static
11497  SCIP_VAR* var, /**< problem variable */
11498  SCIP_SET* set, /**< global SCIP settings */
11499  SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
11500  )
11501 {
11502  SCIP_VAR* parentvar;
11503  SCIP_Real eps;
11504  int i;
11505 
11506  assert(var != NULL);
11507  assert(set != NULL);
11508  assert(var->scip == set->scip);
11509 
11510  /* only use positive values */
11511  eps = SCIPsetEpsilon(set);
11512  branchfactor = MAX(branchfactor, eps);
11513 
11514  SCIPsetDebugMsg(set, "process changing branch factor of <%s> from %f to %f\n", var->name, var->branchfactor, branchfactor);
11515 
11516  if( SCIPsetIsEQ(set, branchfactor, var->branchfactor) )
11517  return SCIP_OKAY;
11518 
11519  /* change the branch factor */
11520  var->branchfactor = branchfactor;
11521 
11522  /* process parent variables */
11523  for( i = 0; i < var->nparentvars; ++i )
11524  {
11525  parentvar = var->parentvars[i];
11526  assert(parentvar != NULL);
11527 
11528  switch( SCIPvarGetStatus(parentvar) )
11529  {
11531  /* do not change priorities across the border between transformed and original problem */
11532  break;
11533 
11534  case SCIP_VARSTATUS_COLUMN:
11535  case SCIP_VARSTATUS_LOOSE:
11536  case SCIP_VARSTATUS_FIXED:
11538  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11539  SCIPABORT();
11540  return SCIP_INVALIDDATA; /*lint !e527*/
11541 
11544  SCIP_CALL( varProcessChgBranchFactor(parentvar, set, branchfactor) );
11545  break;
11546 
11547  default:
11548  SCIPerrorMessage("unknown variable status\n");
11549  SCIPABORT();
11550  return SCIP_ERROR; /*lint !e527*/
11551  }
11552  }
11553 
11554  return SCIP_OKAY;
11555 }
11556 
11557 /** sets the branch factor of the variable; this value can be used in the branching methods to scale the score
11558  * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
11559  */
11561  SCIP_VAR* var, /**< problem variable */
11562  SCIP_SET* set, /**< global SCIP settings */
11563  SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
11564  )
11565 {
11566  int v;
11567 
11568  assert(var != NULL);
11569  assert(set != NULL);
11570  assert(var->scip == set->scip);
11571  assert(branchfactor >= 0.0);
11572 
11573  SCIPdebugMessage("changing branch factor of <%s> from %g to %g\n", var->name, var->branchfactor, branchfactor);
11574 
11575  if( SCIPsetIsEQ(set, var->branchfactor, branchfactor) )
11576  return SCIP_OKAY;
11577 
11578  /* change priorities of attached variables */
11579  switch( SCIPvarGetStatus(var) )
11580  {
11582  if( var->data.original.transvar != NULL )
11583  {
11584  SCIP_CALL( SCIPvarChgBranchFactor(var->data.original.transvar, set, branchfactor) );
11585  }
11586  else
11587  {
11588  assert(set->stage == SCIP_STAGE_PROBLEM);
11589  var->branchfactor = branchfactor;
11590  }
11591  break;
11592 
11593  case SCIP_VARSTATUS_COLUMN:
11594  case SCIP_VARSTATUS_LOOSE:
11595  case SCIP_VARSTATUS_FIXED:
11596  SCIP_CALL( varProcessChgBranchFactor(var, set, branchfactor) );
11597  break;
11598 
11600  assert(!var->donotaggr);
11601  assert(var->data.aggregate.var != NULL);
11602  SCIP_CALL( SCIPvarChgBranchFactor(var->data.aggregate.var, set, branchfactor) );
11603  break;
11604 
11606  assert(!var->donotmultaggr);
11607  for( v = 0; v < var->data.multaggr.nvars; ++v )
11608  {
11609  SCIP_CALL( SCIPvarChgBranchFactor(var->data.multaggr.vars[v], set, branchfactor) );
11610  }
11611  break;
11612 
11614  assert(var->negatedvar != NULL);
11616  assert(var->negatedvar->negatedvar == var);
11617  SCIP_CALL( SCIPvarChgBranchFactor(var->negatedvar, set, branchfactor) );
11618  break;
11619 
11620  default:
11621  SCIPerrorMessage("unknown variable status\n");
11622  SCIPABORT();
11623  return SCIP_ERROR; /*lint !e527*/
11624  }
11625 
11626  return SCIP_OKAY;
11627 }
11628 
11629 /** actually changes the branch priority of the variable and of all parent variables */
11630 static
11632  SCIP_VAR* var, /**< problem variable */
11633  int branchpriority /**< branching priority of the variable */
11634  )
11635 {
11636  SCIP_VAR* parentvar;
11637  int i;
11638 
11639  assert(var != NULL);
11640 
11641  SCIPdebugMessage("process changing branch priority of <%s> from %d to %d\n",
11642  var->name, var->branchpriority, branchpriority);
11643 
11644  if( branchpriority == var->branchpriority )
11645  return SCIP_OKAY;
11646 
11647  /* change the branch priority */
11648  var->branchpriority = branchpriority;
11649 
11650  /* process parent variables */
11651  for( i = 0; i < var->nparentvars; ++i )
11652  {
11653  parentvar = var->parentvars[i];
11654  assert(parentvar != NULL);
11655 
11656  switch( SCIPvarGetStatus(parentvar) )
11657  {
11659  /* do not change priorities across the border between transformed and original problem */
11660  break;
11661 
11662  case SCIP_VARSTATUS_COLUMN:
11663  case SCIP_VARSTATUS_LOOSE:
11664  case SCIP_VARSTATUS_FIXED:
11666  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11667  SCIPABORT();
11668  return SCIP_INVALIDDATA; /*lint !e527*/
11669 
11672  SCIP_CALL( varProcessChgBranchPriority(parentvar, branchpriority) );
11673  break;
11674 
11675  default:
11676  SCIPerrorMessage("unknown variable status\n");
11677  return SCIP_ERROR;
11678  }
11679  }
11680 
11681  return SCIP_OKAY;
11682 }
11683 
11684 /** sets the branch priority of the variable; variables with higher branch priority are always preferred to variables
11685  * with lower priority in selection of branching variable
11686  */
11688  SCIP_VAR* var, /**< problem variable */
11689  int branchpriority /**< branching priority of the variable */
11690  )
11691 {
11692  int v;
11693 
11694  assert(var != NULL);
11695 
11696  SCIPdebugMessage("changing branch priority of <%s> from %d to %d\n", var->name, var->branchpriority, branchpriority);
11697 
11698  if( var->branchpriority == branchpriority )
11699  return SCIP_OKAY;
11700 
11701  /* change priorities of attached variables */
11702  switch( SCIPvarGetStatus(var) )
11703  {
11705  if( var->data.original.transvar != NULL )
11706  {
11707  SCIP_CALL( SCIPvarChgBranchPriority(var->data.original.transvar, branchpriority) );
11708  }
11709  else
11710  var->branchpriority = branchpriority;
11711  break;
11712 
11713  case SCIP_VARSTATUS_COLUMN:
11714  case SCIP_VARSTATUS_LOOSE:
11715  case SCIP_VARSTATUS_FIXED:
11716  SCIP_CALL( varProcessChgBranchPriority(var, branchpriority) );
11717  break;
11718 
11720  assert(!var->donotaggr);
11721  assert(var->data.aggregate.var != NULL);
11722  SCIP_CALL( SCIPvarChgBranchPriority(var->data.aggregate.var, branchpriority) );
11723  break;
11724 
11726  assert(!var->donotmultaggr);
11727  for( v = 0; v < var->data.multaggr.nvars; ++v )
11728  {
11729  SCIP_CALL( SCIPvarChgBranchPriority(var->data.multaggr.vars[v], branchpriority) );
11730  }
11731  break;
11732 
11734  assert(var->negatedvar != NULL);
11736  assert(var->negatedvar->negatedvar == var);
11737  SCIP_CALL( SCIPvarChgBranchPriority(var->negatedvar, branchpriority) );
11738  break;
11739 
11740  default:
11741  SCIPerrorMessage("unknown variable status\n");
11742  SCIPABORT();
11743  return SCIP_ERROR; /*lint !e527*/
11744  }
11745 
11746  return SCIP_OKAY;
11747 }
11748 
11749 /** actually changes the branch direction of the variable and of all parent variables */
11750 static
11752  SCIP_VAR* var, /**< problem variable */
11753  SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
11754  )
11755 {
11756  SCIP_VAR* parentvar;
11757  int i;
11758 
11759  assert(var != NULL);
11760 
11761  SCIPdebugMessage("process changing branch direction of <%s> from %u to %d\n",
11762  var->name, var->branchdirection, branchdirection);
11763 
11764  if( branchdirection == (SCIP_BRANCHDIR)var->branchdirection )
11765  return SCIP_OKAY;
11766 
11767  /* change the branch direction */
11768  var->branchdirection = branchdirection; /*lint !e641*/
11769 
11770  /* process parent variables */
11771  for( i = 0; i < var->nparentvars; ++i )
11772  {
11773  parentvar = var->parentvars[i];
11774  assert(parentvar != NULL);
11775 
11776  switch( SCIPvarGetStatus(parentvar) )
11777  {
11779  /* do not change directions across the border between transformed and original problem */
11780  break;
11781 
11782  case SCIP_VARSTATUS_COLUMN:
11783  case SCIP_VARSTATUS_LOOSE:
11784  case SCIP_VARSTATUS_FIXED:
11786  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11787  SCIPABORT();
11788  return SCIP_INVALIDDATA; /*lint !e527*/
11789 
11791  if( parentvar->data.aggregate.scalar > 0.0 )
11792  {
11793  SCIP_CALL( varProcessChgBranchDirection(parentvar, branchdirection) );
11794  }
11795  else
11796  {
11797  SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
11798  }
11799  break;
11800 
11802  SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
11803  break;
11804 
11805  default:
11806  SCIPerrorMessage("unknown variable status\n");
11807  SCIPABORT();
11808  return SCIP_ERROR; /*lint !e527*/
11809  }
11810  }
11811 
11812  return SCIP_OKAY;
11813 }
11814 
11815 /** sets the branch direction of the variable; variables with higher branch direction are always preferred to variables
11816  * with lower direction in selection of branching variable
11817  */
11819  SCIP_VAR* var, /**< problem variable */
11820  SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
11821  )
11822 {
11823  int v;
11824 
11825  assert(var != NULL);
11826 
11827  SCIPdebugMessage("changing branch direction of <%s> from %u to %d\n", var->name, var->branchdirection, branchdirection);
11828 
11829  if( (SCIP_BRANCHDIR)var->branchdirection == branchdirection )
11830  return SCIP_OKAY;
11831 
11832  /* change directions of attached variables */
11833  switch( SCIPvarGetStatus(var) )
11834  {
11836  if( var->data.original.transvar != NULL )
11837  {
11838  SCIP_CALL( SCIPvarChgBranchDirection(var->data.original.transvar, branchdirection) );
11839  }
11840  else
11841  var->branchdirection = branchdirection; /*lint !e641*/
11842  break;
11843 
11844  case SCIP_VARSTATUS_COLUMN:
11845  case SCIP_VARSTATUS_LOOSE:
11846  case SCIP_VARSTATUS_FIXED:
11847  SCIP_CALL( varProcessChgBranchDirection(var, branchdirection) );
11848  break;
11849 
11851  assert(!var->donotaggr);
11852  assert(var->data.aggregate.var != NULL);
11853  if( var->data.aggregate.scalar > 0.0 )
11854  {
11855  SCIP_CALL( SCIPvarChgBranchDirection(var->data.aggregate.var, branchdirection) );
11856  }
11857  else
11858  {
11860  }
11861  break;
11862 
11864  assert(!var->donotmultaggr);
11865  for( v = 0; v < var->data.multaggr.nvars; ++v )
11866  {
11867  /* only update branching direction of aggregation variables, if they don't have a preferred direction yet */
11868  assert(var->data.multaggr.vars[v] != NULL);
11870  {
11871  if( var->data.multaggr.scalars[v] > 0.0 )
11872  {
11873  SCIP_CALL( SCIPvarChgBranchDirection(var->data.multaggr.vars[v], branchdirection) );
11874  }
11875  else
11876  {
11878  }
11879  }
11880  }
11881  break;
11882 
11884  assert(var->negatedvar != NULL);
11886  assert(var->negatedvar->negatedvar == var);
11888  break;
11889 
11890  default:
11891  SCIPerrorMessage("unknown variable status\n");
11892  SCIPABORT();
11893  return SCIP_ERROR; /*lint !e527*/
11894  }
11895 
11896  return SCIP_OKAY;
11897 }
11898 
11899 /** compares the index of two variables, only active, fixed or negated variables are allowed, if a variable
11900  * is negated then the index of the corresponding active variable is taken, returns -1 if first is
11901  * smaller than, and +1 if first is greater than second variable index; returns 0 if both indices
11902  * are equal, which means both variables are equal
11903  */
11905  SCIP_VAR* var1, /**< first problem variable */
11906  SCIP_VAR* var2 /**< second problem variable */
11907  )
11908 {
11909  assert(var1 != NULL);
11910  assert(var2 != NULL);
11913 
11915  var1 = SCIPvarGetNegatedVar(var1);
11917  var2 = SCIPvarGetNegatedVar(var2);
11918 
11919  assert(var1 != NULL);
11920  assert(var2 != NULL);
11921 
11922  if( SCIPvarGetIndex(var1) < SCIPvarGetIndex(var2) )
11923  return -1;
11924  else if( SCIPvarGetIndex(var1) > SCIPvarGetIndex(var2) )
11925  return +1;
11926 
11927  assert(var1 == var2);
11928  return 0;
11929 }
11930 
11931 /** comparison method for sorting active and negated variables by non-decreasing index, active and negated
11932  * variables are handled as the same variables
11933  */
11934 SCIP_DECL_SORTPTRCOMP(SCIPvarCompActiveAndNegated)
11936  return SCIPvarCompareActiveAndNegated((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
11937 }
11938 
11939 /** compares the index of two variables, returns -1 if first is smaller than, and +1 if first is greater than second
11940  * variable index; returns 0 if both indices are equal, which means both variables are equal
11941  */
11942 int SCIPvarCompare(
11943  SCIP_VAR* var1, /**< first problem variable */
11944  SCIP_VAR* var2 /**< second problem variable */
11945  )
11946 {
11947  assert(var1 != NULL);
11948  assert(var2 != NULL);
11949 
11950  if( var1->index < var2->index )
11951  return -1;
11952  else if( var1->index > var2->index )
11953  return +1;
11954  else
11955  {
11956  assert(var1 == var2);
11957  return 0;
11958  }
11959 }
11960 
11961 /** comparison method for sorting variables by non-decreasing index */
11962 SCIP_DECL_SORTPTRCOMP(SCIPvarComp)
11964  return SCIPvarCompare((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
11965 }
11966 
11967 /** comparison method for sorting variables by non-decreasing objective coefficient */
11968 SCIP_DECL_SORTPTRCOMP(SCIPvarCompObj)
11970  SCIP_Real obj1;
11971  SCIP_Real obj2;
11972 
11973  obj1 = SCIPvarGetObj((SCIP_VAR*)elem1);
11974  obj2 = SCIPvarGetObj((SCIP_VAR*)elem2);
11975 
11976  if( obj1 < obj2 )
11977  return -1;
11978  else if( obj1 > obj2 )
11979  return +1;
11980  else
11981  return 0;
11982 }
11983 
11984 /** hash key retrieval function for variables */
11985 SCIP_DECL_HASHGETKEY(SCIPvarGetHashkey)
11986 { /*lint --e{715}*/
11987  return elem;
11988 }
11989 
11990 /** returns TRUE iff the indices of both variables are equal */
11991 SCIP_DECL_HASHKEYEQ(SCIPvarIsHashkeyEq)
11992 { /*lint --e{715}*/
11993  if( key1 == key2 )
11994  return TRUE;
11995  return FALSE;
11996 }
11997 
11998 /** returns the hash value of the key */
11999 SCIP_DECL_HASHKEYVAL(SCIPvarGetHashkeyVal)
12000 { /*lint --e{715}*/
12001  assert( SCIPvarGetIndex((SCIP_VAR*) key) >= 0 );
12002  return (unsigned int) SCIPvarGetIndex((SCIP_VAR*) key);
12003 }
12004 
12005 /** return for given variables all their active counterparts; all active variables will be pairwise different */
12007  SCIP_SET* set, /**< global SCIP settings */
12008  SCIP_VAR** vars, /**< variable array with given variables and as output all active
12009  * variables, if enough slots exist
12010  */
12011  int* nvars, /**< number of given variables, and as output number of active variables,
12012  * if enough slots exist
12013  */
12014  int varssize, /**< available slots in vars array */
12015  int* requiredsize /**< pointer to store the required array size for the active variables */
12016  )
12017 {
12018  SCIP_VAR** activevars;
12019  int nactivevars;
12020  int activevarssize;
12021 
12022  SCIP_VAR* var;
12023  int v;
12024 
12025  SCIP_VAR** tmpvars;
12026  SCIP_VAR** multvars;
12027  int tmpvarssize;
12028  int ntmpvars;
12029  int noldtmpvars;
12030  int nmultvars;
12031 
12032  assert(set != NULL);
12033  assert(nvars != NULL);
12034  assert(vars != NULL || *nvars == 0);
12035  assert(varssize >= *nvars);
12036  assert(requiredsize != NULL);
12037 
12038  *requiredsize = 0;
12039 
12040  if( *nvars == 0 )
12041  return SCIP_OKAY;
12042 
12043  nactivevars = 0;
12044  activevarssize = *nvars;
12045  ntmpvars = *nvars;
12046  tmpvarssize = *nvars;
12047 
12048  /* temporary memory */
12049  SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
12050  /* coverity[copy_paste_error] */
12051  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
12052 
12053  noldtmpvars = ntmpvars;
12054 
12055  /* sort all variables to combine equal variables easily */
12056  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
12057  for( v = ntmpvars - 1; v > 0; --v )
12058  {
12059  /* combine same variables */
12060  if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
12061  {
12062  --ntmpvars;
12063  tmpvars[v] = tmpvars[ntmpvars];
12064  }
12065  }
12066  /* sort all variables again to combine equal variables later on */
12067  if( noldtmpvars > ntmpvars )
12068  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
12069 
12070  /* collect for each variable the representation in active variables */
12071  while( ntmpvars >= 1 )
12072  {
12073  --ntmpvars;
12074  var = tmpvars[ntmpvars];
12075  assert( var != NULL );
12076 
12077  switch( SCIPvarGetStatus(var) )
12078  {
12080  if( var->data.original.transvar == NULL )
12081  {
12082  SCIPerrorMessage("original variable has no transformed variable attached\n");
12083  SCIPABORT();
12084  return SCIP_INVALIDDATA; /*lint !e527*/
12085  }
12086  tmpvars[ntmpvars] = var->data.original.transvar;
12087  ++ntmpvars;
12088  break;
12089 
12091  tmpvars[ntmpvars] = var->data.aggregate.var;
12092  ++ntmpvars;
12093  break;
12094 
12096  tmpvars[ntmpvars] = var->negatedvar;
12097  ++ntmpvars;
12098  break;
12099 
12100  case SCIP_VARSTATUS_LOOSE:
12101  case SCIP_VARSTATUS_COLUMN:
12102  /* check for space in temporary memory */
12103  if( nactivevars >= activevarssize )
12104  {
12105  activevarssize *= 2;
12106  SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
12107  assert(nactivevars < activevarssize);
12108  }
12109  activevars[nactivevars] = var;
12110  nactivevars++;
12111  break;
12112 
12114  /* x = a_1*y_1 + ... + a_n*y_n + c */
12115  nmultvars = var->data.multaggr.nvars;
12116  multvars = var->data.multaggr.vars;
12117 
12118  /* check for space in temporary memory */
12119  if( nmultvars + ntmpvars > tmpvarssize )
12120  {
12121  while( nmultvars + ntmpvars > tmpvarssize )
12122  tmpvarssize *= 2;
12123  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
12124  assert(nmultvars + ntmpvars <= tmpvarssize);
12125  }
12126 
12127  /* copy all multi-aggregation variables into our working array */
12128  BMScopyMemoryArray(&tmpvars[ntmpvars], multvars, nmultvars); /*lint !e866*/
12129 
12130  /* get active, fixed or multi-aggregated corresponding variables for all new ones */
12131  SCIPvarsGetProbvar(&tmpvars[ntmpvars], nmultvars);
12132 
12133  ntmpvars += nmultvars;
12134  noldtmpvars = ntmpvars;
12135 
12136  /* sort all variables to combine equal variables easily */
12137  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
12138  for( v = ntmpvars - 1; v > 0; --v )
12139  {
12140  /* combine same variables */
12141  if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
12142  {
12143  --ntmpvars;
12144  tmpvars[v] = tmpvars[ntmpvars];
12145  }
12146  }
12147  /* sort all variables again to combine equal variables later on */
12148  if( noldtmpvars > ntmpvars )
12149  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
12150 
12151  break;
12152 
12153  case SCIP_VARSTATUS_FIXED:
12154  /* no need for memorizing fixed variables */
12155  break;
12156 
12157  default:
12158  SCIPerrorMessage("unknown variable status\n");
12159  SCIPABORT();
12160  return SCIP_INVALIDDATA; /*lint !e527*/
12161  }
12162  }
12163 
12164  /* sort variable array by variable index */
12165  SCIPsortPtr((void**)activevars, SCIPvarComp, nactivevars);
12166 
12167  /* eliminate duplicates and count required size */
12168  v = nactivevars - 1;
12169  while( v > 0 )
12170  {
12171  /* combine both variable since they are the same */
12172  if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
12173  {
12174  --nactivevars;
12175  activevars[v] = activevars[nactivevars];
12176  }
12177  --v;
12178  }
12179  *requiredsize = nactivevars;
12180 
12181  if( varssize >= *requiredsize )
12182  {
12183  assert(vars != NULL);
12184 
12185  *nvars = *requiredsize;
12186  BMScopyMemoryArray(vars, activevars, nactivevars);
12187  }
12188 
12189  SCIPsetFreeBufferArray(set, &tmpvars);
12190  SCIPsetFreeBufferArray(set, &activevars);
12191 
12192  return SCIP_OKAY;
12193 }
12194 
12195 /** gets corresponding active, fixed, or multi-aggregated problem variables of given variables,
12196  * @note the content of the given array will/might change
12197  */
12198 void SCIPvarsGetProbvar(
12199  SCIP_VAR** vars, /**< array of problem variables */
12200  int nvars /**< number of variables */
12201  )
12202 {
12203  int v;
12204 
12205  assert(vars != NULL || nvars == 0);
12206 
12207  for( v = nvars - 1; v >= 0; --v )
12208  {
12209  assert(vars != NULL);
12210  assert(vars[v] != NULL);
12211 
12212  vars[v] = SCIPvarGetProbvar(vars[v]);
12213  assert(vars[v] != NULL);
12214  }
12215 }
12216 
12217 /** gets corresponding active, fixed, or multi-aggregated problem variable of a variable */
12219  SCIP_VAR* var /**< problem variable */
12220  )
12221 {
12222  SCIP_VAR* retvar;
12223 
12224  assert(var != NULL);
12225 
12226  retvar = var;
12227 
12228  SCIPdebugMessage("get problem variable of <%s>\n", var->name);
12229 
12230  while( TRUE ) /*lint !e716 */
12231  {
12232  assert(retvar != NULL);
12233 
12234  switch( SCIPvarGetStatus(retvar) )
12235  {
12237  if( retvar->data.original.transvar == NULL )
12238  {
12239  SCIPerrorMessage("original variable has no transformed variable attached\n");
12240  SCIPABORT();
12241  return NULL; /*lint !e527 */
12242  }
12243  retvar = retvar->data.original.transvar;
12244  break;
12245 
12246  case SCIP_VARSTATUS_LOOSE:
12247  case SCIP_VARSTATUS_COLUMN:
12248  case SCIP_VARSTATUS_FIXED:
12249  return retvar;
12250 
12252  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12253  if ( retvar->data.multaggr.nvars == 1 )
12254  retvar = retvar->data.multaggr.vars[0];
12255  else
12256  return retvar;
12257  break;
12258 
12260  retvar = retvar->data.aggregate.var;
12261  break;
12262 
12264  retvar = retvar->negatedvar;
12265  break;
12266 
12267  default:
12268  SCIPerrorMessage("unknown variable status\n");
12269  SCIPABORT();
12270  return NULL; /*lint !e527*/
12271  }
12272  }
12273 }
12274 
12275 /** gets corresponding active, fixed, or multi-aggregated problem variables of binary variables and updates the given
12276  * negation status of each variable
12277  */
12279  SCIP_VAR*** vars, /**< pointer to binary problem variables */
12280  SCIP_Bool** negatedarr, /**< pointer to corresponding array to update the negation status */
12281  int nvars /**< number of variables and values in vars and negated array */
12282  )
12283 {
12284  SCIP_VAR** var;
12285  SCIP_Bool* negated;
12286  int v;
12287 
12288  assert(vars != NULL);
12289  assert(*vars != NULL || nvars == 0);
12290  assert(negatedarr != NULL);
12291  assert(*negatedarr != NULL || nvars == 0);
12292 
12293  for( v = nvars - 1; v >= 0; --v )
12294  {
12295  var = &((*vars)[v]);
12296  negated = &((*negatedarr)[v]);
12297 
12298  /* get problem variable */
12299  SCIP_CALL( SCIPvarGetProbvarBinary(var, negated) );
12300  }
12301 
12302  return SCIP_OKAY;
12303 }
12304 
12305 
12306 /** gets corresponding active, fixed, or multi-aggregated problem variable of a binary variable and updates the given
12307  * negation status (this means you have to assign a value to SCIP_Bool negated before calling this method, usually
12308  * FALSE is used)
12309  */
12311  SCIP_VAR** var, /**< pointer to binary problem variable */
12312  SCIP_Bool* negated /**< pointer to update the negation status */
12313  )
12314 {
12316 #ifndef NDEBUG
12317  SCIP_Real constant = 0.0;
12318  SCIP_Bool orignegated;
12319 #endif
12320 
12321  assert(var != NULL);
12322  assert(*var != NULL);
12323  assert(negated != NULL);
12324  assert(SCIPvarIsBinary(*var));
12325 
12326 #ifndef NDEBUG
12327  orignegated = *negated;
12328 #endif
12329 
12330  while( !active && *var != NULL )
12331  {
12332  switch( SCIPvarGetStatus(*var) )
12333  {
12335  if( (*var)->data.original.transvar == NULL )
12336  return SCIP_OKAY;
12337  *var = (*var)->data.original.transvar;
12338  break;
12339 
12340  case SCIP_VARSTATUS_LOOSE:
12341  case SCIP_VARSTATUS_COLUMN:
12342  case SCIP_VARSTATUS_FIXED:
12343  active = TRUE;
12344  break;
12345 
12347  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12348  if ( (*var)->data.multaggr.nvars == 1 )
12349  {
12350  assert( (*var)->data.multaggr.vars != NULL );
12351  assert( (*var)->data.multaggr.scalars != NULL );
12352  assert( SCIPvarIsBinary((*var)->data.multaggr.vars[0]) );
12353  assert(!EPSZ((*var)->data.multaggr.scalars[0], 1e-06));
12354 
12355  /* if not all variables were fully propagated, it might happen that a variable is multi-aggregated to
12356  * another variable which needs to be fixed
12357  *
12358  * e.g. x = y - 1 => (x = 0 && y = 1)
12359  * e.g. x = y + 1 => (x = 1 && y = 0)
12360  *
12361  * is this special case we need to return the muti-aggregation
12362  */
12363  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)) )
12364  {
12365  assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06));
12366  }
12367  else
12368  {
12369  /* @note due to fixations, a multi-aggregation can have a constant of zero and a negative scalar or even
12370  * a scalar in absolute value unequal to one, in this case this aggregation variable needs to be
12371  * fixed to zero, but this should be done by another enforcement; so not depending on the scalar,
12372  * we will return the aggregated variable;
12373  */
12374  if( !EPSEQ(REALABS((*var)->data.multaggr.scalars[0]), 1.0, 1e-06) )
12375  {
12376  active = TRUE;
12377  break;
12378  }
12379 
12380  /* @note it may also happen that the constant is larger than 1 or smaller than 0, in that case the
12381  * aggregation variable needs to be fixed to one, but this should be done by another enforcement;
12382  * so if this is the case, we will return the aggregated variable
12383  */
12384  assert(EPSZ((*var)->data.multaggr.constant, 1e-06) || EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06)
12385  || EPSZ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1e-06)
12386  || EPSEQ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1.0, 1e-06));
12387 
12388  if( !EPSZ((*var)->data.multaggr.constant, 1e-06) && !EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06) )
12389  {
12390  active = TRUE;
12391  break;
12392  }
12393 
12394  assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06) || EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
12395 
12396  if( EPSZ((*var)->data.multaggr.constant, 1e-06) )
12397  {
12398  /* if the scalar is negative, either the aggregation variable is already fixed to zero or has at
12399  * least one uplock (that hopefully will enforce this fixation to zero); can it happen that this
12400  * variable itself is multi-aggregated again?
12401  */
12402  assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06) ?
12403  ((SCIPvarGetUbGlobal((*var)->data.multaggr.vars[0]) < 0.5) ||
12404  SCIPvarGetNLocksUpType((*var)->data.multaggr.vars[0], SCIP_LOCKTYPE_MODEL) > 0) : TRUE);
12405  }
12406  else
12407  {
12408  assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
12409 #ifndef NDEBUG
12410  constant += (*negated) != orignegated ? -1.0 : 1.0;
12411 #endif
12412 
12413  *negated = !(*negated);
12414  }
12415  *var = (*var)->data.multaggr.vars[0];
12416  break;
12417  }
12418  }
12419  active = TRUE; /*lint !e838*/
12420  break;
12421 
12422  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
12423  assert((*var)->data.aggregate.var != NULL);
12424  assert(EPSEQ((*var)->data.aggregate.scalar, 1.0, 1e-06) || EPSEQ((*var)->data.aggregate.scalar, -1.0, 1e-06));
12425  assert(EPSLE((*var)->data.aggregate.var->glbdom.ub - (*var)->data.aggregate.var->glbdom.lb, 1.0, 1e-06));
12426 #ifndef NDEBUG
12427  constant += (*negated) != orignegated ? -(*var)->data.aggregate.constant : (*var)->data.aggregate.constant;
12428 #endif
12429 
12430  *negated = ((*var)->data.aggregate.scalar > 0.0) ? *negated : !(*negated);
12431  *var = (*var)->data.aggregate.var;
12432  break;
12433 
12434  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
12435  assert((*var)->negatedvar != NULL);
12436 #ifndef NDEBUG
12437  constant += (*negated) != orignegated ? -1.0 : 1.0;
12438 #endif
12439 
12440  *negated = !(*negated);
12441  *var = (*var)->negatedvar;
12442  break;
12443 
12444  default:
12445  SCIPerrorMessage("unknown variable status\n");
12446  return SCIP_INVALIDDATA;
12447  }
12448  }
12449  assert(active == (*var != NULL));
12450 
12451  if( active )
12452  {
12453  assert(SCIPvarIsBinary(*var));
12454  assert(EPSZ(constant, 1e-06) || EPSEQ(constant, 1.0, 1e-06));
12455  assert(EPSZ(constant, 1e-06) == ((*negated) == orignegated));
12456 
12457  return SCIP_OKAY;
12458  }
12459  else
12460  {
12461  SCIPerrorMessage("active variable path leads to NULL pointer\n");
12462  return SCIP_INVALIDDATA;
12463  }
12464 }
12465 
12466 /** transforms given variable, boundtype and bound to the corresponding active, fixed, or multi-aggregated variable
12467  * values
12468  */
12470  SCIP_VAR** var, /**< pointer to problem variable */
12471  SCIP_Real* bound, /**< pointer to bound value to transform */
12472  SCIP_BOUNDTYPE* boundtype /**< pointer to type of bound: lower or upper bound */
12473  )
12474 {
12475  assert(var != NULL);
12476  assert(*var != NULL);
12477  assert(bound != NULL);
12478  assert(boundtype != NULL);
12479 
12480  SCIPdebugMessage("get probvar bound %g of type %d of variable <%s>\n", *bound, *boundtype, (*var)->name);
12481 
12482  switch( SCIPvarGetStatus(*var) )
12483  {
12485  if( (*var)->data.original.transvar == NULL )
12486  {
12487  SCIPerrorMessage("original variable has no transformed variable attached\n");
12488  return SCIP_INVALIDDATA;
12489  }
12490  *var = (*var)->data.original.transvar;
12491  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12492  break;
12493 
12494  case SCIP_VARSTATUS_LOOSE:
12495  case SCIP_VARSTATUS_COLUMN:
12496  case SCIP_VARSTATUS_FIXED:
12497  break;
12498 
12500  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12501  if ( (*var)->data.multaggr.nvars == 1 )
12502  {
12503  assert( (*var)->data.multaggr.vars != NULL );
12504  assert( (*var)->data.multaggr.scalars != NULL );
12505  assert( (*var)->data.multaggr.scalars[0] != 0.0 );
12506 
12507  (*bound) /= (*var)->data.multaggr.scalars[0];
12508  (*bound) -= (*var)->data.multaggr.constant/(*var)->data.multaggr.scalars[0];
12509  if ( (*var)->data.multaggr.scalars[0] < 0.0 )
12510  {
12511  if ( *boundtype == SCIP_BOUNDTYPE_LOWER )
12512  *boundtype = SCIP_BOUNDTYPE_UPPER;
12513  else
12514  *boundtype = SCIP_BOUNDTYPE_LOWER;
12515  }
12516  *var = (*var)->data.multaggr.vars[0];
12517  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12518  }
12519  break;
12520 
12521  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
12522  assert((*var)->data.aggregate.var != NULL);
12523  assert((*var)->data.aggregate.scalar != 0.0);
12524 
12525  (*bound) /= (*var)->data.aggregate.scalar;
12526  (*bound) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12527  if( (*var)->data.aggregate.scalar < 0.0 )
12528  {
12529  if( *boundtype == SCIP_BOUNDTYPE_LOWER )
12530  *boundtype = SCIP_BOUNDTYPE_UPPER;
12531  else
12532  *boundtype = SCIP_BOUNDTYPE_LOWER;
12533  }
12534  *var = (*var)->data.aggregate.var;
12535  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12536  break;
12537 
12538  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12539  assert((*var)->negatedvar != NULL);
12540  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12541  assert((*var)->negatedvar->negatedvar == *var);
12542  (*bound) = (*var)->data.negate.constant - *bound;
12543  if( *boundtype == SCIP_BOUNDTYPE_LOWER )
12544  *boundtype = SCIP_BOUNDTYPE_UPPER;
12545  else
12546  *boundtype = SCIP_BOUNDTYPE_LOWER;
12547  *var = (*var)->negatedvar;
12548  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12549  break;
12550 
12551  default:
12552  SCIPerrorMessage("unknown variable status\n");
12553  return SCIP_INVALIDDATA;
12554  }
12555 
12556  return SCIP_OKAY;
12557 }
12558 
12559 /** transforms given variable and domain hole to the corresponding active, fixed, or multi-aggregated variable
12560  * values
12561  */
12563  SCIP_VAR** var, /**< pointer to problem variable */
12564  SCIP_Real* left, /**< pointer to left bound of open interval in hole to transform */
12565  SCIP_Real* right /**< pointer to right bound of open interval in hole to transform */
12566  )
12567 {
12568  assert(var != NULL);
12569  assert(*var != NULL);
12570  assert(left != NULL);
12571  assert(right != NULL);
12572 
12573  SCIPdebugMessage("get probvar hole (%g,%g) of variable <%s>\n", *left, *right, (*var)->name);
12574 
12575  switch( SCIPvarGetStatus(*var) )
12576  {
12578  if( (*var)->data.original.transvar == NULL )
12579  {
12580  SCIPerrorMessage("original variable has no transformed variable attached\n");
12581  return SCIP_INVALIDDATA;
12582  }
12583  *var = (*var)->data.original.transvar;
12584  SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
12585  break;
12586 
12587  case SCIP_VARSTATUS_LOOSE:
12588  case SCIP_VARSTATUS_COLUMN:
12589  case SCIP_VARSTATUS_FIXED:
12591  break;
12592 
12593  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
12594  assert((*var)->data.aggregate.var != NULL);
12595  assert((*var)->data.aggregate.scalar != 0.0);
12596 
12597  /* scale back */
12598  (*left) /= (*var)->data.aggregate.scalar;
12599  (*right) /= (*var)->data.aggregate.scalar;
12600 
12601  /* shift back */
12602  (*left) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12603  (*right) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12604 
12605  *var = (*var)->data.aggregate.var;
12606 
12607  /* check if the interval bounds have to swapped */
12608  if( (*var)->data.aggregate.scalar < 0.0 )
12609  {
12610  SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
12611  }
12612  else
12613  {
12614  SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
12615  }
12616  break;
12617 
12618  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12619  assert((*var)->negatedvar != NULL);
12620  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12621  assert((*var)->negatedvar->negatedvar == *var);
12622 
12623  /* shift and scale back */
12624  (*left) = (*var)->data.negate.constant - (*left);
12625  (*right) = (*var)->data.negate.constant - (*right);
12626 
12627  *var = (*var)->negatedvar;
12628 
12629  /* through the negated variable the left and right interval bound have to swapped */
12630  SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
12631  break;
12632 
12633  default:
12634  SCIPerrorMessage("unknown variable status\n");
12635  return SCIP_INVALIDDATA;
12636  }
12637 
12638  return SCIP_OKAY;
12639 }
12640 
12641 /** transforms given variable, scalar and constant to the corresponding active, fixed, or
12642  * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed variable,
12643  * "scalar" will be 0.0 and the value of the sum will be stored in "constant"; a multi-aggregation
12644  * with only one active variable (this can happen due to fixings after the multi-aggregation),
12645  * is treated like an aggregation; if the multi-aggregation constant is infinite, "scalar" will be 0.0
12646  */
12648  SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
12649  SCIP_SET* set, /**< global SCIP settings */
12650  SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
12651  SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
12652  )
12653 {
12654  assert(var != NULL);
12655  assert(scalar != NULL);
12656  assert(constant != NULL);
12657 
12658  while( *var != NULL )
12659  {
12660  switch( SCIPvarGetStatus(*var) )
12661  {
12663  if( (*var)->data.original.transvar == NULL )
12664  {
12665  SCIPerrorMessage("original variable has no transformed variable attached\n");
12666  return SCIP_INVALIDDATA;
12667  }
12668  *var = (*var)->data.original.transvar;
12669  break;
12670 
12671  case SCIP_VARSTATUS_LOOSE:
12672  case SCIP_VARSTATUS_COLUMN:
12673  return SCIP_OKAY;
12674 
12675  case SCIP_VARSTATUS_FIXED: /* x = c' => a*x + c == (a*c' + c) */
12676  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12677  {
12678  if( SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)) )
12679  {
12680  assert(*scalar != 0.0);
12681  if( (*scalar) * (*var)->glbdom.lb > 0.0 )
12682  (*constant) = SCIPsetInfinity(set);
12683  else
12684  (*constant) = -SCIPsetInfinity(set);
12685  }
12686  else
12687  (*constant) += *scalar * (*var)->glbdom.lb;
12688  }
12689 #ifndef NDEBUG
12690  else
12691  {
12692  assert(!SCIPsetIsInfinity(set, (*constant)) || !((*scalar) * (*var)->glbdom.lb < 0.0 &&
12693  (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
12694  assert(!SCIPsetIsInfinity(set, -(*constant)) || !((*scalar) * (*var)->glbdom.lb > 0.0 &&
12695  (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
12696  }
12697 #endif
12698  *scalar = 0.0;
12699  return SCIP_OKAY;
12700 
12702  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12703  if ( (*var)->data.multaggr.nvars == 1 )
12704  {
12705  assert((*var)->data.multaggr.vars != NULL);
12706  assert((*var)->data.multaggr.scalars != NULL);
12707  assert((*var)->data.multaggr.vars[0] != NULL);
12708  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12709  {
12710  /* the multi-aggregation constant can be infinite, if one of the multi-aggregation variables
12711  * was fixed to +/-infinity; ensure that the constant is set to +/-infinity, too, and the scalar
12712  * is set to 0.0, because the multi-aggregated variable can be seen as fixed, too
12713  */
12714  if( SCIPsetIsInfinity(set, (*var)->data.multaggr.constant)
12715  || SCIPsetIsInfinity(set, -((*var)->data.multaggr.constant)) )
12716  {
12717  if( (*scalar) * (*var)->data.multaggr.constant > 0 )
12718  {
12719  assert(!SCIPsetIsInfinity(set, -(*constant)));
12720  (*constant) = SCIPsetInfinity(set);
12721  }
12722  else
12723  {
12724  assert(!SCIPsetIsInfinity(set, *constant));
12725  (*constant) = -SCIPsetInfinity(set);
12726  }
12727  (*scalar) = 0.0;
12728  }
12729  else
12730  (*constant) += *scalar * (*var)->data.multaggr.constant;
12731  }
12732  (*scalar) *= (*var)->data.multaggr.scalars[0];
12733  *var = (*var)->data.multaggr.vars[0];
12734  break;
12735  }
12736  return SCIP_OKAY;
12737 
12738  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
12739  assert((*var)->data.aggregate.var != NULL);
12740  assert(!SCIPsetIsInfinity(set, (*var)->data.aggregate.constant)
12741  && !SCIPsetIsInfinity(set, (*var)->data.aggregate.constant));
12742  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12743  (*constant) += *scalar * (*var)->data.aggregate.constant;
12744  (*scalar) *= (*var)->data.aggregate.scalar;
12745  *var = (*var)->data.aggregate.var;
12746  break;
12747 
12748  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
12749  assert((*var)->negatedvar != NULL);
12750  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12751  assert((*var)->negatedvar->negatedvar == *var);
12752  assert(!SCIPsetIsInfinity(set, (*var)->data.negate.constant)
12753  && !SCIPsetIsInfinity(set, (*var)->data.negate.constant));
12754  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12755  (*constant) += *scalar * (*var)->data.negate.constant;
12756  (*scalar) *= -1.0;
12757  *var = (*var)->negatedvar;
12758  break;
12759 
12760  default:
12761  SCIPerrorMessage("unknown variable status\n");
12762  SCIPABORT();
12763  return SCIP_INVALIDDATA; /*lint !e527*/
12764  }
12765  }
12766  *scalar = 0.0;
12767 
12768  return SCIP_OKAY;
12769 }
12770 
12771 /** retransforms given variable, scalar and constant to the corresponding original variable, scalar
12772  * and constant, if possible; if the retransformation is impossible, NULL is returned as variable
12773  */
12775  SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
12776  SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
12777  SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
12778  )
12779 {
12780  SCIP_VAR* parentvar;
12781 
12782  assert(var != NULL);
12783  assert(*var != NULL);
12784  assert(scalar != NULL);
12785  assert(constant != NULL);
12786 
12787  while( !SCIPvarIsOriginal(*var) )
12788  {
12789  /* if the variable has no parent variables, it was generated during solving and has no corresponding original
12790  * var
12791  */
12792  if( (*var)->nparentvars == 0 )
12793  {
12794  /* negated variables do not need to have a parent variables, and negated variables can exist in original
12795  * space
12796  */
12798  ((*var)->negatedvar->nparentvars == 0 || (*var)->negatedvar->parentvars[0] != *var) )
12799  {
12800  *scalar *= -1.0;
12801  *constant -= (*var)->data.negate.constant * (*scalar);
12802  *var = (*var)->negatedvar;
12803 
12804  continue;
12805  }
12806  /* if the variables does not have any parent the variables was created during solving and has no original
12807  * counterpart
12808  */
12809  else
12810  {
12811  *var = NULL;
12812 
12813  return SCIP_OKAY;
12814  }
12815  }
12816 
12817  /* follow the link to the first parent variable */
12818  parentvar = (*var)->parentvars[0];
12819  assert(parentvar != NULL);
12820 
12821  switch( SCIPvarGetStatus(parentvar) )
12822  {
12824  break;
12825 
12826  case SCIP_VARSTATUS_COLUMN:
12827  case SCIP_VARSTATUS_LOOSE:
12828  case SCIP_VARSTATUS_FIXED:
12830  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
12831  return SCIP_INVALIDDATA;
12832 
12833  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + b -> y = (x-b)/a, s*y + c = (s/a)*x + c-b*s/a */
12834  assert(parentvar->data.aggregate.var == *var);
12835  assert(parentvar->data.aggregate.scalar != 0.0);
12836  *scalar /= parentvar->data.aggregate.scalar;
12837  *constant -= parentvar->data.aggregate.constant * (*scalar);
12838  break;
12839 
12840  case SCIP_VARSTATUS_NEGATED: /* x = b - y -> y = b - x, s*y + c = -s*x + c+b*s */
12841  assert(parentvar->negatedvar != NULL);
12842  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
12843  assert(parentvar->negatedvar->negatedvar == parentvar);
12844  *scalar *= -1.0;
12845  *constant -= parentvar->data.negate.constant * (*scalar);
12846  break;
12847 
12848  default:
12849  SCIPerrorMessage("unknown variable status\n");
12850  return SCIP_INVALIDDATA;
12851  }
12852 
12853  assert( parentvar != NULL );
12854  *var = parentvar;
12855  }
12856 
12857  return SCIP_OKAY;
12858 }
12859 
12860 /** returns whether the given variable is the direct counterpart of an original problem variable */
12862  SCIP_VAR* var /**< problem variable */
12863  )
12864 {
12865  SCIP_VAR* parentvar;
12866  assert(var != NULL);
12867 
12868  if( !SCIPvarIsTransformed(var) || var->nparentvars < 1 )
12869  return FALSE;
12870 
12871  assert(var->parentvars != NULL);
12872  parentvar = var->parentvars[0];
12873  assert(parentvar != NULL);
12874 
12875  /* we follow the aggregation tree to the root unless an original variable has been found - the first entries in the parentlist are candidates */
12876  while( parentvar->nparentvars >= 1 && SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL )
12877  parentvar = parentvar->parentvars[0];
12878  assert( parentvar != NULL );
12879 
12880  return ( SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_ORIGINAL );
12881 }
12882 
12883 /** gets objective value of variable in current SCIP_LP; the value can be different from the objective value stored in
12884  * the variable's own data due to diving, that operate only on the LP without updating the variables
12885  */
12887  SCIP_VAR* var /**< problem variable */
12888  )
12889 {
12890  assert(var != NULL);
12891 
12892  /* get bounds of attached variables */
12893  switch( SCIPvarGetStatus(var) )
12894  {
12896  assert(var->data.original.transvar != NULL);
12897  return SCIPvarGetObjLP(var->data.original.transvar);
12898 
12899  case SCIP_VARSTATUS_COLUMN:
12900  assert(var->data.col != NULL);
12901  return SCIPcolGetObj(var->data.col);
12902 
12903  case SCIP_VARSTATUS_LOOSE:
12904  case SCIP_VARSTATUS_FIXED:
12905  return var->obj;
12906 
12907  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12908  assert(var->data.aggregate.var != NULL);
12909  return var->data.aggregate.scalar * SCIPvarGetObjLP(var->data.aggregate.var);
12910 
12912  SCIPerrorMessage("cannot get the objective value of a multiple aggregated variable\n");
12913  SCIPABORT();
12914  return 0.0; /*lint !e527*/
12915 
12916  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12917  assert(var->negatedvar != NULL);
12919  assert(var->negatedvar->negatedvar == var);
12920  return -SCIPvarGetObjLP(var->negatedvar);
12921 
12922  default:
12923  SCIPerrorMessage("unknown variable status\n");
12924  SCIPABORT();
12925  return 0.0; /*lint !e527*/
12926  }
12927 }
12928 
12929 /** gets lower bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
12930  * data due to diving or conflict analysis, that operate only on the LP without updating the variables
12931  */
12933  SCIP_VAR* var, /**< problem variable */
12934  SCIP_SET* set /**< global SCIP settings */
12935  )
12936 {
12937  assert(var != NULL);
12938  assert(set != NULL);
12939  assert(var->scip == set->scip);
12940 
12941  /* get bounds of attached variables */
12942  switch( SCIPvarGetStatus(var) )
12943  {
12945  assert(var->data.original.transvar != NULL);
12946  return SCIPvarGetLbLP(var->data.original.transvar, set);
12947 
12948  case SCIP_VARSTATUS_COLUMN:
12949  assert(var->data.col != NULL);
12950  return SCIPcolGetLb(var->data.col);
12951 
12952  case SCIP_VARSTATUS_LOOSE:
12953  case SCIP_VARSTATUS_FIXED:
12954  return var->locdom.lb;
12955 
12956  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12957  assert(var->data.aggregate.var != NULL);
12958  if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set)))
12959  || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set))) )
12960  {
12961  return -SCIPsetInfinity(set);
12962  }
12963  else if( var->data.aggregate.scalar > 0.0 )
12964  {
12965  /* a > 0 -> get lower bound of y */
12966  return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12967  }
12968  else if( var->data.aggregate.scalar < 0.0 )
12969  {
12970  /* a < 0 -> get upper bound of y */
12971  return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12972  }
12973  else
12974  {
12975  SCIPerrorMessage("scalar is zero in aggregation\n");
12976  SCIPABORT();
12977  return SCIP_INVALID; /*lint !e527*/
12978  }
12979 
12981  /**@todo get the sides of the corresponding linear constraint */
12982  SCIPerrorMessage("getting the bounds of a multiple aggregated variable is not implemented yet\n");
12983  SCIPABORT();
12984  return SCIP_INVALID; /*lint !e527*/
12985 
12986  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12987  assert(var->negatedvar != NULL);
12989  assert(var->negatedvar->negatedvar == var);
12990  return var->data.negate.constant - SCIPvarGetUbLP(var->negatedvar, set);
12991 
12992  default:
12993  SCIPerrorMessage("unknown variable status\n");
12994  SCIPABORT();
12995  return SCIP_INVALID; /*lint !e527*/
12996  }
12997 }
12998 
12999 /** gets upper bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
13000  * data due to diving or conflict analysis, that operate only on the LP without updating the variables
13001  */
13003  SCIP_VAR* var, /**< problem variable */
13004  SCIP_SET* set /**< global SCIP settings */
13005  )
13006 {
13007  assert(var != NULL);
13008  assert(set != NULL);
13009  assert(var->scip == set->scip);
13010 
13011  /* get bounds of attached variables */
13012  switch( SCIPvarGetStatus(var) )
13013  {
13015  assert(var->data.original.transvar != NULL);
13016  return SCIPvarGetUbLP(var->data.original.transvar, set);
13017 
13018  case SCIP_VARSTATUS_COLUMN:
13019  assert(var->data.col != NULL);
13020  return SCIPcolGetUb(var->data.col);
13021 
13022  case SCIP_VARSTATUS_LOOSE:
13023  case SCIP_VARSTATUS_FIXED:
13024  return var->locdom.ub;
13025 
13026  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
13027  assert(var->data.aggregate.var != NULL);
13028  if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set)))
13029  || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set))) )
13030  {
13031  return SCIPsetInfinity(set);
13032  }
13033  if( var->data.aggregate.scalar > 0.0 )
13034  {
13035  /* a > 0 -> get upper bound of y */
13036  return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
13037  }
13038  else if( var->data.aggregate.scalar < 0.0 )
13039  {
13040  /* a < 0 -> get lower bound of y */
13041  return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
13042  }
13043  else
13044  {
13045  SCIPerrorMessage("scalar is zero in aggregation\n");
13046  SCIPABORT();
13047  return SCIP_INVALID; /*lint !e527*/
13048  }
13049 
13051  SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
13052  SCIPABORT();
13053  return SCIP_INVALID; /*lint !e527*/
13054 
13055  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13056  assert(var->negatedvar != NULL);
13058  assert(var->negatedvar->negatedvar == var);
13059  return var->data.negate.constant - SCIPvarGetLbLP(var->negatedvar, set);
13060 
13061  default:
13062  SCIPerrorMessage("unknown variable status\n");
13063  SCIPABORT();
13064  return SCIP_INVALID; /*lint !e527*/
13065  }
13066 }
13067 
13068 /** gets primal LP solution value of variable */
13070  SCIP_VAR* var /**< problem variable */
13071  )
13072 {
13073  assert(var != NULL);
13074 
13075  switch( SCIPvarGetStatus(var) )
13076  {
13078  if( var->data.original.transvar == NULL )
13079  return SCIP_INVALID;
13080  return SCIPvarGetLPSol(var->data.original.transvar);
13081 
13082  case SCIP_VARSTATUS_LOOSE:
13083  return SCIPvarGetBestBoundLocal(var);
13084 
13085  case SCIP_VARSTATUS_COLUMN:
13086  assert(var->data.col != NULL);
13087  return SCIPcolGetPrimsol(var->data.col);
13088 
13089  case SCIP_VARSTATUS_FIXED:
13090  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13091  return var->locdom.lb;
13092 
13094  {
13095  SCIP_Real lpsolval;
13096 
13097  assert(!var->donotaggr);
13098  assert(var->data.aggregate.var != NULL);
13099  lpsolval = SCIPvarGetLPSol(var->data.aggregate.var);
13100 
13101  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13102  * corresponding infinity value instead of performing an arithmetical transformation (compare method
13103  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13104  * (or is called by) a public interface method; instead, we only assert that values are finite
13105  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13106  * positives and negatives if the parameter <numerics/infinity> is modified by the user
13107  */
13108  assert(lpsolval > -SCIP_DEFAULT_INFINITY);
13109  assert(lpsolval < +SCIP_DEFAULT_INFINITY);
13110  return var->data.aggregate.scalar * lpsolval + var->data.aggregate.constant;
13111  }
13113  {
13114  SCIP_Real primsol;
13115  int i;
13116 
13117  assert(!var->donotmultaggr);
13118  assert(var->data.multaggr.vars != NULL);
13119  assert(var->data.multaggr.scalars != NULL);
13120  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13121  * assert(var->data.multaggr.nvars >= 2);
13122  */
13123  primsol = var->data.multaggr.constant;
13124  for( i = 0; i < var->data.multaggr.nvars; ++i )
13125  primsol += var->data.multaggr.scalars[i] * SCIPvarGetLPSol(var->data.multaggr.vars[i]);
13126  return primsol;
13127  }
13128  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13129  assert(var->negatedvar != NULL);
13131  assert(var->negatedvar->negatedvar == var);
13132  return var->data.negate.constant - SCIPvarGetLPSol(var->negatedvar);
13133 
13134  default:
13135  SCIPerrorMessage("unknown variable status\n");
13136  SCIPABORT();
13137  return SCIP_INVALID; /*lint !e527*/
13138  }
13139 }
13140 
13141 /** gets primal NLP solution value of variable */
13143  SCIP_VAR* var /**< problem variable */
13144  )
13145 {
13146  SCIP_Real solval;
13147  int i;
13148 
13149  assert(var != NULL);
13150 
13151  /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
13152  switch( SCIPvarGetStatus(var) )
13153  {
13155  return SCIPvarGetNLPSol(var->data.original.transvar);
13156 
13157  case SCIP_VARSTATUS_LOOSE:
13158  case SCIP_VARSTATUS_COLUMN:
13159  return var->nlpsol;
13160 
13161  case SCIP_VARSTATUS_FIXED:
13162  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
13163  assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
13164  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
13165  return SCIPvarGetLbGlobal(var);
13166 
13167  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13168  solval = SCIPvarGetNLPSol(var->data.aggregate.var);
13169  return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
13170 
13172  solval = var->data.multaggr.constant;
13173  for( i = 0; i < var->data.multaggr.nvars; ++i )
13174  solval += var->data.multaggr.scalars[i] * SCIPvarGetNLPSol(var->data.multaggr.vars[i]);
13175  return solval;
13176 
13178  solval = SCIPvarGetNLPSol(var->negatedvar);
13179  return var->data.negate.constant - solval;
13180 
13181  default:
13182  SCIPerrorMessage("unknown variable status\n");
13183  SCIPABORT();
13184  return SCIP_INVALID; /*lint !e527*/
13185  }
13186 }
13187 
13188 /** gets pseudo solution value of variable at current node */
13189 static
13191  SCIP_VAR* var /**< problem variable */
13192  )
13193 {
13194  SCIP_Real pseudosol;
13195  int i;
13196 
13197  assert(var != NULL);
13198 
13199  switch( SCIPvarGetStatus(var) )
13200  {
13202  if( var->data.original.transvar == NULL )
13203  return SCIP_INVALID;
13205 
13206  case SCIP_VARSTATUS_LOOSE:
13207  case SCIP_VARSTATUS_COLUMN:
13208  return SCIPvarGetBestBoundLocal(var);
13209 
13210  case SCIP_VARSTATUS_FIXED:
13211  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13212  return var->locdom.lb;
13213 
13215  {
13216  SCIP_Real pseudosolval;
13217  assert(!var->donotaggr);
13218  assert(var->data.aggregate.var != NULL);
13219  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13220  * corresponding infinity value instead of performing an arithmetical transformation (compare method
13221  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13222  * (or is called by) a public interface method; instead, we only assert that values are finite
13223  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13224  * positives and negatives if the parameter <numerics/infinity> is modified by the user
13225  */
13226  pseudosolval = SCIPvarGetPseudoSol(var->data.aggregate.var);
13227  assert(pseudosolval > -SCIP_DEFAULT_INFINITY);
13228  assert(pseudosolval < +SCIP_DEFAULT_INFINITY);
13229  return var->data.aggregate.scalar * pseudosolval + var->data.aggregate.constant;
13230  }
13232  assert(!var->donotmultaggr);
13233  assert(var->data.multaggr.vars != NULL);
13234  assert(var->data.multaggr.scalars != NULL);
13235  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13236  * assert(var->data.multaggr.nvars >= 2);
13237  */
13238  pseudosol = var->data.multaggr.constant;
13239  for( i = 0; i < var->data.multaggr.nvars; ++i )
13240  pseudosol += var->data.multaggr.scalars[i] * SCIPvarGetPseudoSol(var->data.multaggr.vars[i]);
13241  return pseudosol;
13242 
13243  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13244  assert(var->negatedvar != NULL);
13246  assert(var->negatedvar->negatedvar == var);
13247  return var->data.negate.constant - SCIPvarGetPseudoSol(var->negatedvar);
13248 
13249  default:
13250  SCIPerrorMessage("unknown variable status\n");
13251  SCIPABORT();
13252  return SCIP_INVALID; /*lint !e527*/
13253  }
13254 }
13255 
13256 /** gets current LP or pseudo solution value of variable */
13258  SCIP_VAR* var, /**< problem variable */
13259  SCIP_Bool getlpval /**< should the LP solution value be returned? */
13260  )
13261 {
13262  if( getlpval )
13263  return SCIPvarGetLPSol(var);
13264  else
13265  return SCIPvarGetPseudoSol(var);
13266 }
13267 
13268 /** remembers the current solution as root solution in the problem variables */
13269 void SCIPvarStoreRootSol(
13270  SCIP_VAR* var, /**< problem variable */
13271  SCIP_Bool roothaslp /**< is the root solution from LP? */
13272  )
13273 {
13274  assert(var != NULL);
13275 
13276  var->rootsol = SCIPvarGetSol(var, roothaslp);
13277 }
13278 
13279 /** updates the current solution as best root solution of the given variable if it is better */
13281  SCIP_VAR* var, /**< problem variable */
13282  SCIP_SET* set, /**< global SCIP settings */
13283  SCIP_Real rootsol, /**< root solution value */
13284  SCIP_Real rootredcost, /**< root reduced cost */
13285  SCIP_Real rootlpobjval /**< objective value of the root LP */
13286  )
13287 {
13288  assert(var != NULL);
13289  assert(set != NULL);
13290  assert(var->scip == set->scip);
13291 
13292  /* if reduced cost are zero nothing to update */
13293  if( SCIPsetIsDualfeasZero(set, rootredcost) )
13294  return;
13295 
13296  /* check if we have already a best combination stored */
13297  if( !SCIPsetIsDualfeasZero(set, var->bestrootredcost) )
13298  {
13299  SCIP_Real currcutoffbound;
13300  SCIP_Real cutoffbound;
13301  SCIP_Real bound;
13302 
13303  /* compute the cutoff bound which would improve the corresponding bound with the current stored root solution,
13304  * root reduced cost, and root LP objective value combination
13305  */
13306  if( var->bestrootredcost > 0.0 )
13307  bound = SCIPvarGetUbGlobal(var);
13308  else
13309  bound = SCIPvarGetLbGlobal(var);
13310 
13311  currcutoffbound = (bound - var->bestrootsol) * var->bestrootredcost + var->bestrootlpobjval;
13312 
13313  /* compute the cutoff bound which would improve the corresponding bound with new root solution, root reduced
13314  * cost, and root LP objective value combination
13315  */
13316  if( rootredcost > 0.0 )
13317  bound = SCIPvarGetUbGlobal(var);
13318  else
13319  bound = SCIPvarGetLbGlobal(var);
13320 
13321  cutoffbound = (bound - rootsol) * rootredcost + rootlpobjval;
13322 
13323  /* check if an improving root solution, root reduced cost, and root LP objective value is at hand */
13324  if( cutoffbound > currcutoffbound )
13325  {
13326  SCIPsetDebugMsg(set, "-> <%s> update potential cutoff bound <%g> -> <%g>\n",
13327  SCIPvarGetName(var), currcutoffbound, cutoffbound);
13328 
13329  var->bestrootsol = rootsol;
13330  var->bestrootredcost = rootredcost;
13331  var->bestrootlpobjval = rootlpobjval;
13332  }
13333  }
13334  else
13335  {
13336  SCIPsetDebugMsg(set, "-> <%s> initialize best root reduced cost information\n", SCIPvarGetName(var));
13337  SCIPsetDebugMsg(set, " -> rootsol <%g>\n", rootsol);
13338  SCIPsetDebugMsg(set, " -> rootredcost <%g>\n", rootredcost);
13339  SCIPsetDebugMsg(set, " -> rootlpobjval <%g>\n", rootlpobjval);
13340 
13341  var->bestrootsol = rootsol;
13342  var->bestrootredcost = rootredcost;
13343  var->bestrootlpobjval = rootlpobjval;
13344  }
13345 }
13346 
13347 /** returns the solution of the variable in the last root node's relaxation, if the root relaxation is not yet
13348  * completely solved, zero is returned
13349  */
13351  SCIP_VAR* var /**< problem variable */
13352  )
13353 {
13354  SCIP_Real rootsol;
13355  int i;
13356 
13357  assert(var != NULL);
13358 
13359  switch( SCIPvarGetStatus(var) )
13360  {
13362  if( var->data.original.transvar == NULL )
13363  return 0.0;
13364  return SCIPvarGetRootSol(var->data.original.transvar);
13365 
13366  case SCIP_VARSTATUS_LOOSE:
13367  case SCIP_VARSTATUS_COLUMN:
13368  return var->rootsol;
13369 
13370  case SCIP_VARSTATUS_FIXED:
13371  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13372  return var->locdom.lb;
13373 
13375  assert(!var->donotaggr);
13376  assert(var->data.aggregate.var != NULL);
13377  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13378  * corresponding infinity value instead of performing an arithmetical transformation (compare method
13379  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13380  * (or is called by) a public interface method; instead, we only assert that values are finite
13381  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13382  * positives and negatives if the parameter <numerics/infinity> is modified by the user
13383  */
13387 
13389  assert(!var->donotmultaggr);
13390  assert(var->data.multaggr.vars != NULL);
13391  assert(var->data.multaggr.scalars != NULL);
13392  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13393  * assert(var->data.multaggr.nvars >= 2);
13394  */
13395  rootsol = var->data.multaggr.constant;
13396  for( i = 0; i < var->data.multaggr.nvars; ++i )
13397  rootsol += var->data.multaggr.scalars[i] * SCIPvarGetRootSol(var->data.multaggr.vars[i]);
13398  return rootsol;
13399 
13400  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13401  assert(var->negatedvar != NULL);
13403  assert(var->negatedvar->negatedvar == var);
13404  return var->data.negate.constant - SCIPvarGetRootSol(var->negatedvar);
13405 
13406  default:
13407  SCIPerrorMessage("unknown variable status\n");
13408  SCIPABORT();
13409  return SCIP_INVALID; /*lint !e527*/
13410  }
13411 }
13412 
13413 /** returns for given variable the reduced cost */
13414 static
13416  SCIP_VAR* var, /**< problem variable */
13417  SCIP_SET* set, /**< global SCIP settings */
13418  SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
13419  SCIP_STAT* stat, /**< problem statistics */
13420  SCIP_LP* lp /**< current LP data */
13421  )
13422 {
13424  {
13425  SCIP_COL* col;
13426  SCIP_Real primsol;
13427  SCIP_BASESTAT basestat;
13428  SCIP_Bool lpissolbasic;
13429 
13430  col = SCIPvarGetCol(var);
13431  assert(col != NULL);
13432 
13433  basestat = SCIPcolGetBasisStatus(col);
13434  lpissolbasic = SCIPlpIsSolBasic(lp);
13435  primsol = SCIPcolGetPrimsol(col);
13436 
13437  if( (lpissolbasic && (basestat == SCIP_BASESTAT_LOWER || basestat == SCIP_BASESTAT_UPPER)) ||
13438  (!lpissolbasic && (SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol) || SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol))) )
13439  {
13440  SCIP_Real redcost = SCIPcolGetRedcost(col, stat, lp);
13441 
13442  assert(((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)) ||
13443  (lpissolbasic && basestat == SCIP_BASESTAT_LOWER)) ? (!SCIPsetIsDualfeasNegative(set, redcost) ||
13445  assert(((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)) ||
13446  (lpissolbasic && basestat == SCIP_BASESTAT_UPPER)) ? (!SCIPsetIsDualfeasPositive(set, redcost) ||
13447  SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var))) : TRUE);
13448 
13449  if( (varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_LOWER) ||
13450  (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)))) ||
13451  (!varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_UPPER) ||
13452  (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)))) )
13453  return redcost;
13454  else
13455  return 0.0;
13456  }
13457 
13458  return 0.0;
13459  }
13460 
13461  return 0.0;
13462 }
13463 
13464 #define MAX_CLIQUELENGTH 50
13465 /** returns for the given binary variable the reduced cost which are given by the variable itself and its implication if
13466  * the binary variable is fixed to the given value
13467  */
13469  SCIP_VAR* var, /**< problem variable */
13470  SCIP_SET* set, /**< global SCIP settings */
13471  SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
13472  SCIP_STAT* stat, /**< problem statistics */
13473  SCIP_PROB* prob, /**< transformed problem, or NULL */
13474  SCIP_LP* lp /**< current LP data */
13475  )
13476 {
13477  SCIP_Real implredcost;
13478  int ncliques;
13479  int nvars;
13480 
13481  assert(SCIPvarIsBinary(var));
13482  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
13483 
13484  /* get reduced cost of given variable */
13485  implredcost = getImplVarRedcost(var, set, varfixing, stat, lp);
13486 
13487 #ifdef SCIP_MORE_DEBUG
13488  SCIPsetDebugMsg(set, "variable <%s> itself has reduced cost of %g\n", SCIPvarGetName(var), implredcost);
13489 #endif
13490 
13491  /* the following algorithm is expensive */
13492  ncliques = SCIPvarGetNCliques(var, varfixing);
13493 
13494  if( ncliques > 0 )
13495  {
13496  SCIP_CLIQUE** cliques;
13497  SCIP_CLIQUE* clique;
13498  SCIP_VAR** clqvars;
13499  SCIP_VAR** probvars;
13500  SCIP_VAR* clqvar;
13501  SCIP_Bool* clqvalues;
13502  int* entries;
13503  int* ids;
13504  SCIP_Real redcost;
13505  SCIP_Bool cleanedup;
13506  int nclqvars;
13507  int nentries;
13508  int nids;
13509  int id;
13510  int c;
13511  int v;
13512 
13513  assert(prob != NULL);
13514  assert(SCIPprobIsTransformed(prob));
13515 
13516  nentries = SCIPprobGetNVars(prob) - SCIPprobGetNContVars(prob) + 1;
13517 
13518  SCIP_CALL_ABORT( SCIPsetAllocBufferArray(set, &ids, nentries) );
13519  nids = 0;
13520  SCIP_CALL_ABORT( SCIPsetAllocCleanBufferArray(set, &entries, nentries) );
13521 
13522  cliques = SCIPvarGetCliques(var, varfixing);
13523  assert(cliques != NULL);
13524 
13525  for( c = ncliques - 1; c >= 0; --c )
13526  {
13527  clique = cliques[c];
13528  assert(clique != NULL);
13529  nclqvars = SCIPcliqueGetNVars(clique);
13530  assert(nclqvars > 0);
13531 
13532  if( nclqvars > MAX_CLIQUELENGTH )
13533  continue;
13534 
13535  clqvars = SCIPcliqueGetVars(clique);
13536  clqvalues = SCIPcliqueGetValues(clique);
13537  assert(clqvars != NULL);
13538  assert(clqvalues != NULL);
13539 
13540  cleanedup = SCIPcliqueIsCleanedUp(clique);
13541 
13542  for( v = nclqvars - 1; v >= 0; --v )
13543  {
13544  clqvar = clqvars[v];
13545  assert(clqvar != NULL);
13546 
13547  /* ignore binary variable which are fixed */
13548  if( clqvar != var && (cleanedup || SCIPvarIsActive(clqvar)) &&
13549  (SCIPvarGetLbLocal(clqvar) < 0.5 && SCIPvarGetUbLocal(clqvar) > 0.5) )
13550  {
13551  int probindex = SCIPvarGetProbindex(clqvar) + 1;
13552  assert(0 < probindex && probindex < nentries);
13553 
13554 #if 0
13555  /* check that the variable was not yet visited or does not appear with two contradicting implications, ->
13556  * can appear since there is no guarantee that all these infeasible bounds were found
13557  */
13558  assert(!entries[probindex] || entries[probindex] == (clqvalues[v] ? probindex : -probindex));
13559 #endif
13560  if( entries[probindex] == 0 )
13561  {
13562  ids[nids] = probindex;
13563  ++nids;
13564 
13565  /* mark variable as visited */
13566  entries[probindex] = (clqvalues[v] ? probindex : -probindex);
13567  }
13568  }
13569  }
13570  }
13571 
13572  probvars = SCIPprobGetVars(prob);
13573  assert(probvars != NULL);
13574 
13575  /* add all implied reduced cost */
13576  for( v = nids - 1; v >= 0; --v )
13577  {
13578  id = ids[v];
13579  assert(0 < id && id < nentries);
13580  assert(entries[id] != 0);
13581  assert(probvars[id - 1] != NULL);
13582  assert(SCIPvarIsActive(probvars[id - 1]));
13583  assert(SCIPvarIsBinary(probvars[id - 1]));
13584  assert(SCIPvarGetLbLocal(probvars[id - 1]) < 0.5 && SCIPvarGetUbLocal(probvars[id - 1]) > 0.5);
13585 
13586  if( (entries[id] > 0) != varfixing )
13587  redcost = getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
13588  else
13589  redcost = -getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
13590 
13591  if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
13592  implredcost += redcost;
13593 
13594  /* reset entries clear buffer array */
13595  entries[id] = 0;
13596  }
13597 
13598  SCIPsetFreeCleanBufferArray(set, &entries);
13599  SCIPsetFreeBufferArray(set, &ids);
13600  }
13601 
13602 #ifdef SCIP_MORE_DEBUG
13603  SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) has implied reduced cost of %g\n", SCIPvarGetName(var), ncliques,
13604  implredcost);
13605 #endif
13606 
13607  /* collect non-binary implication information */
13608  nvars = SCIPimplicsGetNImpls(var->implics, varfixing);
13609 
13610  if( nvars > 0 )
13611  {
13612  SCIP_VAR** vars;
13613  SCIP_VAR* implvar;
13614  SCIP_COL* col;
13615  SCIP_Real* bounds;
13616  SCIP_BOUNDTYPE* boundtypes;
13617  SCIP_Real redcost;
13618  SCIP_Real lb;
13619  SCIP_Real ub;
13620  SCIP_Bool lpissolbasic;
13621  int v;
13622 
13623  vars = SCIPimplicsGetVars(var->implics, varfixing);
13624  boundtypes = SCIPimplicsGetTypes(var->implics, varfixing);
13625  bounds = SCIPimplicsGetBounds(var->implics, varfixing);
13626  lpissolbasic = SCIPlpIsSolBasic(lp);
13627 
13628  for( v = nvars - 1; v >= 0; --v )
13629  {
13630  implvar = vars[v];
13631  assert(implvar != NULL);
13632 
13633  lb = SCIPvarGetLbLocal(implvar);
13634  ub = SCIPvarGetUbLocal(implvar);
13635 
13636  /* ignore binary variable which are fixed or not of column status */
13637  if( SCIPvarGetStatus(implvar) != SCIP_VARSTATUS_COLUMN || SCIPsetIsFeasEQ(set, lb, ub) )
13638  continue;
13639 
13640  col = SCIPvarGetCol(implvar);
13641  assert(col != NULL);
13642  redcost = 0.0;
13643 
13644  /* solved lp with basis information or not? */
13645  if( lpissolbasic )
13646  {
13647  SCIP_BASESTAT basestat = SCIPcolGetBasisStatus(col);
13648 
13649  /* check if the implication is not not yet applied */
13650  if( basestat == SCIP_BASESTAT_LOWER && boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGT(set, bounds[v], lb) )
13651  {
13652  redcost = SCIPcolGetRedcost(col, stat, lp);
13653  assert(!SCIPsetIsDualfeasNegative(set, redcost));
13654 
13655  if( !varfixing )
13656  redcost *= (lb - bounds[v]);
13657  else
13658  redcost *= (bounds[v] - lb);
13659  }
13660  else if( basestat == SCIP_BASESTAT_UPPER && boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLT(set, bounds[v], ub) )
13661  {
13662  redcost = SCIPcolGetRedcost(col, stat, lp);
13663  assert(!SCIPsetIsDualfeasPositive(set, redcost));
13664 
13665  if( varfixing )
13666  redcost *= (bounds[v] - ub);
13667  else
13668  redcost *= (ub - bounds[v]);
13669  }
13670  }
13671  else
13672  {
13673  SCIP_Real primsol = SCIPcolGetPrimsol(col);
13674 
13675  /* check if the implication is not not yet applied */
13676  if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasEQ(set, lb, primsol) && SCIPsetIsFeasGT(set, bounds[v], lb) )
13677  {
13678  redcost = SCIPcolGetRedcost(col, stat, lp);
13679  assert(!SCIPsetIsDualfeasNegative(set, redcost));
13680 
13681  if( varfixing )
13682  redcost *= (lb - bounds[v]);
13683  else
13684  redcost *= (bounds[v] - lb);
13685  }
13686  else if( boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasEQ(set, ub, primsol) && SCIPsetIsFeasLT(set, bounds[v], ub) )
13687  {
13688  redcost = SCIPcolGetRedcost(col, stat, lp);
13689  assert(!SCIPsetIsDualfeasPositive(set, redcost));
13690 
13691  if( varfixing )
13692  redcost *= (bounds[v] - ub);
13693  else
13694  redcost *= (ub - bounds[v]);
13695  }
13696  }
13697 
13698  /* improve implied reduced cost */
13699  if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
13700  implredcost += redcost;
13701  }
13702  }
13703 
13704 #ifdef SCIP_MORE_DEBUG
13705  SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) and implications (%d) has implied reduced cost of %g\n",
13706  SCIPvarGetName(var), ncliques, nvars, implredcost);
13707 #endif
13708 
13709  return implredcost;
13710 }
13711 
13712 /** returns the best solution (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation, if
13713  * the root relaxation is not yet completely solved, zero is returned
13714  */
13716  SCIP_VAR* var /**< problem variable */
13717  )
13718 {
13719  SCIP_Real rootsol;
13720  int i;
13721 
13722  assert(var != NULL);
13723 
13724  switch( SCIPvarGetStatus(var) )
13725  {
13727  if( var->data.original.transvar == NULL )
13728  return 0.0;
13730 
13731  case SCIP_VARSTATUS_LOOSE:
13732  case SCIP_VARSTATUS_COLUMN:
13733  return var->bestrootsol;
13734 
13735  case SCIP_VARSTATUS_FIXED:
13736  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13737  return var->locdom.lb;
13738 
13740  assert(!var->donotaggr);
13741  assert(var->data.aggregate.var != NULL);
13742  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13743  * corresponding infinity value instead of performing an arithmetical transformation (compare method
13744  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13745  * (or is called by) a public interface method; instead, we only assert that values are finite
13746  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13747  * positives and negatives if the parameter <numerics/infinity> is modified by the user
13748  */
13752 
13754  assert(!var->donotmultaggr);
13755  assert(var->data.multaggr.vars != NULL);
13756  assert(var->data.multaggr.scalars != NULL);
13757  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13758  * assert(var->data.multaggr.nvars >= 2);
13759  */
13760  rootsol = var->data.multaggr.constant;
13761  for( i = 0; i < var->data.multaggr.nvars; ++i )
13762  rootsol += var->data.multaggr.scalars[i] * SCIPvarGetBestRootSol(var->data.multaggr.vars[i]);
13763  return rootsol;
13764 
13765  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13766  assert(var->negatedvar != NULL);
13768  assert(var->negatedvar->negatedvar == var);
13769  return var->data.negate.constant - SCIPvarGetBestRootSol(var->negatedvar);
13770 
13771  default:
13772  SCIPerrorMessage("unknown variable status\n");
13773  SCIPABORT();
13774  return 0.0; /*lint !e527*/
13775  }
13776 }
13777 
13778 /** returns the best reduced costs (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation,
13779  * if the root relaxation is not yet completely solved, or the variable was no column of the root LP, SCIP_INVALID is
13780  * returned
13781  */
13783  SCIP_VAR* var /**< problem variable */
13784  )
13785 {
13786  assert(var != NULL);
13787 
13788  switch( SCIPvarGetStatus(var) )
13789  {
13791  if( var->data.original.transvar == NULL )
13792  return SCIP_INVALID;
13794 
13795  case SCIP_VARSTATUS_LOOSE:
13796  case SCIP_VARSTATUS_COLUMN:
13797  return var->bestrootredcost;
13798 
13799  case SCIP_VARSTATUS_FIXED:
13803  return 0.0;
13804 
13805  default:
13806  SCIPerrorMessage("unknown variable status\n");
13807  SCIPABORT();
13808  return 0.0; /*lint !e527*/
13809  }
13810 }
13811 
13812 /** returns the best objective value (w.r.t. root reduced cost propagation) of the root LP which belongs the root
13813  * reduced cost which is accessible via SCIPvarGetRootRedcost() or the variable was no column of the root LP,
13814  * SCIP_INVALID is returned
13815  */
13817  SCIP_VAR* var /**< problem variable */
13818  )
13819 {
13820  assert(var != NULL);
13821 
13822  switch( SCIPvarGetStatus(var) )
13823  {
13825  if( var->data.original.transvar == NULL )
13826  return SCIP_INVALID;
13828 
13829  case SCIP_VARSTATUS_LOOSE:
13830  case SCIP_VARSTATUS_COLUMN:
13831  return var->bestrootlpobjval;
13832 
13833  case SCIP_VARSTATUS_FIXED:
13837  return SCIP_INVALID;
13838 
13839  default:
13840  SCIPerrorMessage("unknown variable status\n");
13841  SCIPABORT();
13842  return SCIP_INVALID; /*lint !e527*/
13843  }
13844 }
13845 
13846 /** set the given solution as the best root solution w.r.t. root reduced cost propagation in the variables */
13848  SCIP_VAR* var, /**< problem variable */
13849  SCIP_Real rootsol, /**< root solution value */
13850  SCIP_Real rootredcost, /**< root reduced cost */
13851  SCIP_Real rootlpobjval /**< objective value of the root LP */
13852  )
13853 {
13854  assert(var != NULL);
13855 
13856  var->bestrootsol = rootsol;
13857  var->bestrootredcost = rootredcost;
13858  var->bestrootlpobjval = rootlpobjval;
13859 }
13860 
13861 /** stores the solution value as relaxation solution in the problem variable */
13863  SCIP_VAR* var, /**< problem variable */
13864  SCIP_SET* set, /**< global SCIP settings */
13865  SCIP_RELAXATION* relaxation, /**< global relaxation data */
13866  SCIP_Real solval, /**< solution value in the current relaxation solution */
13867  SCIP_Bool updateobj /**< should the objective value be updated? */
13868  )
13869 {
13870  assert(var != NULL);
13871  assert(relaxation != NULL);
13872  assert(set != NULL);
13873  assert(var->scip == set->scip);
13874 
13875  /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
13876  switch( SCIPvarGetStatus(var) )
13877  {
13879  SCIP_CALL( SCIPvarSetRelaxSol(var->data.original.transvar, set, relaxation, solval, updateobj) );
13880  break;
13881 
13882  case SCIP_VARSTATUS_LOOSE:
13883  case SCIP_VARSTATUS_COLUMN:
13884  if( updateobj )
13885  SCIPrelaxationSolObjAdd(relaxation, var->obj * (solval - var->relaxsol));
13886  var->relaxsol = solval;
13887  break;
13888 
13889  case SCIP_VARSTATUS_FIXED:
13890  if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
13891  {
13892  SCIPerrorMessage("cannot set relaxation solution value for variable <%s> fixed to %.15g to different value %.15g\n",
13893  SCIPvarGetName(var), var->glbdom.lb, solval);
13894  return SCIP_INVALIDDATA;
13895  }
13896  break;
13897 
13898  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13899  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
13900  SCIP_CALL( SCIPvarSetRelaxSol(var->data.aggregate.var, set, relaxation,
13901  (solval - var->data.aggregate.constant)/var->data.aggregate.scalar, updateobj) );
13902  break;
13904  SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
13905  return SCIP_INVALIDDATA;
13906 
13908  SCIP_CALL( SCIPvarSetRelaxSol(var->negatedvar, set, relaxation, var->data.negate.constant - solval, updateobj) );
13909  break;
13910 
13911  default:
13912  SCIPerrorMessage("unknown variable status\n");
13913  return SCIP_INVALIDDATA;
13914  }
13915 
13916  return SCIP_OKAY;
13917 }
13918 
13919 /** returns the solution value of the problem variable in the relaxation solution
13920  *
13921  * @todo Inline this function - similar to SCIPvarGetLPSol_rec.
13922  */
13924  SCIP_VAR* var, /**< problem variable */
13925  SCIP_SET* set /**< global SCIP settings */
13926  )
13927 {
13928  SCIP_Real solvalsum;
13929  SCIP_Real solval;
13930  int i;
13931 
13932  assert(var != NULL);
13933  assert(set != NULL);
13934  assert(var->scip == set->scip);
13935 
13936  /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
13937  switch( SCIPvarGetStatus(var) )
13938  {
13940  return SCIPvarGetRelaxSol(var->data.original.transvar, set);
13941 
13942  case SCIP_VARSTATUS_LOOSE:
13943  case SCIP_VARSTATUS_COLUMN:
13944  return var->relaxsol;
13945 
13946  case SCIP_VARSTATUS_FIXED:
13947  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
13948  assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
13949  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
13950  return SCIPvarGetLbGlobal(var);
13951 
13952  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13953  solval = SCIPvarGetRelaxSol(var->data.aggregate.var, set);
13954  if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
13955  {
13956  if( var->data.aggregate.scalar * solval > 0.0 )
13957  return SCIPsetInfinity(set);
13958  if( var->data.aggregate.scalar * solval < 0.0 )
13959  return -SCIPsetInfinity(set);
13960  }
13961  return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
13962 
13964  solvalsum = var->data.multaggr.constant;
13965  for( i = 0; i < var->data.multaggr.nvars; ++i )
13966  {
13967  solval = SCIPvarGetRelaxSol(var->data.multaggr.vars[i], set);
13968  if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
13969  {
13970  if( var->data.multaggr.scalars[i] * solval > 0.0 )
13971  return SCIPsetInfinity(set);
13972  if( var->data.multaggr.scalars[i] * solval < 0.0 )
13973  return -SCIPsetInfinity(set);
13974  }
13975  solvalsum += var->data.multaggr.scalars[i] * solval;
13976  }
13977  return solvalsum;
13978 
13980  solval = SCIPvarGetRelaxSol(var->negatedvar, set);
13981  if( SCIPsetIsInfinity(set, solval) )
13982  return -SCIPsetInfinity(set);
13983  if( SCIPsetIsInfinity(set, -solval) )
13984  return SCIPsetInfinity(set);
13985  return var->data.negate.constant - solval;
13986 
13987  default:
13988  SCIPerrorMessage("unknown variable status\n");
13989  SCIPABORT();
13990  return SCIP_INVALID; /*lint !e527*/
13991  }
13992 }
13993 
13994 /** returns the solution value of the transformed problem variable in the relaxation solution */
13996  SCIP_VAR* var /**< problem variable */
13997  )
13998 {
13999  assert(var != NULL);
14001 
14002  return var->relaxsol;
14003 }
14004 
14005 /** stores the solution value as NLP solution in the problem variable */
14007  SCIP_VAR* var, /**< problem variable */
14008  SCIP_SET* set, /**< global SCIP settings */
14009  SCIP_Real solval /**< solution value in the current NLP solution */
14010  )
14011 {
14012  assert(var != NULL);
14013  assert(set != NULL);
14014  assert(var->scip == set->scip);
14015 
14016  /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
14017  switch( SCIPvarGetStatus(var) )
14018  {
14020  SCIP_CALL( SCIPvarSetNLPSol(var->data.original.transvar, set, solval) );
14021  break;
14022 
14023  case SCIP_VARSTATUS_LOOSE:
14024  case SCIP_VARSTATUS_COLUMN:
14025  var->nlpsol = solval;
14026  break;
14027 
14028  case SCIP_VARSTATUS_FIXED:
14029  if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
14030  {
14031  SCIPerrorMessage("cannot set NLP solution value for variable <%s> fixed to %.15g to different value %.15g\n",
14032  SCIPvarGetName(var), var->glbdom.lb, solval);
14033  SCIPABORT();
14034  return SCIP_INVALIDCALL; /*lint !e527*/
14035  }
14036  break;
14037 
14038  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
14039  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
14040  SCIP_CALL( SCIPvarSetNLPSol(var->data.aggregate.var, set, (solval - var->data.aggregate.constant)/var->data.aggregate.scalar) );
14041  break;
14042 
14044  SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
14045  SCIPABORT();
14046  return SCIP_INVALIDCALL; /*lint !e527*/
14047 
14049  SCIP_CALL( SCIPvarSetNLPSol(var->negatedvar, set, var->data.negate.constant - solval) );
14050  break;
14051 
14052  default:
14053  SCIPerrorMessage("unknown variable status\n");
14054  SCIPABORT();
14055  return SCIP_ERROR; /*lint !e527*/
14056  }
14057 
14058  return SCIP_OKAY;
14059 }
14060 
14061 /** returns a weighted average solution value of the variable in all feasible primal solutions found so far */
14063  SCIP_VAR* var /**< problem variable */
14064  )
14065 {
14066  SCIP_Real avgsol;
14067  int i;
14068 
14069  assert(var != NULL);
14070 
14071  switch( SCIPvarGetStatus(var) )
14072  {
14074  if( var->data.original.transvar == NULL )
14075  return 0.0;
14076  return SCIPvarGetAvgSol(var->data.original.transvar);
14077 
14078  case SCIP_VARSTATUS_LOOSE:
14079  case SCIP_VARSTATUS_COLUMN:
14080  avgsol = var->primsolavg;
14081  avgsol = MAX(avgsol, var->glbdom.lb);
14082  avgsol = MIN(avgsol, var->glbdom.ub);
14083  return avgsol;
14084 
14085  case SCIP_VARSTATUS_FIXED:
14086  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
14087  return var->locdom.lb;
14088 
14090  assert(!var->donotaggr);
14091  assert(var->data.aggregate.var != NULL);
14092  return var->data.aggregate.scalar * SCIPvarGetAvgSol(var->data.aggregate.var)
14093  + var->data.aggregate.constant;
14094 
14096  assert(!var->donotmultaggr);
14097  assert(var->data.multaggr.vars != NULL);
14098  assert(var->data.multaggr.scalars != NULL);
14099  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
14100  * assert(var->data.multaggr.nvars >= 2);
14101  */
14102  avgsol = var->data.multaggr.constant;
14103  for( i = 0; i < var->data.multaggr.nvars; ++i )
14104  avgsol += var->data.multaggr.scalars[i] * SCIPvarGetAvgSol(var->data.multaggr.vars[i]);
14105  return avgsol;
14106 
14107  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
14108  assert(var->negatedvar != NULL);
14110  assert(var->negatedvar->negatedvar == var);
14111  return var->data.negate.constant - SCIPvarGetAvgSol(var->negatedvar);
14112 
14113  default:
14114  SCIPerrorMessage("unknown variable status\n");
14115  SCIPABORT();
14116  return 0.0; /*lint !e527*/
14117  }
14118 }
14119 
14120 /** returns solution value and index of variable lower bound that is closest to the variable's value in the given primal solution
14121  * or current LP solution if no primal solution is given; returns an index of -1 if no variable lower bound is available
14122  */
14124  SCIP_VAR* var, /**< active problem variable */
14125  SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
14126  SCIP_SET* set, /**< global SCIP settings */
14127  SCIP_STAT* stat, /**< problem statistics */
14128  SCIP_Real* closestvlb, /**< pointer to store the value of the closest variable lower bound */
14129  int* closestvlbidx /**< pointer to store the index of the closest variable lower bound */
14130  )
14131 {
14132  int nvlbs;
14133 
14134  assert(var != NULL);
14135  assert(stat != NULL);
14136  assert(set != NULL);
14137  assert(var->scip == set->scip);
14138  assert(closestvlb != NULL);
14139  assert(closestvlbidx != NULL);
14140 
14141  *closestvlbidx = -1;
14142  *closestvlb = SCIP_REAL_MIN;
14143 
14144  nvlbs = SCIPvarGetNVlbs(var);
14145  if( nvlbs > 0 )
14146  {
14147  SCIP_VAR** vlbvars;
14148  SCIP_Real* vlbcoefs;
14149  SCIP_Real* vlbconsts;
14150  int i;
14151 
14152  vlbvars = SCIPvarGetVlbVars(var);
14153  vlbcoefs = SCIPvarGetVlbCoefs(var);
14154  vlbconsts = SCIPvarGetVlbConstants(var);
14155 
14156  /* check for cached values */
14157  if( var->closestvblpcount == stat->lpcount && var->closestvlbidx != -1 && sol == NULL)
14158  {
14159  i = var->closestvlbidx;
14160  assert(0 <= i && i < nvlbs);
14161  assert(SCIPvarIsActive(vlbvars[i]));
14162  *closestvlbidx = i;
14163  *closestvlb = vlbcoefs[i] * SCIPvarGetLPSol(vlbvars[i]) + vlbconsts[i];
14164  }
14165  else
14166  {
14167  /* search best VUB */
14168  for( i = 0; i < nvlbs; i++ )
14169  {
14170  if( SCIPvarIsActive(vlbvars[i]) )
14171  {
14172  SCIP_Real vlbsol;
14173 
14174  vlbsol = vlbcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vlbvars[i]) : SCIPsolGetVal(sol, set, stat, vlbvars[i])) + vlbconsts[i];
14175  if( vlbsol > *closestvlb )
14176  {
14177  *closestvlb = vlbsol;
14178  *closestvlbidx = i;
14179  }
14180  }
14181  }
14182 
14183  if( sol == NULL )
14184  {
14185  /* update cached value */
14186  if( var->closestvblpcount != stat->lpcount )
14187  var->closestvubidx = -1;
14188  var->closestvlbidx = *closestvlbidx;
14189  var->closestvblpcount = stat->lpcount;
14190  }
14191  }
14192  }
14193 }
14194 
14195 /** returns solution value and index of variable upper bound that is closest to the variable's value in the given primal solution;
14196  * or current LP solution if no primal solution is given; returns an index of -1 if no variable upper bound is available
14197  */
14199  SCIP_VAR* var, /**< active problem variable */
14200  SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
14201  SCIP_SET* set, /**< global SCIP settings */
14202  SCIP_STAT* stat, /**< problem statistics */
14203  SCIP_Real* closestvub, /**< pointer to store the value of the closest variable upper bound */
14204  int* closestvubidx /**< pointer to store the index of the closest variable upper bound */
14205  )
14206 {
14207  int nvubs;
14208 
14209  assert(var != NULL);
14210  assert(set != NULL);
14211  assert(var->scip == set->scip);
14212  assert(closestvub != NULL);
14213  assert(closestvubidx != NULL);
14214 
14215  *closestvubidx = -1;
14216  *closestvub = SCIP_REAL_MAX;
14217 
14218  nvubs = SCIPvarGetNVubs(var);
14219  if( nvubs > 0 )
14220  {
14221  SCIP_VAR** vubvars;
14222  SCIP_Real* vubcoefs;
14223  SCIP_Real* vubconsts;
14224  int i;
14225 
14226  vubvars = SCIPvarGetVubVars(var);
14227  vubcoefs = SCIPvarGetVubCoefs(var);
14228  vubconsts = SCIPvarGetVubConstants(var);
14229 
14230  /* check for cached values */
14231  if( var->closestvblpcount == stat->lpcount && var->closestvubidx != -1 && sol == NULL)
14232  {
14233  i = var->closestvubidx;
14234  assert(0 <= i && i < nvubs);
14235  assert(SCIPvarIsActive(vubvars[i]));
14236  *closestvubidx = i;
14237  *closestvub = vubcoefs[i] * SCIPvarGetLPSol(vubvars[i]) + vubconsts[i];
14238  }
14239  else
14240  {
14241  /* search best VUB */
14242  for( i = 0; i < nvubs; i++ )
14243  {
14244  if( SCIPvarIsActive(vubvars[i]) )
14245  {
14246  SCIP_Real vubsol;
14247 
14248  vubsol = vubcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vubvars[i]) : SCIPsolGetVal(sol, set, stat, vubvars[i])) + vubconsts[i];
14249  if( vubsol < *closestvub )
14250  {
14251  *closestvub = vubsol;
14252  *closestvubidx = i;
14253  }
14254  }
14255  }
14256 
14257  if( sol == NULL )
14258  {
14259  /* update cached value */
14260  if( var->closestvblpcount != stat->lpcount )
14261  var->closestvlbidx = -1;
14262  var->closestvubidx = *closestvubidx;
14263  var->closestvblpcount = stat->lpcount;
14264  }
14265  }
14266  }
14267 }
14268 
14269 /** resolves variable to columns and adds them with the coefficient to the row */
14271  SCIP_VAR* var, /**< problem variable */
14272  BMS_BLKMEM* blkmem, /**< block memory */
14273  SCIP_SET* set, /**< global SCIP settings */
14274  SCIP_STAT* stat, /**< problem statistics */
14275  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
14276  SCIP_PROB* prob, /**< problem data */
14277  SCIP_LP* lp, /**< current LP data */
14278  SCIP_ROW* row, /**< LP row */
14279  SCIP_Real val /**< value of coefficient */
14280  )
14281 {
14282  int i;
14283 
14284  assert(var != NULL);
14285  assert(set != NULL);
14286  assert(var->scip == set->scip);
14287  assert(row != NULL);
14288  assert(!SCIPsetIsInfinity(set, REALABS(val)));
14289 
14290  SCIPsetDebugMsg(set, "adding coefficient %g<%s> to row <%s>\n", val, var->name, row->name);
14291 
14292  if ( SCIPsetIsZero(set, val) )
14293  return SCIP_OKAY;
14294 
14295  switch( SCIPvarGetStatus(var) )
14296  {
14298  if( var->data.original.transvar == NULL )
14299  {
14300  SCIPerrorMessage("cannot add untransformed original variable <%s> to LP row <%s>\n", var->name, row->name);
14301  return SCIP_INVALIDDATA;
14302  }
14303  SCIP_CALL( SCIPvarAddToRow(var->data.original.transvar, blkmem, set, stat, eventqueue, prob, lp, row, val) );
14304  return SCIP_OKAY;
14305 
14306  case SCIP_VARSTATUS_LOOSE:
14307  /* add globally fixed variables as constant */
14308  if( SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub) )
14309  {
14310  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->glbdom.lb) );
14311  return SCIP_OKAY;
14312  }
14313  /* convert loose variable into column */
14314  SCIP_CALL( SCIPvarColumn(var, blkmem, set, stat, prob, lp) );
14315  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
14316  /*lint -fallthrough*/
14317 
14318  case SCIP_VARSTATUS_COLUMN:
14319  assert(var->data.col != NULL);
14320  assert(var->data.col->var == var);
14321  SCIP_CALL( SCIProwIncCoef(row, blkmem, set, eventqueue, lp, var->data.col, val) );
14322  return SCIP_OKAY;
14323 
14324  case SCIP_VARSTATUS_FIXED:
14325  assert(var->glbdom.lb == var->glbdom.ub); /*lint !e777*/
14326  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
14327  assert(var->locdom.lb == var->glbdom.lb); /*lint !e777*/
14328  assert(!SCIPsetIsInfinity(set, REALABS(var->locdom.lb)));
14329  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->locdom.lb) );
14330  return SCIP_OKAY;
14331 
14333  assert(!var->donotaggr);
14334  assert(var->data.aggregate.var != NULL);
14335  SCIP_CALL( SCIPvarAddToRow(var->data.aggregate.var, blkmem, set, stat, eventqueue, prob, lp,
14336  row, var->data.aggregate.scalar * val) );
14337  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.aggregate.constant * val) );
14338  return SCIP_OKAY;
14339 
14341  assert(!var->donotmultaggr);
14342  assert(var->data.multaggr.vars != NULL);
14343  assert(var->data.multaggr.scalars != NULL);
14344  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
14345  * assert(var->data.multaggr.nvars >= 2);
14346  */
14347  for( i = 0; i < var->data.multaggr.nvars; ++i )
14348  {
14349  SCIP_CALL( SCIPvarAddToRow(var->data.multaggr.vars[i], blkmem, set, stat, eventqueue, prob, lp,
14350  row, var->data.multaggr.scalars[i] * val) );
14351  }
14352  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.multaggr.constant * val) );
14353  return SCIP_OKAY;
14354 
14355  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
14356  assert(var->negatedvar != NULL);
14358  assert(var->negatedvar->negatedvar == var);
14359  SCIP_CALL( SCIPvarAddToRow(var->negatedvar, blkmem, set, stat, eventqueue, prob, lp, row, -val) );
14360  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.negate.constant * val) );
14361  return SCIP_OKAY;
14362 
14363  default:
14364  SCIPerrorMessage("unknown variable status\n");
14365  return SCIP_INVALIDDATA;
14366  }
14367 }
14368 
14369 /* optionally, define this compiler flag to write complete variable histories to a file */
14370 #ifdef SCIP_HISTORYTOFILE
14371 SCIP_Longint counter = 0l;
14372 const char* historypath="."; /* allows for user-defined path; use '.' for calling directory of SCIP */
14373 #include "scip/scip.h"
14374 #endif
14375 
14376 /** updates the pseudo costs of the given variable and the global pseudo costs after a change of
14377  * "solvaldelta" in the variable's solution value and resulting change of "objdelta" in the in the LP's objective value
14378  */
14380  SCIP_VAR* var, /**< problem variable */
14381  SCIP_SET* set, /**< global SCIP settings */
14382  SCIP_STAT* stat, /**< problem statistics */
14383  SCIP_Real solvaldelta, /**< difference of variable's new LP value - old LP value */
14384  SCIP_Real objdelta, /**< difference of new LP's objective value - old LP's objective value */
14385  SCIP_Real weight /**< weight in (0,1] of this update in pseudo cost sum */
14386  )
14387 {
14388  SCIP_Real oldrootpseudocosts;
14389  assert(var != NULL);
14390  assert(set != NULL);
14391  assert(var->scip == set->scip);
14392  assert(stat != NULL);
14393 
14394  /* check if history statistics should be collected for a variable */
14395  if( !stat->collectvarhistory )
14396  return SCIP_OKAY;
14397 
14398  switch( SCIPvarGetStatus(var) )
14399  {
14401  if( var->data.original.transvar == NULL )
14402  {
14403  SCIPerrorMessage("cannot update pseudo costs of original untransformed variable\n");
14404  return SCIP_INVALIDDATA;
14405  }
14406  SCIP_CALL( SCIPvarUpdatePseudocost(var->data.original.transvar, set, stat, solvaldelta, objdelta, weight) );
14407  return SCIP_OKAY;
14408 
14409  case SCIP_VARSTATUS_LOOSE:
14410  case SCIP_VARSTATUS_COLUMN:
14411  /* store old pseudo-costs for root LP best-estimate update */
14412  oldrootpseudocosts = SCIPvarGetMinPseudocostScore(var, stat, set, SCIPvarGetRootSol(var));
14413 
14414  /* update history */
14415  SCIPhistoryUpdatePseudocost(var->history, set, solvaldelta, objdelta, weight);
14416  SCIPhistoryUpdatePseudocost(var->historycrun, set, solvaldelta, objdelta, weight);
14417  SCIPhistoryUpdatePseudocost(stat->glbhistory, set, solvaldelta, objdelta, weight);
14418  SCIPhistoryUpdatePseudocost(stat->glbhistorycrun, set, solvaldelta, objdelta, weight);
14419 
14420  /* update root LP best-estimate */
14421  SCIP_CALL( SCIPstatUpdateVarRootLPBestEstimate(stat, set, var, oldrootpseudocosts) );
14422 
14423  /* append history to file */
14424 #ifdef SCIP_HISTORYTOFILE
14425  {
14426  FILE* f;
14427  char filename[256];
14428  SCIP_NODE* currentnode;
14429  SCIP_NODE* parentnode;
14430  currentnode = SCIPgetFocusNode(set->scip);
14431  parentnode = SCIPnodeGetParent(currentnode);
14432 
14433  sprintf(filename, "%s/%s.pse", historypath, SCIPgetProbName(set->scip));
14434  f = fopen(filename, "a");
14435  if( NULL != f )
14436  {
14437  fprintf(f, "%lld %s \t %lld \t %lld \t %lld \t %d \t %15.9f \t %.3f\n",
14438  ++counter,
14439  SCIPvarGetName(var),
14440  SCIPnodeGetNumber(currentnode),
14441  parentnode != NULL ? SCIPnodeGetNumber(parentnode) : -1,
14442  SCIPgetNLPIterations(set->scip),
14443  SCIPgetDepth(set->scip),
14444  objdelta,
14445  solvaldelta);
14446  fclose(f);
14447  }
14448  }
14449 #endif
14450  return SCIP_OKAY;
14451 
14452  case SCIP_VARSTATUS_FIXED:
14453  SCIPerrorMessage("cannot update pseudo cost values of a fixed variable\n");
14454  return SCIP_INVALIDDATA;
14455 
14457  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
14459  solvaldelta/var->data.aggregate.scalar, objdelta, weight) );
14460  return SCIP_OKAY;
14461 
14463  SCIPerrorMessage("cannot update pseudo cost values of a multi-aggregated variable\n");
14464  return SCIP_INVALIDDATA;
14465 
14467  SCIP_CALL( SCIPvarUpdatePseudocost(var->negatedvar, set, stat, -solvaldelta, objdelta, weight) );
14468  return SCIP_OKAY;
14469 
14470  default:
14471  SCIPerrorMessage("unknown variable status\n");
14472  return SCIP_INVALIDDATA;
14473  }
14474 }
14475 
14476 /** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value */
14478  SCIP_VAR* var, /**< problem variable */
14479  SCIP_STAT* stat, /**< problem statistics */
14480  SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
14481  )
14482 {
14483  SCIP_BRANCHDIR dir;
14484 
14485  assert(var != NULL);
14486  assert(stat != NULL);
14487 
14488  switch( SCIPvarGetStatus(var) )
14489  {
14491  if( var->data.original.transvar == NULL )
14492  return SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
14493  else
14494  return SCIPvarGetPseudocost(var->data.original.transvar, stat, solvaldelta);
14495 
14496  case SCIP_VARSTATUS_LOOSE:
14497  case SCIP_VARSTATUS_COLUMN:
14498  dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
14499 
14500  return SCIPhistoryGetPseudocostCount(var->history, dir) > 0.0
14501  ? SCIPhistoryGetPseudocost(var->history, solvaldelta)
14502  : SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
14503 
14504  case SCIP_VARSTATUS_FIXED:
14505  return 0.0;
14506 
14508  return SCIPvarGetPseudocost(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
14509 
14511  return 0.0;
14512 
14514  return SCIPvarGetPseudocost(var->negatedvar, stat, -solvaldelta);
14515 
14516  default:
14517  SCIPerrorMessage("unknown variable status\n");
14518  SCIPABORT();
14519  return 0.0; /*lint !e527*/
14520  }
14521 }
14522 
14523 /** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value,
14524  * only using the pseudo cost information of the current run
14525  */
14527  SCIP_VAR* var, /**< problem variable */
14528  SCIP_STAT* stat, /**< problem statistics */
14529  SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
14530  )
14531 {
14532  SCIP_BRANCHDIR dir;
14533 
14534  assert(var != NULL);
14535  assert(stat != NULL);
14536 
14537  switch( SCIPvarGetStatus(var) )
14538  {
14540  if( var->data.original.transvar == NULL )
14541  return SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
14542  else
14543  return SCIPvarGetPseudocostCurrentRun(var->data.original.transvar, stat, solvaldelta);
14544 
14545  case SCIP_VARSTATUS_LOOSE:
14546  case SCIP_VARSTATUS_COLUMN:
14547  dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
14548 
14549  return SCIPhistoryGetPseudocostCount(var->historycrun, dir) > 0.0
14550  ? SCIPhistoryGetPseudocost(var->historycrun, solvaldelta)
14551  : SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
14552 
14553  case SCIP_VARSTATUS_FIXED:
14554  return 0.0;
14555 
14557  return SCIPvarGetPseudocostCurrentRun(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
14558 
14560  return 0.0;
14561 
14563  return SCIPvarGetPseudocostCurrentRun(var->negatedvar, stat, -solvaldelta);
14564 
14565  default:
14566  SCIPerrorMessage("unknown variable status\n");
14567  SCIPABORT();
14568  return 0.0; /*lint !e527*/
14569  }
14570 }
14571 
14572 /** gets the variable's (possible fractional) number of pseudo cost updates for the given direction */
14574  SCIP_VAR* var, /**< problem variable */
14575  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14576  )
14577 {
14578  assert(var != NULL);
14579  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14580 
14581  switch( SCIPvarGetStatus(var) )
14582  {
14584  if( var->data.original.transvar == NULL )
14585  return 0.0;
14586  else
14587  return SCIPvarGetPseudocostCount(var->data.original.transvar, dir);
14588 
14589  case SCIP_VARSTATUS_LOOSE:
14590  case SCIP_VARSTATUS_COLUMN:
14591  return SCIPhistoryGetPseudocostCount(var->history, dir);
14592 
14593  case SCIP_VARSTATUS_FIXED:
14594  return 0.0;
14595 
14597  if( var->data.aggregate.scalar > 0.0 )
14598  return SCIPvarGetPseudocostCount(var->data.aggregate.var, dir);
14599  else
14601 
14603  return 0.0;
14604 
14607 
14608  default:
14609  SCIPerrorMessage("unknown variable status\n");
14610  SCIPABORT();
14611  return 0.0; /*lint !e527*/
14612  }
14613 }
14614 
14615 /** gets the variable's (possible fractional) number of pseudo cost updates for the given direction,
14616  * only using the pseudo cost information of the current run
14617  */
14619  SCIP_VAR* var, /**< problem variable */
14620  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14621  )
14622 {
14623  assert(var != NULL);
14624  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14625 
14626  switch( SCIPvarGetStatus(var) )
14627  {
14629  if( var->data.original.transvar == NULL )
14630  return 0.0;
14631  else
14633 
14634  case SCIP_VARSTATUS_LOOSE:
14635  case SCIP_VARSTATUS_COLUMN:
14636  return SCIPhistoryGetPseudocostCount(var->historycrun, dir);
14637 
14638  case SCIP_VARSTATUS_FIXED:
14639  return 0.0;
14640 
14642  if( var->data.aggregate.scalar > 0.0 )
14644  else
14646 
14648  return 0.0;
14649 
14652 
14653  default:
14654  SCIPerrorMessage("unknown variable status\n");
14655  SCIPABORT();
14656  return 0.0; /*lint !e527*/
14657  }
14658 }
14659 
14660 /** compares both possible directions for rounding the given solution value and returns the minimum pseudo-costs of the variable */
14662  SCIP_VAR* var, /**< problem variable */
14663  SCIP_STAT* stat, /**< problem statistics */
14664  SCIP_SET* set, /**< global SCIP settings */
14665  SCIP_Real solval /**< solution value, e.g., LP solution value */
14666  )
14667 {
14668  SCIP_Real upscore;
14669  SCIP_Real downscore;
14670  SCIP_Real solvaldeltaup;
14671  SCIP_Real solvaldeltadown;
14672 
14673  /* LP root estimate only works for variables with fractional LP root solution */
14674  if( SCIPsetIsFeasIntegral(set, solval) )
14675  return 0.0;
14676 
14677  /* no min pseudo-cost score is calculated as long as the variable was not initialized in a direction */
14679  return 0.0;
14680 
14681  /* compute delta's to ceil and floor of root LP solution value */
14682  solvaldeltaup = SCIPsetCeil(set, solval) - solval;
14683  solvaldeltadown = SCIPsetFloor(set, solval) - solval;
14684 
14685  upscore = SCIPvarGetPseudocost(var, stat, solvaldeltaup);
14686  downscore = SCIPvarGetPseudocost(var, stat, solvaldeltadown);
14687 
14688  return MIN(upscore, downscore);
14689 }
14690 
14691 /** gets the an estimate of the variable's pseudo cost variance in direction \p dir */
14693  SCIP_VAR* var, /**< problem variable */
14694  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
14695  SCIP_Bool onlycurrentrun /**< return pseudo cost variance only for current branch and bound run */
14696  )
14697 {
14698  assert(var != NULL);
14699  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14700 
14701  switch( SCIPvarGetStatus(var) )
14702  {
14704  if( var->data.original.transvar == NULL )
14705  return 0.0;
14706  else
14707  return SCIPvarGetPseudocostVariance(var->data.original.transvar, dir, onlycurrentrun);
14708 
14709  case SCIP_VARSTATUS_LOOSE:
14710  case SCIP_VARSTATUS_COLUMN:
14711  if( onlycurrentrun )
14713  else
14714  return SCIPhistoryGetPseudocostVariance(var->history, dir);
14715 
14716  case SCIP_VARSTATUS_FIXED:
14717  return 0.0;
14718 
14720  if( var->data.aggregate.scalar > 0.0 )
14721  return SCIPvarGetPseudocostVariance(var->data.aggregate.var, dir, onlycurrentrun);
14722  else
14723  return SCIPvarGetPseudocostVariance(var->data.aggregate.var, SCIPbranchdirOpposite(dir), onlycurrentrun);
14724 
14726  return 0.0;
14727 
14729  return SCIPvarGetPseudocostVariance(var->negatedvar, SCIPbranchdirOpposite(dir), onlycurrentrun);
14730 
14731  default:
14732  SCIPerrorMessage("unknown variable status\n");
14733  SCIPABORT();
14734  return 0.0; /*lint !e527*/
14735  }
14736 }
14737 
14738 /** calculates a confidence bound for this variable under the assumption of normally distributed pseudo costs
14739  *
14740  * The confidence bound \f$ \theta \geq 0\f$ denotes the interval borders \f$ [X - \theta, \ X + \theta]\f$, which contains
14741  * the true pseudo costs of the variable, i.e., the expected value of the normal distribution, with a probability
14742  * of 2 * clevel - 1.
14743  *
14744  * @return value of confidence bound for this variable
14745  */
14747  SCIP_VAR* var, /**< variable in question */
14748  SCIP_SET* set, /**< global SCIP settings */
14749  SCIP_BRANCHDIR dir, /**< the branching direction for the confidence bound */
14750  SCIP_Bool onlycurrentrun, /**< should only the current run be taken into account */
14751  SCIP_CONFIDENCELEVEL clevel /**< confidence level for the interval */
14752  )
14753 {
14754  SCIP_Real confidencebound;
14755 
14756  confidencebound = SCIPvarGetPseudocostVariance(var, dir, onlycurrentrun);
14757  if( SCIPsetIsFeasPositive(set, confidencebound) )
14758  {
14759  SCIP_Real count;
14760 
14761  if( onlycurrentrun )
14762  count = SCIPvarGetPseudocostCountCurrentRun(var, dir);
14763  else
14764  count = SCIPvarGetPseudocostCount(var, dir);
14765  /* assertion is valid because variance is positive */
14766  assert(count >= 1.9);
14767 
14768  confidencebound /= count; /*lint !e414 division by zero can obviously not occur */
14769  confidencebound = sqrt(confidencebound);
14770 
14771  /* the actual, underlying distribution of the mean is a student-t-distribution with degrees of freedom equal to
14772  * the number of pseudo cost evaluations of this variable in the respective direction. */
14773  confidencebound *= SCIPstudentTGetCriticalValue(clevel, (int)SCIPsetFloor(set, count) - 1);
14774  }
14775  else
14776  confidencebound = 0.0;
14777 
14778  return confidencebound;
14779 }
14780 
14781 /** check if the current pseudo cost relative error in a direction violates the given threshold. The Relative
14782  * Error is calculated at a specific confidence level
14783  */
14785  SCIP_VAR* var, /**< variable in question */
14786  SCIP_SET* set, /**< global SCIP settings */
14787  SCIP_STAT* stat, /**< problem statistics */
14788  SCIP_Real threshold, /**< threshold for relative errors to be considered reliable (enough) */
14789  SCIP_CONFIDENCELEVEL clevel /**< a given confidence level */
14790  )
14791 {
14792  SCIP_Real downsize;
14793  SCIP_Real upsize;
14794  SCIP_Real size;
14795  SCIP_Real relerrorup;
14796  SCIP_Real relerrordown;
14797  SCIP_Real relerror;
14798 
14799  /* check, if the pseudo cost score of the variable is reliable */
14802  size = MIN(downsize, upsize);
14803 
14804  /* Pseudo costs relative error can only be reliable if both directions have been tried at least twice */
14805  if( size <= 1.9 )
14806  return FALSE;
14807 
14808  /* use the relative error between the current mean pseudo cost value of the candidate and its upper
14809  * confidence interval bound at confidence level of 95% for individual variable reliability.
14810  * this is only possible if we have at least 2 measurements and therefore a valid variance estimate.
14811  */
14812  if( downsize >= 1.9 )
14813  {
14814  SCIP_Real normval;
14815 
14816  relerrordown = SCIPvarCalcPscostConfidenceBound(var, set, SCIP_BRANCHDIR_DOWNWARDS, TRUE, clevel);
14817  normval = SCIPvarGetPseudocostCurrentRun(var, stat, -1.0);
14818  normval = MAX(1.0, normval);
14819 
14820  relerrordown /= normval;
14821  }
14822  else
14823  relerrordown = 0.0;
14824 
14825  if( upsize >= 1.9 )
14826  {
14827  SCIP_Real normval;
14828 
14829  relerrorup = SCIPvarCalcPscostConfidenceBound(var, set, SCIP_BRANCHDIR_UPWARDS, TRUE, clevel);
14830  normval = SCIPvarGetPseudocostCurrentRun(var, stat, +1.0);
14831  normval = MAX(1.0, normval);
14832  relerrorup /= normval;
14833  }
14834  else
14835  relerrorup = 0.0;
14836 
14837  /* consider the relative error threshold violated, if it is violated in at least one branching direction */
14838  relerror = MAX(relerrorup, relerrordown);
14839 
14840  return (relerror <= threshold);
14841 }
14842 
14843 /** check if variable pseudo-costs have a significant difference in location. The significance depends on
14844  * the choice of \p clevel and on the kind of tested hypothesis. The one-sided hypothesis, which
14845  * should be rejected, is that fracy * mu_y >= fracx * mu_x, where mu_y and mu_x denote the
14846  * unknown location means of the underlying pseudo-cost distributions of x and y.
14847  *
14848  * This method is applied best if variable x has a better pseudo-cost score than y. The method hypothesizes that y were actually
14849  * better than x (despite the current information), meaning that y can be expected to yield branching
14850  * decisions as least as good as x in the long run. If the method returns TRUE, the current history information is
14851  * sufficient to safely rely on the alternative hypothesis that x yields indeed a better branching score (on average)
14852  * than y.
14853  *
14854  * @note The order of x and y matters for the one-sided hypothesis
14855  *
14856  * @note set \p onesided to FALSE if you are not sure which variable is better. The hypothesis tested then reads
14857  * fracy * mu_y == fracx * mu_x vs the alternative hypothesis fracy * mu_y != fracx * mu_x.
14858  *
14859  * @return TRUE if the hypothesis can be safely rejected at the given confidence level
14860  */
14862  SCIP_SET* set, /**< global SCIP settings */
14863  SCIP_STAT* stat, /**< problem statistics */
14864  SCIP_VAR* varx, /**< variable x */
14865  SCIP_Real fracx, /**< the fractionality of variable x */
14866  SCIP_VAR* vary, /**< variable y */
14867  SCIP_Real fracy, /**< the fractionality of variable y */
14868  SCIP_BRANCHDIR dir, /**< branching direction */
14869  SCIP_CONFIDENCELEVEL clevel, /**< confidence level for rejecting hypothesis */
14870  SCIP_Bool onesided /**< should a one-sided hypothesis y >= x be tested? */
14871  )
14872 {
14873  SCIP_Real meanx;
14874  SCIP_Real meany;
14875  SCIP_Real variancex;
14876  SCIP_Real variancey;
14877  SCIP_Real countx;
14878  SCIP_Real county;
14879  SCIP_Real tresult;
14880  SCIP_Real realdirection;
14881 
14882  if( varx == vary )
14883  return FALSE;
14884 
14885  countx = SCIPvarGetPseudocostCount(varx, dir);
14886  county = SCIPvarGetPseudocostCount(vary, dir);
14887 
14888  /* if not at least 2 measurements were taken, return FALSE */
14889  if( countx <= 1.9 || county <= 1.9 )
14890  return FALSE;
14891 
14892  realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
14893 
14894  meanx = fracx * SCIPvarGetPseudocost(varx, stat, realdirection);
14895  meany = fracy * SCIPvarGetPseudocost(vary, stat, realdirection);
14896 
14897  variancex = SQR(fracx) * SCIPvarGetPseudocostVariance(varx, dir, FALSE);
14898  variancey = SQR(fracy) * SCIPvarGetPseudocostVariance(vary, dir, FALSE);
14899 
14900  /* if there is no variance, the means are taken from a constant distribution */
14901  if( SCIPsetIsFeasEQ(set, variancex + variancey, 0.0) )
14902  return (onesided ? SCIPsetIsFeasGT(set, meanx, meany) : !SCIPsetIsFeasEQ(set, meanx, meany));
14903 
14904  tresult = SCIPcomputeTwoSampleTTestValue(meanx, meany, variancex, variancey, countx, county);
14905 
14906  /* for the two-sided hypothesis, just take the absolute of t */
14907  if( !onesided )
14908  tresult = REALABS(tresult);
14909 
14910  return (tresult >= SCIPstudentTGetCriticalValue(clevel, (int)(countx + county - 2)));
14911 }
14912 
14913 /** tests at a given confidence level whether the variable pseudo-costs only have a small probability to
14914  * exceed a \p threshold. This is useful to determine if past observations provide enough evidence
14915  * to skip an expensive strong-branching step if there is already a candidate that has been proven to yield an improvement
14916  * of at least \p threshold.
14917  *
14918  * @note use \p clevel to adjust the level of confidence. For SCIP_CONFIDENCELEVEL_MIN, the method returns TRUE if
14919  * the estimated probability to exceed \p threshold is less than 25 %.
14920  *
14921  * @see SCIP_Confidencelevel for a list of available levels. The used probability limits refer to the one-sided levels
14922  * of confidence.
14923  *
14924  * @return TRUE if the variable pseudo-cost probabilistic model is likely to be smaller than \p threshold
14925  * at the given confidence level \p clevel.
14926  */
14928  SCIP_SET* set, /**< global SCIP settings */
14929  SCIP_STAT* stat, /**< problem statistics */
14930  SCIP_VAR* var, /**< variable x */
14931  SCIP_Real frac, /**< the fractionality of variable x */
14932  SCIP_Real threshold, /**< the threshold to test against */
14933  SCIP_BRANCHDIR dir, /**< branching direction */
14934  SCIP_CONFIDENCELEVEL clevel /**< confidence level for rejecting hypothesis */
14935  )
14936 {
14937  SCIP_Real mean;
14938  SCIP_Real variance;
14939  SCIP_Real count;
14940  SCIP_Real realdirection;
14941  SCIP_Real probability;
14942  SCIP_Real problimit;
14943 
14944  count = SCIPvarGetPseudocostCount(var, dir);
14945 
14946  /* if not at least 2 measurements were taken, return FALSE */
14947  if( count <= 1.9 )
14948  return FALSE;
14949 
14950  realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
14951 
14952  mean = frac * SCIPvarGetPseudocost(var, stat, realdirection);
14953  variance = SQR(frac) * SCIPvarGetPseudocostVariance(var, dir, FALSE);
14954 
14955  /* if mean is at least threshold, it has at least a 50% probability to exceed threshold, we therefore return FALSE */
14956  if( SCIPsetIsFeasGE(set, mean, threshold) )
14957  return FALSE;
14958 
14959  /* if there is no variance, the means are taken from a constant distribution */
14960  if( SCIPsetIsFeasEQ(set, variance, 0.0) )
14961  return SCIPsetIsFeasLT(set, mean, threshold);
14962 
14963  /* obtain probability of a normally distributed random variable at given mean and variance to yield at most threshold */
14964  probability = SCIPnormalCDF(mean, variance, threshold);
14965 
14966  /* determine a probability limit corresponding to the given confidence level */
14967  switch( clevel )
14968  {
14970  problimit = 0.75;
14971  break;
14973  problimit = 0.875;
14974  break;
14976  problimit = 0.9;
14977  break;
14979  problimit = 0.95;
14980  break;
14982  problimit = 0.975;
14983  break;
14984  default:
14985  problimit = -1;
14986  SCIPerrorMessage("Confidence level set to unknown value <%d>", (int)clevel);
14987  SCIPABORT();
14988  break;
14989  }
14990 
14991  return (probability >= problimit);
14992 }
14993 
14994 /** find the corresponding history entry if already existing, otherwise create new entry */
14995 static
14997  SCIP_VAR* var, /**< problem variable */
14998  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14999  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15000  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15001  SCIP_HISTORY** history /**< pointer to store the value based history, or NULL */
15002  )
15003 {
15004  assert(var != NULL);
15005  assert(blkmem != NULL);
15006  assert(set != NULL);
15007  assert(history != NULL);
15008 
15009  (*history) = NULL;
15010 
15011  if( var->valuehistory == NULL )
15012  {
15013  SCIP_CALL( SCIPvaluehistoryCreate(&var->valuehistory, blkmem) );
15014  }
15015 
15016  SCIP_CALL( SCIPvaluehistoryFind(var->valuehistory, blkmem, set, value, history) );
15017 
15018  return SCIP_OKAY;
15019 }
15020 
15021 /** check if value based history should be used */
15022 static
15024  SCIP_VAR* var, /**< problem variable */
15025  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15026  SCIP_SET* set /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15027  )
15028 {
15029  /* check if the domain value is unknown (not specific) */
15030  if( value == SCIP_UNKNOWN ) /*lint !e777*/
15031  return FALSE;
15032 
15033  assert(set != NULL);
15034 
15035  /* check if value based history should be collected */
15036  if( !set->history_valuebased )
15037  return FALSE;
15038 
15039  /* value based history is not collected for binary variable since the standard history already contains all information */
15040  if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
15041  return FALSE;
15042 
15043  /* value based history is not collected for continuous variables */
15045  return FALSE;
15046 
15047  return TRUE;
15048 }
15049 
15050 /** increases VSIDS of the variable by the given weight */
15052  SCIP_VAR* var, /**< problem variable */
15053  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15054  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15055  SCIP_STAT* stat, /**< problem statistics */
15056  SCIP_BRANCHDIR dir, /**< branching direction */
15057  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15058  SCIP_Real weight /**< weight of this update in VSIDS */
15059  )
15060 {
15061  assert(var != NULL);
15062  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15063 
15064  /* check if history statistics should be collected for a variable */
15065  if( !stat->collectvarhistory )
15066  return SCIP_OKAY;
15067 
15068  if( SCIPsetIsZero(set, weight) )
15069  return SCIP_OKAY;
15070 
15071  switch( SCIPvarGetStatus(var) )
15072  {
15074  if( var->data.original.transvar == NULL )
15075  {
15076  SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
15077  return SCIP_INVALIDDATA;
15078  }
15079  SCIP_CALL( SCIPvarIncVSIDS(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
15080  return SCIP_OKAY;
15081 
15082  case SCIP_VARSTATUS_LOOSE:
15083  case SCIP_VARSTATUS_COLUMN:
15084  {
15085  SCIPhistoryIncVSIDS(var->history, dir, weight);
15086  SCIPhistoryIncVSIDS(var->historycrun, dir, weight);
15087 
15088  if( useValuehistory(var, value, set) )
15089  {
15090  SCIP_HISTORY* history;
15091 
15092  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15093  assert(history != NULL);
15094 
15095  SCIPhistoryIncVSIDS(history, dir, weight);
15096  SCIPsetDebugMsg(set, "variable (<%s> %s %g) + <%g> = <%g>\n", SCIPvarGetName(var), dir == SCIP_BRANCHDIR_UPWARDS ? ">=" : "<=",
15097  value, weight, SCIPhistoryGetVSIDS(history, dir));
15098  }
15099 
15100  return SCIP_OKAY;
15101  }
15102  case SCIP_VARSTATUS_FIXED:
15103  SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
15104  return SCIP_INVALIDDATA;
15105 
15107  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15108 
15109  if( var->data.aggregate.scalar > 0.0 )
15110  {
15111  SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
15112  }
15113  else
15114  {
15115  assert(var->data.aggregate.scalar < 0.0);
15116  SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15117  }
15118  return SCIP_OKAY;
15119 
15121  SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
15122  return SCIP_INVALIDDATA;
15123 
15125  value = 1.0 - value;
15126 
15127  SCIP_CALL( SCIPvarIncVSIDS(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15128  return SCIP_OKAY;
15129 
15130  default:
15131  SCIPerrorMessage("unknown variable status\n");
15132  return SCIP_INVALIDDATA;
15133  }
15134 }
15135 
15136 /** scales the VSIDS of the variable by the given scalar */
15138  SCIP_VAR* var, /**< problem variable */
15139  SCIP_Real scalar /**< scalar to multiply the VSIDSs with */
15140  )
15141 {
15142  assert(var != NULL);
15143 
15144  switch( SCIPvarGetStatus(var) )
15145  {
15147  if( var->data.original.transvar == NULL )
15148  {
15149  SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
15150  return SCIP_INVALIDDATA;
15151  }
15153  return SCIP_OKAY;
15154 
15155  case SCIP_VARSTATUS_LOOSE:
15156  case SCIP_VARSTATUS_COLUMN:
15157  {
15158  SCIPhistoryScaleVSIDS(var->history, scalar);
15159  SCIPhistoryScaleVSIDS(var->historycrun, scalar);
15161 
15162  return SCIP_OKAY;
15163  }
15164  case SCIP_VARSTATUS_FIXED:
15165  SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
15166  return SCIP_INVALIDDATA;
15167 
15169  SCIP_CALL( SCIPvarScaleVSIDS(var->data.aggregate.var, scalar) );
15170  return SCIP_OKAY;
15171 
15173  SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
15174  return SCIP_INVALIDDATA;
15175 
15177  SCIP_CALL( SCIPvarScaleVSIDS(var->negatedvar, scalar) );
15178  return SCIP_OKAY;
15179 
15180  default:
15181  SCIPerrorMessage("unknown variable status\n");
15182  return SCIP_INVALIDDATA;
15183  }
15184 }
15185 
15186 /** increases the number of active conflicts by one and the overall length of the variable by the given length */
15188  SCIP_VAR* var, /**< problem variable */
15189  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15190  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15191  SCIP_STAT* stat, /**< problem statistics */
15192  SCIP_BRANCHDIR dir, /**< branching direction */
15193  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15194  SCIP_Real length /**< length of the conflict */
15195  )
15196 {
15197  assert(var != NULL);
15198  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15199 
15200  /* check if history statistics should be collected for a variable */
15201  if( !stat->collectvarhistory )
15202  return SCIP_OKAY;
15203 
15204  switch( SCIPvarGetStatus(var) )
15205  {
15207  if( var->data.original.transvar == NULL )
15208  {
15209  SCIPerrorMessage("cannot update conflict score of original untransformed variable\n");
15210  return SCIP_INVALIDDATA;
15211  }
15212  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.original.transvar, blkmem, set, stat, dir, value, length) );
15213  return SCIP_OKAY;
15214 
15215  case SCIP_VARSTATUS_LOOSE:
15216  case SCIP_VARSTATUS_COLUMN:
15217  {
15218  SCIPhistoryIncNActiveConflicts(var->history, dir, length);
15219  SCIPhistoryIncNActiveConflicts(var->historycrun, dir, length);
15220 
15221  if( useValuehistory(var, value, set) )
15222  {
15223  SCIP_HISTORY* history;
15224 
15225  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15226  assert(history != NULL);
15227 
15228  SCIPhistoryIncNActiveConflicts(history, dir, length);
15229  }
15230 
15231  return SCIP_OKAY;
15232  }
15233  case SCIP_VARSTATUS_FIXED:
15234  SCIPerrorMessage("cannot update conflict score of a fixed variable\n");
15235  return SCIP_INVALIDDATA;
15236 
15238  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15239 
15240  if( var->data.aggregate.scalar > 0.0 )
15241  {
15242  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, dir, value, length) );
15243  }
15244  else
15245  {
15246  assert(var->data.aggregate.scalar < 0.0);
15247  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
15248  }
15249  return SCIP_OKAY;
15250 
15252  SCIPerrorMessage("cannot update conflict score of a multi-aggregated variable\n");
15253  return SCIP_INVALIDDATA;
15254 
15256  value = 1.0 - value;
15257 
15258  SCIP_CALL( SCIPvarIncNActiveConflicts(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
15259  return SCIP_OKAY;
15260 
15261  default:
15262  SCIPerrorMessage("unknown variable status\n");
15263  return SCIP_INVALIDDATA;
15264  }
15265 }
15266 
15267 /** gets the number of active conflicts containing this variable in given direction */
15269  SCIP_VAR* var, /**< problem variable */
15270  SCIP_STAT* stat, /**< problem statistics */
15271  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15272  )
15273 {
15274  assert(var != NULL);
15275  assert(stat != NULL);
15276  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15277 
15278  switch( SCIPvarGetStatus(var) )
15279  {
15281  if( var->data.original.transvar == NULL )
15282  return 0;
15283  else
15284  return SCIPvarGetNActiveConflicts(var->data.original.transvar, stat, dir);
15285 
15286  case SCIP_VARSTATUS_LOOSE:
15287  case SCIP_VARSTATUS_COLUMN:
15288  return SCIPhistoryGetNActiveConflicts(var->history, dir);
15289 
15290  case SCIP_VARSTATUS_FIXED:
15291  return 0;
15292 
15294  if( var->data.aggregate.scalar > 0.0 )
15295  return SCIPvarGetNActiveConflicts(var->data.aggregate.var, stat, dir);
15296  else
15298 
15300  return 0;
15301 
15304 
15305  default:
15306  SCIPerrorMessage("unknown variable status\n");
15307  SCIPABORT();
15308  return 0; /*lint !e527*/
15309  }
15310 }
15311 
15312 /** gets the number of active conflicts containing this variable in given direction
15313  * in the current run
15314  */
15316  SCIP_VAR* var, /**< problem variable */
15317  SCIP_STAT* stat, /**< problem statistics */
15318  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15319  )
15320 {
15321  assert(var != NULL);
15322  assert(stat != NULL);
15323  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15324 
15325  switch( SCIPvarGetStatus(var) )
15326  {
15328  if( var->data.original.transvar == NULL )
15329  return 0;
15330  else
15332 
15333  case SCIP_VARSTATUS_LOOSE:
15334  case SCIP_VARSTATUS_COLUMN:
15335  return SCIPhistoryGetNActiveConflicts(var->historycrun, dir);
15336 
15337  case SCIP_VARSTATUS_FIXED:
15338  return 0;
15339 
15341  if( var->data.aggregate.scalar > 0.0 )
15342  return SCIPvarGetNActiveConflictsCurrentRun(var->data.aggregate.var, stat, dir);
15343  else
15345 
15347  return 0;
15348 
15351 
15352  default:
15353  SCIPerrorMessage("unknown variable status\n");
15354  SCIPABORT();
15355  return 0; /*lint !e527*/
15356  }
15357 }
15358 
15359 /** gets the average conflict length in given direction due to branching on the variable */
15361  SCIP_VAR* var, /**< problem variable */
15362  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15363  )
15364 {
15365  assert(var != NULL);
15366  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15367 
15368  switch( SCIPvarGetStatus(var) )
15369  {
15371  if( var->data.original.transvar == NULL )
15372  return 0.0;
15373  else
15375 
15376  case SCIP_VARSTATUS_LOOSE:
15377  case SCIP_VARSTATUS_COLUMN:
15378  return SCIPhistoryGetAvgConflictlength(var->history, dir);
15379  case SCIP_VARSTATUS_FIXED:
15380  return 0.0;
15381 
15383  if( var->data.aggregate.scalar > 0.0 )
15384  return SCIPvarGetAvgConflictlength(var->data.aggregate.var, dir);
15385  else
15387 
15389  return 0.0;
15390 
15393 
15394  default:
15395  SCIPerrorMessage("unknown variable status\n");
15396  SCIPABORT();
15397  return 0.0; /*lint !e527*/
15398  }
15399 }
15400 
15401 /** gets the average conflict length in given direction due to branching on the variable
15402  * in the current run
15403  */
15405  SCIP_VAR* var, /**< problem variable */
15406  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15407  )
15408 {
15409  assert(var != NULL);
15410  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15411 
15412  switch( SCIPvarGetStatus(var) )
15413  {
15415  if( var->data.original.transvar == NULL )
15416  return 0.0;
15417  else
15419 
15420  case SCIP_VARSTATUS_LOOSE:
15421  case SCIP_VARSTATUS_COLUMN:
15422  return SCIPhistoryGetAvgConflictlength(var->historycrun, dir);
15423 
15424  case SCIP_VARSTATUS_FIXED:
15425  return 0.0;
15426 
15428  if( var->data.aggregate.scalar > 0.0 )
15430  else
15432 
15434  return 0.0;
15435 
15438 
15439  default:
15440  SCIPerrorMessage("unknown variable status\n");
15441  SCIPABORT();
15442  return 0.0; /*lint !e527*/
15443  }
15444 }
15445 
15446 /** increases the number of branchings counter of the variable */
15448  SCIP_VAR* var, /**< problem variable */
15449  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15450  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15451  SCIP_STAT* stat, /**< problem statistics */
15452  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
15453  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15454  int depth /**< depth at which the bound change took place */
15455  )
15456 {
15457  assert(var != NULL);
15458  assert(stat != NULL);
15459  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15460 
15461  /* check if history statistics should be collected for a variable */
15462  if( !stat->collectvarhistory )
15463  return SCIP_OKAY;
15464 
15465  switch( SCIPvarGetStatus(var) )
15466  {
15468  if( var->data.original.transvar == NULL )
15469  {
15470  SCIPerrorMessage("cannot update branching counter of original untransformed variable\n");
15471  return SCIP_INVALIDDATA;
15472  }
15473  SCIP_CALL( SCIPvarIncNBranchings(var->data.original.transvar, blkmem, set, stat, dir, value, depth) );
15474  return SCIP_OKAY;
15475 
15476  case SCIP_VARSTATUS_LOOSE:
15477  case SCIP_VARSTATUS_COLUMN:
15478  {
15479  SCIPhistoryIncNBranchings(var->history, dir, depth);
15480  SCIPhistoryIncNBranchings(var->historycrun, dir, depth);
15481  SCIPhistoryIncNBranchings(stat->glbhistory, dir, depth);
15482  SCIPhistoryIncNBranchings(stat->glbhistorycrun, dir, depth);
15483 
15484  if( useValuehistory(var, value, set) )
15485  {
15486  SCIP_HISTORY* history;
15487 
15488  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15489  assert(history != NULL);
15490 
15491  SCIPhistoryIncNBranchings(history, dir, depth);
15492  }
15493 
15494  return SCIP_OKAY;
15495  }
15496  case SCIP_VARSTATUS_FIXED:
15497  SCIPerrorMessage("cannot update branching counter of a fixed variable\n");
15498  return SCIP_INVALIDDATA;
15499 
15501  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15502 
15503  if( var->data.aggregate.scalar > 0.0 )
15504  {
15505  SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, dir, value, depth) );
15506  }
15507  else
15508  {
15509  assert(var->data.aggregate.scalar < 0.0);
15510  SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
15511  }
15512  return SCIP_OKAY;
15513 
15515  SCIPerrorMessage("cannot update branching counter of a multi-aggregated variable\n");
15516  return SCIP_INVALIDDATA;
15517 
15519  value = 1.0 - value;
15520 
15521  SCIP_CALL( SCIPvarIncNBranchings(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
15522  return SCIP_OKAY;
15523 
15524  default:
15525  SCIPerrorMessage("unknown variable status\n");
15526  return SCIP_INVALIDDATA;
15527  }
15528 }
15529 
15530 /** increases the inference sum of the variable by the given weight */
15532  SCIP_VAR* var, /**< problem variable */
15533  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15534  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15535  SCIP_STAT* stat, /**< problem statistics */
15536  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
15537  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15538  SCIP_Real weight /**< weight of this update in inference score */
15539  )
15540 {
15541  assert(var != NULL);
15542  assert(stat != NULL);
15543  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15544 
15545  /* check if history statistics should be collected for a variable */
15546  if( !stat->collectvarhistory )
15547  return SCIP_OKAY;
15548 
15549  switch( SCIPvarGetStatus(var) )
15550  {
15552  if( var->data.original.transvar == NULL )
15553  {
15554  SCIPerrorMessage("cannot update inference counter of original untransformed variable\n");
15555  return SCIP_INVALIDDATA;
15556  }
15557  SCIP_CALL( SCIPvarIncInferenceSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
15558  return SCIP_OKAY;
15559 
15560  case SCIP_VARSTATUS_LOOSE:
15561  case SCIP_VARSTATUS_COLUMN:
15562  {
15563  SCIPhistoryIncInferenceSum(var->history, dir, weight);
15564  SCIPhistoryIncInferenceSum(var->historycrun, dir, weight);
15565  SCIPhistoryIncInferenceSum(stat->glbhistory, dir, weight);
15566  SCIPhistoryIncInferenceSum(stat->glbhistorycrun, dir, weight);
15567 
15568  if( useValuehistory(var, value, set) )
15569  {
15570  SCIP_HISTORY* history;
15571 
15572  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15573  assert(history != NULL);
15574 
15575  SCIPhistoryIncInferenceSum(history, dir, weight);
15576  }
15577 
15578  return SCIP_OKAY;
15579  }
15580  case SCIP_VARSTATUS_FIXED:
15581  SCIPerrorMessage("cannot update inference counter of a fixed variable\n");
15582  return SCIP_INVALIDDATA;
15583 
15585  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15586 
15587  if( var->data.aggregate.scalar > 0.0 )
15588  {
15589  SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
15590  }
15591  else
15592  {
15593  assert(var->data.aggregate.scalar < 0.0);
15594  SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15595  }
15596  return SCIP_OKAY;
15597 
15599  SCIPerrorMessage("cannot update inference counter of a multi-aggregated variable\n");
15600  return SCIP_INVALIDDATA;
15601 
15603  value = 1.0 - value;
15604 
15605  SCIP_CALL( SCIPvarIncInferenceSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15606  return SCIP_OKAY;
15607 
15608  default:
15609  SCIPerrorMessage("unknown variable status\n");
15610  return SCIP_INVALIDDATA;
15611  }
15612 }
15613 
15614 /** increases the cutoff sum of the variable by the given weight */
15616  SCIP_VAR* var, /**< problem variable */
15617  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15618  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15619  SCIP_STAT* stat, /**< problem statistics */
15620  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
15621  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15622  SCIP_Real weight /**< weight of this update in cutoff score */
15623  )
15624 {
15625  assert(var != NULL);
15626  assert(stat != NULL);
15627  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15628 
15629  /* check if history statistics should be collected for a variable */
15630  if( !stat->collectvarhistory )
15631  return SCIP_OKAY;
15632 
15633  switch( SCIPvarGetStatus(var) )
15634  {
15636  if( var->data.original.transvar == NULL )
15637  {
15638  SCIPerrorMessage("cannot update cutoff sum of original untransformed variable\n");
15639  return SCIP_INVALIDDATA;
15640  }
15641  SCIP_CALL( SCIPvarIncCutoffSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
15642  return SCIP_OKAY;
15643 
15644  case SCIP_VARSTATUS_LOOSE:
15645  case SCIP_VARSTATUS_COLUMN:
15646  {
15647  SCIPhistoryIncCutoffSum(var->history, dir, weight);
15648  SCIPhistoryIncCutoffSum(var->historycrun, dir, weight);
15649  SCIPhistoryIncCutoffSum(stat->glbhistory, dir, weight);
15650  SCIPhistoryIncCutoffSum(stat->glbhistorycrun, dir, weight);
15651 
15652  if( useValuehistory(var, value, set) )
15653  {
15654  SCIP_HISTORY* history;
15655 
15656  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15657  assert(history != NULL);
15658 
15659  SCIPhistoryIncCutoffSum(history, dir, weight);
15660  }
15661 
15662  return SCIP_OKAY;
15663  }
15664  case SCIP_VARSTATUS_FIXED:
15665  SCIPerrorMessage("cannot update cutoff sum of a fixed variable\n");
15666  return SCIP_INVALIDDATA;
15667 
15669  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15670 
15671  if( var->data.aggregate.scalar > 0.0 )
15672  {
15673  SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
15674  }
15675  else
15676  {
15677  assert(var->data.aggregate.scalar < 0.0);
15678  SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15679  }
15680  return SCIP_OKAY;
15681 
15683  SCIPerrorMessage("cannot update cutoff sum of a multi-aggregated variable\n");
15684  return SCIP_INVALIDDATA;
15685 
15687  value = 1.0 - value;
15688 
15689  SCIP_CALL( SCIPvarIncCutoffSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15690  return SCIP_OKAY;
15691 
15692  default:
15693  SCIPerrorMessage("unknown variable status\n");
15694  return SCIP_INVALIDDATA;
15695  }
15696 }
15697 
15698 /** returns the number of times, a bound of the variable was changed in given direction due to branching */
15700  SCIP_VAR* var, /**< problem variable */
15701  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15702  )
15703 {
15704  assert(var != NULL);
15705  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15706 
15707  switch( SCIPvarGetStatus(var) )
15708  {
15710  if( var->data.original.transvar == NULL )
15711  return 0;
15712  else
15713  return SCIPvarGetNBranchings(var->data.original.transvar, dir);
15714 
15715  case SCIP_VARSTATUS_LOOSE:
15716  case SCIP_VARSTATUS_COLUMN:
15717  return SCIPhistoryGetNBranchings(var->history, dir);
15718 
15719  case SCIP_VARSTATUS_FIXED:
15720  return 0;
15721 
15723  if( var->data.aggregate.scalar > 0.0 )
15724  return SCIPvarGetNBranchings(var->data.aggregate.var, dir);
15725  else
15727 
15729  return 0;
15730 
15733 
15734  default:
15735  SCIPerrorMessage("unknown variable status\n");
15736  SCIPABORT();
15737  return 0; /*lint !e527*/
15738  }
15739 }
15740 
15741 /** returns the number of times, a bound of the variable was changed in given direction due to branching
15742  * in the current run
15743  */
15745  SCIP_VAR* var, /**< problem variable */
15746  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15747  )
15748 {
15749  assert(var != NULL);
15750  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15751 
15752  switch( SCIPvarGetStatus(var) )
15753  {
15755  if( var->data.original.transvar == NULL )
15756  return 0;
15757  else
15759 
15760  case SCIP_VARSTATUS_LOOSE:
15761  case SCIP_VARSTATUS_COLUMN:
15762  return SCIPhistoryGetNBranchings(var->historycrun, dir);
15763 
15764  case SCIP_VARSTATUS_FIXED:
15765  return 0;
15766 
15768  if( var->data.aggregate.scalar > 0.0 )
15770  else
15772 
15774  return 0;
15775 
15778 
15779  default:
15780  SCIPerrorMessage("unknown variable status\n");
15781  SCIPABORT();
15782  return 0; /*lint !e527*/
15783  }
15784 }
15785 
15786 /** returns the average depth of bound changes in given direction due to branching on the variable */
15788  SCIP_VAR* var, /**< problem variable */
15789  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15790  )
15791 {
15792  assert(var != NULL);
15793  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15794 
15795  switch( SCIPvarGetStatus(var) )
15796  {
15798  if( var->data.original.transvar == NULL )
15799  return 0.0;
15800  else
15801  return SCIPvarGetAvgBranchdepth(var->data.original.transvar, dir);
15802 
15803  case SCIP_VARSTATUS_LOOSE:
15804  case SCIP_VARSTATUS_COLUMN:
15805  return SCIPhistoryGetAvgBranchdepth(var->history, dir);
15806 
15807  case SCIP_VARSTATUS_FIXED:
15808  return 0.0;
15809 
15811  if( var->data.aggregate.scalar > 0.0 )
15812  return SCIPvarGetAvgBranchdepth(var->data.aggregate.var, dir);
15813  else
15815 
15817  return 0.0;
15818 
15821 
15822  default:
15823  SCIPerrorMessage("unknown variable status\n");
15824  SCIPABORT();
15825  return 0.0; /*lint !e527*/
15826  }
15827 }
15828 
15829 /** returns the average depth of bound changes in given direction due to branching on the variable
15830  * in the current run
15831  */
15833  SCIP_VAR* var, /**< problem variable */
15834  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15835  )
15836 {
15837  assert(var != NULL);
15838  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15839 
15840  switch( SCIPvarGetStatus(var) )
15841  {
15843  if( var->data.original.transvar == NULL )
15844  return 0.0;
15845  else
15847 
15848  case SCIP_VARSTATUS_LOOSE:
15849  case SCIP_VARSTATUS_COLUMN:
15850  return SCIPhistoryGetAvgBranchdepth(var->historycrun, dir);
15851 
15852  case SCIP_VARSTATUS_FIXED:
15853  return 0.0;
15854 
15856  if( var->data.aggregate.scalar > 0.0 )
15858  else
15861 
15863  return 0.0;
15864 
15867  dir == SCIP_BRANCHDIR_DOWNWARDS ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
15868 
15869  default:
15870  SCIPerrorMessage("unknown variable status\n");
15871  SCIPABORT();
15872  return 0.0; /*lint !e527*/
15873  }
15874 }
15875 
15876 /** returns the variable's VSIDS score */
15878  SCIP_VAR* var, /**< problem variable */
15879  SCIP_STAT* stat, /**< problem statistics */
15880  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15881  )
15882 {
15883  assert(var != NULL);
15884  assert(stat != NULL);
15885  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15886 
15888  return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
15889 
15890  switch( SCIPvarGetStatus(var) )
15891  {
15893  if( var->data.original.transvar == NULL )
15894  return 0.0;
15895  else
15896  return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
15897 
15898  case SCIP_VARSTATUS_LOOSE:
15899  case SCIP_VARSTATUS_COLUMN:
15900  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE); /* column case already handled in if condition above */
15901  return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
15902 
15903  case SCIP_VARSTATUS_FIXED:
15904  return 0.0;
15905 
15907  if( var->data.aggregate.scalar > 0.0 )
15908  return SCIPvarGetVSIDS(var->data.aggregate.var, stat, dir);
15909  else
15910  /* coverity[overrun-local] */
15911  return SCIPvarGetVSIDS(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
15912 
15914  return 0.0;
15915 
15917  /* coverity[overrun-local] */
15918  return SCIPvarGetVSIDS(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15919 
15920  default:
15921  SCIPerrorMessage("unknown variable status\n");
15922  SCIPABORT();
15923  return 0.0; /*lint !e527*/
15924  }
15925 }
15926 
15927 /** returns the variable's VSIDS score only using conflicts of the current run */
15929  SCIP_VAR* var, /**< problem variable */
15930  SCIP_STAT* stat, /**< problem statistics */
15931  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15932  )
15933 {
15934  assert(var != NULL);
15935  assert(stat != NULL);
15936  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15937 
15938  if( dir != SCIP_BRANCHDIR_DOWNWARDS && dir != SCIP_BRANCHDIR_UPWARDS )
15939  {
15940  SCIPerrorMessage("invalid branching direction %d when asking for VSIDS value\n", dir);
15941  return SCIP_INVALID;
15942  }
15943 
15944  switch( SCIPvarGetStatus(var) )
15945  {
15947  if( var->data.original.transvar == NULL )
15948  return 0.0;
15949  else
15950  return SCIPvarGetVSIDSCurrentRun(var->data.original.transvar, stat, dir);
15951 
15952  case SCIP_VARSTATUS_LOOSE:
15953  case SCIP_VARSTATUS_COLUMN:
15954  return SCIPhistoryGetVSIDS(var->historycrun, dir)/stat->vsidsweight;
15955 
15956  case SCIP_VARSTATUS_FIXED:
15957  return 0.0;
15958 
15960  if( var->data.aggregate.scalar > 0.0 )
15961  return SCIPvarGetVSIDSCurrentRun(var->data.aggregate.var, stat, dir);
15962  else
15964 
15966  return 0.0;
15967 
15970 
15971  default:
15972  SCIPerrorMessage("unknown variable status\n");
15973  SCIPABORT();
15974  return 0.0; /*lint !e527*/
15975  }
15976 }
15977 
15978 /** returns the number of inferences branching on this variable in given direction triggered */
15980  SCIP_VAR* var, /**< problem variable */
15981  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15982  )
15983 {
15984  assert(var != NULL);
15985  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15986 
15987  switch( SCIPvarGetStatus(var) )
15988  {
15990  if( var->data.original.transvar == NULL )
15991  return 0.0;
15992  else
15993  return SCIPvarGetInferenceSum(var->data.original.transvar, dir);
15994 
15995  case SCIP_VARSTATUS_LOOSE:
15996  case SCIP_VARSTATUS_COLUMN:
15997  return SCIPhistoryGetInferenceSum(var->history, dir);
15998 
15999  case SCIP_VARSTATUS_FIXED:
16000  return 0.0;
16001 
16003  if( var->data.aggregate.scalar > 0.0 )
16004  return SCIPvarGetInferenceSum(var->data.aggregate.var, dir);
16005  else
16007 
16009  return 0.0;
16010 
16013 
16014  default:
16015  SCIPerrorMessage("unknown variable status\n");
16016  SCIPABORT();
16017  return 0.0; /*lint !e527*/
16018  }
16019 }
16020 
16021 /** returns the number of inferences branching on this variable in given direction triggered
16022  * in the current run
16023  */
16025  SCIP_VAR* var, /**< problem variable */
16026  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16027  )
16028 {
16029  assert(var != NULL);
16030  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16031 
16032  switch( SCIPvarGetStatus(var) )
16033  {
16035  if( var->data.original.transvar == NULL )
16036  return 0.0;
16037  else
16039 
16040  case SCIP_VARSTATUS_LOOSE:
16041  case SCIP_VARSTATUS_COLUMN:
16042  return SCIPhistoryGetInferenceSum(var->historycrun, dir);
16043 
16044  case SCIP_VARSTATUS_FIXED:
16045  return 0.0;
16046 
16048  if( var->data.aggregate.scalar > 0.0 )
16050  else
16052 
16054  return 0.0;
16055 
16058 
16059  default:
16060  SCIPerrorMessage("unknown variable status\n");
16061  SCIPABORT();
16062  return 0.0; /*lint !e527*/
16063  }
16064 }
16065 
16066 /** returns the average number of inferences found after branching on the variable in given direction */
16068  SCIP_VAR* var, /**< problem variable */
16069  SCIP_STAT* stat, /**< problem statistics */
16070  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16071  )
16072 {
16073  assert(var != NULL);
16074  assert(stat != NULL);
16075  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16076 
16077  switch( SCIPvarGetStatus(var) )
16078  {
16080  if( var->data.original.transvar == NULL )
16081  return SCIPhistoryGetAvgInferences(stat->glbhistory, dir);
16082  else
16083  return SCIPvarGetAvgInferences(var->data.original.transvar, stat, dir);
16084 
16085  case SCIP_VARSTATUS_LOOSE:
16086  case SCIP_VARSTATUS_COLUMN:
16087  if( SCIPhistoryGetNBranchings(var->history, dir) > 0 )
16088  return SCIPhistoryGetAvgInferences(var->history, dir);
16089  else
16090  {
16091  int nimpls;
16092  int ncliques;
16093 
16094  nimpls = SCIPvarGetNImpls(var, dir == SCIP_BRANCHDIR_UPWARDS);
16095  ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
16096  return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistory, dir); /*lint !e790*/
16097  }
16098 
16099  case SCIP_VARSTATUS_FIXED:
16100  return 0.0;
16101 
16103  if( var->data.aggregate.scalar > 0.0 )
16104  return SCIPvarGetAvgInferences(var->data.aggregate.var, stat, dir);
16105  else
16107 
16109  return 0.0;
16110 
16112  return SCIPvarGetAvgInferences(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
16113 
16114  default:
16115  SCIPerrorMessage("unknown variable status\n");
16116  SCIPABORT();
16117  return 0.0; /*lint !e527*/
16118  }
16119 }
16120 
16121 /** returns the average number of inferences found after branching on the variable in given direction
16122  * in the current run
16123  */
16125  SCIP_VAR* var, /**< problem variable */
16126  SCIP_STAT* stat, /**< problem statistics */
16127  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16128  )
16129 {
16130  assert(var != NULL);
16131  assert(stat != NULL);
16132  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16133 
16134  switch( SCIPvarGetStatus(var) )
16135  {
16137  if( var->data.original.transvar == NULL )
16138  return SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir);
16139  else
16140  return SCIPvarGetAvgInferencesCurrentRun(var->data.original.transvar, stat, dir);
16141 
16142  case SCIP_VARSTATUS_LOOSE:
16143  case SCIP_VARSTATUS_COLUMN:
16144  if( SCIPhistoryGetNBranchings(var->historycrun, dir) > 0 )
16145  return SCIPhistoryGetAvgInferences(var->historycrun, dir);
16146  else
16147  {
16148  int nimpls;
16149  int ncliques;
16150 
16151  nimpls = SCIPvarGetNImpls(var, dir == SCIP_BRANCHDIR_UPWARDS);
16152  ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
16153  return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir); /*lint !e790*/
16154  }
16155 
16156  case SCIP_VARSTATUS_FIXED:
16157  return 0.0;
16158 
16160  if( var->data.aggregate.scalar > 0.0 )
16161  return SCIPvarGetAvgInferencesCurrentRun(var->data.aggregate.var, stat, dir);
16162  else
16164 
16166  return 0.0;
16167 
16170 
16171  default:
16172  SCIPerrorMessage("unknown variable status\n");
16173  SCIPABORT();
16174  return 0.0; /*lint !e527*/
16175  }
16176 }
16177 
16178 /** returns the number of cutoffs branching on this variable in given direction produced */
16180  SCIP_VAR* var, /**< problem variable */
16181  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16182  )
16183 {
16184  assert(var != NULL);
16185  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16186 
16187  switch( SCIPvarGetStatus(var) )
16188  {
16190  if( var->data.original.transvar == NULL )
16191  return 0;
16192  else
16193  return SCIPvarGetCutoffSum(var->data.original.transvar, dir);
16194 
16195  case SCIP_VARSTATUS_LOOSE:
16196  case SCIP_VARSTATUS_COLUMN:
16197  return SCIPhistoryGetCutoffSum(var->history, dir);
16198 
16199  case SCIP_VARSTATUS_FIXED:
16200  return 0;
16201 
16203  if( var->data.aggregate.scalar > 0.0 )
16204  return SCIPvarGetCutoffSum(var->data.aggregate.var, dir);
16205  else
16207 
16209  return 0;
16210 
16213 
16214  default:
16215  SCIPerrorMessage("unknown variable status\n");
16216  SCIPABORT();
16217  return 0; /*lint !e527*/
16218  }
16219 }
16220 
16221 /** returns the number of cutoffs branching on this variable in given direction produced in the current run */
16223  SCIP_VAR* var, /**< problem variable */
16224  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16225  )
16226 {
16227  assert(var != NULL);
16228  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16229 
16230  switch( SCIPvarGetStatus(var) )
16231  {
16233  if( var->data.original.transvar == NULL )
16234  return 0;
16235  else
16237 
16238  case SCIP_VARSTATUS_LOOSE:
16239  case SCIP_VARSTATUS_COLUMN:
16240  return SCIPhistoryGetCutoffSum(var->historycrun, dir);
16241 
16242  case SCIP_VARSTATUS_FIXED:
16243  return 0;
16244 
16246  if( var->data.aggregate.scalar > 0.0 )
16247  return SCIPvarGetCutoffSumCurrentRun(var->data.aggregate.var, dir);
16248  else
16250 
16252  return 0;
16253 
16256 
16257  default:
16258  SCIPerrorMessage("unknown variable status\n");
16259  SCIPABORT();
16260  return 0; /*lint !e527*/
16261  }
16262 }
16263 
16264 /** returns the average number of cutoffs found after branching on the variable in given direction */
16266  SCIP_VAR* var, /**< problem variable */
16267  SCIP_STAT* stat, /**< problem statistics */
16268  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16269  )
16270 {
16271  assert(var != NULL);
16272  assert(stat != NULL);
16273  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16274 
16275  switch( SCIPvarGetStatus(var) )
16276  {
16278  if( var->data.original.transvar == NULL )
16279  return SCIPhistoryGetAvgCutoffs(stat->glbhistory, dir);
16280  else
16281  return SCIPvarGetAvgCutoffs(var->data.original.transvar, stat, dir);
16282 
16283  case SCIP_VARSTATUS_LOOSE:
16284  case SCIP_VARSTATUS_COLUMN:
16285  return SCIPhistoryGetNBranchings(var->history, dir) > 0
16286  ? SCIPhistoryGetAvgCutoffs(var->history, dir)
16287  : SCIPhistoryGetAvgCutoffs(stat->glbhistory, dir);
16288 
16289  case SCIP_VARSTATUS_FIXED:
16290  return 0.0;
16291 
16293  if( var->data.aggregate.scalar > 0.0 )
16294  return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, dir);
16295  else
16296  return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
16297 
16299  return 0.0;
16300 
16302  return SCIPvarGetAvgCutoffs(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
16303 
16304  default:
16305  SCIPerrorMessage("unknown variable status\n");
16306  SCIPABORT();
16307  return 0.0; /*lint !e527*/
16308  }
16309 }
16310 
16311 /** returns the average number of cutoffs found after branching on the variable in given direction in the current run */
16313  SCIP_VAR* var, /**< problem variable */
16314  SCIP_STAT* stat, /**< problem statistics */
16315  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16316  )
16317 {
16318  assert(var != NULL);
16319  assert(stat != NULL);
16320  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16321 
16322  switch( SCIPvarGetStatus(var) )
16323  {
16325  if( var->data.original.transvar == NULL )
16326  return SCIPhistoryGetAvgCutoffs(stat->glbhistorycrun, dir);
16327  else
16328  return SCIPvarGetAvgCutoffsCurrentRun(var->data.original.transvar, stat, dir);
16329 
16330  case SCIP_VARSTATUS_LOOSE:
16331  case SCIP_VARSTATUS_COLUMN:
16332  return SCIPhistoryGetNBranchings(var->historycrun, dir) > 0
16335 
16336  case SCIP_VARSTATUS_FIXED:
16337  return 0.0;
16338 
16340  if( var->data.aggregate.scalar > 0.0 )
16341  return SCIPvarGetAvgCutoffsCurrentRun(var->data.aggregate.var, stat, dir);
16342  else
16344 
16346  return 0.0;
16347 
16350 
16351  default:
16352  SCIPerrorMessage("unknown variable status\n");
16353  SCIPABORT();
16354  return 0.0; /*lint !e527*/
16355  }
16356 }
16357 
16358 /** returns the variable's average GMI efficacy score value generated from simplex tableau rows of this variable */
16360  SCIP_VAR* var, /**< problem variable */
16361  SCIP_STAT* stat /**< problem statistics */
16362 )
16363 {
16364  assert(var != NULL);
16365  assert(stat != NULL);
16366 
16367  switch( SCIPvarGetStatus(var) )
16368  {
16370  if( var->data.original.transvar == NULL )
16371  return 0.0;
16372  else
16373  return SCIPvarGetAvgGMIScore(var->data.original.transvar, stat);
16374 
16375  case SCIP_VARSTATUS_LOOSE:
16376  case SCIP_VARSTATUS_COLUMN:
16377  return SCIPhistoryGetAvgGMIeff(var->history);
16378 
16379  case SCIP_VARSTATUS_FIXED:
16380  return 0.0;
16381 
16383  return SCIPvarGetAvgGMIScore(var->data.aggregate.var, stat);
16384 
16386  return 0.0;
16387 
16389  return SCIPvarGetAvgGMIScore(var->negatedvar, stat);
16390 
16391  default:
16392  SCIPerrorMessage("unknown variable status\n");
16393  SCIPABORT();
16394  return 0.0; /*lint !e527*/
16395  }
16396 }
16397 
16398 /** increase the variable's GMI efficacy scores generated from simplex tableau rows of this variable */
16400  SCIP_VAR* var, /**< problem variable */
16401  SCIP_STAT* stat, /**< problem statistics */
16402  SCIP_Real gmieff /**< efficacy of last GMI cut produced when variable was frac and basic */
16403 )
16404 {
16405  assert(var != NULL);
16406  assert(stat != NULL);
16407  assert(gmieff >= 0);
16408 
16409  switch( SCIPvarGetStatus(var) )
16410  {
16412  if( var->data.original.transvar != NULL )
16413  SCIP_CALL( SCIPvarIncGMIeffSum(var->data.original.transvar, stat, gmieff) );
16414  return SCIP_OKAY;
16415 
16416  case SCIP_VARSTATUS_LOOSE:
16417  case SCIP_VARSTATUS_COLUMN:
16418  SCIPhistoryIncGMIeffSum(var->history, gmieff);
16419  return SCIP_OKAY;
16420 
16421  case SCIP_VARSTATUS_FIXED:
16422  return SCIP_INVALIDDATA;
16423 
16425  SCIP_CALL( SCIPvarIncGMIeffSum(var->data.aggregate.var, stat, gmieff) );
16426  return SCIP_OKAY;
16427 
16429  SCIP_CALL( SCIPvarIncGMIeffSum(var->negatedvar, stat, gmieff) );
16430  return SCIP_OKAY;
16431 
16433  return SCIP_INVALIDDATA;
16434 
16435  default:
16436  SCIPerrorMessage("unknown variable status\n");
16437  SCIPABORT();
16438  return SCIP_INVALIDDATA; /*lint !e527*/
16439  }
16440 }
16441 
16442 /** returns the variable's last GMI efficacy score value generated from a simplex tableau row of this variable */
16444  SCIP_VAR* var, /**< problem variable */
16445  SCIP_STAT* stat /**< problem statistics */
16446 )
16447 {
16448  assert(var != NULL);
16449  assert(stat != NULL);
16450 
16451  switch( SCIPvarGetStatus(var) )
16452  {
16454  if( var->data.original.transvar != NULL )
16455  return SCIPvarGetLastGMIScore(var->data.original.transvar, stat);
16456  return 0.0;
16457 
16458  case SCIP_VARSTATUS_LOOSE:
16459  case SCIP_VARSTATUS_COLUMN:
16460  return SCIPhistoryGetLastGMIeff(var->history);
16461 
16462  case SCIP_VARSTATUS_FIXED:
16463  return 0.0;
16464 
16466  return SCIPvarGetLastGMIScore(var->data.aggregate.var, stat);
16467 
16469  return 0.0;
16470 
16472  return SCIPvarGetLastGMIScore(var->negatedvar, stat);
16473 
16474  default:
16475  SCIPerrorMessage("unknown variable status\n");
16476  SCIPABORT();
16477  return 0.0; /*lint !e527*/
16478  }
16479 }
16480 
16481 
16482 /** sets the variable's last GMI efficacy score value generated from a simplex tableau row of this variable */
16484  SCIP_VAR* var, /**< problem variable */
16485  SCIP_STAT* stat, /**< problem statistics */
16486  SCIP_Real gmieff /**< efficacy of last GMI cut produced when variable was frac and basic */
16487 )
16488 {
16489  assert(var != NULL);
16490  assert(stat != NULL);
16491  assert(gmieff >= 0);
16492 
16493  switch( SCIPvarGetStatus(var) )
16494  {
16496  if( var->data.original.transvar != NULL )
16497  SCIP_CALL( SCIPvarSetLastGMIScore(var->data.original.transvar, stat, gmieff) );
16498  return SCIP_OKAY;
16499 
16500  case SCIP_VARSTATUS_LOOSE:
16501  case SCIP_VARSTATUS_COLUMN:
16502  SCIPhistorySetLastGMIeff(var->history, gmieff);
16503  return SCIP_OKAY;
16504 
16505  case SCIP_VARSTATUS_FIXED:
16506  return SCIP_INVALIDDATA;
16507 
16509  SCIP_CALL( SCIPvarSetLastGMIScore(var->data.aggregate.var, stat, gmieff) );
16510  return SCIP_OKAY;
16511 
16513  SCIP_CALL( SCIPvarSetLastGMIScore(var->negatedvar, stat, gmieff) );
16514  return SCIP_OKAY;
16515 
16517  return SCIP_INVALIDDATA;
16518 
16519  default:
16520  SCIPerrorMessage("unknown variable status\n");
16521  SCIPABORT();
16522  return SCIP_INVALIDDATA; /*lint !e527*/
16523  }
16524 }
16525 
16526 
16527 
16528 /*
16529  * information methods for bound changes
16530  */
16531 
16532 /** creates an artificial bound change information object with depth = INT_MAX and pos = -1 */
16534  SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
16535  BMS_BLKMEM* blkmem, /**< block memory */
16536  SCIP_VAR* var, /**< active variable that changed the bounds */
16537  SCIP_BOUNDTYPE boundtype, /**< type of bound for var: lower or upper bound */
16538  SCIP_Real oldbound, /**< old value for bound */
16539  SCIP_Real newbound /**< new value for bound */
16540  )
16541 {
16542  assert(bdchginfo != NULL);
16543 
16544  SCIP_ALLOC( BMSallocBlockMemory(blkmem, bdchginfo) );
16545  (*bdchginfo)->oldbound = oldbound;
16546  (*bdchginfo)->newbound = newbound;
16547  (*bdchginfo)->var = var;
16548  (*bdchginfo)->inferencedata.var = var;
16549  (*bdchginfo)->inferencedata.reason.prop = NULL;
16550  (*bdchginfo)->inferencedata.info = 0;
16551  (*bdchginfo)->bdchgidx.depth = INT_MAX;
16552  (*bdchginfo)->bdchgidx.pos = -1;
16553  (*bdchginfo)->pos = 0;
16554  (*bdchginfo)->boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
16555  (*bdchginfo)->boundtype = boundtype; /*lint !e641*/
16556  (*bdchginfo)->inferboundtype = boundtype; /*lint !e641*/
16557  (*bdchginfo)->redundant = FALSE;
16558 
16559  return SCIP_OKAY;
16560 }
16561 
16562 /** frees a bound change information object */
16563 void SCIPbdchginfoFree(
16564  SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
16565  BMS_BLKMEM* blkmem /**< block memory */
16566  )
16567 {
16568  assert(bdchginfo != NULL);
16569 
16570  BMSfreeBlockMemory(blkmem, bdchginfo);
16571 }
16572 
16573 /** returns the bound change information for the last lower bound change on given active problem variable before or
16574  * after the bound change with the given index was applied;
16575  * returns NULL, if no change to the lower bound was applied up to this point of time
16576  */
16578  SCIP_VAR* var, /**< active problem variable */
16579  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16580  SCIP_Bool after /**< should the bound change with given index be included? */
16581  )
16582 {
16583  int i;
16584 
16585  assert(var != NULL);
16586  assert(SCIPvarIsActive(var));
16587 
16588  /* search the correct bound change information for the given bound change index */
16589  if( after )
16590  {
16591  for( i = var->nlbchginfos-1; i >= 0; --i )
16592  {
16593  assert(var->lbchginfos[i].var == var);
16595  assert(var->lbchginfos[i].pos == i);
16596 
16597  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16598  if( var->lbchginfos[i].redundant )
16599  return NULL;
16600  assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
16601 
16602  /* if we reached the bound change index, return the current bound change info */
16603  if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->lbchginfos[i].bdchgidx) )
16604  return &var->lbchginfos[i];
16605  }
16606  }
16607  else
16608  {
16609  for( i = var->nlbchginfos-1; i >= 0; --i )
16610  {
16611  assert(var->lbchginfos[i].var == var);
16613  assert(var->lbchginfos[i].pos == i);
16614 
16615  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16616  if( var->lbchginfos[i].redundant )
16617  return NULL;
16618  assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
16619 
16620  /* if we reached the bound change index, return the current bound change info */
16621  if( SCIPbdchgidxIsEarlier(&var->lbchginfos[i].bdchgidx, bdchgidx) )
16622  return &var->lbchginfos[i];
16623  }
16624  }
16625 
16626  return NULL;
16627 }
16628 
16629 /** returns the bound change information for the last upper bound change on given active problem variable before or
16630  * after the bound change with the given index was applied;
16631  * returns NULL, if no change to the upper bound was applied up to this point of time
16632  */
16634  SCIP_VAR* var, /**< active problem variable */
16635  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16636  SCIP_Bool after /**< should the bound change with given index be included? */
16637  )
16638 {
16639  int i;
16640 
16641  assert(var != NULL);
16642  assert(SCIPvarIsActive(var));
16643 
16644  /* search the correct bound change information for the given bound change index */
16645  if( after )
16646  {
16647  for( i = var->nubchginfos-1; i >= 0; --i )
16648  {
16649  assert(var->ubchginfos[i].var == var);
16651  assert(var->ubchginfos[i].pos == i);
16652 
16653  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16654  if( var->ubchginfos[i].redundant )
16655  return NULL;
16656  assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
16657 
16658  /* if we reached the bound change index, return the current bound change info */
16659  if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->ubchginfos[i].bdchgidx) )
16660  return &var->ubchginfos[i];
16661  }
16662  }
16663  else
16664  {
16665  for( i = var->nubchginfos-1; i >= 0; --i )
16666  {
16667  assert(var->ubchginfos[i].var == var);
16669  assert(var->ubchginfos[i].pos == i);
16670 
16671  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16672  if( var->ubchginfos[i].redundant )
16673  return NULL;
16674  assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
16675 
16676  /* if we reached the bound change index, return the current bound change info */
16677  if( SCIPbdchgidxIsEarlier(&var->ubchginfos[i].bdchgidx, bdchgidx) )
16678  return &var->ubchginfos[i];
16679  }
16680  }
16681 
16682  return NULL;
16683 }
16684 
16685 /** returns the bound change information for the last lower or upper bound change on given active problem variable
16686  * before or after the bound change with the given index was applied;
16687  * returns NULL, if no change to the lower/upper bound was applied up to this point of time
16688  */
16690  SCIP_VAR* var, /**< active problem variable */
16691  SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
16692  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16693  SCIP_Bool after /**< should the bound change with given index be included? */
16694  )
16695 {
16696  if( boundtype == SCIP_BOUNDTYPE_LOWER )
16697  return SCIPvarGetLbchgInfo(var, bdchgidx, after);
16698  else
16699  {
16700  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16701  return SCIPvarGetUbchgInfo(var, bdchgidx, after);
16702  }
16703 }
16704 
16705 /** returns lower bound of variable directly before or after the bound change given by the bound change index
16706  * was applied
16707  *
16708  * @deprecated Please use SCIPgetVarLbAtIndex()
16709  */
16711  SCIP_VAR* var, /**< problem variable */
16712  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16713  SCIP_Bool after /**< should the bound change with given index be included? */
16714  )
16715 {
16716  SCIP_VARSTATUS varstatus;
16717  assert(var != NULL);
16718 
16719  varstatus = SCIPvarGetStatus(var);
16720 
16721  /* get bounds of attached variables */
16722  switch( varstatus )
16723  {
16725  assert(var->data.original.transvar != NULL);
16726  return SCIPvarGetLbAtIndex(var->data.original.transvar, bdchgidx, after);
16727 
16728  case SCIP_VARSTATUS_LOOSE:
16729  case SCIP_VARSTATUS_COLUMN:
16730  if( bdchgidx == NULL )
16731  return SCIPvarGetLbLocal(var);
16732  else
16733  {
16734  SCIP_BDCHGINFO* bdchginfo;
16735 
16736  bdchginfo = SCIPvarGetLbchgInfo(var, bdchgidx, after);
16737  if( bdchginfo != NULL )
16738  return SCIPbdchginfoGetNewbound(bdchginfo);
16739  else
16740  return var->glbdom.lb;
16741  }
16742  case SCIP_VARSTATUS_FIXED:
16743  return var->glbdom.lb;
16744 
16745  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
16746  assert(var->data.aggregate.var != NULL);
16747  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
16748  * corresponding infinity value instead of performing an arithmetical transformation (compare method
16749  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
16750  * (or is called by) a public interface method; instead, we only assert that values are finite
16751  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
16752  * positives and negatives if the parameter <numerics/infinity> is modified by the user
16753  */
16754  if( var->data.aggregate.scalar > 0.0 )
16755  {
16756  /* a > 0 -> get lower bound of y */
16757  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16758  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16759  return var->data.aggregate.scalar * SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after)
16760  + var->data.aggregate.constant;
16761  }
16762  else if( var->data.aggregate.scalar < 0.0 )
16763  {
16764  /* a < 0 -> get upper bound of y */
16765  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16766  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16767  return var->data.aggregate.scalar * SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after)
16768  + var->data.aggregate.constant;
16769  }
16770  else
16771  {
16772  SCIPerrorMessage("scalar is zero in aggregation\n");
16773  SCIPABORT();
16774  return SCIP_INVALID; /*lint !e527*/
16775  }
16776 
16778  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
16779  if ( var->data.multaggr.nvars == 1 )
16780  {
16781  assert(var->data.multaggr.vars != NULL);
16782  assert(var->data.multaggr.scalars != NULL);
16783  assert(var->data.multaggr.vars[0] != NULL);
16784 
16785  if( var->data.multaggr.scalars[0] > 0.0 )
16786  {
16787  /* a > 0 -> get lower bound of y */
16788  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16789  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16790  return var->data.multaggr.scalars[0] * SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16791  + var->data.multaggr.constant;
16792  }
16793  else if( var->data.multaggr.scalars[0] < 0.0 )
16794  {
16795  /* a < 0 -> get upper bound of y */
16796  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16797  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16798  return var->data.multaggr.scalars[0] * SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16799  + var->data.multaggr.constant;
16800  }
16801  else
16802  {
16803  SCIPerrorMessage("scalar is zero in multi-aggregation\n");
16804  SCIPABORT();
16805  return SCIP_INVALID; /*lint !e527*/
16806  }
16807  }
16808  SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
16809  SCIPABORT();
16810  return SCIP_INVALID; /*lint !e527*/
16811 
16812  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
16813  assert(var->negatedvar != NULL);
16815  assert(var->negatedvar->negatedvar == var);
16816  return var->data.negate.constant - SCIPvarGetUbAtIndex(var->negatedvar, bdchgidx, after);
16817  default:
16818  SCIPerrorMessage("unknown variable status\n");
16819  SCIPABORT();
16820  return SCIP_INVALID; /*lint !e527*/
16821  }
16822 }
16823 
16824 /** returns upper bound of variable directly before or after the bound change given by the bound change index
16825  * was applied
16826  *
16827  * @deprecated Please use SCIPgetVarUbAtIndex()
16828  */
16830  SCIP_VAR* var, /**< problem variable */
16831  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16832  SCIP_Bool after /**< should the bound change with given index be included? */
16833  )
16834 {
16835  SCIP_VARSTATUS varstatus;
16836  assert(var != NULL);
16837 
16838  varstatus = SCIPvarGetStatus(var);
16839 
16840  /* get bounds of attached variables */
16841  switch( varstatus )
16842  {
16844  assert(var->data.original.transvar != NULL);
16845  return SCIPvarGetUbAtIndex(var->data.original.transvar, bdchgidx, after);
16846 
16847  case SCIP_VARSTATUS_COLUMN:
16848  case SCIP_VARSTATUS_LOOSE:
16849  if( bdchgidx == NULL )
16850  return SCIPvarGetUbLocal(var);
16851  else
16852  {
16853  SCIP_BDCHGINFO* bdchginfo;
16854 
16855  bdchginfo = SCIPvarGetUbchgInfo(var, bdchgidx, after);
16856  if( bdchginfo != NULL )
16857  return SCIPbdchginfoGetNewbound(bdchginfo);
16858  else
16859  return var->glbdom.ub;
16860  }
16861 
16862  case SCIP_VARSTATUS_FIXED:
16863  return var->glbdom.ub;
16864 
16865  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
16866  assert(var->data.aggregate.var != NULL);
16867  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
16868  * corresponding infinity value instead of performing an arithmetical transformation (compare method
16869  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
16870  * (or is called by) a public interface method; instead, we only assert that values are finite
16871  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
16872  * positives and negatives if the parameter <numerics/infinity> is modified by the user
16873  */
16874  if( var->data.aggregate.scalar > 0.0 )
16875  {
16876  /* a > 0 -> get lower bound of y */
16877  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16878  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16879  return var->data.aggregate.scalar * SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after)
16880  + var->data.aggregate.constant;
16881  }
16882  else if( var->data.aggregate.scalar < 0.0 )
16883  {
16884  /* a < 0 -> get upper bound of y */
16885  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16886  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16887  return var->data.aggregate.scalar * SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after)
16888  + var->data.aggregate.constant;
16889  }
16890  else
16891  {
16892  SCIPerrorMessage("scalar is zero in aggregation\n");
16893  SCIPABORT();
16894  return SCIP_INVALID; /*lint !e527*/
16895  }
16896 
16898  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
16899  if ( var->data.multaggr.nvars == 1 )
16900  {
16901  assert(var->data.multaggr.vars != NULL);
16902  assert(var->data.multaggr.scalars != NULL);
16903  assert(var->data.multaggr.vars[0] != NULL);
16904 
16905  if( var->data.multaggr.scalars[0] > 0.0 )
16906  {
16907  /* a > 0 -> get lower bound of y */
16908  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16909  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16910  return var->data.multaggr.scalars[0] * SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16911  + var->data.multaggr.constant;
16912  }
16913  else if( var->data.multaggr.scalars[0] < 0.0 )
16914  {
16915  /* a < 0 -> get upper bound of y */
16916  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16917  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16918  return var->data.multaggr.scalars[0] * SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16919  + var->data.multaggr.constant;
16920  }
16921  else
16922  {
16923  SCIPerrorMessage("scalar is zero in multi-aggregation\n");
16924  SCIPABORT();
16925  return SCIP_INVALID; /*lint !e527*/
16926  }
16927  }
16928  SCIPerrorMessage("cannot get the bounds of a multiple aggregated variable.\n");
16929  SCIPABORT();
16930  return SCIP_INVALID; /*lint !e527*/
16931 
16932  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
16933  assert(var->negatedvar != NULL);
16935  assert(var->negatedvar->negatedvar == var);
16936  return var->data.negate.constant - SCIPvarGetLbAtIndex(var->negatedvar, bdchgidx, after);
16937 
16938  default:
16939  SCIPerrorMessage("unknown variable status\n");
16940  SCIPABORT();
16941  return SCIP_INVALID; /*lint !e527*/
16942  }
16943 }
16944 
16945 /** returns lower or upper bound of variable directly before or after the bound change given by the bound change index
16946  * was applied
16947  *
16948  * @deprecated Please use SCIPgetVarBdAtIndex()
16949  */
16951  SCIP_VAR* var, /**< problem variable */
16952  SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
16953  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16954  SCIP_Bool after /**< should the bound change with given index be included? */
16955  )
16956 {
16957  if( boundtype == SCIP_BOUNDTYPE_LOWER )
16958  return SCIPvarGetLbAtIndex(var, bdchgidx, after);
16959  else
16960  {
16961  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16962  return SCIPvarGetUbAtIndex(var, bdchgidx, after);
16963  }
16964 }
16965 
16966 /** returns whether the binary variable was fixed at the time given by the bound change index
16967  *
16968  * @deprecated Please use SCIPgetVarWasFixedAtIndex()
16969  */
16971  SCIP_VAR* var, /**< problem variable */
16972  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16973  SCIP_Bool after /**< should the bound change with given index be included? */
16974  )
16975 {
16976  assert(var != NULL);
16977  assert(SCIPvarIsBinary(var));
16978 
16979  /* check the current bounds first in order to decide at which bound change information we have to look
16980  * (which is expensive because we have to follow the aggregation tree to the active variable)
16981  */
16982  return ((SCIPvarGetLbLocal(var) > 0.5 && SCIPvarGetLbAtIndex(var, bdchgidx, after) > 0.5)
16983  || (SCIPvarGetUbLocal(var) < 0.5 && SCIPvarGetUbAtIndex(var, bdchgidx, after) < 0.5));
16984 }
16985 
16986 /** bound change index representing the initial time before any bound changes took place */
16987 static SCIP_BDCHGIDX initbdchgidx = {-2, 0};
16989 /** bound change index representing the presolving stage */
16990 static SCIP_BDCHGIDX presolvebdchgidx = {-1, 0};
16992 /** returns the last bound change index, at which the bounds of the given variable were tightened */
16994  SCIP_VAR* var /**< problem variable */
16995  )
16996 {
16997  SCIP_BDCHGIDX* lbchgidx;
16998  SCIP_BDCHGIDX* ubchgidx;
16999 
17000  assert(var != NULL);
17001 
17002  var = SCIPvarGetProbvar(var);
17003 
17004  /* check, if variable is original without transformed variable */
17005  if( var == NULL )
17006  return &initbdchgidx;
17007 
17008  /* check, if variable was fixed in presolving */
17009  if( !SCIPvarIsActive(var) )
17010  return &presolvebdchgidx;
17011 
17013 
17014  /* get depths of last bound change information for the lower and upper bound */
17015  lbchgidx = (var->nlbchginfos > 0 && !var->lbchginfos[var->nlbchginfos-1].redundant
17016  ? &var->lbchginfos[var->nlbchginfos-1].bdchgidx : &initbdchgidx);
17017  ubchgidx = (var->nubchginfos > 0 && !var->ubchginfos[var->nubchginfos-1].redundant
17018  ? &var->ubchginfos[var->nubchginfos-1].bdchgidx : &initbdchgidx);
17019 
17020  if( SCIPbdchgidxIsEarlierNonNull(lbchgidx, ubchgidx) )
17021  return ubchgidx;
17022  else
17023  return lbchgidx;
17024 }
17025 
17026 /** returns the last depth level, at which the bounds of the given variable were tightened;
17027  * returns -2, if the variable's bounds are still the global bounds
17028  * returns -1, if the variable was fixed in presolving
17029  */
17031  SCIP_VAR* var /**< problem variable */
17032  )
17033 {
17034  SCIP_BDCHGIDX* bdchgidx;
17035 
17036  bdchgidx = SCIPvarGetLastBdchgIndex(var);
17037  assert(bdchgidx != NULL);
17038 
17039  return bdchgidx->depth;
17040 }
17041 
17042 /** returns at which depth in the tree a bound change was applied to the variable that conflicts with the
17043  * given bound; returns -1 if the bound does not conflict with the current local bounds of the variable
17044  */
17046  SCIP_VAR* var, /**< problem variable */
17047  SCIP_SET* set, /**< global SCIP settings */
17048  SCIP_BOUNDTYPE boundtype, /**< bound type of the conflicting bound */
17049  SCIP_Real bound /**< conflicting bound */
17050  )
17051 {
17052  int i;
17053 
17054  assert(var != NULL);
17055  assert(set != NULL);
17056  assert(var->scip == set->scip);
17057 
17058  if( boundtype == SCIP_BOUNDTYPE_LOWER )
17059  {
17060  /* check if the bound is in conflict with the current local bounds */
17061  if( SCIPsetIsLE(set, bound, var->locdom.ub) )
17062  return -1;
17063 
17064  /* check if the bound is in conflict with the global bound */
17065  if( SCIPsetIsGT(set, bound, var->glbdom.ub) )
17066  return 0;
17067 
17068  /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
17069  assert(var->nubchginfos > 0);
17070  assert(SCIPsetIsGT(set, bound, var->ubchginfos[var->nubchginfos-1].newbound));
17071 
17072  /* search for the first conflicting bound change */
17073  for( i = var->nubchginfos-1; i > 0 && SCIPsetIsGT(set, bound, var->ubchginfos[i-1].newbound); --i )
17074  {
17075  assert(var->ubchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
17077  }
17078  assert(SCIPsetIsGT(set, bound, var->ubchginfos[i].newbound)); /* bound change i is conflicting */
17079  assert(i == 0 || SCIPsetIsLE(set, bound, var->ubchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
17080 
17081  /* return the depth at which the first conflicting bound change took place */
17082  return var->ubchginfos[i].bdchgidx.depth;
17083  }
17084  else
17085  {
17086  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
17087 
17088  /* check if the bound is in conflict with the current local bounds */
17089  if( SCIPsetIsGE(set, bound, var->locdom.lb) )
17090  return -1;
17091 
17092  /* check if the bound is in conflict with the global bound */
17093  if( SCIPsetIsLT(set, bound, var->glbdom.lb) )
17094  return 0;
17095 
17096  /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
17097  assert(var->nlbchginfos > 0);
17098  assert(SCIPsetIsLT(set, bound, var->lbchginfos[var->nlbchginfos-1].newbound));
17099 
17100  /* search for the first conflicting bound change */
17101  for( i = var->nlbchginfos-1; i > 0 && SCIPsetIsLT(set, bound, var->lbchginfos[i-1].newbound); --i )
17102  {
17103  assert(var->lbchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
17105  }
17106  assert(SCIPsetIsLT(set, bound, var->lbchginfos[i].newbound)); /* bound change i is conflicting */
17107  assert(i == 0 || SCIPsetIsGE(set, bound, var->lbchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
17108 
17109  /* return the depth at which the first conflicting bound change took place */
17110  return var->lbchginfos[i].bdchgidx.depth;
17111  }
17112 }
17113 
17114 /** returns whether the first binary variable was fixed earlier than the second one;
17115  * returns FALSE, if the first variable is not fixed, and returns TRUE, if the first variable is fixed, but the
17116  * second one is not fixed
17117  */
17119  SCIP_VAR* var1, /**< first binary variable */
17120  SCIP_VAR* var2 /**< second binary variable */
17121  )
17122 {
17123  SCIP_BDCHGIDX* bdchgidx1;
17124  SCIP_BDCHGIDX* bdchgidx2;
17125 
17126  assert(var1 != NULL);
17127  assert(var2 != NULL);
17128  assert(SCIPvarIsBinary(var1));
17129  assert(SCIPvarIsBinary(var2));
17130 
17131  var1 = SCIPvarGetProbvar(var1);
17132  var2 = SCIPvarGetProbvar(var2);
17133  assert(var1 != NULL);
17134  assert(var2 != NULL);
17135 
17136  /* check, if variables are globally fixed */
17137  if( !SCIPvarIsActive(var2) || var2->glbdom.lb > 0.5 || var2->glbdom.ub < 0.5 )
17138  return FALSE;
17139  if( !SCIPvarIsActive(var1) || var1->glbdom.lb > 0.5 || var1->glbdom.ub < 0.5 )
17140  return TRUE;
17141 
17144  assert(SCIPvarIsBinary(var1));
17145  assert(SCIPvarIsBinary(var2));
17146  assert(var1->nlbchginfos + var1->nubchginfos <= 1);
17147  assert(var2->nlbchginfos + var2->nubchginfos <= 1);
17148  assert(var1->nlbchginfos == 0 || !var1->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
17149  assert(var1->nubchginfos == 0 || !var1->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
17150  assert(var2->nlbchginfos == 0 || !var2->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
17151  assert(var2->nubchginfos == 0 || !var2->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
17152 
17153  if( var1->nlbchginfos == 1 )
17154  bdchgidx1 = &var1->lbchginfos[0].bdchgidx;
17155  else if( var1->nubchginfos == 1 )
17156  bdchgidx1 = &var1->ubchginfos[0].bdchgidx;
17157  else
17158  bdchgidx1 = NULL;
17159 
17160  if( var2->nlbchginfos == 1 )
17161  bdchgidx2 = &var2->lbchginfos[0].bdchgidx;
17162  else if( var2->nubchginfos == 1 )
17163  bdchgidx2 = &var2->ubchginfos[0].bdchgidx;
17164  else
17165  bdchgidx2 = NULL;
17166 
17167  return SCIPbdchgidxIsEarlier(bdchgidx1, bdchgidx2);
17168 }
17169 
17170 
17171 
17172 /*
17173  * Hash functions
17174  */
17175 
17176 /** gets the key (i.e. the name) of the given variable */
17177 SCIP_DECL_HASHGETKEY(SCIPhashGetKeyVar)
17178 { /*lint --e{715}*/
17179  SCIP_VAR* var = (SCIP_VAR*)elem;
17180 
17181  assert(var != NULL);
17182  return var->name;
17183 }
17184 
17185 
17186 
17187 
17188 /*
17189  * simple functions implemented as defines
17190  */
17191 
17192 /* In debug mode, the following methods are implemented as function calls to ensure
17193  * type validity.
17194  * In optimized mode, the methods are implemented as defines to improve performance.
17195  * However, we want to have them in the library anyways, so we have to undef the defines.
17196  */
17197 
17198 #undef SCIPboundchgGetNewbound
17199 #undef SCIPboundchgGetVar
17200 #undef SCIPboundchgGetBoundchgtype
17201 #undef SCIPboundchgGetBoundtype
17202 #undef SCIPboundchgIsRedundant
17203 #undef SCIPdomchgGetNBoundchgs
17204 #undef SCIPdomchgGetBoundchg
17205 #undef SCIPholelistGetLeft
17206 #undef SCIPholelistGetRight
17207 #undef SCIPholelistGetNext
17208 #undef SCIPvarGetName
17209 #undef SCIPvarGetNUses
17210 #undef SCIPvarGetData
17211 #undef SCIPvarSetData
17212 #undef SCIPvarSetDelorigData
17213 #undef SCIPvarSetTransData
17214 #undef SCIPvarSetDeltransData
17215 #undef SCIPvarGetStatus
17216 #undef SCIPvarIsOriginal
17217 #undef SCIPvarIsTransformed
17218 #undef SCIPvarIsNegated
17219 #undef SCIPvarGetType
17220 #undef SCIPvarIsBinary
17221 #undef SCIPvarIsIntegral
17222 #undef SCIPvarIsInitial
17223 #undef SCIPvarIsRemovable
17224 #undef SCIPvarIsDeleted
17225 #undef SCIPvarIsDeletable
17226 #undef SCIPvarMarkDeletable
17227 #undef SCIPvarMarkNotDeletable
17228 #undef SCIPvarIsActive
17229 #undef SCIPvarGetIndex
17230 #undef SCIPvarGetProbindex
17231 #undef SCIPvarGetTransVar
17232 #undef SCIPvarGetCol
17233 #undef SCIPvarIsInLP
17234 #undef SCIPvarGetAggrVar
17235 #undef SCIPvarGetAggrScalar
17236 #undef SCIPvarGetAggrConstant
17237 #undef SCIPvarGetMultaggrNVars
17238 #undef SCIPvarGetMultaggrVars
17239 #undef SCIPvarGetMultaggrScalars
17240 #undef SCIPvarGetMultaggrConstant
17241 #undef SCIPvarGetNegatedVar
17242 #undef SCIPvarGetNegationVar
17243 #undef SCIPvarGetNegationConstant
17244 #undef SCIPvarGetObj
17245 #undef SCIPvarGetLbOriginal
17246 #undef SCIPvarGetUbOriginal
17247 #undef SCIPvarGetHolelistOriginal
17248 #undef SCIPvarGetLbGlobal
17249 #undef SCIPvarGetUbGlobal
17250 #undef SCIPvarGetHolelistGlobal
17251 #undef SCIPvarGetBestBoundGlobal
17252 #undef SCIPvarGetWorstBoundGlobal
17253 #undef SCIPvarGetLbLocal
17254 #undef SCIPvarGetUbLocal
17255 #undef SCIPvarGetHolelistLocal
17256 #undef SCIPvarGetBestBoundLocal
17257 #undef SCIPvarGetWorstBoundLocal
17258 #undef SCIPvarGetBestBoundType
17259 #undef SCIPvarGetWorstBoundType
17260 #undef SCIPvarGetLbLazy
17261 #undef SCIPvarGetUbLazy
17262 #undef SCIPvarGetBranchFactor
17263 #undef SCIPvarGetBranchPriority
17264 #undef SCIPvarGetBranchDirection
17265 #undef SCIPvarGetNVlbs
17266 #undef SCIPvarGetVlbVars
17267 #undef SCIPvarGetVlbCoefs
17268 #undef SCIPvarGetVlbConstants
17269 #undef SCIPvarGetNVubs
17270 #undef SCIPvarGetVubVars
17271 #undef SCIPvarGetVubCoefs
17272 #undef SCIPvarGetVubConstants
17273 #undef SCIPvarGetNImpls
17274 #undef SCIPvarGetImplVars
17275 #undef SCIPvarGetImplTypes
17276 #undef SCIPvarGetImplBounds
17277 #undef SCIPvarGetImplIds
17278 #undef SCIPvarGetNCliques
17279 #undef SCIPvarGetCliques
17280 #undef SCIPvarGetLPSol
17281 #undef SCIPvarGetNLPSol
17282 #undef SCIPvarGetBdchgInfoLb
17283 #undef SCIPvarGetNBdchgInfosLb
17284 #undef SCIPvarGetBdchgInfoUb
17285 #undef SCIPvarGetNBdchgInfosUb
17286 #undef SCIPvarGetValuehistory
17287 #undef SCIPvarGetPseudoSol
17288 #undef SCIPvarCatchEvent
17289 #undef SCIPvarDropEvent
17290 #undef SCIPvarGetVSIDS
17291 #undef SCIPvarGetCliqueComponentIdx
17292 #undef SCIPvarIsRelaxationOnly
17293 #undef SCIPvarMarkRelaxationOnly
17294 #undef SCIPbdchgidxGetPos
17295 #undef SCIPbdchgidxIsEarlierNonNull
17296 #undef SCIPbdchgidxIsEarlier
17297 #undef SCIPbdchginfoGetOldbound
17298 #undef SCIPbdchginfoGetNewbound
17299 #undef SCIPbdchginfoGetVar
17300 #undef SCIPbdchginfoGetChgtype
17301 #undef SCIPbdchginfoGetBoundtype
17302 #undef SCIPbdchginfoGetDepth
17303 #undef SCIPbdchginfoGetPos
17304 #undef SCIPbdchginfoGetIdx
17305 #undef SCIPbdchginfoGetInferVar
17306 #undef SCIPbdchginfoGetInferCons
17307 #undef SCIPbdchginfoGetInferProp
17308 #undef SCIPbdchginfoGetInferInfo
17309 #undef SCIPbdchginfoGetInferBoundtype
17310 #undef SCIPbdchginfoIsRedundant
17311 #undef SCIPbdchginfoHasInferenceReason
17312 #undef SCIPbdchginfoIsTighter
17313 
17314 
17315 /** returns the new value of the bound in the bound change data */
17317  SCIP_BOUNDCHG* boundchg /**< bound change data */
17318  )
17319 {
17320  assert(boundchg != NULL);
17321 
17322  return boundchg->newbound;
17323 }
17324 
17325 /** returns the variable of the bound change in the bound change data */
17327  SCIP_BOUNDCHG* boundchg /**< bound change data */
17328  )
17329 {
17330  assert(boundchg != NULL);
17331 
17332  return boundchg->var;
17333 }
17334 
17335 /** returns the bound change type of the bound change in the bound change data */
17337  SCIP_BOUNDCHG* boundchg /**< bound change data */
17338  )
17339 {
17340  assert(boundchg != NULL);
17341 
17342  return (SCIP_BOUNDCHGTYPE)(boundchg->boundchgtype);
17343 }
17344 
17345 /** returns the bound type of the bound change in the bound change data */
17347  SCIP_BOUNDCHG* boundchg /**< bound change data */
17348  )
17349 {
17350  assert(boundchg != NULL);
17351 
17352  return (SCIP_BOUNDTYPE)(boundchg->boundtype);
17353 }
17354 
17355 /** returns whether the bound change is redundant due to a more global bound that is at least as strong */
17357  SCIP_BOUNDCHG* boundchg /**< bound change data */
17358  )
17359 {
17360  assert(boundchg != NULL);
17361 
17362  return boundchg->redundant;
17363 }
17364 
17365 /** returns the number of bound changes in the domain change data */
17367  SCIP_DOMCHG* domchg /**< domain change data */
17368  )
17369 {
17370  return domchg != NULL ? domchg->domchgbound.nboundchgs : 0;
17371 }
17372 
17373 /** returns a particular bound change in the domain change data */
17375  SCIP_DOMCHG* domchg, /**< domain change data */
17376  int pos /**< position of the bound change in the domain change data */
17377  )
17378 {
17379  assert(domchg != NULL);
17380  assert(0 <= pos && pos < (int)domchg->domchgbound.nboundchgs);
17381 
17382  return &domchg->domchgbound.boundchgs[pos];
17383 }
17384 
17385 /** returns left bound of open interval in hole */
17387  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
17388  )
17389 {
17390  assert(holelist != NULL);
17391 
17392  return holelist->hole.left;
17393 }
17394 
17395 /** returns right bound of open interval in hole */
17397  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
17398  )
17399 {
17400  assert(holelist != NULL);
17401 
17402  return holelist->hole.right;
17403 }
17404 
17405 /** returns next hole in list */
17407  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
17408  )
17409 {
17410  assert(holelist != NULL);
17411 
17412  return holelist->next;
17413 }
17414 
17415 /** returns the name of the variable
17416  *
17417  * @note to change the name of a variable, use SCIPchgVarName() from scip.h
17418  */
17419 const char* SCIPvarGetName(
17420  SCIP_VAR* var /**< problem variable */
17421  )
17422 {
17423  assert(var != NULL);
17424 
17425  return var->name;
17426 }
17427 
17428 /** gets number of times, the variable is currently captured */
17429 int SCIPvarGetNUses(
17430  SCIP_VAR* var /**< problem variable */
17431  )
17432 {
17433  assert(var != NULL);
17434 
17435  return var->nuses;
17436 }
17437 
17438 /** returns the user data of the variable */
17440  SCIP_VAR* var /**< problem variable */
17441  )
17442 {
17443  assert(var != NULL);
17444 
17445  return var->vardata;
17446 }
17447 
17448 /** sets the user data for the variable */
17449 void SCIPvarSetData(
17450  SCIP_VAR* var, /**< problem variable */
17451  SCIP_VARDATA* vardata /**< user variable data */
17452  )
17453 {
17454  assert(var != NULL);
17455 
17456  var->vardata = vardata;
17457 }
17458 
17459 /** sets method to free user data for the original variable */
17461  SCIP_VAR* var, /**< problem variable */
17462  SCIP_DECL_VARDELORIG ((*vardelorig)) /**< frees user data of original variable */
17463  )
17464 {
17465  assert(var != NULL);
17466  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
17467 
17468  var->vardelorig = vardelorig;
17469 }
17470 
17471 /** sets method to transform user data of the variable */
17472 void SCIPvarSetTransData(
17473  SCIP_VAR* var, /**< problem variable */
17474  SCIP_DECL_VARTRANS ((*vartrans)) /**< creates transformed user data by transforming original user data */
17475  )
17476 {
17477  assert(var != NULL);
17478  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
17479 
17480  var->vartrans = vartrans;
17481 }
17482 
17483 /** sets method to free transformed user data for the variable */
17485  SCIP_VAR* var, /**< problem variable */
17486  SCIP_DECL_VARDELTRANS ((*vardeltrans)) /**< frees user data of transformed variable */
17487  )
17488 {
17489  assert(var != NULL);
17490 
17491  var->vardeltrans = vardeltrans;
17492 }
17493 
17494 /** sets method to copy this variable into sub-SCIPs */
17495 void SCIPvarSetCopyData(
17496  SCIP_VAR* var, /**< problem variable */
17497  SCIP_DECL_VARCOPY ((*varcopy)) /**< copy method of the variable */
17498  )
17499 {
17500  assert(var != NULL);
17501 
17502  var->varcopy = varcopy;
17503 }
17504 
17505 /** sets the initial flag of a variable; only possible for original or loose variables */
17507  SCIP_VAR* var, /**< problem variable */
17508  SCIP_Bool initial /**< initial flag */
17509  )
17510 {
17511  assert(var != NULL);
17512 
17514  return SCIP_INVALIDCALL;
17515 
17516  var->initial = initial;
17517 
17518  return SCIP_OKAY;
17519 }
17520 
17521 /** sets the removable flag of a variable; only possible for original or loose variables */
17523  SCIP_VAR* var, /**< problem variable */
17524  SCIP_Bool removable /**< removable flag */
17525  )
17526 {
17527  assert(var != NULL);
17528 
17530  return SCIP_INVALIDCALL;
17531 
17532  var->removable = removable;
17533 
17534  return SCIP_OKAY;
17535 }
17536 
17537 /** gets status of variable */
17539  SCIP_VAR* var /**< problem variable */
17540  )
17541 {
17542  assert(var != NULL);
17543 
17544  return (SCIP_VARSTATUS)(var->varstatus);
17545 }
17546 
17547 /** returns whether the variable belongs to the original problem */
17549  SCIP_VAR* var /**< problem variable */
17550  )
17551 {
17552  assert(var != NULL);
17553  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED || var->negatedvar != NULL);
17554 
17558 }
17559 
17560 /** returns whether the variable belongs to the transformed problem */
17562  SCIP_VAR* var /**< problem variable */
17563  )
17564 {
17565  assert(var != NULL);
17566  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED || var->negatedvar != NULL);
17567 
17571 }
17572 
17573 /** returns whether the variable was created by negation of a different variable */
17575  SCIP_VAR* var /**< problem variable */
17576  )
17577 {
17578  assert(var != NULL);
17579 
17580  return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17581 }
17582 
17583 /** gets type of variable */
17585  SCIP_VAR* var /**< problem variable */
17586  )
17587 {
17588  assert(var != NULL);
17589 
17590  return (SCIP_VARTYPE)(var->vartype);
17591 }
17592 
17593 /** returns TRUE if the variable is of binary type; this is the case if:
17594  * (1) variable type is binary
17595  * (2) variable type is integer or implicit integer and
17596  * (i) the global lower bound is greater than or equal to zero
17597  * (ii) the global upper bound is less than or equal to one
17598  */
17600  SCIP_VAR* var /**< problem variable */
17601  )
17602 {
17603  assert(var != NULL);
17604 
17605  return (SCIPvarGetType(var) == SCIP_VARTYPE_BINARY ||
17606  (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && var->glbdom.lb >= 0.0 && var->glbdom.ub <= 1.0));
17607 }
17608 
17609 /** returns whether variable is of integral type (binary, integer, or implicit integer) */
17611  SCIP_VAR* var /**< problem variable */
17612  )
17613 {
17614  assert(var != NULL);
17615 
17616  return (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
17617 }
17618 
17619 /** returns whether variable's column should be present in the initial root LP */
17621  SCIP_VAR* var /**< problem variable */
17622  )
17623 {
17624  assert(var != NULL);
17625 
17626  return var->initial;
17627 }
17628 
17629 /** returns whether variable's column is removable from the LP (due to aging or cleanup) */
17631  SCIP_VAR* var /**< problem variable */
17632  )
17633 {
17634  assert(var != NULL);
17635 
17636  return var->removable;
17637 }
17638 
17639 /** returns whether the variable was deleted from the problem */
17641  SCIP_VAR* var /**< problem variable */
17642  )
17643 {
17644  assert(var != NULL);
17645 
17646  return var->deleted;
17647 }
17648 
17649 /** marks the variable to be deletable, i.e., it may be deleted completely from the problem;
17650  * method can only be called before the variable is added to the problem by SCIPaddVar() or SCIPaddPricedVar()
17651  */
17653  SCIP_VAR* var /**< problem variable */
17654  )
17655 {
17656  assert(var != NULL);
17657  assert(var->probindex == -1);
17658 
17659  var->deletable = TRUE;
17660 }
17661 
17662 /** marks the variable to be not deletable from the problem */
17665  )
17666 {
17667  assert(var != NULL);
17668 
17669  var->deletable = FALSE;
17670 }
17671 
17672 /** marks variable to be deleted from global structures (cliques etc.) when cleaning up
17673  *
17674  * @note: this is not equivalent to marking the variable itself for deletion, this is done by using SCIPvarMarkDeletable()
17675  */
17677  SCIP_VAR* var /**< problem variable */
17678  )
17679 {
17680  assert(var != NULL);
17681 
17682  var->delglobalstructs = TRUE;
17683 }
17684 
17685 /** returns whether the variable was flagged for deletion from global structures (cliques etc.) */
17687  SCIP_VAR* var /**< problem variable */
17688  )
17689 {
17690  assert(var != NULL);
17691 
17692  return var->delglobalstructs;
17693 }
17694 
17695 /** returns whether a variable has been introduced to define a relaxation
17696  *
17697  * These variables are only valid for the current SCIP solve round,
17698  * they are not contained in any (checked) constraints, but may be used
17699  * in cutting planes, for example.
17700  * Relaxation-only variables are not copied by SCIPcopyVars and cuts
17701  * that contain these variables are not added as linear constraints when
17702  * restarting or transferring information from a copied SCIP to a SCIP.
17703  * Also conflicts with relaxation-only variables are not generated at
17704  * the moment.
17705  */
17707  SCIP_VAR* var /**< problem variable */
17708  )
17709 {
17710  assert(var != NULL);
17711 
17712  return var->relaxationonly;
17713 }
17714 
17715 /** marks that this variable has only been introduced to define a relaxation
17716  *
17717  * The variable must not have a coefficient in the objective and must be deletable.
17718  * If it is not marked deletable, it will be marked as deletable, which is only possible
17719  * before the variable is added to a problem.
17720  *
17721  * @see SCIPvarIsRelaxationOnly
17722  * @see SCIPvarMarkDeletable
17723  */
17725  SCIP_VAR* var /**< problem variable */
17726  )
17727 {
17728  assert(var != NULL);
17729  assert(SCIPvarGetObj(var) == 0.0);
17730 
17731  if( !SCIPvarIsDeletable(var) )
17732  SCIPvarMarkDeletable(var);
17733 
17734  var->relaxationonly = TRUE;
17735 }
17736 
17737 /** returns whether variable is allowed to be deleted completely from the problem */
17740  )
17741 {
17742  assert(var != NULL);
17743 
17744  return var->deletable;
17745 }
17746 
17747 /** returns whether variable is an active (neither fixed nor aggregated) variable */
17749  SCIP_VAR* var /**< problem variable */
17750  )
17751 {
17752  assert(var != NULL);
17753 
17754  return (var->probindex >= 0);
17755 }
17756 
17757 /** gets unique index of variable */
17758 int SCIPvarGetIndex(
17759  SCIP_VAR* var /**< problem variable */
17760  )
17761 {
17762  assert(var != NULL);
17763 
17764  return var->index;
17765 }
17766 
17767 /** gets position of variable in problem, or -1 if variable is not active */
17769  SCIP_VAR* var /**< problem variable */
17770  )
17771 {
17772  assert(var != NULL);
17773 
17774  return var->probindex;
17775 }
17776 
17777 /** gets transformed variable of ORIGINAL variable */
17779  SCIP_VAR* var /**< problem variable */
17780  )
17781 {
17782  assert(var != NULL);
17783  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
17784 
17785  return var->data.original.transvar;
17786 }
17787 
17788 /** gets column of COLUMN variable */
17790  SCIP_VAR* var /**< problem variable */
17791  )
17792 {
17793  assert(var != NULL);
17794  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
17795 
17796  return var->data.col;
17797 }
17798 
17799 /** returns whether the variable is a COLUMN variable that is member of the current LP */
17801  SCIP_VAR* var /**< problem variable */
17802  )
17803 {
17804  assert(var != NULL);
17805 
17806  return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN && SCIPcolIsInLP(var->data.col));
17807 }
17808 
17809 /** gets aggregation variable y of an aggregated variable x = a*y + c */
17811  SCIP_VAR* var /**< problem variable */
17812  )
17813 {
17814  assert(var != NULL);
17816  assert(!var->donotaggr);
17817 
17818  return var->data.aggregate.var;
17819 }
17820 
17821 /** gets aggregation scalar a of an aggregated variable x = a*y + c */
17823  SCIP_VAR* var /**< problem variable */
17824  )
17825 {
17826  assert(var != NULL);
17828  assert(!var->donotaggr);
17829 
17830  return var->data.aggregate.scalar;
17831 }
17832 
17833 /** gets aggregation constant c of an aggregated variable x = a*y + c */
17835  SCIP_VAR* var /**< problem variable */
17836  )
17837 {
17838  assert(var != NULL);
17840  assert(!var->donotaggr);
17841 
17842  return var->data.aggregate.constant;
17843 }
17844 
17845 /** gets number n of aggregation variables of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17847  SCIP_VAR* var /**< problem variable */
17848  )
17849 {
17850  assert(var != NULL);
17851  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17852  assert(!var->donotmultaggr);
17853 
17854  return var->data.multaggr.nvars;
17855 }
17856 
17857 /** gets vector of aggregation variables y of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17859  SCIP_VAR* var /**< problem variable */
17860  )
17861 {
17862  assert(var != NULL);
17863  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17864  assert(!var->donotmultaggr);
17865 
17866  return var->data.multaggr.vars;
17867 }
17868 
17869 /** gets vector of aggregation scalars a of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17871  SCIP_VAR* var /**< problem variable */
17872  )
17873 {
17874  assert(var != NULL);
17875  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17876  assert(!var->donotmultaggr);
17877 
17878  return var->data.multaggr.scalars;
17879 }
17880 
17881 /** gets aggregation constant c of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17883  SCIP_VAR* var /**< problem variable */
17884  )
17885 {
17886  assert(var != NULL);
17887  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17888  assert(!var->donotmultaggr);
17889 
17890  return var->data.multaggr.constant;
17891 }
17892 
17893 /** gets the negation of the given variable; may return NULL, if no negation is existing yet */
17895  SCIP_VAR* var /**< negated problem variable */
17896  )
17897 {
17898  assert(var != NULL);
17899 
17900  return var->negatedvar;
17901 }
17902 
17903 /** gets the negation variable x of a negated variable x' = offset - x */
17905  SCIP_VAR* var /**< negated problem variable */
17906  )
17907 {
17908  assert(var != NULL);
17909  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17910 
17911  return var->negatedvar;
17912 }
17913 
17914 /** gets the negation offset of a negated variable x' = offset - x */
17916  SCIP_VAR* var /**< negated problem variable */
17917  )
17918 {
17919  assert(var != NULL);
17920  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17921 
17922  return var->data.negate.constant;
17923 }
17924 
17925 /** gets objective function value of variable */
17927  SCIP_VAR* var /**< problem variable */
17928  )
17929 {
17930  assert(var != NULL);
17931 
17932  return var->obj;
17933 }
17934 
17935 /** gets the unchanged objective function value of a variable (ignoring temproray changes performed in probing mode) */
17937  SCIP_VAR* var /**< problem variable */
17938  )
17939 {
17940  assert(var != NULL);
17941 
17942  return var->unchangedobj;
17943 }
17944 
17945 /** gets corresponding objective value of active, fixed, or multi-aggregated problem variable of given variable
17946  * e.g. obj(x) = 1 this method returns for ~x the value -1
17947  */
17949  SCIP_VAR* var, /**< problem variable */
17950  SCIP_Real* aggrobj /**< pointer to store the aggregated objective value */
17951  )
17952 {
17953  SCIP_VAR* probvar = var;
17954  SCIP_Real mult = 1.0;
17955 
17956  assert(probvar != NULL);
17957  assert(aggrobj != NULL);
17958 
17959  while( probvar != NULL )
17960  {
17961  switch( SCIPvarGetStatus(probvar) )
17962  {
17964  case SCIP_VARSTATUS_LOOSE:
17965  case SCIP_VARSTATUS_COLUMN:
17966  (*aggrobj) = mult * SCIPvarGetObj(probvar);
17967  return SCIP_OKAY;
17968 
17969  case SCIP_VARSTATUS_FIXED:
17970  assert(SCIPvarGetObj(probvar) == 0.0);
17971  (*aggrobj) = 0.0;
17972  return SCIP_OKAY;
17973 
17975  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
17976  if ( probvar->data.multaggr.nvars == 1 )
17977  {
17978  assert( probvar->data.multaggr.vars != NULL );
17979  assert( probvar->data.multaggr.scalars != NULL );
17980  assert( probvar->data.multaggr.vars[0] != NULL );
17981  mult *= probvar->data.multaggr.scalars[0];
17982  probvar = probvar->data.multaggr.vars[0];
17983  break;
17984  }
17985  else
17986  {
17987  SCIP_Real tmpobj;
17988  int v;
17989 
17990  (*aggrobj) = 0.0;
17991 
17992  for( v = probvar->data.multaggr.nvars - 1; v >= 0; --v )
17993  {
17994  SCIP_CALL( SCIPvarGetAggregatedObj(probvar->data.multaggr.vars[v], &tmpobj) );
17995  (*aggrobj) += probvar->data.multaggr.scalars[v] * tmpobj;
17996  }
17997  return SCIP_OKAY;
17998  }
17999 
18000  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
18001  assert(probvar->data.aggregate.var != NULL);
18002  mult *= probvar->data.aggregate.scalar;
18003  probvar = probvar->data.aggregate.var;
18004  break;
18005 
18006  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
18007  assert(probvar->negatedvar != NULL);
18008  assert(SCIPvarGetStatus(probvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
18009  assert(probvar->negatedvar->negatedvar == probvar);
18010  mult *= -1.0;
18011  probvar = probvar->negatedvar;
18012  break;
18013 
18014  default:
18015  SCIPABORT();
18016  return SCIP_INVALIDDATA; /*lint !e527*/
18017  }
18018  }
18019 
18020  return SCIP_INVALIDDATA;
18021 }
18022 
18023 /** gets original lower bound of original problem variable (i.e. the bound set in problem creation) */
18025  SCIP_VAR* var /**< original problem variable */
18026  )
18027 {
18028  assert(var != NULL);
18029  assert(SCIPvarIsOriginal(var));
18030 
18032  return var->data.original.origdom.lb;
18033  else
18034  {
18035  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
18036  assert(var->negatedvar != NULL);
18038 
18039  return var->data.negate.constant - var->negatedvar->data.original.origdom.ub;
18040  }
18041 }
18042 
18043 /** gets original upper bound of original problem variable (i.e. the bound set in problem creation) */
18045  SCIP_VAR* var /**< original problem variable */
18046  )
18047 {
18048  assert(var != NULL);
18049  assert(SCIPvarIsOriginal(var));
18050 
18052  return var->data.original.origdom.ub;
18053  else
18054  {
18055  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
18056  assert(var->negatedvar != NULL);
18058 
18059  return var->data.negate.constant - var->negatedvar->data.original.origdom.lb;
18060  }
18061 }
18062 
18063 /** gets the original hole list of an original variable */
18065  SCIP_VAR* var /**< problem variable */
18066  )
18067 {
18068  assert(var != NULL);
18069  assert(SCIPvarIsOriginal(var));
18070 
18072  return var->data.original.origdom.holelist;
18073 
18074  return NULL;
18075 }
18076 
18077 /** gets global lower bound of variable */
18079  SCIP_VAR* var /**< problem variable */
18080  )
18081 {
18082  assert(var != NULL);
18083 
18084  return var->glbdom.lb;
18085 }
18086 
18087 /** gets global upper bound of variable */
18089  SCIP_VAR* var /**< problem variable */
18090  )
18091 {
18092  assert(var != NULL);
18093 
18094  return var->glbdom.ub;
18095 }
18096 
18097 /** gets the global hole list of an active variable */
18099  SCIP_VAR* var /**< problem variable */
18100  )
18101 {
18102  assert(var != NULL);
18103 
18104  return var->glbdom.holelist;
18105 }
18106 
18107 /** gets best global bound of variable with respect to the objective function */
18109  SCIP_VAR* var /**< problem variable */
18110  )
18111 {
18112  assert(var != NULL);
18113 
18114  if( var->obj >= 0.0 )
18115  return var->glbdom.lb;
18116  else
18117  return var->glbdom.ub;
18118 }
18119 
18120 /** gets worst global bound of variable with respect to the objective function */
18122  SCIP_VAR* var /**< problem variable */
18123  )
18124 {
18125  assert(var != NULL);
18126 
18127  if( var->obj >= 0.0 )
18128  return var->glbdom.ub;
18129  else
18130  return var->glbdom.lb;
18131 }
18132 
18133 /** gets current lower bound of variable */
18135  SCIP_VAR* var /**< problem variable */
18136  )
18137 {
18138  assert(var != NULL);
18139 
18140  return var->locdom.lb;
18141 }
18142 
18143 /** gets current upper bound of variable */
18145  SCIP_VAR* var /**< problem variable */
18146  )
18147 {
18148  assert(var != NULL);
18149 
18150  return var->locdom.ub;
18151 }
18152 
18153 /** gets the current hole list of an active variable */
18155  SCIP_VAR* var /**< problem variable */
18156  )
18157 {
18158  assert(var != NULL);
18159 
18160  return var->locdom.holelist;
18161 }
18162 
18163 /** gets best local bound of variable with respect to the objective function */
18165  SCIP_VAR* var /**< problem variable */
18166  )
18167 {
18168  assert(var != NULL);
18169 
18170  if( var->obj >= 0.0 )
18171  return var->locdom.lb;
18172  else
18173  return var->locdom.ub;
18174 }
18175 
18176 /** gets worst local bound of variable with respect to the objective function */
18178  SCIP_VAR* var /**< problem variable */
18179  )
18180 {
18181  assert(var != NULL);
18182 
18183  if( var->obj >= 0.0 )
18184  return var->locdom.ub;
18185  else
18186  return var->locdom.lb;
18187 }
18188 
18189 /** gets type (lower or upper) of best bound of variable with respect to the objective function */
18191  SCIP_VAR* var /**< problem variable */
18192  )
18193 {
18194  assert(var != NULL);
18195 
18196  if( var->obj >= 0.0 )
18197  return SCIP_BOUNDTYPE_LOWER;
18198  else
18199  return SCIP_BOUNDTYPE_UPPER;
18200 }
18201 
18202 /** gets type (lower or upper) of worst bound of variable with respect to the objective function */
18204  SCIP_VAR* var /**< problem variable */
18205  )
18206 {
18207  assert(var != NULL);
18208 
18209  if( var->obj >= 0.0 )
18210  return SCIP_BOUNDTYPE_UPPER;
18211  else
18212  return SCIP_BOUNDTYPE_LOWER;
18213 }
18214 
18215 /** gets lazy lower bound of variable, returns -infinity if the variable has no lazy lower bound */
18217  SCIP_VAR* var /**< problem variable */
18218  )
18219 {
18220  assert(var != NULL);
18221 
18222  return var->lazylb;
18223 }
18224 
18225 /** gets lazy upper bound of variable, returns infinity if the variable has no lazy upper bound */
18227  SCIP_VAR* var /**< problem variable */
18228  )
18229 {
18230  assert(var != NULL);
18231 
18232  return var->lazyub;
18233 }
18234 
18235 /** gets the branch factor of the variable; this value can be used in the branching methods to scale the score
18236  * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
18237  */
18239  SCIP_VAR* var /**< problem variable */
18240  )
18241 {
18242  assert(var != NULL);
18243 
18244  return var->branchfactor;
18245 }
18246 
18247 /** gets the branch priority of the variable; variables with higher priority should always be preferred to variables
18248  * with lower priority
18249  */
18251  SCIP_VAR* var /**< problem variable */
18252  )
18253 {
18254  assert(var != NULL);
18255 
18256  return var->branchpriority;
18257 }
18258 
18259 /** gets the preferred branch direction of the variable (downwards, upwards, or auto) */
18261  SCIP_VAR* var /**< problem variable */
18262  )
18263 {
18264  assert(var != NULL);
18265 
18266  return (SCIP_BRANCHDIR)var->branchdirection;
18267 }
18268 
18269 /** gets number of variable lower bounds x >= b_i*z_i + d_i of given variable x */
18270 int SCIPvarGetNVlbs(
18271  SCIP_VAR* var /**< problem variable */
18272  )
18273 {
18274  assert(var != NULL);
18275 
18276  return SCIPvboundsGetNVbds(var->vlbs);
18277 }
18278 
18279 /** gets array with bounding variables z_i in variable lower bounds x >= b_i*z_i + d_i of given variable x;
18280  * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
18281  */
18283  SCIP_VAR* var /**< problem variable */
18284  )
18285 {
18286  assert(var != NULL);
18287 
18288  return SCIPvboundsGetVars(var->vlbs);
18289 }
18290 
18291 /** gets array with bounding coefficients b_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
18293  SCIP_VAR* var /**< problem variable */
18294  )
18295 {
18296  assert(var != NULL);
18297 
18298  return SCIPvboundsGetCoefs(var->vlbs);
18299 }
18300 
18301 /** gets array with bounding constants d_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
18303  SCIP_VAR* var /**< problem variable */
18304  )
18305 {
18306  assert(var != NULL);
18307 
18308  return SCIPvboundsGetConstants(var->vlbs);
18309 }
18310 
18311 /** gets number of variable upper bounds x <= b_i*z_i + d_i of given variable x */
18312 int SCIPvarGetNVubs(
18313  SCIP_VAR* var /**< problem variable */
18314  )
18315 {
18316  assert(var != NULL);
18317 
18318  return SCIPvboundsGetNVbds(var->vubs);
18319 }
18320 
18321 /** gets array with bounding variables z_i in variable upper bounds x <= b_i*z_i + d_i of given variable x;
18322  * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
18323  */
18325  SCIP_VAR* var /**< problem variable */
18326  )
18327 {
18328  assert(var != NULL);
18329 
18330  return SCIPvboundsGetVars(var->vubs);
18331 }
18332 
18333 /** gets array with bounding coefficients b_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
18335  SCIP_VAR* var /**< problem variable */
18336  )
18337 {
18338  assert(var != NULL);
18339 
18340  return SCIPvboundsGetCoefs(var->vubs);
18341 }
18342 
18343 /** gets array with bounding constants d_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
18345  SCIP_VAR* var /**< problem variable */
18346  )
18347 {
18348  assert(var != NULL);
18349 
18350  return SCIPvboundsGetConstants(var->vubs);
18351 }
18352 
18353 /** gets number of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
18354  * there are no implications for nonbinary variable x
18355  */
18356 int SCIPvarGetNImpls(
18357  SCIP_VAR* var, /**< active problem variable */
18358  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
18359  )
18360 {
18361  assert(var != NULL);
18362  assert(SCIPvarIsActive(var));
18363 
18364  return SCIPimplicsGetNImpls(var->implics, varfixing);
18365 }
18366 
18367 /** gets array with implication variables y of implications y <= b or y >= b for x == 0 or x == 1 of given active
18368  * problem variable x, there are no implications for nonbinary variable x;
18369  * the implications are sorted such that implications with binary implied variables precede the ones with non-binary
18370  * implied variables, and as a second criteria, the implied variables are sorted by increasing variable index
18371  * (see SCIPvarGetIndex())
18372  */
18374  SCIP_VAR* var, /**< active problem variable */
18375  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
18376  )
18377 {
18378  assert(var != NULL);
18379  assert(SCIPvarIsActive(var));
18380 
18381  return SCIPimplicsGetVars(var->implics, varfixing);
18382 }
18383 
18384 /** gets array with implication types of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
18385  * variable x (SCIP_BOUNDTYPE_UPPER if y <= b, SCIP_BOUNDTYPE_LOWER if y >= b),
18386  * there are no implications for nonbinary variable x
18387  */
18389  SCIP_VAR* var, /**< active problem variable */
18390  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
18391  )
18392 {
18393  assert(var != NULL);
18394  assert(SCIPvarIsActive(var));
18395 
18396  return SCIPimplicsGetTypes(var->implics, varfixing);
18397 }
18398 
18399 /** gets array with implication bounds b of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
18400  * variable x, there are no implications for nonbinary variable x
18401  */
18403  SCIP_VAR* var, /**< active problem variable */
18404  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
18405  )
18406 {
18407  assert(var != NULL);
18408  assert(SCIPvarIsActive(var));
18409 
18410  return SCIPimplicsGetBounds(var->implics, varfixing);
18411 }
18412 
18413 /** Gets array with unique ids of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
18414  * there are no implications for nonbinary variable x.
18415  * If an implication is a shortcut, i.e., it was added as part of the transitive closure of another implication,
18416  * its id is negative, otherwise it is nonnegative.
18417  */
18418 int* SCIPvarGetImplIds(
18419  SCIP_VAR* var, /**< active problem variable */
18420  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
18421  )
18422 {
18423  assert(var != NULL);
18424  assert(SCIPvarIsActive(var));
18425 
18426  return SCIPimplicsGetIds(var->implics, varfixing);
18427 }
18428 
18429 /** gets number of cliques, the active variable is contained in */
18430 int SCIPvarGetNCliques(
18431  SCIP_VAR* var, /**< active problem variable */
18432  SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
18433  )
18434 {
18435  assert(var != NULL);
18436 
18437  return SCIPcliquelistGetNCliques(var->cliquelist, varfixing);
18438 }
18439 
18440 /** gets array of cliques, the active variable is contained in */
18442  SCIP_VAR* var, /**< active problem variable */
18443  SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
18444  )
18445 {
18446  assert(var != NULL);
18447 
18448  return SCIPcliquelistGetCliques(var->cliquelist, varfixing);
18449 }
18450 
18451 /** gets primal LP solution value of variable */
18453  SCIP_VAR* var /**< problem variable */
18454  )
18455 {
18456  assert(var != NULL);
18457 
18459  return SCIPcolGetPrimsol(var->data.col);
18460  else
18461  return SCIPvarGetLPSol_rec(var);
18462 }
18463 
18464 /** gets primal NLP solution value of variable */
18466  SCIP_VAR* var /**< problem variable */
18467  )
18468 {
18469  assert(var != NULL);
18470 
18472  return var->nlpsol;
18473  else
18474  return SCIPvarGetNLPSol_rec(var);
18475 }
18476 
18477 /** return lower bound change info at requested position */
18479  SCIP_VAR* var, /**< problem variable */
18480  int pos /**< requested position */
18481  )
18482 {
18483  assert(pos >= 0);
18484  assert(pos < var->nlbchginfos);
18485 
18486  return &var->lbchginfos[pos];
18487 }
18488 
18489 /** gets the number of lower bound change info array */
18491  SCIP_VAR* var /**< problem variable */
18492  )
18493 {
18494  return var->nlbchginfos;
18495 }
18496 
18497 /** return upper bound change info at requested position */
18499  SCIP_VAR* var, /**< problem variable */
18500  int pos /**< requested position */
18501  )
18502 {
18503  assert(pos >= 0);
18504  assert(pos < var->nubchginfos);
18505 
18506  return &var->ubchginfos[pos];
18507 }
18508 
18509 /** gets the number upper bound change info array */
18511  SCIP_VAR* var /**< problem variable */
18512  )
18513 {
18514  assert(var != NULL);
18515 
18516  return var->nubchginfos;
18517 }
18518 
18519 /** returns the value based history for the variable */
18521  SCIP_VAR* var /**< problem variable */
18522  )
18523 {
18524  assert(var != NULL);
18525 
18526  return var->valuehistory;
18527 }
18528 
18529 /** gets pseudo solution value of variable */
18531  SCIP_VAR* var /**< problem variable */
18532  )
18533 {
18534  assert(var != NULL);
18535 
18537  return SCIPvarGetBestBoundLocal(var);
18538  else
18539  return SCIPvarGetPseudoSol_rec(var);
18540 }
18541 
18542 /** returns the variable's VSIDS score */
18544  SCIP_VAR* var, /**< problem variable */
18545  SCIP_STAT* stat, /**< problem statistics */
18546  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
18547  )
18548 {
18549  assert(var != NULL);
18550 
18552  return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
18553  else
18554  return SCIPvarGetVSIDS_rec(var, stat, dir);
18555 }
18556 
18557 /** includes event handler with given data in variable's event filter */
18559  SCIP_VAR* var, /**< problem variable */
18560  BMS_BLKMEM* blkmem, /**< block memory */
18561  SCIP_SET* set, /**< global SCIP settings */
18562  SCIP_EVENTTYPE eventtype, /**< event type to catch */
18563  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
18564  SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
18565  int* filterpos /**< pointer to store position of event filter entry, or NULL */
18566  )
18567 {
18568  assert(var != NULL);
18569  assert(set != NULL);
18570  assert(var->scip == set->scip);
18571  assert(var->eventfilter != NULL);
18572  assert((eventtype & ~SCIP_EVENTTYPE_VARCHANGED) == 0);
18573  assert((eventtype & SCIP_EVENTTYPE_VARCHANGED) != 0);
18574  assert(SCIPvarIsTransformed(var));
18575 
18576  SCIPsetDebugMsg(set, "catch event of type 0x%" SCIP_EVENTTYPE_FORMAT " of variable <%s> with handler %p and data %p\n",
18577  eventtype, var->name, (void*)eventhdlr, (void*)eventdata);
18578 
18579  SCIP_CALL( SCIPeventfilterAdd(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
18580 
18581  return SCIP_OKAY;
18582 }
18583 
18584 /** deletes event handler with given data from variable's event filter */
18586  SCIP_VAR* var, /**< problem variable */
18587  BMS_BLKMEM* blkmem, /**< block memory */
18588  SCIP_SET* set, /**< global SCIP settings */
18589  SCIP_EVENTTYPE eventtype, /**< event type mask of dropped event */
18590  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
18591  SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
18592  int filterpos /**< position of event filter entry returned by SCIPvarCatchEvent(), or -1 */
18593  )
18594 {
18595  assert(var != NULL);
18596  assert(set != NULL);
18597  assert(var->scip == set->scip);
18598  assert(var->eventfilter != NULL);
18599  assert(SCIPvarIsTransformed(var));
18600 
18601  SCIPsetDebugMsg(set, "drop event of variable <%s> with handler %p and data %p\n", var->name, (void*)eventhdlr,
18602  (void*)eventdata);
18603 
18604  SCIP_CALL( SCIPeventfilterDel(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
18605 
18606  return SCIP_OKAY;
18607 }
18608 
18609 /** returns the position of the bound change index */
18610 int SCIPbdchgidxGetPos(
18611  SCIP_BDCHGIDX* bdchgidx /**< bound change index */
18612  )
18613 {
18614  assert(bdchgidx != NULL);
18615 
18616  return bdchgidx->pos;
18617 }
18618 
18619 /** returns whether first bound change index belongs to an earlier applied bound change than second one */
18621  SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index */
18622  SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index */
18623  )
18624 {
18625  assert(bdchgidx1 != NULL);
18626  assert(bdchgidx1->depth >= -2);
18627  assert(bdchgidx1->pos >= 0);
18628  assert(bdchgidx2 != NULL);
18629  assert(bdchgidx2->depth >= -2);
18630  assert(bdchgidx2->pos >= 0);
18631 
18632  return (bdchgidx1->depth < bdchgidx2->depth)
18633  || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
18634 }
18635 
18636 /** returns whether first bound change index belongs to an earlier applied bound change than second one;
18637  * if a bound change index is NULL, the bound change index represents the current time, i.e. the time after the
18638  * last bound change was applied to the current node
18639  */
18641  SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index, or NULL */
18642  SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index, or NULL */
18643  )
18644 {
18645  assert(bdchgidx1 == NULL || bdchgidx1->depth >= -2);
18646  assert(bdchgidx1 == NULL || bdchgidx1->pos >= 0);
18647  assert(bdchgidx2 == NULL || bdchgidx2->depth >= -2);
18648  assert(bdchgidx2 == NULL || bdchgidx2->pos >= 0);
18649 
18650  if( bdchgidx1 == NULL )
18651  return FALSE;
18652  else if( bdchgidx2 == NULL )
18653  return TRUE;
18654  else
18655  return (bdchgidx1->depth < bdchgidx2->depth)
18656  || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
18657 }
18658 
18659 /** returns old bound that was overwritten for given bound change information */
18661  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18662  )
18663 {
18664  assert(bdchginfo != NULL);
18665 
18666  return bdchginfo->oldbound;
18667 }
18668 
18669 /** returns new bound installed for given bound change information */
18671  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18672  )
18673 {
18674  assert(bdchginfo != NULL);
18675 
18676  return bdchginfo->newbound;
18677 }
18678 
18679 /** returns variable that belongs to the given bound change information */
18681  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18682  )
18683 {
18684  assert(bdchginfo != NULL);
18685 
18686  return bdchginfo->var;
18687 }
18688 
18689 /** returns whether the bound change information belongs to a branching decision or a deduction */
18691  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18692  )
18693 {
18694  assert(bdchginfo != NULL);
18695 
18696  return (SCIP_BOUNDCHGTYPE)(bdchginfo->boundchgtype);
18697 }
18698 
18699 /** returns whether the bound change information belongs to a lower or upper bound change */
18701  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18702  )
18703 {
18704  assert(bdchginfo != NULL);
18705 
18706  return (SCIP_BOUNDTYPE)(bdchginfo->boundtype);
18707 }
18708 
18709 /** returns depth level of given bound change information */
18711  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18712  )
18713 {
18714  assert(bdchginfo != NULL);
18715 
18716  return bdchginfo->bdchgidx.depth;
18717 }
18718 
18719 /** returns bound change position in its depth level of given bound change information */
18721  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18722  )
18723 {
18724  assert(bdchginfo != NULL);
18725 
18726  return bdchginfo->bdchgidx.pos;
18727 }
18728 
18729 /** returns bound change index of given bound change information */
18731  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18732  )
18733 {
18734  assert(bdchginfo != NULL);
18735 
18736  return &bdchginfo->bdchgidx;
18737 }
18738 
18739 /** returns inference variable of given bound change information */
18741  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18742  )
18743 {
18744  assert(bdchginfo != NULL);
18747 
18748  return bdchginfo->inferencedata.var;
18749 }
18750 
18751 /** returns inference constraint of given bound change information */
18753  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18754  )
18755 {
18756  assert(bdchginfo != NULL);
18758  assert(bdchginfo->inferencedata.reason.cons != NULL);
18759 
18760  return bdchginfo->inferencedata.reason.cons;
18761 }
18762 
18763 /** returns inference propagator of given bound change information, or NULL if no propagator was responsible */
18765  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18766  )
18767 {
18768  assert(bdchginfo != NULL);
18770 
18771  return bdchginfo->inferencedata.reason.prop;
18772 }
18773 
18774 /** returns inference user information of given bound change information */
18776  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18777  )
18778 {
18779  assert(bdchginfo != NULL);
18782 
18783  return bdchginfo->inferencedata.info;
18784 }
18785 
18786 /** returns inference bound of inference variable of given bound change information */
18788  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18789  )
18790 {
18791  assert(bdchginfo != NULL);
18794 
18795  return (SCIP_BOUNDTYPE)(bdchginfo->inferboundtype);
18796 }
18797 
18798 /** returns the relaxed bound change type */
18800  SCIP_BDCHGINFO* bdchginfo /**< bound change to add to the conflict set */
18801  )
18802 {
18803  return ((SCIP_BOUNDTYPE)(bdchginfo->boundtype) == SCIP_BOUNDTYPE_LOWER ? bdchginfo->var->conflictrelaxedlb : bdchginfo->var->conflictrelaxedub);
18804 }
18805 
18806 
18807 /** returns whether the bound change information belongs to a redundant bound change */
18809  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18810  )
18811 {
18812  assert(bdchginfo != NULL);
18813  assert(bdchginfo->redundant == (bdchginfo->oldbound == bdchginfo->newbound)); /*lint !e777*/
18814 
18815  return bdchginfo->redundant;
18816 }
18817 
18818 /** returns whether the bound change has an inference reason (constraint or propagator), that can be resolved */
18820  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18821  )
18822 {
18823  assert(bdchginfo != NULL);
18824 
18827  && bdchginfo->inferencedata.reason.prop != NULL);
18828 }
18829 
18830 /** for two bound change informations belonging to the same variable and bound, returns whether the first bound change
18831  * has a tighter new bound as the second bound change
18832  */
18834  SCIP_BDCHGINFO* bdchginfo1, /**< first bound change information */
18835  SCIP_BDCHGINFO* bdchginfo2 /**< second bound change information */
18836  )
18837 {
18838  assert(bdchginfo1 != NULL);
18839  assert(bdchginfo2 != NULL);
18840  assert(bdchginfo1->var == bdchginfo2->var);
18841  assert(bdchginfo1->boundtype == bdchginfo2->boundtype);
18842 
18843  return (SCIPbdchginfoGetBoundtype(bdchginfo1) == SCIP_BOUNDTYPE_LOWER
18844  ? bdchginfo1->newbound > bdchginfo2->newbound
18845  : bdchginfo1->newbound < bdchginfo2->newbound);
18846 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:61
SCIP_Real SCIPhistoryGetAvgConflictlength(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:578
union SCIP_BoundChg::@21 data
SCIP_HOLELIST * holelist
Definition: struct_var.h:172
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:59
SCIP_RETCODE SCIPeventfilterCreate(SCIP_EVENTFILTER **eventfilter, BMS_BLKMEM *blkmem)
Definition: event.c:1821
SCIP_Real SCIPbdchginfoGetRelaxedBound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18800
void SCIPcliquelistRemoveFromCliques(SCIP_CLIQUELIST *cliquelist, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Bool irrelevantvar)
Definition: implics.c:1683
static SCIP_Real adjustedUb(SCIP_SET *set, SCIP_VARTYPE vartype, SCIP_Real ub)
Definition: var.c:1589
SCIP_Real SCIPvarGetAvgConflictlengthCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15405
SCIP_Real SCIPvarGetWorstBoundLocal(SCIP_VAR *var)
Definition: var.c:18178
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6269
SCIP_Real * SCIPvarGetVlbCoefs(SCIP_VAR *var)
Definition: var.c:18293
#define BMSfreeBlockMemoryArrayNull(mem, ptr, num)
Definition: memory.h:468
#define NULL
Definition: def.h:267
void SCIPvarGetClosestVlb(SCIP_VAR *var, SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *closestvlb, int *closestvlbidx)
Definition: var.c:14124
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:1003
SCIP_BOUNDTYPE SCIPvarGetWorstBoundType(SCIP_VAR *var)
Definition: var.c:18204
static void checkImplic(SCIP_SET *set, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool *redundant, SCIP_Bool *infeasible)
Definition: var.c:9383
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:15532
SCIP_Bool SCIPvarsHaveCommonClique(SCIP_VAR *var1, SCIP_Bool value1, SCIP_VAR *var2, SCIP_Bool value2, SCIP_Bool regardimplics)
Definition: var.c:11476
SCIP_BRANCHINGDATA branchingdata
Definition: struct_var.h:96
void SCIPhistoryIncNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, int depth)
Definition: history.c:591
SCIP_VAR ** SCIPcliqueGetVars(SCIP_CLIQUE *clique)
Definition: implics.c:3380
SCIP_Bool SCIPsetIsLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6327
SCIP_Bool SCIPsetIsFeasZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6777
internal methods for storing primal CIP solutions
void SCIPhistoryIncVSIDS(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition: history.c:510
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:15052
static SCIP_RETCODE varEventImplAdded(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:9265
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:10466
SCIP_Real SCIPvarGetBdAtIndex(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16951
SCIP_PROP * SCIPbdchginfoGetInferProp(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18765
void SCIPvarMarkNotDeletable(SCIP_VAR *var)
Definition: var.c:17664
void SCIPvarUpdateBestRootSol(SCIP_VAR *var, SCIP_SET *set, SCIP_Real rootsol, SCIP_Real rootredcost, SCIP_Real rootlpobjval)
Definition: var.c:13281
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:488
SCIP_RETCODE SCIPvarSetNLPSol(SCIP_VAR *var, SCIP_SET *set, SCIP_Real solval)
Definition: var.c:14007
int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:3296
public methods for branching and inference history structure
SCIP_Bool SCIPlpDiving(SCIP_LP *lp)
Definition: lp.c:17847
int nubchginfos
Definition: struct_var.h:269
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoLb(SCIP_VAR *var, int pos)
Definition: var.c:18479
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition: var.c:17871
SCIP_Real SCIPvarGetAvgGMIScore(SCIP_VAR *var, SCIP_STAT *stat)
Definition: var.c:16360
internal methods for branch and bound tree
SCIP_Longint SCIPgetNLPIterations(SCIP *scip)
SCIP_BDCHGIDX bdchgidx
Definition: struct_var.h:121
void SCIPhistoryIncCutoffSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition: history.c:623
SCIP_Real SCIPvarGetAvgCutoffsCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:16313
SCIP_RETCODE SCIPvaluehistoryCreate(SCIP_VALUEHISTORY **valuehistory, BMS_BLKMEM *blkmem)
Definition: history.c:243
SCIP_Real SCIPsetFeastol(SCIP_SET *set)
Definition: set.c:6176
SCIP_Real SCIPvarGetBranchFactor(SCIP_VAR *var)
Definition: var.c:18239
unsigned int inferboundtype
Definition: struct_var.h:102
SCIP_Real SCIPbdchginfoGetOldbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18661
unsigned int relaxationonly
Definition: struct_var.h:286
char * name
Definition: struct_var.h:235
static SCIP_RETCODE domchgCreate(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem)
Definition: var.c:1040
unsigned int boundchgtype
Definition: struct_var.h:123
SCIP_BRANCHDIR SCIPvarGetBranchDirection(SCIP_VAR *var)
Definition: var.c:18261
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:1151
SCIP_HOLE hole
Definition: struct_var.h:60
SCIP_Real bestrootsol
Definition: struct_var.h:213
char * name
Definition: struct_lp.h:226
SCIP_Real SCIPvarGetUbLazy(SCIP_VAR *var)
Definition: var.c:18227
SCIP_Real SCIPsetFloor(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6456
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:6836
SCIP_Bool SCIPsetIsFeasEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6667
int SCIPvarGetNVlbs(SCIP_VAR *var)
Definition: var.c:18271
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18681
#define SCIPsetDuplicateBufferArray(set, ptr, source, num)
Definition: set.h:1750
SCIP_Real SCIPvarGetWorstBoundGlobal(SCIP_VAR *var)
Definition: var.c:18122
#define SCIP_DECL_VARTRANS(x)
Definition: type_var.h:151
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:7186
enum SCIP_BaseStat SCIP_BASESTAT
Definition: type_lpi.h:96
SCIP_Bool SCIPvarDoNotMultaggr(SCIP_VAR *var)
Definition: var.c:5882
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:2118
public methods for implications, variable bounds, and cliques
SCIP_Real SCIPvarGetPseudocostCountCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14619
methods for implications, variable bounds, and cliques
int SCIPvarGetLastBdchgDepth(SCIP_VAR *var)
Definition: var.c:17031
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:2240
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:18079
SCIP_Real SCIPvarGetAvgBranchdepth(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15788
SCIP_RETCODE SCIPvarGetProbvarBinary(SCIP_VAR **var, SCIP_Bool *negated)
Definition: var.c:12311
SCIP_RETCODE SCIPdomchgAddHolechg(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HOLELIST **ptr, SCIP_HOLELIST *newlist, SCIP_HOLELIST *oldlist)
Definition: var.c:1520
SCIP_Bool SCIPvarIsPscostRelerrorReliable(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real threshold, SCIP_CONFIDENCELEVEL clevel)
Definition: var.c:14785
#define SCIP_MAXSTRLEN
Definition: def.h:288
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:3354
SCIP_DOM origdom
Definition: struct_var.h:178
SCIP_BASESTAT SCIPcolGetBasisStatus(SCIP_COL *col)
Definition: lp.c:17031
SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition: var.c:17621
SCIP_RETCODE SCIPeventCreateImplAdded(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition: event.c:814
SCIP_VAR ** SCIPimplicsGetVars(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3331
SCIP_RETCODE SCIPvarChgLbOriginal(SCIP_VAR *var, SCIP_SET *set, SCIP_Real newbound)
Definition: var.c:6568
SCIP_BOUNDCHG * boundchgs
Definition: struct_var.h:134
void SCIPhistoryIncInferenceSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition: history.c:607
SCIP_Bool SCIPsetIsPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6392
SCIP_Real lastbranchvalue
Definition: struct_stat.h:143
static SCIP_RETCODE domchgMakeDynamic(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem)
Definition: var.c:1110
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition: var.c:17859
static long bound
#define SCIPdebugCheckImplic(set, var, varfixing, implvar, impltype, implbound)
Definition: debug.h:292
static void printHolelist(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, SCIP_HOLELIST *holelist, const char *name)
Definition: var.c:2973
#define MAXABSVBCOEF
Definition: var.c:80
#define SQR(x)
Definition: def.h:214
#define SCIPsetAllocCleanBufferArray(set, ptr, num)
Definition: set.h:1759
static SCIP_Real getImplVarRedcost(SCIP_VAR *var, SCIP_SET *set, SCIP_Bool varfixing, SCIP_STAT *stat, SCIP_LP *lp)
Definition: var.c:13416
SCIP_RETCODE SCIPbdchginfoCreate(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_Real oldbound, SCIP_Real newbound)
Definition: var.c:16534
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:1979
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:18135
SCIP_RETCODE SCIPvarChgLbLazy(SCIP_VAR *var, SCIP_SET *set, SCIP_Real lazylb)
Definition: var.c:7470
SCIP_Real constant
Definition: struct_var.h:193
SCIP_CLIQUE ** SCIPvarGetCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18442
SCIP_RETCODE SCIPprobVarChangedStatus(SCIP_PROB *prob, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_BRANCHCAND *branchcand, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var)
Definition: prob.c:1224
SCIP_Real bestrootredcost
Definition: struct_var.h:214
SCIP_Real SCIPvarGetMultaggrLbGlobal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8567
SCIP_HISTORY * historycrun
Definition: struct_var.h:251
SCIP_BRANCHDIR lastbranchdir
Definition: struct_stat.h:187
SCIP_VALUEHISTORY * SCIPvarGetValuehistory(SCIP_VAR *var)
Definition: var.c:18521
int SCIPcliquelistGetNCliques(SCIP_CLIQUELIST *cliquelist, SCIP_Bool value)
Definition: implics.c:3446
SCIP_NODE * SCIPnodeGetParent(SCIP_NODE *node)
Definition: tree.c:7724
void SCIPprobAddObjoffset(SCIP_PROB *prob, SCIP_Real addval)
Definition: prob.c:1481
void SCIPvarSetTransData(SCIP_VAR *var, SCIP_DECL_VARTRANS((*vartrans)))
Definition: var.c:17473
SCIP_RETCODE SCIPvarChgUbOriginal(SCIP_VAR *var, SCIP_SET *set, SCIP_Real newbound)
Definition: var.c:6627
SCIP_Longint closestvblpcount
Definition: struct_var.h:253
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:8875
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:2497
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:17600
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:6763
SCIP_VAR ** SCIPvboundsGetVars(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3298
SCIP_Real SCIPsetInfinity(SCIP_SET *set)
Definition: set.c:6134
SCIP_DOMCHGBOTH domchgboth
Definition: struct_var.h:163
SCIP_RETCODE SCIPcolChgObj(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newobj)
Definition: lp.c:3698
SCIP_Real SCIPvarGetSol(SCIP_VAR *var, SCIP_Bool getlpval)
Definition: var.c:13258
int SCIPprobGetNVars(SCIP_PROB *prob)
Definition: prob.c:2393
SCIP_BDCHGINFO * ubchginfos
Definition: struct_var.h:249
SCIP_Bool SCIPbdchgidxIsEarlier(SCIP_BDCHGIDX *bdchgidx1, SCIP_BDCHGIDX *bdchgidx2)
Definition: var.c:18641
SCIP_Bool SCIPvarWasFixedAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16971
SCIP_Real SCIPvarGetBestBoundLocal(SCIP_VAR *var)
Definition: var.c:18165
SCIP_Real SCIPvarGetRootSol(SCIP_VAR *var)
Definition: var.c:13351
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:911
SCIP_RETCODE SCIPvarMarkDoNotMultaggr(SCIP_VAR *var)
Definition: var.c:6143
SCIP_RETCODE SCIPvarScaleVSIDS(SCIP_VAR *var, SCIP_Real scalar)
Definition: var.c:15138
SCIP_Real SCIPvarGetLbLP(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:12933
static SCIP_RETCODE holelistDuplicate(SCIP_HOLELIST **target, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HOLELIST *source)
Definition: var.c:203
SCIP_BOUNDTYPE SCIPboundchgGetBoundtype(SCIP_BOUNDCHG *boundchg)
Definition: var.c:17347
unsigned int nboundchgs
Definition: struct_var.h:132
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:18559
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:3279
SCIP_HOLELIST * newlist
Definition: struct_var.h:68
SCIP_Real right
Definition: struct_var.h:54
void SCIPvaluehistoryScaleVSIDS(SCIP_VALUEHISTORY *valuehistory, SCIP_Real scalar)
Definition: history.c:329
void SCIPvarSetProbindex(SCIP_VAR *var, int probindex)
Definition: var.c:6027
#define NLOCKTYPES
Definition: type_var.h:94
SCIP_RETCODE SCIPhistoryCreate(SCIP_HISTORY **history, BMS_BLKMEM *blkmem)
Definition: history.c:51
SCIP_HOLELIST * SCIPholelistGetNext(SCIP_HOLELIST *holelist)
Definition: var.c:17407
#define FALSE
Definition: def.h:94
int lppos
Definition: struct_lp.h:172
#define EPSEQ(x, y, eps)
Definition: def.h:198
#define EPSISINT(x, eps)
Definition: def.h:210
SCIP_Bool SCIPlpIsSolBasic(SCIP_LP *lp)
Definition: lp.c:17837
datastructures for managing events
SCIP_Bool SCIPsetIsFeasIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6810
int SCIPvarGetNBdchgInfosLb(SCIP_VAR *var)
Definition: var.c:18491
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:555
struct SCIP_VarData SCIP_VARDATA
Definition: type_var.h:120
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:1349
SCIP_Real SCIPcolGetUb(SCIP_COL *col)
Definition: lp.c:16973
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:826
SCIP_RETCODE SCIPvarTransform(SCIP_VAR *origvar, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_OBJSENSE objsense, SCIP_VAR **transvar)
Definition: var.c:3462
void SCIPhistoryReset(SCIP_HISTORY *history)
Definition: history.c:78
SCIP_Real SCIPcolGetObj(SCIP_COL *col)
Definition: lp.c:16953
int nlocksup[NLOCKTYPES]
Definition: struct_var.h:264
static SCIP_RETCODE varEventVarUnlocked(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:3147
SCIP_Real constant
Definition: struct_var.h:203
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10877
SCIP_Bool SCIPsetIsZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6381
SCIP_RETCODE SCIPvboundsDel(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem, SCIP_VAR *vbdvar, SCIP_Bool negativecoef)
Definition: implics.c:288
static SCIP_Bool useValuehistory(SCIP_VAR *var, SCIP_Real value, SCIP_SET *set)
Definition: var.c:15024
#define TRUE
Definition: def.h:93
SCIP_Bool SCIPvarHasImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition: var.c:11112
static void varSetProbindex(SCIP_VAR *var, int probindex)
Definition: var.c:6008
SCIP_Real SCIPvarGetAvgConflictlength(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15361
SCIP_INFERENCEDATA inferencedata
Definition: struct_var.h:120
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
SCIP_HOLELIST * oldlist
Definition: struct_var.h:69
SCIP_Real SCIPvarGetNegationConstant(SCIP_VAR *var)
Definition: var.c:17916
#define MAXIMPLSCLOSURE
Definition: var.c:77
void SCIPimplicsGetVarImplicPoss(SCIP_IMPLICS *implics, SCIP_Bool varfixing, SCIP_VAR *implvar, int *lowerimplicpos, int *upperimplicpos)
Definition: implics.c:916
int SCIPvarGetNVubs(SCIP_VAR *var)
Definition: var.c:18313
SCIP_RETCODE SCIPeventCreateUbChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition: event.c:700
int SCIPbdchginfoGetInferInfo(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18776
int nlbchginfos
Definition: struct_var.h:267
static SCIP_BDCHGIDX presolvebdchgidx
Definition: var.c:16991
enum SCIP_Varstatus SCIP_VARSTATUS
Definition: type_var.h:57
#define SCIPsetAllocBufferArray(set, ptr, num)
Definition: set.h:1748
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:2075
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:17769
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:10913
#define SCIP_DECL_VARCOPY(x)
Definition: type_var.h:194
SCIP_RETCODE SCIPvarChgLbDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newbound)
Definition: var.c:8250
void SCIPvarSetNamePointer(SCIP_VAR *var, const char *name)
Definition: var.c:6042
int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
Definition: set.c:5834
#define SCIP_EVENTTYPE_GLBCHANGED
Definition: type_event.h:75
SCIP_Real SCIPsetRound(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6478
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:8224
SCIP_Real SCIPvarGetAggrScalar(SCIP_VAR *var)
Definition: var.c:17823
void SCIPvarInitSolve(SCIP_VAR *var)
Definition: var.c:2932
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:7329
public methods for problem variables
static GRAPHNODE ** active
SCIP_Real SCIPvarGetInferenceSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15980
void SCIPvarMarkDeletable(SCIP_VAR *var)
Definition: var.c:17653
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:1930
SCIP_RETCODE SCIPimplicsDel(SCIP_IMPLICS **implics, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition: implics.c:836
SCIP_Real SCIPvarGetAvgInferences(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:16068
SCIP_Real SCIPhistoryGetVSIDS(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:536
#define SCIPdebugMessage
Definition: pub_message.h:96
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:11271
SCIP_VAR ** SCIPvarGetVlbVars(SCIP_VAR *var)
Definition: var.c:18283
void SCIPprobUpdateNObjVars(SCIP_PROB *prob, SCIP_SET *set, SCIP_Real oldobj, SCIP_Real newobj)
Definition: prob.c:1592
SCIP_RETCODE SCIPvarsGetActiveVars(SCIP_SET *set, SCIP_VAR **vars, int *nvars, int varssize, int *requiredsize)
Definition: var.c:12007
int SCIPbdchgidxGetPos(SCIP_BDCHGIDX *bdchgidx)
Definition: var.c:18611
SCIP_CLIQUE ** SCIPcliquelistGetCliques(SCIP_CLIQUELIST *cliquelist, SCIP_Bool value)
Definition: implics.c:3455
SCIP_PROB * transprob
Definition: struct_scip.h:99
int index
Definition: struct_var.h:254
SCIP_Real constant
Definition: struct_var.h:186
unsigned int domchgtype
Definition: struct_var.h:151
SCIP_Bool SCIPsetIsNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6403
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:6179
SCIP_RETCODE SCIPcliquelistAdd(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: implics.c:1482
SCIP_Bool SCIPvarIsDeletable(SCIP_VAR *var)
Definition: var.c:17739
int SCIPvarGetConflictingBdchgDepth(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real bound)
Definition: var.c:17046
SCIP_RETCODE SCIPvarUpdatePseudocost(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition: var.c:14380
#define SCIPsetFreeBufferArray(set, ptr)
Definition: set.h:1755
SCIP_Longint SCIPvarGetNBranchingsCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15745
SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
Definition: var.c:17631
void SCIPvarAdjustLb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *lb)
Definition: var.c:6518
static SCIP_RETCODE domchgEnsureBoundchgsSize(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: var.c:1251
#define SCIPdebugCheckVbound(set, var, vbtype, vbvar, vbcoef, vbconstant)
Definition: debug.h:291
SCIP_RETCODE SCIPvarChgBranchDirection(SCIP_VAR *var, SCIP_BRANCHDIR branchdirection)
Definition: var.c:11819
SCIP_Real SCIPhistoryGetAvgCutoffs(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:691
SCIP_HOLECHG * holechgs
Definition: struct_var.h:143
SCIP_Real obj
Definition: struct_var.h:209
SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition: var.c:17905
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:5528
SCIP_Real relaxsol
Definition: struct_var.h:216
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:1610
static SCIP_RETCODE boundchgCaptureData(SCIP_BOUNDCHG *boundchg)
Definition: var.c:971
SCIP_Real SCIPsetCeil(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6467
int conflictlbcount
Definition: struct_var.h:270
SCIP_Real SCIPvarGetRelaxSolTransVar(SCIP_VAR *var)
Definition: var.c:13996
#define SCIPstatIncrement(stat, set, field)
Definition: stat.h:260
SCIP_Real SCIPsetGetHugeValue(SCIP_SET *set)
Definition: set.c:6146
internal methods for LP management
SCIP_BDCHGIDX * SCIPvarGetLastBdchgIndex(SCIP_VAR *var)
Definition: var.c:16994
int SCIPvarGetNCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18431
Definition: heur_padm.c:134
SCIP_PROB * origprob
Definition: struct_scip.h:81
SCIP_Real SCIPvarGetLPSol_rec(SCIP_VAR *var)
Definition: var.c:13070
SCIP_Real SCIPhistoryGetPseudocost(SCIP_HISTORY *history, SCIP_Real solvaldelta)
Definition: history.c:446
SCIP_VAR ** vars
Definition: struct_var.h:195
static void domMerge(SCIP_DOM *dom, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real *newlb, SCIP_Real *newub)
Definition: var.c:269
real eps
internal methods for branching and inference history
int nrootintfixings
Definition: struct_stat.h:224
int branchpriority
Definition: struct_var.h:265
SCIP_Real SCIPvarGetCutoffSumCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:16223
int * SCIPvarGetImplIds(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18419
SCIP_HOLELIST * SCIPvarGetHolelistOriginal(SCIP_VAR *var)
Definition: var.c:18065
SCIP_RETCODE SCIPeventCreateObjChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldobj, SCIP_Real newobj)
Definition: event.c:605
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:1372
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:2350
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:206
SCIP_DECL_HASHKEYVAL(SCIPvarGetHashkeyVal)
Definition: var.c:12000
SCIP_VAR * var
Definition: struct_var.h:187
#define SCIP_EVENTTYPE_LBCHANGED
Definition: type_event.h:121
SCIP_Real SCIPvarGetUbLP(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:13003
int nrootboundchgs
Definition: struct_stat.h:222
#define SCIP_DECL_VARDELTRANS(x)
Definition: type_var.h:164
SCIP_Bool SCIPsetIsGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6363
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:7547
SCIP_HISTORY * glbhistorycrun
Definition: struct_stat.h:182
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:17895
const char * SCIPgetProbName(SCIP *scip)
Definition: scip_prob.c:1067
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3423
SCIP_Real SCIPvarGetVSIDSCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15929
void SCIPhistoryScaleVSIDS(SCIP_HISTORY *history, SCIP_Real scalar)
Definition: history.c:524
enum SCIP_BranchDir SCIP_BRANCHDIR
Definition: type_history.h:48
SCIP_Bool SCIPrealToRational(SCIP_Real val, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Longint *nominator, SCIP_Longint *denominator)
Definition: misc.c:9394
SCIP_Real SCIPvarGetNLPSol_rec(SCIP_VAR *var)
Definition: var.c:13143
int SCIPvarGetNBdchgInfosUb(SCIP_VAR *var)
Definition: var.c:18511
void SCIPcliquelistFree(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem)
Definition: implics.c:1441
SCIP_Real conflictrelaxedub
Definition: struct_var.h:222
SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
Definition: tree.c:7444
SCIP_Bool SCIPbdchginfoIsTighter(SCIP_BDCHGINFO *bdchginfo1, SCIP_BDCHGINFO *bdchginfo2)
Definition: var.c:18834
unsigned int inferboundtype
Definition: struct_var.h:125
SCIP_RETCODE SCIPeventCreateVarFixed(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition: event.c:562
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:7971
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:18089
SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6309
SCIP_RETCODE SCIPvarIncGMIeffSum(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real gmieff)
Definition: var.c:16400
SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
Definition: var.c:12219
SCIP_Real SCIPvarGetObjLP(SCIP_VAR *var)
Definition: var.c:12887
void SCIPhistoryIncGMIeffSum(SCIP_HISTORY *history, SCIP_Real gmieff)
Definition: history.c:759
SCIP_RETCODE SCIPvaluehistoryFind(SCIP_VALUEHISTORY *valuehistory, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real value, SCIP_HISTORY **history)
Definition: history.c:284
SCIP_Real SCIPvarGetBestRootLPObjval(SCIP_VAR *var)
Definition: var.c:13817
void SCIPvarSetHistory(SCIP_VAR *var, SCIP_HISTORY *history, SCIP_STAT *stat)
Definition: var.c:4536
public methods for managing constraints
static SCIP_RETCODE varProcessChgBranchFactor(SCIP_VAR *var, SCIP_SET *set, SCIP_Real branchfactor)
Definition: var.c:11497
SCIP_Real SCIPhistoryGetPseudocostVariance(SCIP_HISTORY *history, SCIP_BRANCHDIR direction)
Definition: history.c:460
SCIP_Real SCIPvarGetImplRedcost(SCIP_VAR *var, SCIP_SET *set, SCIP_Bool varfixing, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_LP *lp)
Definition: var.c:13469
SCIP_RETCODE SCIPstatUpdateVarRootLPBestEstimate(SCIP_STAT *stat, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldrootpscostscore)
Definition: stat.c:807
void SCIPvaluehistoryFree(SCIP_VALUEHISTORY **valuehistory, BMS_BLKMEM *blkmem)
Definition: history.c:262
SCIP_Real conflictrelaxedlb
Definition: struct_var.h:221
void SCIPvarSetDelorigData(SCIP_VAR *var, SCIP_DECL_VARDELORIG((*vardelorig)))
Definition: var.c:17461
enum SCIP_Confidencelevel SCIP_CONFIDENCELEVEL
Definition: type_misc.h:53
SCIP_RETCODE SCIPvarChgBranchPriority(SCIP_VAR *var, int branchpriority)
Definition: var.c:11688
SCIP_Real SCIPvarGetPseudocost(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition: var.c:14478
SCIP_AGGREGATE aggregate
Definition: struct_var.h:231
SCIP_Real lazylb
Definition: struct_var.h:223
#define BMSduplicateBlockMemoryArray(mem, ptr, source, num)
Definition: memory.h:462
SCIP_Real SCIPcolGetPrimsol(SCIP_COL *col)
Definition: lp.c:16996
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:7585
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:1384
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:1886
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:4551
void SCIPvarSetDeltransData(SCIP_VAR *var, SCIP_DECL_VARDELTRANS((*vardeltrans)))
Definition: var.c:17485
SCIP_RETCODE SCIPvarChgUbLazy(SCIP_VAR *var, SCIP_SET *set, SCIP_Real lazyub)
Definition: var.c:7493
SCIP_Real SCIPvarGetBestBoundGlobal(SCIP_VAR *var)
Definition: var.c:18109
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:7805
void SCIPvarMergeHistories(SCIP_VAR *targetvar, SCIP_VAR *othervar, SCIP_STAT *stat)
Definition: var.c:4520
enum SCIP_LockType SCIP_LOCKTYPE
Definition: type_var.h:100
void SCIPhistoryIncNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real length)
Definition: history.c:549
SCIP_BOUNDTYPE * SCIPimplicsGetTypes(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3340
SCIP_Bool SCIPvarDoNotAggr(SCIP_VAR *var)
Definition: var.c:5849
internal methods for storing and manipulating the main problem
#define MAX_CLIQUELENGTH
Definition: var.c:13465
#define SCIPerrorMessage
Definition: pub_message.h:64
SCIP_Bool SCIPboundchgIsRedundant(SCIP_BOUNDCHG *boundchg)
Definition: var.c:17357
void SCIPlpDecNLoosevars(SCIP_LP *lp)
Definition: lp.c:14330
SCIP_Real SCIPvarGetLbOriginal(SCIP_VAR *var)
Definition: var.c:18025
void SCIPcliqueDelVar(SCIP_CLIQUE *clique, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Bool value)
Definition: implics.c:1285
SCIP_RETCODE SCIPdomchgMakeStatic(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:1162
SCIP_VBOUNDS * vlbs
Definition: struct_var.h:243
SCIP_RETCODE SCIPdomchgFree(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:1061
static SCIP_BDCHGIDX initbdchgidx
Definition: var.c:16988
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:14928
static SCIP_RETCODE varEnsureUbchginfosSize(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: var.c:454
SCIP_Bool SCIPimplicsContainsImpl(SCIP_IMPLICS *implics, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition: implics.c:933
SCIP_Longint lpcount
Definition: struct_stat.h:190
SCIP_Bool SCIPbdchgidxIsEarlierNonNull(SCIP_BDCHGIDX *bdchgidx1, SCIP_BDCHGIDX *bdchgidx2)
Definition: var.c:18621
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:633
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:6265
int SCIPvarCompareActiveAndNegated(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11905
int lbchginfossize
Definition: struct_var.h:266
SCIP_Real SCIPvarGetAvgBranchdepthCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15833
unsigned int varstatus
Definition: struct_var.h:281
SCIP_RETCODE SCIPvarRelease(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:2873
SCIP_Real SCIPvarGetUbOriginal(SCIP_VAR *var)
Definition: var.c:18045
SCIP_Bool SCIPvarIsTransformedOrigvar(SCIP_VAR *var)
Definition: var.c:12862
SCIP_Real SCIPhistoryGetAvgBranchdepth(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:704
void SCIPhistorySetLastGMIeff(SCIP_HISTORY *history, SCIP_Real gmieff)
Definition: history.c:782
SCIP_Real bestrootlpobjval
Definition: struct_var.h:215
SCIP_VARDATA * vardata
Definition: struct_var.h:240
SCIP_RETCODE SCIPvarChgObjDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newobj)
Definition: var.c:6455
SCIP_EVENTTYPE eventmask
Definition: struct_event.h:198
SCIP_DECL_SORTPTRCOMP(SCIPvarCompActiveAndNegated)
Definition: var.c:11935
SCIP_Real SCIPvarGetPseudocostCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition: var.c:14527
SCIP_Real SCIPvarGetUbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16830
SCIP_Bool SCIPsortedvecFindPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), void *val, int len, int *pos)
SCIP_Real primsolavg
Definition: struct_var.h:218
void SCIPstrCopySection(const char *str, char startchar, char endchar, char *token, int size, char **endptr)
Definition: misc.c:11007
SCIP_Bool SCIPvarHasBinaryImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_Bool implvarfixing)
Definition: var.c:11132
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:3168
SCIP_RETCODE SCIPvarGetTransformed(SCIP_VAR *origvar, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **transvar)
Definition: var.c:3549
#define SCIPdebugCheckAggregation(set, var, aggrvars, scalars, constant, naggrvars)
Definition: debug.h:293
SCIP_HOLECHG * holechgs
Definition: struct_var.h:153
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8216
SCIP_Real * SCIPvarGetVubConstants(SCIP_VAR *var)
Definition: var.c:18345
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:7012
SCIP_OBJSENSE objsense
Definition: struct_prob.h:87
unsigned int pos
Definition: struct_var.h:122
static SCIP_RETCODE varSetName(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_STAT *stat, const char *name)
Definition: var.c:1898
SCIP_Real SCIPvarGetAggrConstant(SCIP_VAR *var)
Definition: var.c:17835
SCIP_Real SCIPcolGetLb(SCIP_COL *col)
Definition: lp.c:16963
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:173
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17420
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:5055
SCIP_VAR * transvar
Definition: struct_var.h:179
SCIP_DOMCHGDYN domchgdyn
Definition: struct_var.h:164
#define MAXDNOM
SCIP_Real SCIPsetFeasCeil(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6845
void SCIPhistoryUnite(SCIP_HISTORY *history, SCIP_HISTORY *addhistory, SCIP_Bool switcheddirs)
Definition: history.c:113
void SCIPmessagePrintWarning(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
Definition: message.c:427
#define SCIPsetReallocBufferArray(set, ptr, num)
Definition: set.h:1752
SCIP_Longint SCIPhistoryGetNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:565
SCIP_RETCODE SCIPeventCreateLbChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition: event.c:674
SCIP_DECL_HASHGETKEY(SCIPvarGetHashkey)
Definition: var.c:11986
unsigned int initial
Definition: struct_var.h:274
void SCIPvarGetClosestVub(SCIP_VAR *var, SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *closestvub, int *closestvubidx)
Definition: var.c:14199
SCIP_NEGATE negate
Definition: struct_var.h:233
static SCIP_RETCODE holelistCreate(SCIP_HOLELIST **holelist, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real left, SCIP_Real right)
Definition: var.c:153
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:7638
SCIP_RETCODE SCIPvarSetRelaxSol(SCIP_VAR *var, SCIP_SET *set, SCIP_RELAXATION *relaxation, SCIP_Real solval, SCIP_Bool updateobj)
Definition: var.c:13863
SCIP_HISTORY * glbhistory
Definition: struct_stat.h:181
SCIP_Real SCIPboundchgGetNewbound(SCIP_BOUNDCHG *boundchg)
Definition: var.c:17317
SCIP_Real * SCIPvboundsGetCoefs(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3306
#define REALABS(x)
Definition: def.h:197
int nparentvars
Definition: struct_var.h:261
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition: var.c:18453
SCIP_Real unchangedobj
Definition: struct_var.h:210
SCIP_HOLELIST * SCIPvarGetHolelistGlobal(SCIP_VAR *var)
Definition: var.c:18099
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:10002
SCIP_Longint SCIPvarGetNActiveConflicts(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15269
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:17949
SCIP_Real SCIPvarCalcPscostConfidenceBound(SCIP_VAR *var, SCIP_SET *set, SCIP_BRANCHDIR dir, SCIP_Bool onlycurrentrun, SCIP_CONFIDENCELEVEL clevel)
Definition: var.c:14747
#define SCIP_CALL(x)
Definition: def.h:380
SCIP main data structure.
SCIP_Bool SCIPbdchginfoHasInferenceReason(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18820
SCIP_VBOUNDS * vubs
Definition: struct_var.h:244
SCIP_Real SCIPvarGetLbLazy(SCIP_VAR *var)
Definition: var.c:18217
SCIP_Bool SCIPsetIsFeasGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6755
SCIP_Real * SCIPvarGetVlbConstants(SCIP_VAR *var)
Definition: var.c:18303
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:15448
SCIP_Real SCIPvarGetMultaggrConstant(SCIP_VAR *var)
Definition: var.c:17883
SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
Definition: var.c:17707
int SCIPprobGetNContVars(SCIP_PROB *prob)
Definition: prob.c:2429
SCIP_Real SCIPvarGetPseudocostCount(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14574
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:9721
static SCIP_VAR * varGetActiveVar(SCIP_VAR *var)
Definition: var.c:5800
SCIP_Real * SCIPvboundsGetConstants(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3314
SCIP_Real SCIPvarGetCutoffSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:16180
SCIP_Real * SCIPvarGetVubCoefs(SCIP_VAR *var)
Definition: var.c:18335
SCIP_Bool SCIPbdchginfoIsRedundant(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18809
int closestvubidx
Definition: struct_var.h:273
internal methods for relaxators
SCIP_Real SCIPvarGetMinPseudocostScore(SCIP_VAR *var, SCIP_STAT *stat, SCIP_SET *set, SCIP_Real solval)
Definition: var.c:14662
SCIP_Real SCIPhistoryGetPseudocostCount(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:484
SCIP_Bool SCIPsetIsEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6291
static SCIP_RETCODE varProcessChgBranchPriority(SCIP_VAR *var, int branchpriority)
Definition: var.c:11632
SCIP_Real vsidsweight
Definition: struct_stat.h:132
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:8098
#define SCIPdebugCheckLbGlobal(scip, var, lb)
Definition: debug.h:285
unsigned int nboundchgs
Definition: struct_var.h:150
SCIP_BDCHGIDX * SCIPbdchginfoGetIdx(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18731
SCIP_Longint SCIPvarGetNActiveConflictsCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15316
SCIP_RETCODE SCIPvarPrint(SCIP_VAR *var, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: var.c:3007
unsigned int branchdirection
Definition: struct_var.h:283
int ubchginfossize
Definition: struct_var.h:268
SCIP_Bool SCIPcliquelistsHaveCommonClique(SCIP_CLIQUELIST *cliquelist1, SCIP_Bool value1, SCIP_CLIQUELIST *cliquelist2, SCIP_Bool value2)
Definition: implics.c:1605
SCIP_Bool SCIPsetIsFeasLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6711
#define SCIPdebugCheckUbGlobal(scip, var, ub)
Definition: debug.h:286
#define SCIP_EVENTTYPE_UBCHANGED
Definition: type_event.h:122
void SCIPvboundsShrink(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem, int newnvbds)
Definition: implics.c:333
void SCIPvarSetBestRootSol(SCIP_VAR *var, SCIP_Real rootsol, SCIP_Real rootredcost, SCIP_Real rootlpobjval)
Definition: var.c:13848
int var_probindex
Definition: struct_lp.h:178
int nlocksdown[NLOCKTYPES]
Definition: struct_var.h:263
void SCIPvarAdjustBd(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real *bd)
Definition: var.c:6552
#define BMSfreeBlockMemory(mem, ptr)
Definition: memory.h:465
internal methods for problem variables
SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
Definition: var.c:17549
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:6230
SCIP_RETCODE SCIPvarChgBranchFactor(SCIP_VAR *var, SCIP_SET *set, SCIP_Real branchfactor)
Definition: var.c:11561
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:5293
#define SCIP_UNKNOWN
Definition: def.h:194
SCIP_Bool SCIPsetIsIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6414
public data structures and miscellaneous methods
unsigned int vartype
Definition: struct_var.h:280
SCIP_BOUNDTYPE * SCIPvarGetImplTypes(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18389
unsigned int boundchgtype
Definition: struct_var.h:100
#define BMSfreeBlockMemorySize(mem, ptr, size)
Definition: memory.h:469
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:15616
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:6687
SCIP_VAR * var
Definition: struct_var.h:99
SCIP_INFERENCEDATA inferencedata
Definition: struct_var.h:97
SCIP_Real SCIPholelistGetRight(SCIP_HOLELIST *holelist)
Definition: var.c:17397
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:8994
#define SCIP_Bool
Definition: def.h:91
void SCIPvarCapture(SCIP_VAR *var)
Definition: var.c:2848
#define BMSreallocBlockMemorySize(mem, ptr, oldsize, newsize)
Definition: memory.h:456
SCIP_BOUNDCHGTYPE SCIPboundchgGetBoundchgtype(SCIP_BOUNDCHG *boundchg)
Definition: var.c:17337
SCIP_Real SCIPhistoryGetAvgGMIeff(SCIP_HISTORY *history)
Definition: history.c:749
SCIP_Real ub
Definition: struct_var.h:171
unsigned int boundtype
Definition: struct_var.h:101
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:4742
int SCIPbdchginfoGetPos(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18721
unsigned int deletable
Definition: struct_var.h:276
enum SCIP_Objsense SCIP_OBJSENSE
Definition: type_prob.h:50
SCIP_Bool SCIPvarWasFixedEarlier(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:17119
SCIP_Real SCIPvarGetInferenceSumCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:16025
SCIP_Bool SCIPvarIsInLP(SCIP_VAR *var)
Definition: var.c:17801
SCIP_RETCODE SCIPvarRemove(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_CLIQUETABLE *cliquetable, SCIP_SET *set, SCIP_Bool final)
Definition: var.c:6060
SCIP_RETCODE SCIPconsRelease(SCIP_CONS **cons, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: cons.c:6268
void SCIPvarMarkRelaxationOnly(SCIP_VAR *var)
Definition: var.c:17725
void SCIPvarStoreRootSol(SCIP_VAR *var, SCIP_Bool roothaslp)
Definition: var.c:13270
SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
Definition: var.c:18466
int SCIPvarGetBranchPriority(SCIP_VAR *var)
Definition: var.c:18251
int SCIPgetDepth(SCIP *scip)
Definition: scip_tree.c:670
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:3750
SCIP_Real SCIPvarGetLbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16711
SCIP_Bool divingobjchg
Definition: struct_lp.h:381
int SCIPvarGetNImpls(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18357
SCIP_MULTAGGR multaggr
Definition: struct_var.h:232
SCIP_RETCODE SCIPvarChgUbDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newbound)
Definition: var.c:8340
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition: memory.h:467
SCIP_RETCODE SCIPeventCreateGlbChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition: event.c:628
unsigned int deleted
Definition: struct_var.h:277
int * SCIPimplicsGetIds(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3361
SCIP_VARDATA * SCIPvarGetData(SCIP_VAR *var)
Definition: var.c:17440
SCIP_RETCODE SCIPcolChgLb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newlb)
Definition: lp.c:3757
int SCIPvarGetNLocksUp(SCIP_VAR *var)
Definition: var.c:3430
SCIP_Bool SCIPstrToRealValue(const char *str, SCIP_Real *value, char **endptr)
Definition: misc.c:10977
int SCIPimplicsGetNImpls(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3322
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:629
SCIP_VAR * SCIPboundchgGetVar(SCIP_BOUNDCHG *boundchg)
Definition: var.c:17327
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11943
#define MIN(x, y)
Definition: def.h:243
SCIP_Bool * SCIPcliqueGetValues(SCIP_CLIQUE *clique)
Definition: implics.c:3392
SCIP_BOUNDCHG * SCIPdomchgGetBoundchg(SCIP_DOMCHG *domchg, int pos)
Definition: var.c:17375
SCIP_Real SCIPvarGetUnchangedObj(SCIP_VAR *var)
Definition: var.c:17937
public methods for LP management
unsigned int removable
Definition: struct_var.h:275
#define SCIPsetDebugMsg
Definition: set.h:1784
static SCIP_RETCODE varAddParent(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_VAR *parentvar)
Definition: var.c:2644
SCIP_Real SCIPvarGetMultaggrUbGlobal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8633
unsigned int redundant
Definition: struct_var.h:104
SCIP_Real oldbound
Definition: struct_var.h:117
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17927
SCIP_RETCODE SCIPvarAddCliqueToList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:11394
union SCIP_Var::@22 data
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18671
SCIP_Real SCIPvarGetBestRootRedcost(SCIP_VAR *var)
Definition: var.c:13783
SCIP_VAR * SCIPvarGetAggrVar(SCIP_VAR *var)
Definition: var.c:17811
int closestvlbidx
Definition: struct_var.h:272
#define EPSLE(x, y, eps)
Definition: def.h:200
SCIP_RETCODE SCIPvarFlattenAggregationGraph(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:4425
int nuses
Definition: struct_var.h:262
SCIP_Real SCIPvarGetAvgInferencesCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:16125
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:11183
SCIP_Real SCIPcomputeTwoSampleTTestValue(SCIP_Real meanx, SCIP_Real meany, SCIP_Real variancex, SCIP_Real variancey, SCIP_Real countx, SCIP_Real county)
Definition: misc.c:123
SCIP_RETCODE SCIPvarDelClique(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:11433
#define SCIP_EVENTTYPE_GHOLEADDED
Definition: type_event.h:81
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:134
void SCIPhistoryUpdatePseudocost(SCIP_HISTORY *history, SCIP_SET *set, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition: history.c:174
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition: var.c:17790
int probindex
Definition: struct_var.h:255
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:8746
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:2160
SCIP_Real SCIPvarGetRelaxSol(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:13924
datastructures for problem statistics
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:17847
SCIP_Longint SCIPhistoryGetNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:639
SCIP_Real * SCIPvarGetImplBounds(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18403
SCIP_Real SCIPhistoryGetLastGMIeff(SCIP_HISTORY *history)
Definition: history.c:772
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12775
SCIP_Bool SCIPsetIsFeasLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6689
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:2376
static SCIP_Real adjustedLb(SCIP_SET *set, SCIP_VARTYPE vartype, SCIP_Real lb)
Definition: var.c:1569
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:6340
SCIP_Real SCIPvarGetLastGMIScore(SCIP_VAR *var, SCIP_STAT *stat)
Definition: var.c:16444
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:15188
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:9513
SCIP_NODE * SCIPgetFocusNode(SCIP *scip)
Definition: scip_tree.c:72
SCIP_RETCODE SCIPcolChgUb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newub)
Definition: lp.c:3802
SCIP_RETCODE SCIPcolFree(SCIP_COL **col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: lp.c:3377
SCIP * scip
Definition: struct_var.h:288
SCIP_EVENTFILTER * eventfilter
Definition: struct_var.h:247
static SCIP_Real SCIPvarGetPseudoSol_rec(SCIP_VAR *var)
Definition: var.c:13191
SCIP_BDCHGINFO * SCIPvarGetLbchgInfo(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16578
SCIP_Bool SCIPprobIsTransformed(SCIP_PROB *prob)
Definition: prob.c:2328
SCIP_BOUNDTYPE SCIPbdchginfoGetInferBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18788
const char * SCIPpropGetName(SCIP_PROP *prop)
Definition: prop.c:941
SCIP_BDCHGINFO * SCIPvarGetUbchgInfo(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16634
int conflictubcount
Definition: struct_var.h:271
int SCIPvboundsGetNVbds(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3290
SCIP_RETCODE SCIPvarGetProbvarBound(SCIP_VAR **var, SCIP_Real *bound, SCIP_BOUNDTYPE *boundtype)
Definition: var.c:12470
static SCIP_RETCODE parseValue(SCIP_SET *set, const char *str, SCIP_Real *value, char **endptr)
Definition: var.c:2273
SCIP_DOM locdom
Definition: struct_var.h:226
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoUb(SCIP_VAR *var, int pos)
Definition: var.c:18499
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:9794
SCIP_BDCHGINFO * SCIPvarGetBdchgInfo(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16690
#define SCIP_REAL_MAX
Definition: def.h:174
SCIP_Bool SCIPsetIsDualfeasPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6999
SCIP_VALUEHISTORY * valuehistory
Definition: struct_var.h:252
static void printBounds(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, FILE *file, SCIP_Real lb, SCIP_Real ub, const char *name)
Definition: var.c:2945
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:480
#define SCIP_DECL_VARDELORIG(x)
Definition: type_var.h:131
SCIP_Real SCIPhistoryGetCutoffSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:678
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:14271
SCIP_RETCODE SCIPvarLoose(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *prob, SCIP_LP *lp)
Definition: var.c:3614
SCIP_Real newbound
Definition: struct_var.h:93
#define SCIP_REAL_MIN
Definition: def.h:175
static SCIP_RETCODE varEventVarFixed(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, int fixeventtype)
Definition: var.c:3655
methods for sorting joint arrays of various types
SCIP_VAR ** parentvars
Definition: struct_var.h:241
SCIP_BRANCHDIR SCIPbranchdirOpposite(SCIP_BRANCHDIR dir)
Definition: history.c:437
SCIP_VAR ** SCIPvarGetImplVars(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18374
static SCIP_RETCODE varFreeParents(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:2672
SCIP_Real SCIPsetFeasFloor(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6834
SCIP_DOMCHGBOUND domchgbound
Definition: struct_var.h:162
SCIP_VAR ** b
Definition: circlepacking.c:65
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:7519
#define MAX(x, y)
Definition: def.h:239
#define SCIP_DEFAULT_INFINITY
Definition: def.h:178
static SCIP_RETCODE domchgEnsureHolechgsSize(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: var.c:1276
int SCIPvarGetNLocksDown(SCIP_VAR *var)
Definition: var.c:3417
SCIP_Real SCIPstudentTGetCriticalValue(SCIP_CONFIDENCELEVEL clevel, int df)
Definition: misc.c:106
SCIP_HOLELIST * next
Definition: struct_var.h:61
void SCIPconsCapture(SCIP_CONS *cons)
Definition: cons.c:6256
SCIP_Real SCIPhistoryGetInferenceSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:652
#define BMSallocBlockMemorySize(mem, ptr, size)
Definition: memory.h:453
unsigned int boundtype
Definition: struct_var.h:124
#define SCIPsetFreeCleanBufferArray(set, ptr)
Definition: set.h:1762
void SCIPrelaxationSolObjAdd(SCIP_RELAXATION *relaxation, SCIP_Real val)
Definition: relax.c:849
static const SCIP_Real scalars[]
Definition: lp.c:5743
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:5447
int lpipos
Definition: struct_lp.h:173
SCIP_NODE * SCIPtreeGetRootNode(SCIP_TREE *tree)
Definition: tree.c:8454
int SCIPdomchgGetNBoundchgs(SCIP_DOMCHG *domchg)
Definition: var.c:17367
SCIP_RETCODE SCIPvarColumn(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_LP *lp)
Definition: var.c:3580
SCIP_RETCODE SCIPvarSetLastGMIScore(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real gmieff)
Definition: var.c:16484
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:2087
unsigned int donotaggr
Definition: struct_var.h:278
SCIP_Real lazyub
Definition: struct_var.h:224
int SCIPbdchginfoGetDepth(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18711
SCIP_RETCODE SCIPeventfilterFree(SCIP_EVENTFILTER **eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: event.c:1846
#define SCIP_EVENTTYPE_FORMAT
Definition: type_event.h:152
unsigned int redundant
Definition: struct_var.h:126
SCIP_MESSAGEHDLR * messagehdlr
Definition: struct_visual.h:53
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:3930
SCIP_Real SCIPnormalCDF(SCIP_Real mean, SCIP_Real variance, SCIP_Real value)
Definition: misc.c:196
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:14862
SCIP_RETCODE SCIPvarMarkDoNotAggr(SCIP_VAR *var)
Definition: var.c:6107
SCIP_DECL_HASHKEYEQ(SCIPvarIsHashkeyEq)
Definition: var.c:11992
SCIP_Real SCIPvarGetBestRootSol(SCIP_VAR *var)
Definition: var.c:13716
SCIP_VAR * var
Definition: struct_var.h:119
public methods for message output
data structures for LP management
int nrootboundchgsrun
Definition: struct_stat.h:223
void SCIPcliquelistCheck(SCIP_CLIQUELIST *cliquelist, SCIP_VAR *var)
Definition: implics.c:3464
SCIP_VAR * a
Definition: circlepacking.c:66
void SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr,...)
Definition: message.c:618
void SCIPvarSetCopyData(SCIP_VAR *var, SCIP_DECL_VARCOPY((*varcopy)))
Definition: var.c:17496
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:9285
SCIP_Real * scalars
Definition: struct_var.h:194
SCIP_IMPLICS * implics
Definition: struct_var.h:245
SCIP_Real SCIPholelistGetLeft(SCIP_HOLELIST *holelist)
Definition: var.c:17387
SCIP_Bool SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6345
datastructures for problem variables
static void holelistFree(SCIP_HOLELIST **holelist, BMS_BLKMEM *blkmem)
Definition: var.c:177
static SCIP_RETCODE varEnsureLbchginfosSize(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: var.c:428
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:17539
SCIP_RETCODE SCIPvarResetBounds(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat)
Definition: var.c:9232
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:225
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:9414
#define SCIP_Real
Definition: def.h:173
internal methods for problem statistics
#define SCIP_EVENTTYPE_VARCHANGED
Definition: type_event.h:130
static SCIP_RETCODE varFree(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:2745
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:1300
SCIP_Longint SCIPvarGetNBranchings(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15700
SCIP_RETCODE SCIPvarsGetProbvarBinary(SCIP_VAR ***vars, SCIP_Bool **negatedarr, int nvars)
Definition: var.c:12279
SCIP_VAR * SCIPbdchginfoGetInferVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18741
SCIP_Bool SCIPsetIsFeasPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6788
SCIP_RETCODE SCIPeventCreateTypeChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_VARTYPE oldtype, SCIP_VARTYPE newtype)
Definition: event.c:833
int parentvarssize
Definition: struct_var.h:260
SCIP_CLIQUELIST * cliquelist
Definition: struct_var.h:246
SCIP_RETCODE SCIPvarSetInitial(SCIP_VAR *var, SCIP_Bool initial)
Definition: var.c:17507
SCIP_VAR ** SCIPprobGetVars(SCIP_PROB *prob)
Definition: prob.c:2438
SCIP_RETCODE SCIPvarGetProbvarHole(SCIP_VAR **var, SCIP_Real *left, SCIP_Real *right)
Definition: var.c:12563
SCIP_RETCODE SCIPlpUpdateVarLoose(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:14309
SCIP_Real SCIPvarGetVSIDS(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:18544
#define SCIP_INVALID
Definition: def.h:193
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:726
void SCIPsortPtrReal(void **ptrarray, SCIP_Real *realarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
int SCIPvarGetNUses(SCIP_VAR *var)
Definition: var.c:17430
void SCIPvarsGetProbvar(SCIP_VAR **vars, int nvars)
Definition: var.c:12199
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:2561
static SCIP_RETCODE parseBounds(SCIP_SET *set, const char *str, char *type, SCIP_Real *lb, SCIP_Real *ub, char **endptr)
Definition: var.c:2305
SCIP_VAR ** SCIPvarGetVubVars(SCIP_VAR *var)
Definition: var.c:18325
SCIP_RETCODE SCIPeventCreateVarUnlocked(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition: event.c:584
SCIP_Real branchfactor
Definition: struct_var.h:211
unsigned int donotmultaggr
Definition: struct_var.h:279
#define SCIP_Longint
Definition: def.h:158
SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
Definition: var.c:18191
SCIP_CONS * SCIPbdchginfoGetInferCons(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18753
SCIP_Bool SCIPsetIsDualfeasZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6988
SCIP_Real SCIPvarGetAvgSol(SCIP_VAR *var)
Definition: var.c:14063
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:17759
SCIP_Real nlpsol
Definition: struct_var.h:217
SCIP_VAR * lastbranchvar
Definition: struct_stat.h:183
static SCIP_RETCODE varEnsureParentvarsSize(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: var.c:2620
SCIP_Real SCIPvarGetAvgCutoffs(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:16266
SCIP_Real lb
Definition: struct_var.h:170
SCIP_VAR * var
Definition: struct_lp.h:160
SCIP_Bool SCIPsetIsFeasGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6733
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:9123
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:17585
SCIP_Real SCIPvarGetMultaggrUbLocal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8501
SCIP_RETCODE SCIPvarChgName(SCIP_VAR *var, BMS_BLKMEM *blkmem, const char *name)
Definition: var.c:2914
SCIP_DOM glbdom
Definition: struct_var.h:225
SCIP_Real SCIPsetEpsilon(SCIP_SET *set)
Definition: set.c:6156
SCIP_Real SCIPhistoryGetAvgInferences(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:665
SCIP_STAGE SCIPsetGetStage(SCIP_SET *set)
Definition: set.c:3022
enum SCIP_Vartype SCIP_VARTYPE
Definition: type_var.h:73
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:6725
SCIP_Bool collectvarhistory
Definition: struct_stat.h:281
SCIP_VAR * negatedvar
Definition: struct_var.h:242
SCIP_Bool SCIPvarIsMarkedDeleteGlobalStructures(SCIP_VAR *var)
Definition: var.c:17687
SCIP_Bool SCIPcliqueIsCleanedUp(SCIP_CLIQUE *clique)
Definition: implics.c:3426
SCIP_Real newbound
Definition: struct_var.h:118
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:18145
int SCIPcliqueGetNVars(SCIP_CLIQUE *clique)
Definition: implics.c:3370
SCIP_RETCODE SCIPvarAddHoleOriginal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real left, SCIP_Real right)
Definition: var.c:8694
void SCIPbdchginfoFree(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem)
Definition: var.c:16564
void SCIPvarAdjustUb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *ub)
Definition: var.c:6535
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:17562
static void varIncRootboundchgs(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat)
Definition: var.c:6795
#define BMSallocBlockMemory(mem, ptr)
Definition: memory.h:451
SCIP_HOLELIST * SCIPvarGetHolelistLocal(SCIP_VAR *var)
Definition: var.c:18155
unsigned int delglobalstructs
Definition: struct_var.h:285
SCIP_Bool SCIPsetIsDualfeasNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:7010
SCIP_BOUNDTYPE SCIPbdchginfoGetBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18701
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:18586
SCIP_Real rootsol
Definition: struct_var.h:212
SCIP_Bool SCIPeventqueueIsDelayed(SCIP_EVENTQUEUE *eventqueue)
Definition: event.c:2568
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:3156
SCIP_RETCODE SCIPlpUpdateVarColumn(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:14185
SCIP_HISTORY * history
Definition: struct_var.h:250
SCIP_RETCODE SCIPvarSetRemovable(SCIP_VAR *var, SCIP_Bool removable)
Definition: var.c:17523
SCIP_Real SCIPvarGetVSIDS_rec(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15878
int nrootintfixingsrun
Definition: struct_stat.h:225
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:437
SCIP_RETCODE SCIPvarGetProbvarSum(SCIP_VAR **var, SCIP_SET *set, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12648
#define SCIP_EVENTTYPE_GUBCHANGED
Definition: type_event.h:76
#define SCIP_CALL_ABORT(x)
Definition: def.h:359
SCIP_Real SCIPvarGetPseudoSol(SCIP_VAR *var)
Definition: var.c:18531
enum SCIP_BoundchgType SCIP_BOUNDCHGTYPE
Definition: type_var.h:91
SCIP_Real * SCIPimplicsGetBounds(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3349
SCIP_ORIGINAL original
Definition: struct_var.h:229
SCIP_Real SCIPcolGetRedcost(SCIP_COL *col, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:3952
SCIP_VAR * SCIPvarGetTransVar(SCIP_VAR *var)
Definition: var.c:17779
#define SCIP_ALLOC(x)
Definition: def.h:391
#define SCIPABORT()
Definition: def.h:352
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:17611
SCIP_RETCODE SCIPeventCreateGubChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition: event.c:651
void SCIPhistoryFree(SCIP_HISTORY **history, BMS_BLKMEM *blkmem)
Definition: history.c:66
SCIP_Real SCIPvarGetMultaggrLbLocal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8435
const char * SCIPprobGetName(SCIP_PROB *prob)
Definition: prob.c:2384
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9121
unsigned int applied
Definition: struct_var.h:103
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition: var.c:17641
void SCIPvboundsFree(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem)
Definition: implics.c:73
SCIP_RETCODE SCIPvarsAddClique(SCIP_VAR **vars, SCIP_Bool *values, int nvars, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_CLIQUE *clique)
Definition: var.c:11356
void SCIPvarGetImplicVarBounds(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_Real *lb, SCIP_Real *ub)
Definition: var.c:11147
datastructures for global SCIP settings
SCIP_HOLELIST ** ptr
Definition: struct_var.h:67
#define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
Definition: memory.h:458
SCIP_BOUNDCHG * boundchgs
Definition: struct_var.h:152
void SCIPvarMarkDeleted(SCIP_VAR *var)
Definition: var.c:6096
void SCIPvarSetData(SCIP_VAR *var, SCIP_VARDATA *vardata)
Definition: var.c:17450
SCIP_Bool SCIPcolIsInLP(SCIP_COL *col)
Definition: lp.c:17115
SCIP_COL * col
Definition: struct_var.h:230
SCIP_RETCODE SCIPvarNegate(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **negvar)
Definition: var.c:5918
SCIP_Real left
Definition: struct_var.h:53
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9373
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:1423
SCIP_Bool SCIPvarMayRoundUp(SCIP_VAR *var)
Definition: var.c:3452
#define EPSZ(x, eps)
Definition: def.h:203
#define ABS(x)
Definition: def.h:235
void SCIPimplicsFree(SCIP_IMPLICS **implics, BMS_BLKMEM *blkmem)
Definition: implics.c:451
static SCIP_RETCODE varProcessChgBranchDirection(SCIP_VAR *var, SCIP_BRANCHDIR branchdirection)
Definition: var.c:11752
SCIP_Bool SCIPvarMayRoundDown(SCIP_VAR *var)
Definition: var.c:3441
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:970
SCIP callable library.
SCIP_Bool SCIPsetIsFeasNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6799
SCIP_Real SCIPvarGetPseudocostVariance(SCIP_VAR *var, SCIP_BRANCHDIR dir, SCIP_Bool onlycurrentrun)
Definition: var.c:14693
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:17749
SCIP_Real objscale
Definition: struct_prob.h:51
SCIP_BDCHGINFO * lbchginfos
Definition: struct_var.h:248
static SCIP_RETCODE findValuehistoryEntry(SCIP_VAR *var, SCIP_Real value, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HISTORY **history)
Definition: var.c:14997
public methods for propagators
SCIP_RETCODE SCIPcliquelistDel(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: implics.c:1527
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:17575
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:5640
SCIP_Real scalar
Definition: struct_var.h:185
uint64_t SCIP_EVENTTYPE
Definition: type_event.h:151
void SCIPvarMarkDeleteGlobalStructures(SCIP_VAR *var)
Definition: var.c:17677
SCIP_BOUNDCHGTYPE SCIPbdchginfoGetChgtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18691
SCIP_RETCODE SCIPvarDelCliqueFromList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:11416