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-2023 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  {
1887  SCIPcliquelistRemoveFromCliques(var->cliquelist, cliquetable, var, irrelevantvar);
1888  SCIPcliquelistFree(&var->cliquelist, blkmem);
1889  }
1890 
1891  /**@todo variable bounds like x <= b*z + d with z general integer are not removed from x's vbd arrays, because
1892  * z has no link (like in the binary case) to x
1893  */
1894 
1895  return SCIP_OKAY;
1896 }
1897 
1898 /** sets the variable name */
1899 static
1901  SCIP_VAR* var, /**< problem variable */
1902  BMS_BLKMEM* blkmem, /**< block memory */
1903  SCIP_STAT* stat, /**< problem statistics, or NULL */
1904  const char* name /**< name of variable, or NULL for automatic name creation */
1905  )
1906 {
1907  assert(blkmem != NULL);
1908  assert(var != NULL);
1909 
1910  if( name == NULL )
1911  {
1912  char s[SCIP_MAXSTRLEN];
1913 
1914  assert(stat != NULL);
1915 
1916  (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "_var%d_", stat->nvaridx);
1917  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->name, s, strlen(s)+1) );
1918  }
1919  else
1920  {
1921  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->name, name, strlen(name)+1) );
1922  }
1923 
1924  return SCIP_OKAY;
1925 }
1926 
1927 
1928 /** creates variable; if variable is of integral type, fractional bounds are automatically rounded; an integer variable
1929  * with bounds zero and one is automatically converted into a binary variable
1930  */
1931 static
1933  SCIP_VAR** var, /**< pointer to variable data */
1934  BMS_BLKMEM* blkmem, /**< block memory */
1935  SCIP_SET* set, /**< global SCIP settings */
1936  SCIP_STAT* stat, /**< problem statistics */
1937  const char* name, /**< name of variable, or NULL for automatic name creation */
1938  SCIP_Real lb, /**< lower bound of variable */
1939  SCIP_Real ub, /**< upper bound of variable */
1940  SCIP_Real obj, /**< objective function value */
1941  SCIP_VARTYPE vartype, /**< type of variable */
1942  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
1943  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
1944  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
1945  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
1946  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
1947  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
1948  SCIP_VARDATA* vardata /**< user data for this specific variable */
1949  )
1950 {
1951  int i;
1952 
1953  assert(var != NULL);
1954  assert(blkmem != NULL);
1955  assert(stat != NULL);
1956 
1957  /* adjust bounds of variable */
1958  lb = adjustedLb(set, vartype, lb);
1959  ub = adjustedUb(set, vartype, ub);
1960 
1961  /* convert [0,1]-integers into binary variables and check that binary variables have correct bounds */
1962  if( (SCIPsetIsEQ(set, lb, 0.0) || SCIPsetIsEQ(set, lb, 1.0))
1963  && (SCIPsetIsEQ(set, ub, 0.0) || SCIPsetIsEQ(set, ub, 1.0)) )
1964  {
1965  if( vartype == SCIP_VARTYPE_INTEGER )
1966  vartype = SCIP_VARTYPE_BINARY;
1967  }
1968  else
1969  {
1970  if( vartype == SCIP_VARTYPE_BINARY )
1971  {
1972  SCIPerrorMessage("invalid bounds [%.2g,%.2g] for binary variable <%s>\n", lb, ub, name);
1973  return SCIP_INVALIDDATA;
1974  }
1975  }
1976 
1977  assert(vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, lb, 0.0) || SCIPsetIsEQ(set, lb, 1.0));
1978  assert(vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, ub, 0.0) || SCIPsetIsEQ(set, ub, 1.0));
1979 
1980  SCIP_ALLOC( BMSallocBlockMemory(blkmem, var) );
1981 
1982  /* set variable's name */
1983  SCIP_CALL( varSetName(*var, blkmem, stat, name) );
1984 
1985 #ifndef NDEBUG
1986  (*var)->scip = set->scip;
1987 #endif
1988  (*var)->obj = obj;
1989  (*var)->unchangedobj = obj;
1990  (*var)->branchfactor = 1.0;
1991  (*var)->rootsol = 0.0;
1992  (*var)->bestrootsol = 0.0;
1993  (*var)->bestrootredcost = 0.0;
1994  (*var)->bestrootlpobjval = SCIP_INVALID;
1995  (*var)->relaxsol = 0.0;
1996  (*var)->nlpsol = 0.0;
1997  (*var)->primsolavg = 0.5 * (lb + ub);
1998  (*var)->conflictlb = SCIP_REAL_MIN;
1999  (*var)->conflictub = SCIP_REAL_MAX;
2000  (*var)->conflictrelaxedlb = (*var)->conflictlb;
2001  (*var)->conflictrelaxedub = (*var)->conflictub;
2002  (*var)->lazylb = -SCIPsetInfinity(set);
2003  (*var)->lazyub = SCIPsetInfinity(set);
2004  (*var)->glbdom.holelist = NULL;
2005  (*var)->glbdom.lb = lb;
2006  (*var)->glbdom.ub = ub;
2007  (*var)->locdom.holelist = NULL;
2008  (*var)->locdom.lb = lb;
2009  (*var)->locdom.ub = ub;
2010  (*var)->varcopy = varcopy;
2011  (*var)->vardelorig = vardelorig;
2012  (*var)->vartrans = vartrans;
2013  (*var)->vardeltrans = vardeltrans;
2014  (*var)->vardata = vardata;
2015  (*var)->parentvars = NULL;
2016  (*var)->negatedvar = NULL;
2017  (*var)->vlbs = NULL;
2018  (*var)->vubs = NULL;
2019  (*var)->implics = NULL;
2020  (*var)->cliquelist = NULL;
2021  (*var)->eventfilter = NULL;
2022  (*var)->lbchginfos = NULL;
2023  (*var)->ubchginfos = NULL;
2024  (*var)->index = stat->nvaridx;
2025  (*var)->probindex = -1;
2026  (*var)->pseudocandindex = -1;
2027  (*var)->eventqueueindexobj = -1;
2028  (*var)->eventqueueindexlb = -1;
2029  (*var)->eventqueueindexub = -1;
2030  (*var)->parentvarssize = 0;
2031  (*var)->nparentvars = 0;
2032  (*var)->nuses = 0;
2033  (*var)->branchpriority = 0;
2034  (*var)->branchdirection = SCIP_BRANCHDIR_AUTO; /*lint !e641*/
2035  (*var)->lbchginfossize = 0;
2036  (*var)->nlbchginfos = 0;
2037  (*var)->ubchginfossize = 0;
2038  (*var)->nubchginfos = 0;
2039  (*var)->conflictlbcount = 0;
2040  (*var)->conflictubcount = 0;
2041  (*var)->closestvlbidx = -1;
2042  (*var)->closestvubidx = -1;
2043  (*var)->closestvblpcount = -1;
2044  (*var)->initial = initial;
2045  (*var)->removable = removable;
2046  (*var)->deleted = FALSE;
2047  (*var)->donotaggr = FALSE;
2048  (*var)->donotmultaggr = FALSE;
2049  (*var)->vartype = vartype; /*lint !e641*/
2050  (*var)->pseudocostflag = FALSE;
2051  (*var)->eventqueueimpl = FALSE;
2052  (*var)->deletable = FALSE;
2053  (*var)->delglobalstructs = FALSE;
2054  (*var)->relaxationonly = FALSE;
2055 
2056  for( i = 0; i < NLOCKTYPES; i++ )
2057  {
2058  (*var)->nlocksdown[i] = 0;
2059  (*var)->nlocksup[i] = 0;
2060  }
2061 
2062  stat->nvaridx++;
2063 
2064  /* create branching and inference history entries */
2065  SCIP_CALL( SCIPhistoryCreate(&(*var)->history, blkmem) );
2066  SCIP_CALL( SCIPhistoryCreate(&(*var)->historycrun, blkmem) );
2067 
2068  /* the value based history is only created on demand */
2069  (*var)->valuehistory = NULL;
2070 
2071  return SCIP_OKAY;
2072 }
2073 
2074 /** creates and captures an original problem variable; an integer variable with bounds
2075  * zero and one is automatically converted into a binary variable
2076  */
2078  SCIP_VAR** var, /**< pointer to variable data */
2079  BMS_BLKMEM* blkmem, /**< block memory */
2080  SCIP_SET* set, /**< global SCIP settings */
2081  SCIP_STAT* stat, /**< problem statistics */
2082  const char* name, /**< name of variable, or NULL for automatic name creation */
2083  SCIP_Real lb, /**< lower bound of variable */
2084  SCIP_Real ub, /**< upper bound of variable */
2085  SCIP_Real obj, /**< objective function value */
2086  SCIP_VARTYPE vartype, /**< type of variable */
2087  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2088  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2089  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2090  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2091  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2092  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2093  SCIP_VARDATA* vardata /**< user data for this specific variable */
2094  )
2095 {
2096  assert(var != NULL);
2097  assert(blkmem != NULL);
2098  assert(stat != NULL);
2099 
2100  /* create variable */
2101  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2102  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2103 
2104  /* set variable status and data */
2105  (*var)->varstatus = SCIP_VARSTATUS_ORIGINAL; /*lint !e641*/
2106  (*var)->data.original.origdom.holelist = NULL;
2107  (*var)->data.original.origdom.lb = lb;
2108  (*var)->data.original.origdom.ub = ub;
2109  (*var)->data.original.transvar = NULL;
2110 
2111  /* capture variable */
2112  SCIPvarCapture(*var);
2113 
2114  return SCIP_OKAY;
2115 }
2116 
2117 /** creates and captures a loose variable belonging to the transformed problem; an integer variable with bounds
2118  * zero and one is automatically converted into a binary variable
2119  */
2121  SCIP_VAR** var, /**< pointer to variable data */
2122  BMS_BLKMEM* blkmem, /**< block memory */
2123  SCIP_SET* set, /**< global SCIP settings */
2124  SCIP_STAT* stat, /**< problem statistics */
2125  const char* name, /**< name of variable, or NULL for automatic name creation */
2126  SCIP_Real lb, /**< lower bound of variable */
2127  SCIP_Real ub, /**< upper bound of variable */
2128  SCIP_Real obj, /**< objective function value */
2129  SCIP_VARTYPE vartype, /**< type of variable */
2130  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2131  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2132  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2133  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2134  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2135  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2136  SCIP_VARDATA* vardata /**< user data for this specific variable */
2137  )
2138 {
2139  assert(var != NULL);
2140  assert(blkmem != NULL);
2141 
2142  /* create variable */
2143  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2144  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2145 
2146  /* create event filter for transformed variable */
2147  SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
2148 
2149  /* set variable status and data */
2150  (*var)->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
2151 
2152  /* capture variable */
2153  SCIPvarCapture(*var);
2154 
2155  return SCIP_OKAY;
2156 }
2157 
2158 /** copies and captures a variable from source to target SCIP; an integer variable with bounds zero and one is
2159  * automatically converted into a binary variable; in case the variable data cannot be copied the variable is not
2160  * copied at all
2161  */
2163  SCIP_VAR** var, /**< pointer to store the target variable */
2164  BMS_BLKMEM* blkmem, /**< block memory */
2165  SCIP_SET* set, /**< global SCIP settings */
2166  SCIP_STAT* stat, /**< problem statistics */
2167  SCIP* sourcescip, /**< source SCIP data structure */
2168  SCIP_VAR* sourcevar, /**< source variable */
2169  SCIP_HASHMAP* varmap, /**< a hashmap to store the mapping of source variables corresponding
2170  * target variables */
2171  SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
2172  * target constraints */
2173  SCIP_Bool global /**< should global or local bounds be used? */
2174  )
2175 {
2176  SCIP_VARDATA* targetdata;
2177  SCIP_RESULT result;
2178  SCIP_Real lb;
2179  SCIP_Real ub;
2180 
2181  assert(set != NULL);
2182  assert(blkmem != NULL);
2183  assert(stat != NULL);
2184  assert(sourcescip != NULL);
2185  assert(sourcevar != NULL);
2186  assert(var != NULL);
2187  assert(set->stage == SCIP_STAGE_PROBLEM);
2188  assert(varmap != NULL);
2189  assert(consmap != NULL);
2190 
2191  /** @todo copy hole lists */
2192  assert(global || SCIPvarGetHolelistLocal(sourcevar) == NULL);
2193  assert(!global || SCIPvarGetHolelistGlobal(sourcevar) == NULL);
2194 
2195  result = SCIP_DIDNOTRUN;
2196  targetdata = NULL;
2197 
2198  if( SCIPvarGetStatus(sourcevar) == SCIP_VARSTATUS_ORIGINAL )
2199  {
2200  lb = SCIPvarGetLbOriginal(sourcevar);
2201  ub = SCIPvarGetUbOriginal(sourcevar);
2202  }
2203  else
2204  {
2205  lb = global ? SCIPvarGetLbGlobal(sourcevar) : SCIPvarGetLbLocal(sourcevar);
2206  ub = global ? SCIPvarGetUbGlobal(sourcevar) : SCIPvarGetUbLocal(sourcevar);
2207  }
2208 
2209  /* creates and captures the variable in the target SCIP and initialize callback methods and variable data to NULL */
2210  SCIP_CALL( SCIPvarCreateOriginal(var, blkmem, set, stat, SCIPvarGetName(sourcevar),
2211  lb, ub, SCIPvarGetObj(sourcevar), SCIPvarGetType(sourcevar),
2212  SCIPvarIsInitial(sourcevar), SCIPvarIsRemovable(sourcevar),
2213  NULL, NULL, NULL, NULL, NULL) );
2214  assert(*var != NULL);
2215 
2216  /* directly copy donot(mult)aggr flag */
2217  (*var)->donotaggr = sourcevar->donotaggr;
2218  (*var)->donotmultaggr = sourcevar->donotmultaggr;
2219 
2220  /* insert variable into mapping between source SCIP and the target SCIP */
2221  assert(!SCIPhashmapExists(varmap, sourcevar));
2222  SCIP_CALL( SCIPhashmapInsert(varmap, sourcevar, *var) );
2223 
2224  /* in case there exists variable data and the variable data copy callback, try to copy variable data */
2225  if( sourcevar->vardata != NULL && sourcevar->varcopy != NULL )
2226  {
2227  SCIP_CALL( sourcevar->varcopy(set->scip, sourcescip, sourcevar, sourcevar->vardata,
2228  varmap, consmap, (*var), &targetdata, &result) );
2229 
2230  /* evaluate result */
2231  if( result != SCIP_DIDNOTRUN && result != SCIP_SUCCESS )
2232  {
2233  SCIPerrorMessage("variable data copying method returned invalid result <%d>\n", result);
2234  return SCIP_INVALIDRESULT;
2235  }
2236 
2237  assert(targetdata == NULL || result == SCIP_SUCCESS);
2238 
2239  /* if copying was successful, add the created variable data to the variable as well as all callback methods */
2240  if( result == SCIP_SUCCESS )
2241  {
2242  (*var)->varcopy = sourcevar->varcopy;
2243  (*var)->vardelorig = sourcevar->vardelorig;
2244  (*var)->vartrans = sourcevar->vartrans;
2245  (*var)->vardeltrans = sourcevar->vardeltrans;
2246  (*var)->vardata = targetdata;
2247  }
2248  }
2249 
2250  /* we initialize histories of the variables by copying the source variable-information */
2251  if( set->history_allowtransfer )
2252  {
2253  SCIPvarMergeHistories((*var), sourcevar, stat);
2254  }
2255 
2256  /* in case the copying was successfully, add the created variable data to the variable as well as all callback
2257  * methods
2258  */
2259  if( result == SCIP_SUCCESS )
2260  {
2261  (*var)->varcopy = sourcevar->varcopy;
2262  (*var)->vardelorig = sourcevar->vardelorig;
2263  (*var)->vartrans = sourcevar->vartrans;
2264  (*var)->vardeltrans = sourcevar->vardeltrans;
2265  (*var)->vardata = targetdata;
2266  }
2267 
2268  SCIPsetDebugMsg(set, "created copy <%s> of variable <%s>\n", SCIPvarGetName(*var), SCIPvarGetName(sourcevar));
2269 
2270  return SCIP_OKAY;
2271 }
2272 
2273 /** parse given string for a SCIP_Real bound */
2274 static
2276  SCIP_SET* set, /**< global SCIP settings */
2277  const char* str, /**< string to parse */
2278  SCIP_Real* value, /**< pointer to store the parsed value */
2279  char** endptr /**< pointer to store the final string position if successfully parsed */
2280  )
2281 {
2282  /* first check for infinity value */
2283  if( strncmp(str, "+inf", 4) == 0 )
2284  {
2285  *value = SCIPsetInfinity(set);
2286  (*endptr) = (char*)str + 4;
2287  }
2288  else if( strncmp(str, "-inf", 4) == 0 )
2289  {
2290  *value = -SCIPsetInfinity(set);
2291  (*endptr) = (char*)str + 4;
2292  }
2293  else
2294  {
2295  if( !SCIPstrToRealValue(str, value, endptr) )
2296  {
2297  SCIPerrorMessage("expected value: %s.\n", str);
2298  return SCIP_READERROR;
2299  }
2300  }
2301 
2302  return SCIP_OKAY;
2303 }
2304 
2305 /** parse the characters as bounds */
2306 static
2308  SCIP_SET* set, /**< global SCIP settings */
2309  const char* str, /**< string to parse */
2310  char* type, /**< bound type (global, local, or lazy) */
2311  SCIP_Real* lb, /**< pointer to store the lower bound */
2312  SCIP_Real* ub, /**< pointer to store the upper bound */
2313  char** endptr /**< pointer to store the final string position if successfully parsed (or NULL if an error occured) */
2314  )
2315 {
2316  char token[SCIP_MAXSTRLEN];
2317  char* tmpend;
2318 
2319  SCIPsetDebugMsg(set, "parsing bounds: '%s'\n", str);
2320 
2321  /* get bound type */
2322  SCIPstrCopySection(str, ' ', ' ', type, SCIP_MAXSTRLEN, endptr);
2323  if ( *endptr == str
2324  || ( strncmp(type, "original", 8) != 0 && strncmp(type, "global", 6) != 0 && strncmp(type, "local", 5) != 0 && strncmp(type, "lazy", 4) != 0 ) )
2325  {
2326  SCIPsetDebugMsg(set, "unkown bound type\n");
2327  *endptr = NULL;
2328  return SCIP_OKAY;
2329  }
2330 
2331  SCIPsetDebugMsg(set, "parsed bound type <%s>\n", type);
2332 
2333  /* get lower bound */
2334  SCIPstrCopySection(str, '[', ',', token, SCIP_MAXSTRLEN, endptr);
2335  str = *endptr;
2336  SCIP_CALL( parseValue(set, token, lb, &tmpend) );
2337 
2338  /* get upper bound */
2339  SCIP_CALL( parseValue(set, str, ub, endptr) );
2340 
2341  SCIPsetDebugMsg(set, "parsed bounds: [%g,%g]\n", *lb, *ub);
2342 
2343  /* skip end of bounds */
2344  while ( **endptr != '\0' && (**endptr == ']' || **endptr == ',') )
2345  ++(*endptr);
2346 
2347  return SCIP_OKAY;
2348 }
2349 
2350 /** parses a given string for a variable informations */
2351 static
2353  SCIP_SET* set, /**< global SCIP settings */
2354  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2355  const char* str, /**< string to parse */
2356  char* name, /**< pointer to store the variable name */
2357  SCIP_Real* lb, /**< pointer to store the lower bound */
2358  SCIP_Real* ub, /**< pointer to store the upper bound */
2359  SCIP_Real* obj, /**< pointer to store the objective coefficient */
2360  SCIP_VARTYPE* vartype, /**< pointer to store the variable type */
2361  SCIP_Real* lazylb, /**< pointer to store if the lower bound is lazy */
2362  SCIP_Real* lazyub, /**< pointer to store if the upper bound is lazy */
2363  SCIP_Bool local, /**< should the local bound be applied */
2364  char** endptr, /**< pointer to store the final string position if successfully */
2365  SCIP_Bool* success /**< pointer store if the paring process was successful */
2366  )
2367 {
2368  SCIP_Real parsedlb;
2369  SCIP_Real parsedub;
2370  char token[SCIP_MAXSTRLEN];
2371  char* strptr;
2372  int i;
2373 
2374  assert(lb != NULL);
2375  assert(ub != NULL);
2376  assert(obj != NULL);
2377  assert(vartype != NULL);
2378  assert(lazylb != NULL);
2379  assert(lazyub != NULL);
2380  assert(success != NULL);
2381 
2382  (*success) = TRUE;
2383 
2384  /* copy variable type */
2385  SCIPstrCopySection(str, '[', ']', token, SCIP_MAXSTRLEN, endptr);
2386  assert(*endptr != str);
2387  SCIPsetDebugMsg(set, "parsed variable type <%s>\n", token);
2388 
2389  /* get variable type */
2390  if( strncmp(token, "binary", 3) == 0 )
2391  (*vartype) = SCIP_VARTYPE_BINARY;
2392  else if( strncmp(token, "integer", 3) == 0 )
2393  (*vartype) = SCIP_VARTYPE_INTEGER;
2394  else if( strncmp(token, "implicit", 3) == 0 )
2395  (*vartype) = SCIP_VARTYPE_IMPLINT;
2396  else if( strncmp(token, "continuous", 3) == 0 )
2397  (*vartype) = SCIP_VARTYPE_CONTINUOUS;
2398  else
2399  {
2400  SCIPmessagePrintWarning(messagehdlr, "unknown variable type\n");
2401  (*success) = FALSE;
2402  return SCIP_OKAY;
2403  }
2404 
2405  /* move string pointer behind variable type */
2406  str = *endptr;
2407 
2408  /* get variable name */
2409  SCIPstrCopySection(str, '<', '>', name, SCIP_MAXSTRLEN, endptr);
2410  assert(*endptr != str);
2411  SCIPsetDebugMsg(set, "parsed variable name <%s>\n", name);
2412 
2413  /* move string pointer behind variable name */
2414  str = *endptr;
2415 
2416  /* cut out objective coefficient */
2417  SCIPstrCopySection(str, '=', ',', token, SCIP_MAXSTRLEN, endptr);
2418 
2419  /* move string pointer behind objective coefficient */
2420  str = *endptr;
2421 
2422  /* get objective coefficient */
2423  if( !SCIPstrToRealValue(token, obj, endptr) )
2424  {
2425  *endptr = NULL;
2426  return SCIP_READERROR;
2427  }
2428 
2429  SCIPsetDebugMsg(set, "parsed objective coefficient <%g>\n", *obj);
2430 
2431  /* parse global/original bounds */
2432  SCIP_CALL( parseBounds(set, str, token, lb, ub, endptr) );
2433  if ( *endptr == NULL )
2434  {
2435  SCIPerrorMessage("Expected bound type: %s.\n", token);
2436  return SCIP_READERROR;
2437  }
2438  assert(strncmp(token, "global", 6) == 0 || strncmp(token, "original", 8) == 0);
2439 
2440  /* initialize the lazy bound */
2441  *lazylb = -SCIPsetInfinity(set);
2442  *lazyub = SCIPsetInfinity(set);
2443 
2444  /* store pointer */
2445  strptr = *endptr;
2446 
2447  /* possibly parse optional local and lazy bounds */
2448  for( i = 0; i < 2 && *endptr != NULL && **endptr != '\0'; ++i )
2449  {
2450  /* start after previous bounds */
2451  strptr = *endptr;
2452 
2453  /* parse global bounds */
2454  SCIP_CALL( parseBounds(set, strptr, token, &parsedlb, &parsedub, endptr) );
2455 
2456  /* stop if parsing of bounds failed */
2457  if( *endptr == NULL )
2458  break;
2459 
2460  if( strncmp(token, "local", 5) == 0 && local )
2461  {
2462  *lb = parsedlb;
2463  *ub = parsedub;
2464  }
2465  else if( strncmp(token, "lazy", 4) == 0 )
2466  {
2467  *lazylb = parsedlb;
2468  *lazyub = parsedub;
2469  }
2470  }
2471 
2472  /* restore pointer */
2473  if ( *endptr == NULL )
2474  *endptr = strptr;
2475 
2476  /* check bounds for binary variables */
2477  if ( (*vartype) == SCIP_VARTYPE_BINARY )
2478  {
2479  if ( SCIPsetIsLT(set, *lb, 0.0) || SCIPsetIsGT(set, *ub, 1.0) )
2480  {
2481  SCIPerrorMessage("Parsed invalid bounds for binary variable <%s>: [%f, %f].\n", name, *lb, *ub);
2482  return SCIP_READERROR;
2483  }
2484  if ( !SCIPsetIsInfinity(set, -(*lazylb)) && !SCIPsetIsInfinity(set, *lazyub) &&
2485  ( SCIPsetIsLT(set, *lazylb, 0.0) || SCIPsetIsGT(set, *lazyub, 1.0) ) )
2486  {
2487  SCIPerrorMessage("Parsed invalid lazy bounds for binary variable <%s>: [%f, %f].\n", name, *lazylb, *lazyub);
2488  return SCIP_READERROR;
2489  }
2490  }
2491 
2492  return SCIP_OKAY;
2493 }
2494 
2495 /** parses variable information (in cip format) out of a string; if the parsing process was successful an original
2496  * variable is created and captured; if variable is of integral type, fractional bounds are automatically rounded; an
2497  * integer variable with bounds zero and one is automatically converted into a binary variable
2498  */
2500  SCIP_VAR** var, /**< pointer to variable data */
2501  BMS_BLKMEM* blkmem, /**< block memory */
2502  SCIP_SET* set, /**< global SCIP settings */
2503  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2504  SCIP_STAT* stat, /**< problem statistics */
2505  const char* str, /**< string to parse */
2506  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2507  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2508  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2509  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable */
2510  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data */
2511  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable */
2512  SCIP_VARDATA* vardata, /**< user data for this specific variable */
2513  char** endptr, /**< pointer to store the final string position if successfully */
2514  SCIP_Bool* success /**< pointer store if the paring process was successful */
2515  )
2516 {
2517  char name[SCIP_MAXSTRLEN];
2518  SCIP_Real lb;
2519  SCIP_Real ub;
2520  SCIP_Real obj;
2521  SCIP_VARTYPE vartype;
2522  SCIP_Real lazylb;
2523  SCIP_Real lazyub;
2524 
2525  assert(var != NULL);
2526  assert(blkmem != NULL);
2527  assert(stat != NULL);
2528  assert(endptr != NULL);
2529  assert(success != NULL);
2530 
2531  /* parse string in cip format for variable information */
2532  SCIP_CALL( varParse(set, messagehdlr, str, name, &lb, &ub, &obj, &vartype, &lazylb, &lazyub, FALSE, endptr, success) );
2533 
2534  if( *success ) /*lint !e774*/
2535  {
2536  /* create variable */
2537  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2538  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2539 
2540  /* set variable status and data */
2541  (*var)->varstatus = SCIP_VARSTATUS_ORIGINAL; /*lint !e641*/
2542  (*var)->data.original.origdom.holelist = NULL;
2543  (*var)->data.original.origdom.lb = lb;
2544  (*var)->data.original.origdom.ub = ub;
2545  (*var)->data.original.transvar = NULL;
2546 
2547  /* set lazy status of variable bounds */
2548  (*var)->lazylb = lazylb;
2549  (*var)->lazyub = lazyub;
2550 
2551  /* capture variable */
2552  SCIPvarCapture(*var);
2553  }
2554 
2555  return SCIP_OKAY;
2556 }
2557 
2558 /** parses variable information (in cip format) out of a string; if the parsing process was successful a loose variable
2559  * belonging to the transformed problem is created and captured; if variable is of integral type, fractional bounds are
2560  * automatically rounded; an integer variable with bounds zero and one is automatically converted into a binary
2561  * variable
2562  */
2564  SCIP_VAR** var, /**< pointer to variable data */
2565  BMS_BLKMEM* blkmem, /**< block memory */
2566  SCIP_SET* set, /**< global SCIP settings */
2567  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2568  SCIP_STAT* stat, /**< problem statistics */
2569  const char* str, /**< string to parse */
2570  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2571  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2572  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2573  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable */
2574  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data */
2575  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable */
2576  SCIP_VARDATA* vardata, /**< user data for this specific variable */
2577  char** endptr, /**< pointer to store the final string position if successfully */
2578  SCIP_Bool* success /**< pointer store if the paring process was successful */
2579  )
2580 {
2581  char name[SCIP_MAXSTRLEN];
2582  SCIP_Real lb;
2583  SCIP_Real ub;
2584  SCIP_Real obj;
2585  SCIP_VARTYPE vartype;
2586  SCIP_Real lazylb;
2587  SCIP_Real lazyub;
2588 
2589  assert(var != NULL);
2590  assert(blkmem != NULL);
2591  assert(endptr != NULL);
2592  assert(success != NULL);
2593 
2594  /* parse string in cip format for variable information */
2595  SCIP_CALL( varParse(set, messagehdlr, str, name, &lb, &ub, &obj, &vartype, &lazylb, &lazyub, TRUE, endptr, success) );
2596 
2597  if( *success ) /*lint !e774*/
2598  {
2599  /* create variable */
2600  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2601  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2602 
2603  /* create event filter for transformed variable */
2604  SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
2605 
2606  /* set variable status and data */
2607  (*var)->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
2608 
2609  /* set lazy status of variable bounds */
2610  (*var)->lazylb = lazylb;
2611  (*var)->lazyub = lazyub;
2612 
2613  /* capture variable */
2614  SCIPvarCapture(*var);
2615  }
2616 
2617  return SCIP_OKAY;
2618 }
2619 
2620 /** ensures, that parentvars array of var can store at least num entries */
2621 static
2623  SCIP_VAR* var, /**< problem variable */
2624  BMS_BLKMEM* blkmem, /**< block memory */
2625  SCIP_SET* set, /**< global SCIP settings */
2626  int num /**< minimum number of entries to store */
2627  )
2628 {
2629  assert(var->nparentvars <= var->parentvarssize);
2630 
2631  if( num > var->parentvarssize )
2632  {
2633  int newsize;
2634 
2635  newsize = SCIPsetCalcMemGrowSize(set, num);
2636  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->parentvars, var->parentvarssize, newsize) );
2637  var->parentvarssize = newsize;
2638  }
2639  assert(num <= var->parentvarssize);
2640 
2641  return SCIP_OKAY;
2642 }
2643 
2644 /** adds variable to parent list of a variable and captures parent variable */
2645 static
2647  SCIP_VAR* var, /**< variable to add parent to */
2648  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
2649  SCIP_SET* set, /**< global SCIP settings */
2650  SCIP_VAR* parentvar /**< parent variable to add */
2651  )
2652 {
2653  assert(var != NULL);
2654  assert(parentvar != NULL);
2655 
2656  /* the direct original counterpart must be stored as first parent */
2657  assert(var->nparentvars == 0 || SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL);
2658 
2659  SCIPsetDebugMsg(set, "adding parent <%s>[%p] to variable <%s>[%p] in slot %d\n",
2660  parentvar->name, (void*)parentvar, var->name, (void*)var, var->nparentvars);
2661 
2662  SCIP_CALL( varEnsureParentvarsSize(var, blkmem, set, var->nparentvars+1) );
2663 
2664  var->parentvars[var->nparentvars] = parentvar;
2665  var->nparentvars++;
2666 
2667  SCIPvarCapture(parentvar);
2668 
2669  return SCIP_OKAY;
2670 }
2671 
2672 /** deletes and releases all variables from the parent list of a variable, frees the memory of parents array */
2673 static
2675  SCIP_VAR** var, /**< pointer to variable */
2676  BMS_BLKMEM* blkmem, /**< block memory */
2677  SCIP_SET* set, /**< global SCIP settings */
2678  SCIP_EVENTQUEUE* eventqueue, /**< event queue (or NULL, if it's an original variable) */
2679  SCIP_LP* lp /**< current LP data (or NULL, if it's an original variable) */
2680  )
2681 {
2682  SCIP_VAR* parentvar;
2683  int i;
2684 
2685  SCIPsetDebugMsg(set, "free parents of <%s>\n", (*var)->name);
2686 
2687  /* release the parent variables and remove the link from the parent variable to the child */
2688  for( i = 0; i < (*var)->nparentvars; ++i )
2689  {
2690  assert((*var)->parentvars != NULL);
2691  parentvar = (*var)->parentvars[i];
2692  assert(parentvar != NULL);
2693 
2694  switch( SCIPvarGetStatus(parentvar) )
2695  {
2697  assert(parentvar->data.original.transvar == *var);
2698  assert(&parentvar->data.original.transvar != var);
2699  parentvar->data.original.transvar = NULL;
2700  break;
2701 
2703  assert(parentvar->data.aggregate.var == *var);
2704  assert(&parentvar->data.aggregate.var != var);
2705  parentvar->data.aggregate.var = NULL;
2706  break;
2707 
2708 #if 0
2709  /* The following code is unclear: should the current variable be removed from its parents? */
2711  assert(parentvar->data.multaggr.vars != NULL);
2712  for( v = 0; v < parentvar->data.multaggr.nvars && parentvar->data.multaggr.vars[v] != *var; ++v )
2713  {}
2714  assert(v < parentvar->data.multaggr.nvars && parentvar->data.multaggr.vars[v] == *var);
2715  if( v < parentvar->data.multaggr.nvars-1 )
2716  {
2717  parentvar->data.multaggr.vars[v] = parentvar->data.multaggr.vars[parentvar->data.multaggr.nvars-1];
2718  parentvar->data.multaggr.scalars[v] = parentvar->data.multaggr.scalars[parentvar->data.multaggr.nvars-1];
2719  }
2720  parentvar->data.multaggr.nvars--;
2721  break;
2722 #endif
2723 
2725  assert(parentvar->negatedvar == *var);
2726  assert((*var)->negatedvar == parentvar);
2727  parentvar->negatedvar = NULL;
2728  (*var)->negatedvar = NULL;
2729  break;
2730 
2731  default:
2732  SCIPerrorMessage("parent variable is neither ORIGINAL, AGGREGATED nor NEGATED\n");
2733  return SCIP_INVALIDDATA;
2734  } /*lint !e788*/
2735 
2736  SCIP_CALL( SCIPvarRelease(&(*var)->parentvars[i], blkmem, set, eventqueue, lp) );
2737  }
2738 
2739  /* free parentvars array */
2740  BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->parentvars, (*var)->parentvarssize);
2741 
2742  return SCIP_OKAY;
2743 }
2744 
2745 /** frees a variable */
2746 static
2748  SCIP_VAR** var, /**< pointer to variable */
2749  BMS_BLKMEM* blkmem, /**< block memory */
2750  SCIP_SET* set, /**< global SCIP settings */
2751  SCIP_EVENTQUEUE* eventqueue, /**< event queue (may be NULL, if it's not a column variable) */
2752  SCIP_LP* lp /**< current LP data (may be NULL, if it's not a column variable) */
2753  )
2754 {
2755  assert(var != NULL);
2756  assert(*var != NULL);
2757  assert(SCIPvarGetStatus(*var) != SCIP_VARSTATUS_COLUMN || &(*var)->data.col->var != var);
2758  assert((*var)->nuses == 0);
2759  assert((*var)->probindex == -1);
2760  assert((*var)->nlocksup[SCIP_LOCKTYPE_MODEL] == 0);
2761  assert((*var)->nlocksdown[SCIP_LOCKTYPE_MODEL] == 0);
2762 
2763  SCIPsetDebugMsg(set, "free variable <%s> with status=%d\n", (*var)->name, SCIPvarGetStatus(*var));
2764 
2765  switch( SCIPvarGetStatus(*var) )
2766  {
2768  assert((*var)->data.original.transvar == NULL); /* cannot free variable, if transformed variable is still existing */
2769  holelistFree(&(*var)->data.original.origdom.holelist, blkmem);
2770  assert((*var)->data.original.origdom.holelist == NULL);
2771  break;
2772  case SCIP_VARSTATUS_LOOSE:
2773  break;
2774  case SCIP_VARSTATUS_COLUMN:
2775  SCIP_CALL( SCIPcolFree(&(*var)->data.col, blkmem, set, eventqueue, lp) ); /* free corresponding LP column */
2776  break;
2777  case SCIP_VARSTATUS_FIXED:
2779  break;
2781  BMSfreeBlockMemoryArray(blkmem, &(*var)->data.multaggr.vars, (*var)->data.multaggr.varssize);
2782  BMSfreeBlockMemoryArray(blkmem, &(*var)->data.multaggr.scalars, (*var)->data.multaggr.varssize);
2783  break;
2785  break;
2786  default:
2787  SCIPerrorMessage("unknown variable status\n");
2788  return SCIP_INVALIDDATA;
2789  }
2790 
2791  /* release all parent variables and free the parentvars array */
2792  SCIP_CALL( varFreeParents(var, blkmem, set, eventqueue, lp) );
2793 
2794  /* free user data */
2796  {
2797  if( (*var)->vardelorig != NULL )
2798  {
2799  SCIP_CALL( (*var)->vardelorig(set->scip, *var, &(*var)->vardata) );
2800  }
2801  }
2802  else
2803  {
2804  if( (*var)->vardeltrans != NULL )
2805  {
2806  SCIP_CALL( (*var)->vardeltrans(set->scip, *var, &(*var)->vardata) );
2807  }
2808  }
2809 
2810  /* free event filter */
2811  if( (*var)->eventfilter != NULL )
2812  {
2813  SCIP_CALL( SCIPeventfilterFree(&(*var)->eventfilter, blkmem, set) );
2814  }
2815  assert((*var)->eventfilter == NULL);
2816 
2817  /* free hole lists */
2818  holelistFree(&(*var)->glbdom.holelist, blkmem);
2819  holelistFree(&(*var)->locdom.holelist, blkmem);
2820  assert((*var)->glbdom.holelist == NULL);
2821  assert((*var)->locdom.holelist == NULL);
2822 
2823  /* free variable bounds data structures */
2824  SCIPvboundsFree(&(*var)->vlbs, blkmem);
2825  SCIPvboundsFree(&(*var)->vubs, blkmem);
2826 
2827  /* free implications data structures */
2828  SCIPimplicsFree(&(*var)->implics, blkmem);
2829 
2830  /* free clique list data structures */
2831  SCIPcliquelistFree(&(*var)->cliquelist, blkmem);
2832 
2833  /* free bound change information arrays */
2834  BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->lbchginfos, (*var)->lbchginfossize);
2835  BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->ubchginfos, (*var)->ubchginfossize);
2836 
2837  /* free branching and inference history entries */
2838  SCIPhistoryFree(&(*var)->history, blkmem);
2839  SCIPhistoryFree(&(*var)->historycrun, blkmem);
2840  SCIPvaluehistoryFree(&(*var)->valuehistory, blkmem);
2841 
2842  /* free variable data structure */
2843  BMSfreeBlockMemoryArray(blkmem, &(*var)->name, strlen((*var)->name)+1);
2844  BMSfreeBlockMemory(blkmem, var);
2845 
2846  return SCIP_OKAY;
2847 }
2848 
2849 /** increases usage counter of variable */
2850 void SCIPvarCapture(
2851  SCIP_VAR* var /**< variable */
2852  )
2853 {
2854  assert(var != NULL);
2855  assert(var->nuses >= 0);
2856 
2857  SCIPdebugMessage("capture variable <%s> with nuses=%d\n", var->name, var->nuses);
2858  var->nuses++;
2859 
2860 #ifdef DEBUGUSES_VARNAME
2861  if( strcmp(var->name, DEBUGUSES_VARNAME) == 0
2862 #ifdef DEBUGUSES_PROBNAME
2863  && ((var->scip->transprob != NULL && strcmp(SCIPprobGetName(var->scip->transprob), DEBUGUSES_PROBNAME) == 0) ||
2864  strcmp(SCIPprobGetName(var->scip->origprob), DEBUGUSES_PROBNAME) == 0)
2865 #endif
2866  )
2867  {
2868  printf("Captured variable " DEBUGUSES_VARNAME " in SCIP %p, now %d uses; captured at\n", (void*)var->scip, var->nuses);
2869  print_backtrace();
2870  }
2871 #endif
2872 }
2873 
2874 /** decreases usage counter of variable, and frees memory if necessary */
2876  SCIP_VAR** var, /**< pointer to variable */
2877  BMS_BLKMEM* blkmem, /**< block memory */
2878  SCIP_SET* set, /**< global SCIP settings */
2879  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2880  SCIP_LP* lp /**< current LP data (or NULL, if it's an original variable) */
2881  )
2882 {
2883  assert(var != NULL);
2884  assert(*var != NULL);
2885  assert((*var)->nuses >= 1);
2886  assert(blkmem != NULL);
2887  assert((*var)->scip == set->scip);
2888 
2889  SCIPsetDebugMsg(set, "release variable <%s> with nuses=%d\n", (*var)->name, (*var)->nuses);
2890  (*var)->nuses--;
2891 
2892 #ifdef DEBUGUSES_VARNAME
2893  if( strcmp((*var)->name, DEBUGUSES_VARNAME) == 0
2894 #ifdef DEBUGUSES_PROBNAME
2895  && (((*var)->scip->transprob != NULL && strcmp(SCIPprobGetName((*var)->scip->transprob), DEBUGUSES_PROBNAME) == 0) ||
2896  strcmp(SCIPprobGetName((*var)->scip->origprob), DEBUGUSES_PROBNAME) == 0)
2897 #endif
2898  )
2899  {
2900  printf("Released variable " DEBUGUSES_VARNAME " in SCIP %p, now %d uses; released at\n", (void*)(*var)->scip, (*var)->nuses);
2901  print_backtrace();
2902  }
2903 #endif
2904 
2905  if( (*var)->nuses == 0 )
2906  {
2907  SCIP_CALL( varFree(var, blkmem, set, eventqueue, lp) );
2908  }
2909 
2910  *var = NULL;
2911 
2912  return SCIP_OKAY;
2913 }
2914 
2915 /** change variable name */
2917  SCIP_VAR* var, /**< problem variable */
2918  BMS_BLKMEM* blkmem, /**< block memory */
2919  const char* name /**< name of variable */
2920  )
2921 {
2922  assert(name != NULL);
2923 
2924  /* remove old variable name */
2925  BMSfreeBlockMemoryArray(blkmem, &var->name, strlen(var->name)+1);
2926 
2927  /* set new variable name */
2928  SCIP_CALL( varSetName(var, blkmem, NULL, name) );
2929 
2930  return SCIP_OKAY;
2931 }
2932 
2933 /** initializes variable data structure for solving */
2934 void SCIPvarInitSolve(
2935  SCIP_VAR* var /**< problem variable */
2936  )
2937 {
2938  assert(var != NULL);
2939 
2941  var->conflictlbcount = 0;
2942  var->conflictubcount = 0;
2943 }
2944 
2945 /** outputs the given bounds into the file stream */
2946 static
2947 void printBounds(
2948  SCIP_SET* set, /**< global SCIP settings */
2949  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2950  FILE* file, /**< output file (or NULL for standard output) */
2951  SCIP_Real lb, /**< lower bound */
2952  SCIP_Real ub, /**< upper bound */
2953  const char* name /**< bound type name */
2954  )
2955 {
2956  assert(set != NULL);
2957 
2958  SCIPmessageFPrintInfo(messagehdlr, file, ", %s=", name);
2959  if( SCIPsetIsInfinity(set, lb) )
2960  SCIPmessageFPrintInfo(messagehdlr, file, "[+inf,");
2961  else if( SCIPsetIsInfinity(set, -lb) )
2962  SCIPmessageFPrintInfo(messagehdlr, file, "[-inf,");
2963  else
2964  SCIPmessageFPrintInfo(messagehdlr, file, "[%.15g,", lb);
2965  if( SCIPsetIsInfinity(set, ub) )
2966  SCIPmessageFPrintInfo(messagehdlr, file, "+inf]");
2967  else if( SCIPsetIsInfinity(set, -ub) )
2968  SCIPmessageFPrintInfo(messagehdlr, file, "-inf]");
2969  else
2970  SCIPmessageFPrintInfo(messagehdlr, file, "%.15g]", ub);
2971 }
2972 
2973 /** prints hole list to file stream */
2974 static
2975 void printHolelist(
2976  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2977  FILE* file, /**< output file (or NULL for standard output) */
2978  SCIP_HOLELIST* holelist, /**< hole list pointer to hole of interest */
2979  const char* name /**< hole type name */
2980  )
2981 { /*lint --e{715}*/
2982  SCIP_Real left;
2983  SCIP_Real right;
2984 
2985  if( holelist == NULL )
2986  return;
2987 
2988  left = SCIPholelistGetLeft(holelist);
2989  right = SCIPholelistGetRight(holelist);
2990 
2991  /* display first hole */
2992  SCIPmessageFPrintInfo(messagehdlr, file, ", %s=(%g,%g)", name, left, right);
2993  holelist = SCIPholelistGetNext(holelist);
2994 
2995  while(holelist != NULL )
2996  {
2997  left = SCIPholelistGetLeft(holelist);
2998  right = SCIPholelistGetRight(holelist);
2999 
3000  /* display hole */
3001  SCIPmessageFPrintInfo(messagehdlr, file, "(%g,%g)", left, right);
3002 
3003  /* get next hole */
3004  holelist = SCIPholelistGetNext(holelist);
3005  }
3006 }
3007 
3008 /** outputs variable information into file stream */
3010  SCIP_VAR* var, /**< problem variable */
3011  SCIP_SET* set, /**< global SCIP settings */
3012  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3013  FILE* file /**< output file (or NULL for standard output) */
3014  )
3015 {
3016  SCIP_HOLELIST* holelist;
3017  SCIP_Real lb;
3018  SCIP_Real ub;
3019  int i;
3020 
3021  assert(var != NULL);
3022  assert(var->scip == set->scip);
3023 
3024  /* type of variable */
3025  switch( SCIPvarGetType(var) )
3026  {
3027  case SCIP_VARTYPE_BINARY:
3028  SCIPmessageFPrintInfo(messagehdlr, file, " [binary]");
3029  break;
3030  case SCIP_VARTYPE_INTEGER:
3031  SCIPmessageFPrintInfo(messagehdlr, file, " [integer]");
3032  break;
3033  case SCIP_VARTYPE_IMPLINT:
3034  SCIPmessageFPrintInfo(messagehdlr, file, " [implicit]");
3035  break;
3037  SCIPmessageFPrintInfo(messagehdlr, file, " [continuous]");
3038  break;
3039  default:
3040  SCIPerrorMessage("unknown variable type\n");
3041  SCIPABORT();
3042  return SCIP_ERROR; /*lint !e527*/
3043  }
3044 
3045  /* name */
3046  SCIPmessageFPrintInfo(messagehdlr, file, " <%s>:", var->name);
3047 
3048  /* objective value */
3049  SCIPmessageFPrintInfo(messagehdlr, file, " obj=%.15g", var->obj);
3050 
3051  /* bounds (global bounds for transformed variables, original bounds for original variables) */
3052  if( !SCIPvarIsTransformed(var) )
3053  {
3054  /* output original bound */
3055  lb = SCIPvarGetLbOriginal(var);
3056  ub = SCIPvarGetUbOriginal(var);
3057  printBounds(set, messagehdlr, file, lb, ub, "original bounds");
3058 
3059  /* output lazy bound */
3060  lb = SCIPvarGetLbLazy(var);
3061  ub = SCIPvarGetUbLazy(var);
3062 
3063  /* only display the lazy bounds if they are different from [-infinity,infinity] */
3064  if( !SCIPsetIsInfinity(set, -lb) || !SCIPsetIsInfinity(set, ub) )
3065  printBounds(set, messagehdlr, file, lb, ub, "lazy bounds");
3066 
3067  holelist = SCIPvarGetHolelistOriginal(var);
3068  printHolelist(messagehdlr, file, holelist, "original holes");
3069  }
3070  else
3071  {
3072  /* output global bound */
3073  lb = SCIPvarGetLbGlobal(var);
3074  ub = SCIPvarGetUbGlobal(var);
3075  printBounds(set, messagehdlr, file, lb, ub, "global bounds");
3076 
3077  /* output local bound */
3078  lb = SCIPvarGetLbLocal(var);
3079  ub = SCIPvarGetUbLocal(var);
3080  printBounds(set, messagehdlr, file, lb, ub, "local bounds");
3081 
3082  /* output lazy bound */
3083  lb = SCIPvarGetLbLazy(var);
3084  ub = SCIPvarGetUbLazy(var);
3085 
3086  /* only display the lazy bounds if they are different from [-infinity,infinity] */
3087  if( !SCIPsetIsInfinity(set, -lb) || !SCIPsetIsInfinity(set, ub) )
3088  printBounds(set, messagehdlr, file, lb, ub, "lazy bounds");
3089 
3090  /* global hole list */
3091  holelist = SCIPvarGetHolelistGlobal(var);
3092  printHolelist(messagehdlr, file, holelist, "global holes");
3093 
3094  /* local hole list */
3095  holelist = SCIPvarGetHolelistLocal(var);
3096  printHolelist(messagehdlr, file, holelist, "local holes");
3097  }
3098 
3099  /* fixings and aggregations */
3100  switch( SCIPvarGetStatus(var) )
3101  {
3103  case SCIP_VARSTATUS_LOOSE:
3104  case SCIP_VARSTATUS_COLUMN:
3105  break;
3106 
3107  case SCIP_VARSTATUS_FIXED:
3108  SCIPmessageFPrintInfo(messagehdlr, file, ", fixed:");
3109  if( SCIPsetIsInfinity(set, var->glbdom.lb) )
3110  SCIPmessageFPrintInfo(messagehdlr, file, "+inf");
3111  else if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
3112  SCIPmessageFPrintInfo(messagehdlr, file, "-inf");
3113  else
3114  SCIPmessageFPrintInfo(messagehdlr, file, "%.15g", var->glbdom.lb);
3115  break;
3116 
3118  SCIPmessageFPrintInfo(messagehdlr, file, ", aggregated:");
3119  if( !SCIPsetIsZero(set, var->data.aggregate.constant) )
3120  SCIPmessageFPrintInfo(messagehdlr, file, " %.15g", var->data.aggregate.constant);
3121  SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g<%s>", var->data.aggregate.scalar, SCIPvarGetName(var->data.aggregate.var));
3122  break;
3123 
3125  SCIPmessageFPrintInfo(messagehdlr, file, ", aggregated:");
3126  if( var->data.multaggr.nvars == 0 || !SCIPsetIsZero(set, var->data.multaggr.constant) )
3127  SCIPmessageFPrintInfo(messagehdlr, file, " %.15g", var->data.multaggr.constant);
3128  for( i = 0; i < var->data.multaggr.nvars; ++i )
3129  SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g<%s>", var->data.multaggr.scalars[i], SCIPvarGetName(var->data.multaggr.vars[i]));
3130  break;
3131 
3133  SCIPmessageFPrintInfo(messagehdlr, file, ", negated: %.15g - <%s>", var->data.negate.constant, SCIPvarGetName(var->negatedvar));
3134  break;
3135 
3136  default:
3137  SCIPerrorMessage("unknown variable status\n");
3138  SCIPABORT();
3139  return SCIP_ERROR; /*lint !e527*/
3140  }
3141 
3142  SCIPmessageFPrintInfo(messagehdlr, file, "\n");
3143 
3144  return SCIP_OKAY;
3145 }
3146 
3147 /** issues a VARUNLOCKED event on the given variable */
3148 static
3150  SCIP_VAR* var, /**< problem variable to change */
3151  BMS_BLKMEM* blkmem, /**< block memory */
3152  SCIP_SET* set, /**< global SCIP settings */
3153  SCIP_EVENTQUEUE* eventqueue /**< event queue */
3154  )
3155 {
3156  SCIP_EVENT* event;
3157 
3158  assert(var != NULL);
3159  assert(var->nlocksdown[SCIP_LOCKTYPE_MODEL] <= 1 && var->nlocksup[SCIP_LOCKTYPE_MODEL] <= 1);
3160  assert(var->scip == set->scip);
3161 
3162  /* issue VARUNLOCKED event on variable */
3163  SCIP_CALL( SCIPeventCreateVarUnlocked(&event, blkmem, var) );
3164  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
3165 
3166  return SCIP_OKAY;
3167 }
3168 
3169 /** modifies lock numbers for rounding */
3171  SCIP_VAR* var, /**< problem variable */
3172  BMS_BLKMEM* blkmem, /**< block memory */
3173  SCIP_SET* set, /**< global SCIP settings */
3174  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3175  SCIP_LOCKTYPE locktype, /**< type of the variable locks */
3176  int addnlocksdown, /**< increase in number of rounding down locks */
3177  int addnlocksup /**< increase in number of rounding up locks */
3178  )
3179 {
3180  SCIP_VAR* lockvar;
3181 
3182  assert(var != NULL);
3183  assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
3184  assert(var->nlocksup[locktype] >= 0);
3185  assert(var->nlocksdown[locktype] >= 0);
3186  assert(var->scip == set->scip);
3187 
3188  if( addnlocksdown == 0 && addnlocksup == 0 )
3189  return SCIP_OKAY;
3190 
3191 #ifdef SCIP_DEBUG
3192  SCIPsetDebugMsg(set, "add rounding locks %d/%d to variable <%s> (locks=%d/%d, type=%u)\n",
3193  addnlocksdown, addnlocksup, var->name, var->nlocksdown[locktype], var->nlocksup[locktype], locktype);
3194 #endif
3195 
3196  lockvar = var;
3197 
3198  while( TRUE ) /*lint !e716 */
3199  {
3200  assert(lockvar != NULL);
3201 
3202  switch( SCIPvarGetStatus(lockvar) )
3203  {
3205  if( lockvar->data.original.transvar != NULL )
3206  {
3207  lockvar = lockvar->data.original.transvar;
3208  break;
3209  }
3210  else
3211  {
3212  lockvar->nlocksdown[locktype] += addnlocksdown;
3213  lockvar->nlocksup[locktype] += addnlocksup;
3214 
3215  assert(lockvar->nlocksdown[locktype] >= 0);
3216  assert(lockvar->nlocksup[locktype] >= 0);
3217 
3218  return SCIP_OKAY;
3219  }
3220  case SCIP_VARSTATUS_LOOSE:
3221  case SCIP_VARSTATUS_COLUMN:
3222  case SCIP_VARSTATUS_FIXED:
3223  lockvar->nlocksdown[locktype] += addnlocksdown;
3224  lockvar->nlocksup[locktype] += addnlocksup;
3225 
3226  assert(lockvar->nlocksdown[locktype] >= 0);
3227  assert(lockvar->nlocksup[locktype] >= 0);
3228 
3229  if( locktype == SCIP_LOCKTYPE_MODEL && lockvar->nlocksdown[locktype] <= 1
3230  && lockvar->nlocksup[locktype] <= 1 )
3231  {
3232  SCIP_CALL( varEventVarUnlocked(lockvar, blkmem, set, eventqueue) );
3233  }
3234 
3235  return SCIP_OKAY;
3237  assert(!lockvar->donotaggr);
3238 
3239  if( lockvar->data.aggregate.scalar < 0.0 )
3240  {
3241  int tmp = addnlocksup;
3242 
3243  addnlocksup = addnlocksdown;
3244  addnlocksdown = tmp;
3245  }
3246 
3247  lockvar = lockvar->data.aggregate.var;
3248  break;
3250  {
3251  int v;
3252 
3253  assert(!lockvar->donotmultaggr);
3254 
3255  lockvar->nlocksdown[locktype] += addnlocksdown;
3256  lockvar->nlocksup[locktype] += addnlocksup;
3257 
3258  assert(lockvar->nlocksdown[locktype] >= 0);
3259  assert(lockvar->nlocksup[locktype] >= 0);
3260 
3261  for( v = lockvar->data.multaggr.nvars - 1; v >= 0; --v )
3262  {
3263  if( lockvar->data.multaggr.scalars[v] > 0.0 )
3264  {
3265  SCIP_CALL( SCIPvarAddLocks(lockvar->data.multaggr.vars[v], blkmem, set, eventqueue, locktype, addnlocksdown,
3266  addnlocksup) );
3267  }
3268  else
3269  {
3270  SCIP_CALL( SCIPvarAddLocks(lockvar->data.multaggr.vars[v], blkmem, set, eventqueue, locktype, addnlocksup,
3271  addnlocksdown) );
3272  }
3273  }
3274  return SCIP_OKAY;
3275  }
3277  {
3278  int tmp = addnlocksup;
3279 
3280  assert(lockvar->negatedvar != NULL);
3281  assert(SCIPvarGetStatus(lockvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
3282  assert(lockvar->negatedvar->negatedvar == lockvar);
3283 
3284  addnlocksup = addnlocksdown;
3285  addnlocksdown = tmp;
3286 
3287  lockvar = lockvar->negatedvar;
3288  break;
3289  }
3290  default:
3291  SCIPerrorMessage("unknown variable status\n");
3292  return SCIP_INVALIDDATA;
3293  }
3294  }
3295 }
3296 
3297 /** gets number of locks for rounding down of a special type */
3299  SCIP_VAR* var, /**< problem variable */
3300  SCIP_LOCKTYPE locktype /**< type of variable locks */
3301  )
3302 {
3303  int nlocks;
3304  int i;
3305 
3306  assert(var != NULL);
3307  assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
3308  assert(var->nlocksdown[locktype] >= 0);
3309 
3310  switch( SCIPvarGetStatus(var) )
3311  {
3313  if( var->data.original.transvar != NULL )
3314  return SCIPvarGetNLocksDownType(var->data.original.transvar, locktype);
3315  else
3316  return var->nlocksdown[locktype];
3317 
3318  case SCIP_VARSTATUS_LOOSE:
3319  case SCIP_VARSTATUS_COLUMN:
3320  case SCIP_VARSTATUS_FIXED:
3321  return var->nlocksdown[locktype];
3322 
3324  assert(!var->donotaggr);
3325  if( var->data.aggregate.scalar > 0.0 )
3326  return SCIPvarGetNLocksDownType(var->data.aggregate.var, locktype);
3327  else
3328  return SCIPvarGetNLocksUpType(var->data.aggregate.var, locktype);
3329 
3331  assert(!var->donotmultaggr);
3332  nlocks = 0;
3333  for( i = 0; i < var->data.multaggr.nvars; ++i )
3334  {
3335  if( var->data.multaggr.scalars[i] > 0.0 )
3336  nlocks += SCIPvarGetNLocksDownType(var->data.multaggr.vars[i], locktype);
3337  else
3338  nlocks += SCIPvarGetNLocksUpType(var->data.multaggr.vars[i], locktype);
3339  }
3340  return nlocks;
3341 
3343  assert(var->negatedvar != NULL);
3345  assert(var->negatedvar->negatedvar == var);
3346  return SCIPvarGetNLocksUpType(var->negatedvar, locktype);
3347 
3348  default:
3349  SCIPerrorMessage("unknown variable status\n");
3350  SCIPABORT();
3351  return INT_MAX; /*lint !e527*/
3352  }
3353 }
3354 
3355 /** gets number of locks for rounding up of a special type */
3357  SCIP_VAR* var, /**< problem variable */
3358  SCIP_LOCKTYPE locktype /**< type of variable locks */
3359  )
3360 {
3361  int nlocks;
3362  int i;
3363 
3364  assert(var != NULL);
3365  assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
3366  assert(var->nlocksup[locktype] >= 0);
3367 
3368  switch( SCIPvarGetStatus(var) )
3369  {
3371  if( var->data.original.transvar != NULL )
3372  return SCIPvarGetNLocksUpType(var->data.original.transvar, locktype);
3373  else
3374  return var->nlocksup[locktype];
3375 
3376  case SCIP_VARSTATUS_LOOSE:
3377  case SCIP_VARSTATUS_COLUMN:
3378  case SCIP_VARSTATUS_FIXED:
3379  return var->nlocksup[locktype];
3380 
3382  assert(!var->donotaggr);
3383  if( var->data.aggregate.scalar > 0.0 )
3384  return SCIPvarGetNLocksUpType(var->data.aggregate.var, locktype);
3385  else
3386  return SCIPvarGetNLocksDownType(var->data.aggregate.var, locktype);
3387 
3389  assert(!var->donotmultaggr);
3390  nlocks = 0;
3391  for( i = 0; i < var->data.multaggr.nvars; ++i )
3392  {
3393  if( var->data.multaggr.scalars[i] > 0.0 )
3394  nlocks += SCIPvarGetNLocksUpType(var->data.multaggr.vars[i], locktype);
3395  else
3396  nlocks += SCIPvarGetNLocksDownType(var->data.multaggr.vars[i], locktype);
3397  }
3398  return nlocks;
3399 
3401  assert(var->negatedvar != NULL);
3403  assert(var->negatedvar->negatedvar == var);
3404  return SCIPvarGetNLocksDownType(var->negatedvar, locktype);
3405 
3406  default:
3407  SCIPerrorMessage("unknown variable status\n");
3408  SCIPABORT();
3409  return INT_MAX; /*lint !e527*/
3410  }
3411 }
3412 
3413 /** gets number of locks for rounding down
3414  *
3415  * @note This method will always return variable locks of type model
3416  *
3417  * @note It is recommented to use SCIPvarGetNLocksDownType()
3418  */
3420  SCIP_VAR* var /**< problem variable */
3421  )
3422 {
3424 }
3425 
3426 /** gets number of locks for rounding up
3427  *
3428  * @note This method will always return variable locks of type model
3429  *
3430  * @note It is recommented to use SCIPvarGetNLocksUpType()
3431  */
3432 int SCIPvarGetNLocksUp(
3433  SCIP_VAR* var /**< problem variable */
3434  )
3435 {
3437 }
3438 
3439 /** is it possible, to round variable down and stay feasible?
3440  *
3441  * @note This method will always check w.r.t variable locks of type model
3442  */
3444  SCIP_VAR* var /**< problem variable */
3445  )
3446 {
3447  return (SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 0);
3448 }
3449 
3450 /** is it possible, to round variable up and stay feasible?
3451  *
3452  * @note This method will always check w.r.t. variable locks of type model
3453  */
3455  SCIP_VAR* var /**< problem variable */
3456  )
3457 {
3458  return (SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 0);
3459 }
3460 
3461 /** gets and captures transformed variable of a given variable; if the variable is not yet transformed,
3462  * a new transformed variable for this variable is created
3463  */
3465  SCIP_VAR* origvar, /**< original problem variable */
3466  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3467  SCIP_SET* set, /**< global SCIP settings */
3468  SCIP_STAT* stat, /**< problem statistics */
3469  SCIP_OBJSENSE objsense, /**< objective sense of original problem; transformed is always MINIMIZE */
3470  SCIP_VAR** transvar /**< pointer to store the transformed variable */
3471  )
3472 {
3473  char name[SCIP_MAXSTRLEN];
3474 
3475  assert(origvar != NULL);
3476  assert(origvar->scip == set->scip);
3477  assert(SCIPvarGetStatus(origvar) == SCIP_VARSTATUS_ORIGINAL);
3478  assert(SCIPsetIsEQ(set, origvar->glbdom.lb, origvar->locdom.lb));
3479  assert(SCIPsetIsEQ(set, origvar->glbdom.ub, origvar->locdom.ub));
3480  assert(origvar->vlbs == NULL);
3481  assert(origvar->vubs == NULL);
3482  assert(transvar != NULL);
3483 
3484  /* check if variable is already transformed */
3485  if( origvar->data.original.transvar != NULL )
3486  {
3487  *transvar = origvar->data.original.transvar;
3488  SCIPvarCapture(*transvar);
3489  }
3490  else
3491  {
3492  int i;
3493 
3494  /* create transformed variable */
3495  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "t_%s", origvar->name);
3496  SCIP_CALL( SCIPvarCreateTransformed(transvar, blkmem, set, stat, name,
3497  origvar->glbdom.lb, origvar->glbdom.ub, (SCIP_Real)objsense * origvar->obj,
3498  SCIPvarGetType(origvar), origvar->initial, origvar->removable,
3499  origvar->vardelorig, origvar->vartrans, origvar->vardeltrans, origvar->varcopy, NULL) );
3500 
3501  /* copy the branch factor and priority */
3502  (*transvar)->branchfactor = origvar->branchfactor;
3503  (*transvar)->branchpriority = origvar->branchpriority;
3504  (*transvar)->branchdirection = origvar->branchdirection; /*lint !e732*/
3505 
3506  /* duplicate hole lists */
3507  SCIP_CALL( holelistDuplicate(&(*transvar)->glbdom.holelist, blkmem, set, origvar->glbdom.holelist) );
3508  SCIP_CALL( holelistDuplicate(&(*transvar)->locdom.holelist, blkmem, set, origvar->locdom.holelist) );
3509 
3510  /* link original and transformed variable */
3511  origvar->data.original.transvar = *transvar;
3512  SCIP_CALL( varAddParent(*transvar, blkmem, set, origvar) );
3513 
3514  /* copy rounding locks */
3515  for( i = 0; i < NLOCKTYPES; i++ )
3516  {
3517  (*transvar)->nlocksdown[i] = origvar->nlocksdown[i];
3518  (*transvar)->nlocksup[i] = origvar->nlocksup[i];
3519  assert((*transvar)->nlocksdown[i] >= 0);
3520  assert((*transvar)->nlocksup[i] >= 0);
3521  }
3522 
3523  /* copy donot(mult)aggr status */
3524  (*transvar)->donotaggr = origvar->donotaggr;
3525  (*transvar)->donotmultaggr = origvar->donotmultaggr;
3526 
3527  /* copy lazy bounds */
3528  (*transvar)->lazylb = origvar->lazylb;
3529  (*transvar)->lazyub = origvar->lazyub;
3530 
3531  /* transfer eventual variable statistics; do not update global statistics, because this has been done
3532  * when original variable was created
3533  */
3534  SCIPhistoryUnite((*transvar)->history, origvar->history, FALSE);
3535 
3536  /* transform user data */
3537  if( origvar->vartrans != NULL )
3538  {
3539  SCIP_CALL( origvar->vartrans(set->scip, origvar, origvar->vardata, *transvar, &(*transvar)->vardata) );
3540  }
3541  else
3542  (*transvar)->vardata = origvar->vardata;
3543  }
3544 
3545  SCIPsetDebugMsg(set, "transformed variable: <%s>[%p] -> <%s>[%p]\n", origvar->name, (void*)origvar, (*transvar)->name, (void*)*transvar);
3546 
3547  return SCIP_OKAY;
3548 }
3549 
3550 /** gets corresponding transformed variable of an original or negated original variable */
3552  SCIP_VAR* origvar, /**< original problem variable */
3553  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3554  SCIP_SET* set, /**< global SCIP settings */
3555  SCIP_STAT* stat, /**< problem statistics */
3556  SCIP_VAR** transvar /**< pointer to store the transformed variable, or NULL if not existing yet */
3557  )
3558 {
3559  assert(origvar != NULL);
3561  assert(origvar->scip == set->scip);
3562 
3563  if( SCIPvarGetStatus(origvar) == SCIP_VARSTATUS_NEGATED )
3564  {
3565  assert(origvar->negatedvar != NULL);
3567 
3568  if( origvar->negatedvar->data.original.transvar == NULL )
3569  *transvar = NULL;
3570  else
3571  {
3572  SCIP_CALL( SCIPvarNegate(origvar->negatedvar->data.original.transvar, blkmem, set, stat, transvar) );
3573  }
3574  }
3575  else
3576  *transvar = origvar->data.original.transvar;
3577 
3578  return SCIP_OKAY;
3579 }
3580 
3581 /** converts loose transformed variable into column variable, creates LP column */
3583  SCIP_VAR* var, /**< problem variable */
3584  BMS_BLKMEM* blkmem, /**< block memory */
3585  SCIP_SET* set, /**< global SCIP settings */
3586  SCIP_STAT* stat, /**< problem statistics */
3587  SCIP_PROB* prob, /**< problem data */
3588  SCIP_LP* lp /**< current LP data */
3589  )
3590 {
3591  assert(var != NULL);
3592  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
3593  assert(var->scip == set->scip);
3594 
3595  SCIPsetDebugMsg(set, "creating column for variable <%s>\n", var->name);
3596 
3597  /* switch variable status */
3598  var->varstatus = SCIP_VARSTATUS_COLUMN; /*lint !e641*/
3599 
3600  /* create column of variable */
3601  SCIP_CALL( SCIPcolCreate(&var->data.col, blkmem, set, stat, var, 0, NULL, NULL, var->removable) );
3602 
3603  if( var->probindex != -1 )
3604  {
3605  /* inform problem about the variable's status change */
3606  SCIP_CALL( SCIPprobVarChangedStatus(prob, blkmem, set, NULL, NULL, var) );
3607 
3608  /* inform LP, that problem variable is now a column variable and no longer loose */
3609  SCIP_CALL( SCIPlpUpdateVarColumn(lp, set, var) );
3610  }
3611 
3612  return SCIP_OKAY;
3613 }
3614 
3615 /** converts column transformed variable back into loose variable, frees LP column */
3617  SCIP_VAR* var, /**< problem variable */
3618  BMS_BLKMEM* blkmem, /**< block memory */
3619  SCIP_SET* set, /**< global SCIP settings */
3620  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3621  SCIP_PROB* prob, /**< problem data */
3622  SCIP_LP* lp /**< current LP data */
3623  )
3624 {
3625  assert(var != NULL);
3626  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
3627  assert(var->scip == set->scip);
3628  assert(var->data.col != NULL);
3629  assert(var->data.col->lppos == -1);
3630  assert(var->data.col->lpipos == -1);
3631 
3632  SCIPsetDebugMsg(set, "deleting column for variable <%s>\n", var->name);
3633 
3634  /* free column of variable */
3635  SCIP_CALL( SCIPcolFree(&var->data.col, blkmem, set, eventqueue, lp) );
3636 
3637  /* switch variable status */
3638  var->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
3639 
3640  if( var->probindex != -1 )
3641  {
3642  /* inform problem about the variable's status change */
3643  SCIP_CALL( SCIPprobVarChangedStatus(prob, blkmem, set, NULL, NULL, var) );
3644 
3645  /* inform LP, that problem variable is now a loose variable and no longer a column */
3646  SCIP_CALL( SCIPlpUpdateVarLoose(lp, set, var) );
3647  }
3648 
3649  return SCIP_OKAY;
3650 }
3651 
3652 /** issues a VARFIXED event on the given variable and all its parents (except ORIGINAL parents);
3653  * the event issuing on the parents is necessary, because unlike with bound changes, the parent variables
3654  * are not informed about a fixing of an active variable they are pointing to
3655  */
3656 static
3658  SCIP_VAR* var, /**< problem variable to change */
3659  BMS_BLKMEM* blkmem, /**< block memory */
3660  SCIP_SET* set, /**< global SCIP settings */
3661  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3662  int fixeventtype /**< is this event a fixation(0), an aggregation(1), or a
3663  * multi-aggregation(2)
3664  */
3665  )
3666 {
3667  SCIP_EVENT* event;
3668  SCIP_VARSTATUS varstatus;
3669  int i;
3670 
3671  assert(var != NULL);
3672  assert(var->scip == set->scip);
3673  assert(0 <= fixeventtype && fixeventtype <= 2);
3674 
3675  /* issue VARFIXED event on variable */
3676  SCIP_CALL( SCIPeventCreateVarFixed(&event, blkmem, var) );
3677  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
3678 
3679 #ifndef NDEBUG
3680  for( i = var->nparentvars -1; i >= 0; --i )
3681  {
3683  }
3684 #endif
3685 
3686  switch( fixeventtype )
3687  {
3688  case 0:
3689  /* process all parents of a fixed variable */
3690  for( i = var->nparentvars - 1; i >= 0; --i )
3691  {
3692  varstatus = SCIPvarGetStatus(var->parentvars[i]);
3693 
3694  assert(varstatus != SCIP_VARSTATUS_FIXED);
3695 
3696  /* issue event on all not yet fixed parent variables, (that should already issued this event) except the original
3697  * one
3698  */
3699  if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3700  {
3701  SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3702  }
3703  }
3704  break;
3705  case 1:
3706  /* process all parents of a aggregated variable */
3707  for( i = var->nparentvars - 1; i >= 0; --i )
3708  {
3709  varstatus = SCIPvarGetStatus(var->parentvars[i]);
3710 
3711  assert(varstatus != SCIP_VARSTATUS_FIXED);
3712 
3713  /* issue event for not aggregated parent variable, because for these and its parents the var event was already
3714  * issued(, except the original one)
3715  *
3716  * @note that even before an aggregated parent variable, there might be variables, for which the vent was not
3717  * yet issued
3718  */
3719  if( varstatus == SCIP_VARSTATUS_AGGREGATED )
3720  continue;
3721 
3722  if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3723  {
3724  SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3725  }
3726  }
3727  break;
3728  case 2:
3729  /* process all parents of a aggregated variable */
3730  for( i = var->nparentvars - 1; i >= 0; --i )
3731  {
3732  varstatus = SCIPvarGetStatus(var->parentvars[i]);
3733 
3734  assert(varstatus != SCIP_VARSTATUS_FIXED);
3735 
3736  /* issue event on all parent variables except the original one */
3737  if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3738  {
3739  SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3740  }
3741  }
3742  break;
3743  default:
3744  SCIPerrorMessage("unknown variable fixation event origin\n");
3745  return SCIP_INVALIDDATA;
3746  }
3747 
3748  return SCIP_OKAY;
3749 }
3750 
3751 /** converts variable into fixed variable */
3753  SCIP_VAR* var, /**< problem variable */
3754  BMS_BLKMEM* blkmem, /**< block memory */
3755  SCIP_SET* set, /**< global SCIP settings */
3756  SCIP_STAT* stat, /**< problem statistics */
3757  SCIP_PROB* transprob, /**< tranformed problem data */
3758  SCIP_PROB* origprob, /**< original problem data */
3759  SCIP_PRIMAL* primal, /**< primal data */
3760  SCIP_TREE* tree, /**< branch and bound tree */
3761  SCIP_REOPT* reopt, /**< reoptimization data structure */
3762  SCIP_LP* lp, /**< current LP data */
3763  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3764  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
3765  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3766  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
3767  SCIP_Real fixedval, /**< value to fix variable at */
3768  SCIP_Bool* infeasible, /**< pointer to store whether the fixing is infeasible */
3769  SCIP_Bool* fixed /**< pointer to store whether the fixing was performed (variable was unfixed) */
3770  )
3771 {
3772  SCIP_Real obj;
3773  SCIP_Real childfixedval;
3774 
3775  assert(var != NULL);
3776  assert(var->scip == set->scip);
3777  assert(SCIPsetIsEQ(set, var->glbdom.lb, var->locdom.lb));
3778  assert(SCIPsetIsEQ(set, var->glbdom.ub, var->locdom.ub));
3779  assert(infeasible != NULL);
3780  assert(fixed != NULL);
3781 
3782  SCIPsetDebugMsg(set, "fix variable <%s>[%g,%g] to %g\n", var->name, var->glbdom.lb, var->glbdom.ub, fixedval);
3783 
3784  *infeasible = FALSE;
3785  *fixed = FALSE;
3786 
3788  {
3789  *infeasible = !SCIPsetIsFeasEQ(set, fixedval, var->locdom.lb);
3790  SCIPsetDebugMsg(set, " -> variable already fixed to %g (fixedval=%g): infeasible=%u\n", var->locdom.lb, fixedval, *infeasible);
3791  return SCIP_OKAY;
3792  }
3793  else if( (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPsetIsFeasIntegral(set, fixedval))
3794  || SCIPsetIsFeasLT(set, fixedval, var->locdom.lb)
3795  || SCIPsetIsFeasGT(set, fixedval, var->locdom.ub) )
3796  {
3797  SCIPsetDebugMsg(set, " -> fixing infeasible: locdom=[%g,%g], fixedval=%g\n", var->locdom.lb, var->locdom.ub, fixedval);
3798  *infeasible = TRUE;
3799  return SCIP_OKAY;
3800  }
3801 
3802  switch( SCIPvarGetStatus(var) )
3803  {
3805  if( var->data.original.transvar == NULL )
3806  {
3807  SCIPerrorMessage("cannot fix an untransformed original variable\n");
3808  return SCIP_INVALIDDATA;
3809  }
3810  SCIP_CALL( SCIPvarFix(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
3811  lp, branchcand, eventfilter, eventqueue, cliquetable, fixedval, infeasible, fixed) );
3812  break;
3813 
3814  case SCIP_VARSTATUS_LOOSE:
3815  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
3816 
3817  /* set the fixed variable's objective value to 0.0 */
3818  obj = var->obj;
3819  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
3820 
3821  /* since we change the variable type form loose to fixed, we have to adjust the number of loose
3822  * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
3823  * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
3824  * objective of this variable is set to zero
3825  */
3826  SCIPlpDecNLoosevars(lp);
3827 
3828  /* change variable's bounds to fixed value (thereby removing redundant implications and variable bounds) */
3829  holelistFree(&var->glbdom.holelist, blkmem);
3830  holelistFree(&var->locdom.holelist, blkmem);
3831  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, fixedval) );
3832  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, fixedval) );
3833 
3834  /* explicitly set variable's bounds, even if the fixed value is in epsilon range of the old bound */
3835  var->glbdom.lb = fixedval;
3836  var->glbdom.ub = fixedval;
3837  var->locdom.lb = fixedval;
3838  var->locdom.ub = fixedval;
3839 
3840  /* delete implications and variable bounds information */
3841  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
3842  assert(var->vlbs == NULL);
3843  assert(var->vubs == NULL);
3844  assert(var->implics == NULL);
3845  assert(var->cliquelist == NULL);
3846 
3847  /* clear the history of the variable */
3848  SCIPhistoryReset(var->history);
3850 
3851  /* convert variable into fixed variable */
3852  var->varstatus = SCIP_VARSTATUS_FIXED; /*lint !e641*/
3853 
3854  /* inform problem about the variable's status change */
3855  if( var->probindex != -1 )
3856  {
3857  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
3858  }
3859 
3860  /* reset the objective value of the fixed variable, thus adjusting the problem's objective offset */
3861  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventfilter, eventqueue, obj) );
3862 
3863  /* issue VARFIXED event */
3864  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 0) );
3865 
3866  *fixed = TRUE;
3867  break;
3868 
3869  case SCIP_VARSTATUS_COLUMN:
3870  SCIPerrorMessage("cannot fix a column variable\n");
3871  return SCIP_INVALIDDATA;
3872 
3873  case SCIP_VARSTATUS_FIXED:
3874  SCIPerrorMessage("cannot fix a fixed variable again\n"); /*lint !e527*/
3875  SCIPABORT(); /* case is already handled in earlier if condition */
3876  return SCIP_INVALIDDATA; /*lint !e527*/
3877 
3879  /* fix aggregation variable y in x = a*y + c, instead of fixing x directly */
3880  assert(SCIPsetIsZero(set, var->obj));
3881  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
3882  if( SCIPsetIsInfinity(set, fixedval) || SCIPsetIsInfinity(set, -fixedval) )
3883  childfixedval = (var->data.aggregate.scalar < 0.0 ? -fixedval : fixedval);
3884  else
3885  childfixedval = (fixedval - var->data.aggregate.constant)/var->data.aggregate.scalar;
3886  SCIP_CALL( SCIPvarFix(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
3887  branchcand, eventfilter, eventqueue, cliquetable, childfixedval, infeasible, fixed) );
3888  break;
3889 
3891  SCIPerrorMessage("cannot fix a multiple aggregated variable\n");
3892  SCIPABORT();
3893  return SCIP_INVALIDDATA; /*lint !e527*/
3894 
3896  /* fix negation variable x in x' = offset - x, instead of fixing x' directly */
3897  assert(SCIPsetIsZero(set, var->obj));
3898  assert(var->negatedvar != NULL);
3900  assert(var->negatedvar->negatedvar == var);
3901  SCIP_CALL( SCIPvarFix(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
3902  branchcand, eventfilter, eventqueue, cliquetable, var->data.negate.constant - fixedval, infeasible, fixed) );
3903  break;
3904 
3905  default:
3906  SCIPerrorMessage("unknown variable status\n");
3907  return SCIP_INVALIDDATA;
3908  }
3909 
3910  return SCIP_OKAY;
3911 }
3912 
3913 /** transforms given variables, scalars and constant to the corresponding active variables, scalars and constant
3914  *
3915  * If the number of needed active variables is greater than the available slots in the variable array, nothing happens except
3916  * that the required size is stored in the corresponding variable; hence, if afterwards the required size is greater than the
3917  * available slots (varssize), nothing happens; otherwise, the active variable representation is stored in the arrays.
3918  *
3919  * The reason for this approach is that we cannot reallocate memory, since we do not know how the
3920  * memory has been allocated (e.g., by a C++ 'new' or SCIP functions).
3921  */
3923  SCIP_SET* set, /**< global SCIP settings */
3924  SCIP_VAR** vars, /**< variable array to get active variables */
3925  SCIP_Real* scalars, /**< scalars a_1, ..., a_n in linear sum a_1*x_1 + ... + a_n*x_n + c */
3926  int* nvars, /**< pointer to number of variables and values in vars and scalars array */
3927  int varssize, /**< available slots in vars and scalars array */
3928  SCIP_Real* constant, /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c */
3929  int* requiredsize, /**< pointer to store the required array size for the active variables */
3930  SCIP_Bool mergemultiples /**< should multiple occurrences of a var be replaced by a single coeff? */
3931  )
3932 {
3933  SCIP_VAR** activevars;
3934  SCIP_Real* activescalars;
3935  int nactivevars;
3936  SCIP_Real activeconstant;
3937  SCIP_Bool activeconstantinf;
3938  int activevarssize;
3939 
3940  SCIP_VAR* var;
3941  SCIP_Real scalar;
3942  int v;
3943  int k;
3944 
3945  SCIP_VAR** tmpvars;
3946  SCIP_VAR** multvars;
3947  SCIP_Real* tmpscalars;
3948  SCIP_Real* multscalars;
3949  int tmpvarssize;
3950  int ntmpvars;
3951  int nmultvars;
3952 
3953  SCIP_VAR* multvar;
3954  SCIP_Real multscalar;
3955  SCIP_Real multconstant;
3956  int pos;
3957 
3958  int noldtmpvars;
3959 
3960  SCIP_VAR** tmpvars2;
3961  SCIP_Real* tmpscalars2;
3962  int tmpvarssize2;
3963  int ntmpvars2;
3964 
3965  SCIP_Bool sortagain = FALSE;
3966 
3967  assert(set != NULL);
3968  assert(nvars != NULL);
3969  assert(scalars != NULL || *nvars == 0);
3970  assert(constant != NULL);
3971  assert(requiredsize != NULL);
3972  assert(*nvars <= varssize);
3973 
3974  *requiredsize = 0;
3975 
3976  if( *nvars == 0 )
3977  return SCIP_OKAY;
3978 
3979  assert(vars != NULL);
3980 
3981  /* handle the "easy" case of just one variable and avoid memory allocation if the variable is already active */
3982  if( *nvars == 1 && (vars[0]->varstatus == ((int) SCIP_VARSTATUS_COLUMN) || vars[0]->varstatus == ((int) SCIP_VARSTATUS_LOOSE)) )
3983  {
3984  *requiredsize = 1;
3985 
3986  return SCIP_OKAY;
3987  }
3988 
3989  nactivevars = 0;
3990  activeconstant = 0.0;
3991  activeconstantinf = FALSE;
3992  activevarssize = (*nvars) * 2;
3993  ntmpvars = *nvars;
3994  tmpvarssize = *nvars;
3995 
3996  tmpvarssize2 = 1;
3997 
3998  /* allocate temporary memory */
3999  SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpvars2, tmpvarssize2) );
4000  SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpscalars2, tmpvarssize2) );
4001  SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
4002  SCIP_CALL( SCIPsetAllocBufferArray(set, &activescalars, activevarssize) );
4003  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
4004  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpscalars, scalars, ntmpvars) );
4005 
4006  /* to avoid unnecessary expanding of variable arrays while disaggregating several variables multiple times combine same variables
4007  * first, first get all corresponding variables with status loose, column, multaggr or fixed
4008  */
4009  for( v = ntmpvars - 1; v >= 0; --v )
4010  {
4011  var = tmpvars[v];
4012  scalar = tmpscalars[v];
4013 
4014  assert(var != NULL);
4015  /* transforms given variable, scalar and constant to the corresponding active, fixed, or
4016  * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed
4017  * variable, "scalar" will be 0.0 and the value of the sum will be stored in "constant".
4018  */
4019  SCIP_CALL( SCIPvarGetProbvarSum(&var, set, &scalar, &activeconstant) );
4020  assert(var != NULL);
4021 
4022  assert(SCIPsetIsInfinity(set, activeconstant) == (activeconstant == SCIPsetInfinity(set))); /*lint !e777*/
4023  assert(SCIPsetIsInfinity(set, -activeconstant) == (activeconstant == -SCIPsetInfinity(set))); /*lint !e777*/
4024 
4025  activeconstantinf = SCIPsetIsInfinity(set, activeconstant) || SCIPsetIsInfinity(set, -activeconstant);
4026 
4027  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
4028  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
4031 
4032  tmpvars[v] = var;
4033  tmpscalars[v] = scalar;
4034  }
4035  noldtmpvars = ntmpvars;
4036 
4037  /* sort all variables to combine equal variables easily */
4038  SCIPsortPtrReal((void**)tmpvars, tmpscalars, SCIPvarComp, noldtmpvars);
4039  ntmpvars = 0;
4040  for( v = 1; v < noldtmpvars; ++v )
4041  {
4042  /* combine same variables */
4043  if( SCIPvarCompare(tmpvars[v], tmpvars[ntmpvars]) == 0 )
4044  {
4045  tmpscalars[ntmpvars] += tmpscalars[v];
4046  }
4047  else
4048  {
4049  ++ntmpvars;
4050  if( v > ntmpvars )
4051  {
4052  tmpscalars[ntmpvars] = tmpscalars[v];
4053  tmpvars[ntmpvars] = tmpvars[v];
4054  }
4055  }
4056  }
4057  ++ntmpvars;
4058 
4059 #ifdef SCIP_MORE_DEBUG
4060  for( v = 1; v < ntmpvars; ++v )
4061  assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
4062 #endif
4063 
4064  /* collect for each variable the representation in active variables */
4065  while( ntmpvars >= 1 )
4066  {
4067  --ntmpvars;
4068  ntmpvars2 = 0;
4069  var = tmpvars[ntmpvars];
4070  scalar = tmpscalars[ntmpvars];
4071 
4072  assert(var != NULL);
4073 
4074  /* TODO: maybe we should test here on SCIPsetIsZero() instead of 0.0 */
4075  if( scalar == 0.0 )
4076  continue;
4077 
4078  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
4079  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
4082 
4083  switch( SCIPvarGetStatus(var) )
4084  {
4085  case SCIP_VARSTATUS_LOOSE:
4086  case SCIP_VARSTATUS_COLUMN:
4087  /* x = a*y + c */
4088  if( nactivevars >= activevarssize )
4089  {
4090  activevarssize *= 2;
4091  SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
4092  SCIP_CALL( SCIPsetReallocBufferArray(set, &activescalars, activevarssize) );
4093  assert(nactivevars < activevarssize);
4094  }
4095  activevars[nactivevars] = var;
4096  activescalars[nactivevars] = scalar;
4097  nactivevars++;
4098  break;
4099 
4101  /* x = a_1*y_1 + ... + a_n*y_n + c */
4102  nmultvars = var->data.multaggr.nvars;
4103  multvars = var->data.multaggr.vars;
4104  multscalars = var->data.multaggr.scalars;
4105  sortagain = TRUE;
4106 
4107  if( nmultvars + ntmpvars > tmpvarssize )
4108  {
4109  while( nmultvars + ntmpvars > tmpvarssize )
4110  tmpvarssize *= 2;
4111  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
4112  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpscalars, tmpvarssize) );
4113  assert(nmultvars + ntmpvars <= tmpvarssize);
4114  }
4115 
4116  if( nmultvars > tmpvarssize2 )
4117  {
4118  while( nmultvars > tmpvarssize2 )
4119  tmpvarssize2 *= 2;
4120  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars2, tmpvarssize2) );
4121  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpscalars2, tmpvarssize2) );
4122  assert(nmultvars <= tmpvarssize2);
4123  }
4124 
4125  --nmultvars;
4126 
4127  for( ; nmultvars >= 0; --nmultvars )
4128  {
4129  multvar = multvars[nmultvars];
4130  multscalar = multscalars[nmultvars];
4131  multconstant = 0;
4132 
4133  assert(multvar != NULL);
4134  SCIP_CALL( SCIPvarGetProbvarSum(&multvar, set, &multscalar, &multconstant) );
4135  assert(multvar != NULL);
4136 
4137  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
4138  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
4141 
4142  if( !activeconstantinf )
4143  {
4144  assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
4145 
4146  if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) )
4147  {
4148  assert(scalar != 0.0);
4149  if( scalar * multconstant > 0.0 )
4150  {
4151  activeconstant = SCIPsetInfinity(set);
4152  activeconstantinf = TRUE;
4153  }
4154  else
4155  {
4156  activeconstant = -SCIPsetInfinity(set);
4157  activeconstantinf = TRUE;
4158  }
4159  }
4160  else
4161  activeconstant += scalar * multconstant;
4162  }
4163 #ifndef NDEBUG
4164  else
4165  {
4166  assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
4167  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4168  assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
4169  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4170  }
4171 #endif
4172 
4173  if( SCIPsortedvecFindPtr((void**)tmpvars, SCIPvarComp, multvar, ntmpvars, &pos) )
4174  {
4175  assert(SCIPvarCompare(tmpvars[pos], multvar) == 0);
4176  tmpscalars[pos] += scalar * multscalar;
4177  }
4178  else
4179  {
4180  tmpvars2[ntmpvars2] = multvar;
4181  tmpscalars2[ntmpvars2] = scalar * multscalar;
4182  ++(ntmpvars2);
4183  assert(ntmpvars2 <= tmpvarssize2);
4184  }
4185  }
4186 
4187  if( ntmpvars2 > 0 )
4188  {
4189  /* sort all variables to combine equal variables easily */
4190  SCIPsortPtrReal((void**)tmpvars2, tmpscalars2, SCIPvarComp, ntmpvars2);
4191  pos = 0;
4192  for( v = 1; v < ntmpvars2; ++v )
4193  {
4194  /* combine same variables */
4195  if( SCIPvarCompare(tmpvars2[v], tmpvars2[pos]) == 0 )
4196  {
4197  tmpscalars2[pos] += tmpscalars2[v];
4198  }
4199  else
4200  {
4201  ++pos;
4202  if( v > pos )
4203  {
4204  tmpscalars2[pos] = tmpscalars2[v];
4205  tmpvars2[pos] = tmpvars2[v];
4206  }
4207  }
4208  }
4209  ntmpvars2 = pos + 1;
4210 #ifdef SCIP_MORE_DEBUG
4211  for( v = 1; v < ntmpvars2; ++v )
4212  {
4213  assert(SCIPvarCompare(tmpvars2[v], tmpvars2[v-1]) > 0);
4214  }
4215  for( v = 1; v < ntmpvars; ++v )
4216  {
4217  assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
4218  }
4219 #endif
4220  v = ntmpvars - 1;
4221  k = ntmpvars2 - 1;
4222  pos = ntmpvars + ntmpvars2 - 1;
4223  ntmpvars += ntmpvars2;
4224 
4225  while( v >= 0 && k >= 0 )
4226  {
4227  assert(pos >= 0);
4228  assert(SCIPvarCompare(tmpvars[v], tmpvars2[k]) != 0);
4229  if( SCIPvarCompare(tmpvars[v], tmpvars2[k]) >= 0 )
4230  {
4231  tmpvars[pos] = tmpvars[v];
4232  tmpscalars[pos] = tmpscalars[v];
4233  --v;
4234  }
4235  else
4236  {
4237  tmpvars[pos] = tmpvars2[k];
4238  tmpscalars[pos] = tmpscalars2[k];
4239  --k;
4240  }
4241  --pos;
4242  assert(pos >= 0);
4243  }
4244  while( v >= 0 )
4245  {
4246  assert(pos >= 0);
4247  tmpvars[pos] = tmpvars[v];
4248  tmpscalars[pos] = tmpscalars[v];
4249  --v;
4250  --pos;
4251  }
4252  while( k >= 0 )
4253  {
4254  assert(pos >= 0);
4255  tmpvars[pos] = tmpvars2[k];
4256  tmpscalars[pos] = tmpscalars2[k];
4257  --k;
4258  --pos;
4259  }
4260  }
4261 #ifdef SCIP_MORE_DEBUG
4262  for( v = 1; v < ntmpvars; ++v )
4263  {
4264  assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
4265  }
4266 #endif
4267 
4268  if( !activeconstantinf )
4269  {
4270  assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
4271 
4272  multconstant = SCIPvarGetMultaggrConstant(var);
4273 
4274  if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) )
4275  {
4276  assert(scalar != 0.0);
4277  if( scalar * multconstant > 0.0 )
4278  {
4279  activeconstant = SCIPsetInfinity(set);
4280  activeconstantinf = TRUE;
4281  }
4282  else
4283  {
4284  activeconstant = -SCIPsetInfinity(set);
4285  activeconstantinf = TRUE;
4286  }
4287  }
4288  else
4289  activeconstant += scalar * multconstant;
4290  }
4291 #ifndef NDEBUG
4292  else
4293  {
4294  multconstant = SCIPvarGetMultaggrConstant(var);
4295  assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
4296  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4297  assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
4298  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4299  }
4300 #endif
4301  break;
4302 
4303  case SCIP_VARSTATUS_FIXED:
4307  default:
4308  /* case x = c, but actually we should not be here, since SCIPvarGetProbvarSum() returns a scalar of 0.0 for
4309  * fixed variables and is handled already
4310  */
4311  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED);
4312  assert(SCIPsetIsZero(set, var->glbdom.lb) && SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub));
4313  }
4314  }
4315 
4316  if( mergemultiples )
4317  {
4318  if( sortagain )
4319  {
4320  /* sort variable and scalar array by variable index */
4321  SCIPsortPtrReal((void**)activevars, activescalars, SCIPvarComp, nactivevars);
4322 
4323  /* eliminate duplicates and count required size */
4324  v = nactivevars - 1;
4325  while( v > 0 )
4326  {
4327  /* combine both variable since they are the same */
4328  if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
4329  {
4330  if( activescalars[v - 1] + activescalars[v] != 0.0 )
4331  {
4332  activescalars[v - 1] += activescalars[v];
4333  --nactivevars;
4334  activevars[v] = activevars[nactivevars];
4335  activescalars[v] = activescalars[nactivevars];
4336  }
4337  else
4338  {
4339  --nactivevars;
4340  activevars[v] = activevars[nactivevars];
4341  activescalars[v] = activescalars[nactivevars];
4342  --nactivevars;
4343  --v;
4344  activevars[v] = activevars[nactivevars];
4345  activescalars[v] = activescalars[nactivevars];
4346  }
4347  }
4348  --v;
4349  }
4350  }
4351  /* the variables were added in reverse order, we revert the order now;
4352  * this should not be necessary, but not doing this changes the behavior sometimes
4353  */
4354  else
4355  {
4356  SCIP_VAR* tmpvar;
4357  SCIP_Real tmpscalar;
4358 
4359  for( v = 0; v < nactivevars / 2; ++v )
4360  {
4361  tmpvar = activevars[v];
4362  tmpscalar = activescalars[v];
4363  activevars[v] = activevars[nactivevars - 1 - v];
4364  activescalars[v] = activescalars[nactivevars - 1 - v];
4365  activevars[nactivevars - 1 - v] = tmpvar;
4366  activescalars[nactivevars - 1 - v] = tmpscalar;
4367  }
4368  }
4369  }
4370  *requiredsize = nactivevars;
4371 
4372  if( varssize >= *requiredsize )
4373  {
4374  assert(vars != NULL);
4375 
4376  *nvars = *requiredsize;
4377 
4378  if( !SCIPsetIsInfinity(set, *constant) && !SCIPsetIsInfinity(set, -(*constant)) )
4379  {
4380  /* if the activeconstant is infinite, the constant pointer gets the same value, otherwise add the value */
4381  if( activeconstantinf )
4382  (*constant) = activeconstant;
4383  else
4384  (*constant) += activeconstant;
4385  }
4386 #ifndef NDEBUG
4387  else
4388  {
4389  assert(!SCIPsetIsInfinity(set, (*constant)) || !SCIPsetIsInfinity(set, -activeconstant));
4390  assert(!SCIPsetIsInfinity(set, -(*constant)) || !SCIPsetIsInfinity(set, activeconstant));
4391  }
4392 #endif
4393 
4394  /* copy active variable and scalar array to the given arrays */
4395  for( v = 0; v < *nvars; ++v )
4396  {
4397  vars[v] = activevars[v];
4398  scalars[v] = activescalars[v]; /*lint !e613*/
4399  }
4400  }
4401 
4402  assert(SCIPsetIsInfinity(set, *constant) == ((*constant) == SCIPsetInfinity(set))); /*lint !e777*/
4403  assert(SCIPsetIsInfinity(set, -(*constant)) == ((*constant) == -SCIPsetInfinity(set))); /*lint !e777*/
4404 
4405  SCIPsetFreeBufferArray(set, &tmpscalars);
4406  SCIPsetFreeBufferArray(set, &tmpvars);
4407  SCIPsetFreeBufferArray(set, &activescalars);
4408  SCIPsetFreeBufferArray(set, &activevars);
4409  SCIPsetFreeBufferArray(set, &tmpscalars2);
4410  SCIPsetFreeBufferArray(set, &tmpvars2);
4411 
4412  return SCIP_OKAY;
4413 }
4414 
4415 
4416 /** flattens aggregation graph of multi-aggregated variable in order to avoid exponential recursion later on */
4418  SCIP_VAR* var, /**< problem variable */
4419  BMS_BLKMEM* blkmem, /**< block memory */
4420  SCIP_SET* set, /**< global SCIP settings */
4421  SCIP_EVENTQUEUE* eventqueue /**< event queue */
4422  )
4423 {
4424  int nlocksup[NLOCKTYPES];
4425  int nlocksdown[NLOCKTYPES];
4426  SCIP_Real multconstant;
4427  int multvarssize;
4428  int nmultvars;
4429  int multrequiredsize;
4430  int i;
4431 
4432  assert( var != NULL );
4433  assert( SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR );
4434  assert(var->scip == set->scip);
4435 
4436  /* in order to update the locks on the active representation of the multi-aggregated variable, we remove all locks
4437  * on the current representation now and re-add the locks once the variable graph has been flattened, which
4438  * may lead to duplicate occurences of the same variable being merged
4439  *
4440  * Here is an example. Assume we have the multi-aggregation z = x + y.
4441  * z occures with positive coefficient in a <= constraint c1, so it has an uplock from there.
4442  * When the multi-aggregation is performed, all locks are added to the active representation,
4443  * so x and y both get an uplock from c1. However, z was not yet replaced by x + y in c1.
4444  * Next, a negation y = 1 - x is identified. Again, locks are moved, so that the uplock of y originating
4445  * from c1 is added to x as a downlock. Thus, x has both an up- and downlock from c1.
4446  * The multi-aggregation changes to z = x + 1 - x, which corresponds to the locks.
4447  * However, before z is replaced by that sum, SCIPvarFlattenAggregationGraph() is called
4448  * which changes z = x + y = x + 1 - x = 1, since it merges multiple occurences of the same variable.
4449  * The up- and downlock of x, however, is not removed when replacing z in c1 by its active representation,
4450  * because it is just 1 now. Therefore, we need to update locks when flattening the aggregation graph.
4451  * For this, the multi-aggregated variable knows its locks in addition to adding them to the active
4452  * representation, which corresponds to the locks from constraints where the variable was not replaced yet.
4453  * By removing the locks here, based on the old representation and adding them again after flattening,
4454  * we ensure that the locks are correct afterwards if coefficients were merged.
4455  */
4456  for( i = 0; i < NLOCKTYPES; ++i )
4457  {
4458  nlocksup[i] = var->nlocksup[i];
4459  nlocksdown[i] = var->nlocksdown[i];
4460 
4461  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, -nlocksdown[i], -nlocksup[i]) );
4462  }
4463 
4464  multconstant = var->data.multaggr.constant;
4465  nmultvars = var->data.multaggr.nvars;
4466  multvarssize = var->data.multaggr.varssize;
4467 
4468  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize, TRUE) );
4469 
4470  if( multrequiredsize > multvarssize )
4471  {
4472  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.vars), multvarssize, multrequiredsize) );
4473  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.scalars), multvarssize, multrequiredsize) );
4474  multvarssize = multrequiredsize;
4475  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize, TRUE) );
4476  assert( multrequiredsize <= multvarssize );
4477  }
4478  /**@note After the flattening the multi aggregation might resolve to be in fact an aggregation (or even a fixing?).
4479  * This issue is not resolved right now, since var->data.multaggr.nvars < 2 should not cause troubles. However, one
4480  * may loose performance hereby, since aggregated variables are easier to handle.
4481  *
4482  * Note, that there are two cases where SCIPvarFlattenAggregationGraph() is called: The easier one is that it is
4483  * called while installing the multi-aggregation. in principle, the described issue could be handled straightforward
4484  * in this case by aggregating or fixing the variable instead. The more complicated case is the one, when the
4485  * multi-aggregation is used, e.g., in linear presolving (and the variable is already declared to be multi-aggregated).
4486  *
4487  * By now, it is not allowed to fix or aggregate multi-aggregated variables which would be necessary in this case.
4488  *
4489  * The same issue appears in the SCIPvarGetProbvar...() methods.
4490  */
4491 
4492  var->data.multaggr.constant = multconstant;
4493  var->data.multaggr.nvars = nmultvars;
4494  var->data.multaggr.varssize = multvarssize;
4495 
4496  for( i = 0; i < NLOCKTYPES; ++i )
4497  {
4498  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
4499  }
4500 
4501  return SCIP_OKAY;
4502 }
4503 
4504 /** merge two variable histories together; a typical use case is that \p othervar is an image of the target variable
4505  * in a SCIP copy. Method should be applied with care, especially because no internal checks are performed whether
4506  * the history merge is reasonable
4507  *
4508  * @note Do not use this method if the two variables originate from two SCIP's with different objective functions, since
4509  * this corrupts the variable pseudo costs
4510  * @note Apply with care; no internal checks are performed if the two variables should be merged
4511  */
4513  SCIP_VAR* targetvar, /**< the variable that should contain both histories afterwards */
4514  SCIP_VAR* othervar, /**< the variable whose history is to be merged with that of the target variable */
4515  SCIP_STAT* stat /**< problem statistics */
4516  )
4517 {
4518  /* merge only the history of the current run into the target history */
4519  SCIPhistoryUnite(targetvar->history, othervar->historycrun, FALSE);
4520 
4521  /* apply the changes also to the global history */
4522  SCIPhistoryUnite(stat->glbhistory, othervar->historycrun, FALSE);
4523 }
4524 
4525 /** sets the history of a variable; this method is typically used within reoptimization to keep and update the variable
4526  * history over several iterations
4527  */
4528 void SCIPvarSetHistory(
4529  SCIP_VAR* var, /**< variable */
4530  SCIP_HISTORY* history, /**< the history which is to set */
4531  SCIP_STAT* stat /**< problem statistics */
4532  )
4533 {
4534  /* merge only the history of the current run into the target history */
4535  SCIPhistoryUnite(var->history, history, FALSE);
4536 
4537  /* apply the changes also to the global history */
4538  SCIPhistoryUnite(stat->glbhistory, history, FALSE);
4539 }
4540 
4541 /** tightens the bounds of both variables in aggregation x = a*y + c */
4542 static
4544  SCIP_VAR* var, /**< problem variable */
4545  BMS_BLKMEM* blkmem, /**< block memory */
4546  SCIP_SET* set, /**< global SCIP settings */
4547  SCIP_STAT* stat, /**< problem statistics */
4548  SCIP_PROB* transprob, /**< tranformed problem data */
4549  SCIP_PROB* origprob, /**< original problem data */
4550  SCIP_PRIMAL* primal, /**< primal data */
4551  SCIP_TREE* tree, /**< branch and bound tree */
4552  SCIP_REOPT* reopt, /**< reoptimization data structure */
4553  SCIP_LP* lp, /**< current LP data */
4554  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4555  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4556  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4557  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4558  SCIP_VAR* aggvar, /**< variable y in aggregation x = a*y + c */
4559  SCIP_Real scalar, /**< multiplier a in aggregation x = a*y + c */
4560  SCIP_Real constant, /**< constant shift c in aggregation x = a*y + c */
4561  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4562  SCIP_Bool* fixed /**< pointer to store whether the variables were fixed */
4563  )
4564 {
4565  SCIP_Real varlb;
4566  SCIP_Real varub;
4567  SCIP_Real aggvarlb;
4568  SCIP_Real aggvarub;
4569  SCIP_Bool aggvarbdschanged;
4570 
4571  assert(var != NULL);
4572  assert(var->scip == set->scip);
4573  assert(aggvar != NULL);
4574  assert(!SCIPsetIsZero(set, scalar));
4575  assert(infeasible != NULL);
4576  assert(fixed != NULL);
4577 
4578  *infeasible = FALSE;
4579  *fixed = FALSE;
4580 
4581  SCIPsetDebugMsg(set, "updating bounds of variables in aggregation <%s> == %g*<%s> %+g\n", var->name, scalar, aggvar->name, constant);
4582  SCIPsetDebugMsg(set, " old bounds: <%s> [%g,%g] <%s> [%g,%g]\n",
4583  var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
4584 
4585  /* loop as long additional changes may be found */
4586  do
4587  {
4588  aggvarbdschanged = FALSE;
4589 
4590  /* update the bounds of the aggregated variable x in x = a*y + c */
4591  if( scalar > 0.0 )
4592  {
4593  if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
4594  varlb = -SCIPsetInfinity(set);
4595  else
4596  varlb = aggvar->glbdom.lb * scalar + constant;
4597  if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
4598  varub = SCIPsetInfinity(set);
4599  else
4600  varub = aggvar->glbdom.ub * scalar + constant;
4601  }
4602  else
4603  {
4604  if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
4605  varub = SCIPsetInfinity(set);
4606  else
4607  varub = aggvar->glbdom.lb * scalar + constant;
4608  if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
4609  varlb = -SCIPsetInfinity(set);
4610  else
4611  varlb = aggvar->glbdom.ub * scalar + constant;
4612  }
4613  varlb = MAX(varlb, var->glbdom.lb);
4614  varub = MIN(varub, var->glbdom.ub);
4615  SCIPvarAdjustLb(var, set, &varlb);
4616  SCIPvarAdjustUb(var, set, &varub);
4617 
4618  /* check the new bounds */
4619  if( SCIPsetIsGT(set, varlb, varub) )
4620  {
4621  /* the aggregation is infeasible */
4622  *infeasible = TRUE;
4623  return SCIP_OKAY;
4624  }
4625  else if( SCIPsetIsEQ(set, varlb, varub) )
4626  {
4627  /* the aggregated variable is fixed -> fix both variables */
4628  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4629  eventfilter, eventqueue, cliquetable, varlb, infeasible, fixed) );
4630  if( !(*infeasible) )
4631  {
4632  SCIP_Bool aggfixed;
4633 
4634  SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4635  eventfilter, eventqueue, cliquetable, (varlb-constant)/scalar, infeasible, &aggfixed) );
4636  assert(*fixed == aggfixed);
4637  }
4638  return SCIP_OKAY;
4639  }
4640  else
4641  {
4642  if( SCIPsetIsGT(set, varlb, var->glbdom.lb) )
4643  {
4644  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, varlb) );
4645  }
4646  if( SCIPsetIsLT(set, varub, var->glbdom.ub) )
4647  {
4648  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, varub) );
4649  }
4650 
4651  /* update the hole list of the aggregation variable */
4652  /**@todo update hole list of aggregation variable */
4653  }
4654 
4655  /* update the bounds of the aggregation variable y in x = a*y + c -> y = (x-c)/a */
4656  if( scalar > 0.0 )
4657  {
4658  if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
4659  aggvarlb = -SCIPsetInfinity(set);
4660  else
4661  aggvarlb = (var->glbdom.lb - constant) / scalar;
4662  if( SCIPsetIsInfinity(set, var->glbdom.ub) )
4663  aggvarub = SCIPsetInfinity(set);
4664  else
4665  aggvarub = (var->glbdom.ub - constant) / scalar;
4666  }
4667  else
4668  {
4669  if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
4670  aggvarub = SCIPsetInfinity(set);
4671  else
4672  aggvarub = (var->glbdom.lb - constant) / scalar;
4673  if( SCIPsetIsInfinity(set, var->glbdom.ub) )
4674  aggvarlb = -SCIPsetInfinity(set);
4675  else
4676  aggvarlb = (var->glbdom.ub - constant) / scalar;
4677  }
4678  aggvarlb = MAX(aggvarlb, aggvar->glbdom.lb);
4679  aggvarub = MIN(aggvarub, aggvar->glbdom.ub);
4680  SCIPvarAdjustLb(aggvar, set, &aggvarlb);
4681  SCIPvarAdjustUb(aggvar, set, &aggvarub);
4682 
4683  /* check the new bounds */
4684  if( SCIPsetIsGT(set, aggvarlb, aggvarub) )
4685  {
4686  /* the aggregation is infeasible */
4687  *infeasible = TRUE;
4688  return SCIP_OKAY;
4689  }
4690  else if( SCIPsetIsEQ(set, aggvarlb, aggvarub) )
4691  {
4692  /* the aggregation variable is fixed -> fix both variables */
4693  SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4694  eventfilter, eventqueue, cliquetable, aggvarlb, infeasible, fixed) );
4695  if( !(*infeasible) )
4696  {
4697  SCIP_Bool varfixed;
4698 
4699  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4700  eventfilter, eventqueue, cliquetable, aggvarlb * scalar + constant, infeasible, &varfixed) );
4701  assert(*fixed == varfixed);
4702  }
4703  return SCIP_OKAY;
4704  }
4705  else
4706  {
4707  SCIP_Real oldbd;
4708  if( SCIPsetIsGT(set, aggvarlb, aggvar->glbdom.lb) )
4709  {
4710  oldbd = aggvar->glbdom.lb;
4711  SCIP_CALL( SCIPvarChgLbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, aggvarlb) );
4712  aggvarbdschanged = !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.lb);
4713  }
4714  if( SCIPsetIsLT(set, aggvarub, aggvar->glbdom.ub) )
4715  {
4716  oldbd = aggvar->glbdom.ub;
4717  SCIP_CALL( SCIPvarChgUbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, aggvarub) );
4718  aggvarbdschanged = aggvarbdschanged || !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.ub);
4719  }
4720 
4721  /* update the hole list of the aggregation variable */
4722  /**@todo update hole list of aggregation variable */
4723  }
4724  }
4725  while( aggvarbdschanged );
4726 
4727  SCIPsetDebugMsg(set, " new bounds: <%s> [%g,%g] <%s> [%g,%g]\n",
4728  var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
4729 
4730  return SCIP_OKAY;
4731 }
4732 
4733 /** converts loose variable into aggregated variable */
4735  SCIP_VAR* var, /**< loose problem variable */
4736  BMS_BLKMEM* blkmem, /**< block memory */
4737  SCIP_SET* set, /**< global SCIP settings */
4738  SCIP_STAT* stat, /**< problem statistics */
4739  SCIP_PROB* transprob, /**< tranformed problem data */
4740  SCIP_PROB* origprob, /**< original problem data */
4741  SCIP_PRIMAL* primal, /**< primal data */
4742  SCIP_TREE* tree, /**< branch and bound tree */
4743  SCIP_REOPT* reopt, /**< reoptimization data structure */
4744  SCIP_LP* lp, /**< current LP data */
4745  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4746  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4747  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4748  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4749  SCIP_VAR* aggvar, /**< loose variable y in aggregation x = a*y + c */
4750  SCIP_Real scalar, /**< multiplier a in aggregation x = a*y + c */
4751  SCIP_Real constant, /**< constant shift c in aggregation x = a*y + c */
4752  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4753  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
4754  )
4755 {
4756  SCIP_VAR** vars;
4757  SCIP_Real* coefs;
4758  SCIP_Real* constants;
4759  SCIP_Real obj;
4760  SCIP_Real branchfactor;
4761  SCIP_Bool fixed;
4762  int branchpriority;
4763  int nlocksdown[NLOCKTYPES];
4764  int nlocksup[NLOCKTYPES];
4765  int nvbds;
4766  int i;
4767  int j;
4768 
4769  assert(var != NULL);
4770  assert(aggvar != NULL);
4771  assert(var->scip == set->scip);
4772  assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
4773  assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
4774  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
4775  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
4776  assert(infeasible != NULL);
4777  assert(aggregated != NULL);
4778 
4779  *infeasible = FALSE;
4780  *aggregated = FALSE;
4781 
4782  /* get active problem variable of aggregation variable */
4783  SCIP_CALL( SCIPvarGetProbvarSum(&aggvar, set, &scalar, &constant) );
4784 
4785  /* aggregation is a fixing, if the scalar is zero */
4786  if( SCIPsetIsZero(set, scalar) )
4787  {
4788  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventfilter,
4789  eventqueue, cliquetable, constant, infeasible, aggregated) );
4790  goto TERMINATE;
4791  }
4792 
4793  /* don't perform the aggregation if the aggregation variable is multi-aggregated itself */
4794  if( SCIPvarGetStatus(aggvar) == SCIP_VARSTATUS_MULTAGGR )
4795  return SCIP_OKAY;
4796 
4797  /**@todo currently we don't perform the aggregation if the aggregation variable has a non-empty hole list; this
4798  * should be changed in the future
4799  */
4800  if( SCIPvarGetHolelistGlobal(var) != NULL )
4801  return SCIP_OKAY;
4802 
4803  /* if the variable is not allowed to be aggregated */
4804  if( SCIPvarDoNotAggr(var) )
4805  {
4806  SCIPsetDebugMsg(set, "variable is not allowed to be aggregated.\n");
4807  return SCIP_OKAY;
4808  }
4809 
4810  assert(aggvar->glbdom.lb == aggvar->locdom.lb); /*lint !e777*/
4811  assert(aggvar->glbdom.ub == aggvar->locdom.ub); /*lint !e777*/
4812  assert(SCIPvarGetStatus(aggvar) == SCIP_VARSTATUS_LOOSE);
4813 
4814  SCIPsetDebugMsg(set, "aggregate variable <%s>[%g,%g] == %g*<%s>[%g,%g] %+g\n", var->name, var->glbdom.lb, var->glbdom.ub,
4815  scalar, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub, constant);
4816 
4817  /* if variable and aggregation variable are equal, the variable can be fixed: x == a*x + c => x == c/(1-a) */
4818  if( var == aggvar )
4819  {
4820  if( SCIPsetIsEQ(set, scalar, 1.0) )
4821  *infeasible = !SCIPsetIsZero(set, constant);
4822  else
4823  {
4824  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4825  eventfilter, eventqueue, cliquetable, constant/(1.0-scalar), infeasible, aggregated) );
4826  }
4827  goto TERMINATE;
4828  }
4829 
4830  /* tighten the bounds of aggregated and aggregation variable */
4831  SCIP_CALL( varUpdateAggregationBounds(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
4832  branchcand, eventfilter, eventqueue, cliquetable, aggvar, scalar, constant, infeasible, &fixed) );
4833  if( *infeasible || fixed )
4834  {
4835  *aggregated = fixed;
4836  goto TERMINATE;
4837  }
4838 
4839  /* delete implications and variable bounds of the aggregated variable from other variables, but keep them in the
4840  * aggregated variable
4841  */
4842  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, FALSE) );
4843  assert(var->cliquelist == NULL);
4844 
4845  /* set the aggregated variable's objective value to 0.0 */
4846  obj = var->obj;
4847  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
4848 
4849  /* unlock all locks */
4850  for( i = 0; i < NLOCKTYPES; i++ )
4851  {
4852  nlocksdown[i] = var->nlocksdown[i];
4853  nlocksup[i] = var->nlocksup[i];
4854 
4855  var->nlocksdown[i] = 0;
4856  var->nlocksup[i] = 0;
4857  }
4858 
4859  /* check, if variable should be used as NEGATED variable of the aggregation variable */
4860  if( SCIPvarIsBinary(var) && SCIPvarIsBinary(aggvar)
4861  && var->negatedvar == NULL && aggvar->negatedvar == NULL
4862  && SCIPsetIsEQ(set, scalar, -1.0) && SCIPsetIsEQ(set, constant, 1.0) )
4863  {
4864  /* link both variables as negation pair */
4865  var->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
4866  var->data.negate.constant = 1.0;
4867  var->negatedvar = aggvar;
4868  aggvar->negatedvar = var;
4869 
4870  /* copy donot(mult)aggr status */
4871  aggvar->donotaggr |= var->donotaggr;
4872  aggvar->donotmultaggr |= var->donotmultaggr;
4873 
4874  /* mark both variables to be non-deletable */
4876  SCIPvarMarkNotDeletable(aggvar);
4877  }
4878  else
4879  {
4880  /* convert variable into aggregated variable */
4881  var->varstatus = SCIP_VARSTATUS_AGGREGATED; /*lint !e641*/
4882  var->data.aggregate.var = aggvar;
4883  var->data.aggregate.scalar = scalar;
4884  var->data.aggregate.constant = constant;
4885 
4886  /* copy donot(mult)aggr status */
4887  aggvar->donotaggr |= var->donotaggr;
4888  aggvar->donotmultaggr |= var->donotmultaggr;
4889 
4890  /* mark both variables to be non-deletable */
4892  SCIPvarMarkNotDeletable(aggvar);
4893  }
4894 
4895  /* make aggregated variable a parent of the aggregation variable */
4896  SCIP_CALL( varAddParent(aggvar, blkmem, set, var) );
4897 
4898  /* relock the variable, thus increasing the locks of the aggregation variable */
4899  for( i = 0; i < NLOCKTYPES; i++ )
4900  {
4901  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
4902  }
4903 
4904  /* move the variable bounds to the aggregation variable:
4905  * - add all variable bounds again to the variable, thus adding it to the aggregation variable
4906  * - free the variable bounds data structures
4907  */
4908  if( var->vlbs != NULL )
4909  {
4910  nvbds = SCIPvboundsGetNVbds(var->vlbs);
4911  vars = SCIPvboundsGetVars(var->vlbs);
4912  coefs = SCIPvboundsGetCoefs(var->vlbs);
4913  constants = SCIPvboundsGetConstants(var->vlbs);
4914  for( i = 0; i < nvbds && !(*infeasible); ++i )
4915  {
4916  SCIP_CALL( SCIPvarAddVlb(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
4917  eventqueue, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
4918  }
4919  }
4920  if( var->vubs != NULL )
4921  {
4922  nvbds = SCIPvboundsGetNVbds(var->vubs);
4923  vars = SCIPvboundsGetVars(var->vubs);
4924  coefs = SCIPvboundsGetCoefs(var->vubs);
4925  constants = SCIPvboundsGetConstants(var->vubs);
4926  for( i = 0; i < nvbds && !(*infeasible); ++i )
4927  {
4928  SCIP_CALL( SCIPvarAddVub(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
4929  eventqueue, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
4930  }
4931  }
4932  SCIPvboundsFree(&var->vlbs, blkmem);
4933  SCIPvboundsFree(&var->vubs, blkmem);
4934 
4935  /* move the implications to the aggregation variable:
4936  * - add all implications again to the variable, thus adding it to the aggregation variable
4937  * - free the implications data structures
4938  */
4939  if( var->implics != NULL && SCIPvarGetType(aggvar) == SCIP_VARTYPE_BINARY )
4940  {
4941  assert(SCIPvarIsBinary(var));
4942  for( i = 0; i < 2; ++i )
4943  {
4944  SCIP_VAR** implvars;
4945  SCIP_BOUNDTYPE* impltypes;
4946  SCIP_Real* implbounds;
4947  int nimpls;
4948 
4949  nimpls = SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i);
4950  implvars = SCIPimplicsGetVars(var->implics, (SCIP_Bool)i);
4951  impltypes = SCIPimplicsGetTypes(var->implics, (SCIP_Bool)i);
4952  implbounds = SCIPimplicsGetBounds(var->implics, (SCIP_Bool)i);
4953 
4954  for( j = 0; j < nimpls && !(*infeasible); ++j )
4955  {
4956  /* @todo can't we omit transitive closure, because it should already have been done when adding the
4957  * implication to the aggregated variable?
4958  */
4959  SCIP_CALL( SCIPvarAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
4960  branchcand, eventqueue, (SCIP_Bool)i, implvars[j], impltypes[j], implbounds[j], FALSE, infeasible,
4961  NULL) );
4962  assert(nimpls == SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i));
4963  }
4964  }
4965  }
4966  SCIPimplicsFree(&var->implics, blkmem);
4967 
4968  /* add the history entries to the aggregation variable and clear the history of the aggregated variable */
4969  SCIPhistoryUnite(aggvar->history, var->history, scalar < 0.0);
4970  SCIPhistoryUnite(aggvar->historycrun, var->historycrun, scalar < 0.0);
4971  SCIPhistoryReset(var->history);
4973 
4974  /* update flags of aggregation variable */
4975  aggvar->removable &= var->removable;
4976 
4977  /* update branching factors and priorities of both variables to be the maximum of both variables */
4978  branchfactor = MAX(aggvar->branchfactor, var->branchfactor);
4979  branchpriority = MAX(aggvar->branchpriority, var->branchpriority);
4980  SCIP_CALL( SCIPvarChgBranchFactor(aggvar, set, branchfactor) );
4981  SCIP_CALL( SCIPvarChgBranchPriority(aggvar, branchpriority) );
4982  SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
4983  SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
4984 
4985  /* update branching direction of both variables to agree to a single direction */
4986  if( scalar >= 0.0 )
4987  {
4989  {
4991  }
4992  else if( (SCIP_BRANCHDIR)aggvar->branchdirection == SCIP_BRANCHDIR_AUTO )
4993  {
4995  }
4996  else if( var->branchdirection != aggvar->branchdirection )
4997  {
4999  }
5000  }
5001  else
5002  {
5004  {
5006  }
5007  else if( (SCIP_BRANCHDIR)aggvar->branchdirection == SCIP_BRANCHDIR_AUTO )
5008  {
5010  }
5011  else if( var->branchdirection != aggvar->branchdirection )
5012  {
5014  }
5015  }
5016 
5017  if( var->probindex != -1 )
5018  {
5019  /* inform problem about the variable's status change */
5020  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
5021  }
5022 
5023  /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
5024  * variable and the problem's objective offset
5025  */
5026  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventfilter, eventqueue, obj) );
5027 
5028  /* issue VARFIXED event */
5029  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 1) );
5030 
5031  *aggregated = TRUE;
5032 
5033 TERMINATE:
5034  /* check aggregation on debugging solution */
5035  if( *infeasible || *aggregated )
5036  SCIP_CALL( SCIPdebugCheckAggregation(set, var, &aggvar, &scalar, constant, 1) ); /*lint !e506 !e774*/
5037 
5038  return SCIP_OKAY;
5039 }
5040 
5041 /** Tries to aggregate an equality a*x + b*y == c consisting of two (implicit) integral active problem variables x and
5042  * y. An integer aggregation (i.e. integral coefficients a' and b', such that a'*x + b'*y == c') is searched.
5043  *
5044  * This can lead to the detection of infeasibility (e.g. if c' is fractional), or to a rejection of the aggregation
5045  * (denoted by aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
5046  */
5047 static
5049  SCIP_SET* set, /**< global SCIP settings */
5050  BMS_BLKMEM* blkmem, /**< block memory */
5051  SCIP_STAT* stat, /**< problem statistics */
5052  SCIP_PROB* transprob, /**< tranformed problem data */
5053  SCIP_PROB* origprob, /**< original problem data */
5054  SCIP_PRIMAL* primal, /**< primal data */
5055  SCIP_TREE* tree, /**< branch and bound tree */
5056  SCIP_REOPT* reopt, /**< reoptimization data structure */
5057  SCIP_LP* lp, /**< current LP data */
5058  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5059  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5060  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
5061  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5062  SCIP_VAR* varx, /**< integral variable x in equality a*x + b*y == c */
5063  SCIP_VAR* vary, /**< integral variable y in equality a*x + b*y == c */
5064  SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
5065  SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
5066  SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
5067  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
5068  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
5069  )
5070 {
5071  SCIP_VAR* aggvar;
5072  char aggvarname[SCIP_MAXSTRLEN];
5073  SCIP_Longint scalarxn = 0;
5074  SCIP_Longint scalarxd = 0;
5075  SCIP_Longint scalaryn = 0;
5076  SCIP_Longint scalaryd = 0;
5077  SCIP_Longint a;
5078  SCIP_Longint b;
5079  SCIP_Longint c;
5080  SCIP_Longint scm;
5081  SCIP_Longint gcd;
5082  SCIP_Longint currentclass;
5083  SCIP_Longint classstep;
5084  SCIP_Longint xsol;
5085  SCIP_Longint ysol;
5086  SCIP_Bool success;
5087  SCIP_VARTYPE vartype;
5088 
5089 #define MAXDNOM 1000000LL
5090 
5091  assert(set != NULL);
5092  assert(blkmem != NULL);
5093  assert(stat != NULL);
5094  assert(transprob != NULL);
5095  assert(origprob != NULL);
5096  assert(tree != NULL);
5097  assert(lp != NULL);
5098  assert(cliquetable != NULL);
5099  assert(branchcand != NULL);
5100  assert(eventqueue != NULL);
5101  assert(varx != NULL);
5102  assert(vary != NULL);
5103  assert(varx != vary);
5104  assert(infeasible != NULL);
5105  assert(aggregated != NULL);
5106  assert(SCIPsetGetStage(set) == SCIP_STAGE_PRESOLVING);
5107  assert(SCIPvarGetStatus(varx) == SCIP_VARSTATUS_LOOSE);
5109  assert(SCIPvarGetStatus(vary) == SCIP_VARSTATUS_LOOSE);
5111  assert(!SCIPsetIsZero(set, scalarx));
5112  assert(!SCIPsetIsZero(set, scalary));
5113 
5114  *infeasible = FALSE;
5115  *aggregated = FALSE;
5116 
5117  /* if the variable is not allowed to be aggregated */
5118  if( SCIPvarDoNotAggr(varx) )
5119  {
5120  SCIPsetDebugMsg(set, "variable is not allowed to be aggregated.\n");
5121  return SCIP_OKAY;
5122  }
5123 
5124  /* get rational representation of coefficients */
5125  success = SCIPrealToRational(scalarx, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalarxn, &scalarxd);
5126  if( success )
5127  success = SCIPrealToRational(scalary, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalaryn, &scalaryd);
5128  if( !success )
5129  return SCIP_OKAY;
5130  assert(scalarxd >= 1);
5131  assert(scalaryd >= 1);
5132 
5133  /* multiply equality with smallest common denominator */
5134  scm = SCIPcalcSmaComMul(scalarxd, scalaryd);
5135  a = (scm/scalarxd)*scalarxn;
5136  b = (scm/scalaryd)*scalaryn;
5137  rhs *= scm;
5138 
5139  /* divide equality by the greatest common divisor of a and b */
5140  gcd = SCIPcalcGreComDiv(ABS(a), ABS(b));
5141  a /= gcd;
5142  b /= gcd;
5143  rhs /= gcd;
5144  assert(a != 0);
5145  assert(b != 0);
5146 
5147  /* check, if right hand side is integral */
5148  if( !SCIPsetIsFeasIntegral(set, rhs) )
5149  {
5150  *infeasible = TRUE;
5151  return SCIP_OKAY;
5152  }
5153  c = (SCIP_Longint)(SCIPsetFeasFloor(set, rhs));
5154 
5155  /* check that the scalar and constant in the aggregation are not too large to avoid numerical problems */
5156  if( REALABS((SCIP_Real)(c/a)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) /*lint !e653*/
5157  || REALABS((SCIP_Real)(b)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) /*lint !e653*/
5158  || REALABS((SCIP_Real)(a)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
5159  {
5160  return SCIP_OKAY;
5161  }
5162 
5163  /* check, if we are in an easy case with either |a| = 1 or |b| = 1 */
5164  if( (a == 1 || a == -1) && SCIPvarGetType(vary) == SCIP_VARTYPE_INTEGER )
5165  {
5166  /* aggregate x = - b/a*y + c/a */
5167  /*lint --e{653}*/
5168  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5169  branchcand, eventfilter, eventqueue, vary, (SCIP_Real)(-b/a), (SCIP_Real)(c/a), infeasible, aggregated) );
5170  assert(*aggregated);
5171  return SCIP_OKAY;
5172  }
5173  if( (b == 1 || b == -1) && SCIPvarGetType(varx) == SCIP_VARTYPE_INTEGER )
5174  {
5175  /* aggregate y = - a/b*x + c/b */
5176  /*lint --e{653}*/
5177  SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5178  branchcand, eventfilter, eventqueue, varx, (SCIP_Real)(-a/b), (SCIP_Real)(c/b), infeasible, aggregated) );
5179  assert(*aggregated);
5180  return SCIP_OKAY;
5181  }
5182 
5183  /* Both variables are integers, their coefficients are not multiples of each other, and they don't have any
5184  * common divisor. Let (x',y') be a solution of the equality
5185  * a*x + b*y == c -> a*x == c - b*y
5186  * Then x = -b*z + x', y = a*z + y' with z integral gives all solutions to the equality.
5187  */
5188 
5189  /* find initial solution (x',y'):
5190  * - find y' such that c - b*y' is a multiple of a
5191  * - start in equivalence class c%a
5192  * - step through classes, where each step increases class number by (-b)%a, until class 0 is visited
5193  * - if equivalence class 0 is visited, we are done: y' equals the number of steps taken
5194  * - 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
5195  * - calculate x' with x' = (c - b*y')/a (which must be integral)
5196  *
5197  * Algorithm works for a > 0 only.
5198  */
5199  if( a < 0 )
5200  {
5201  a = -a;
5202  b = -b;
5203  c = -c;
5204  }
5205  assert(a > 0);
5206 
5207  /* search upwards from ysol = 0 */
5208  ysol = 0;
5209  currentclass = c % a;
5210  if( currentclass < 0 )
5211  currentclass += a;
5212  assert(0 <= currentclass && currentclass < a);
5213 
5214  classstep = (-b) % a;
5215 
5216  if( classstep < 0 )
5217  classstep += a;
5218  assert(0 <= classstep && classstep < a);
5219 
5220  while( currentclass != 0 )
5221  {
5222  assert(0 <= currentclass && currentclass < a);
5223  currentclass += classstep;
5224  if( currentclass >= a )
5225  currentclass -= a;
5226  ysol++;
5227  }
5228  assert(ysol < a);
5229  assert(((c - b*ysol) % a) == 0);
5230 
5231  xsol = (c - b*ysol)/a;
5232 
5233  /* determine variable type for new artificial variable:
5234  *
5235  * if both variables are implicit integer the new variable can be implicit too, because the integer implication on
5236  * these both variables should be enforced by some other variables, otherwise the new variable needs to be of
5237  * integral type
5238  */
5241 
5242  /* feasible solutions are (x,y) = (x',y') + z*(-b,a)
5243  * - create new integer variable z with infinite bounds
5244  * - aggregate variable x = -b*z + x'
5245  * - aggregate variable y = a*z + y'
5246  * - the bounds of z are calculated automatically during aggregation
5247  */
5248  (void) SCIPsnprintf(aggvarname, SCIP_MAXSTRLEN, "agg%d", stat->nvaridx);
5249  SCIP_CALL( SCIPvarCreateTransformed(&aggvar, blkmem, set, stat,
5250  aggvarname, -SCIPsetInfinity(set), SCIPsetInfinity(set), 0.0, vartype,
5252  NULL, NULL, NULL, NULL, NULL) );
5253 
5254  SCIP_CALL( SCIPprobAddVar(transprob, blkmem, set, lp, branchcand, eventfilter, eventqueue, aggvar) );
5255 
5256  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5257  branchcand, eventfilter, eventqueue, aggvar, (SCIP_Real)(-b), (SCIP_Real)xsol, infeasible, aggregated) );
5258  assert(*aggregated || *infeasible);
5259 
5260  if( !(*infeasible) )
5261  {
5262  SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5263  branchcand, eventfilter, eventqueue, aggvar, (SCIP_Real)a, (SCIP_Real)ysol, infeasible, aggregated) );
5264  assert(*aggregated || *infeasible);
5265  }
5266 
5267  /* release z */
5268  SCIP_CALL( SCIPvarRelease(&aggvar, blkmem, set, eventqueue, lp) );
5269 
5270  return SCIP_OKAY; /*lint !e438*/
5271 }
5272 
5273 /** performs second step of SCIPaggregateVars():
5274  * the variable to be aggregated is chosen among active problem variables x' and y', preferring a less strict variable
5275  * type as aggregation variable (i.e. continuous variables are preferred over implicit integers, implicit integers
5276  * or integers over binaries). If none of the variables is continuous, it is tried to find an integer
5277  * aggregation (i.e. integral coefficients a'' and b'', such that a''*x' + b''*y' == c''). This can lead to
5278  * the detection of infeasibility (e.g. if c'' is fractional), or to a rejection of the aggregation (denoted by
5279  * aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
5280  *
5281  * @todo check for fixings, infeasibility, bound changes, or domain holes:
5282  * a) if there is no easy aggregation and we have one binary variable and another integer/implicit/binary variable
5283  * b) for implicit integer variables with fractional aggregation scalar (we cannot (for technical reasons) and do
5284  * not want to aggregate implicit integer variables, since we loose the corresponding divisibility property)
5285  */
5287  SCIP_SET* set, /**< global SCIP settings */
5288  BMS_BLKMEM* blkmem, /**< block memory */
5289  SCIP_STAT* stat, /**< problem statistics */
5290  SCIP_PROB* transprob, /**< tranformed problem data */
5291  SCIP_PROB* origprob, /**< original problem data */
5292  SCIP_PRIMAL* primal, /**< primal data */
5293  SCIP_TREE* tree, /**< branch and bound tree */
5294  SCIP_REOPT* reopt, /**< reoptimization data structure */
5295  SCIP_LP* lp, /**< current LP data */
5296  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5297  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5298  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
5299  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5300  SCIP_VAR* varx, /**< variable x in equality a*x + b*y == c */
5301  SCIP_VAR* vary, /**< variable y in equality a*x + b*y == c */
5302  SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
5303  SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
5304  SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
5305  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
5306  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
5307  )
5308 {
5309  SCIP_Bool easyaggr;
5310  SCIP_Real maxscalar;
5311  SCIP_Real absquot;
5312 
5313  assert(set != NULL);
5314  assert(blkmem != NULL);
5315  assert(stat != NULL);
5316  assert(transprob != NULL);
5317  assert(origprob != NULL);
5318  assert(tree != NULL);
5319  assert(lp != NULL);
5320  assert(cliquetable != NULL);
5321  assert(branchcand != NULL);
5322  assert(eventqueue != NULL);
5323  assert(varx != NULL);
5324  assert(vary != NULL);
5325  assert(varx != vary);
5326  assert(infeasible != NULL);
5327  assert(aggregated != NULL);
5328  assert(SCIPsetGetStage(set) == SCIP_STAGE_PRESOLVING);
5329  assert(SCIPvarGetStatus(varx) == SCIP_VARSTATUS_LOOSE);
5330  assert(SCIPvarGetStatus(vary) == SCIP_VARSTATUS_LOOSE);
5331  assert(!SCIPsetIsZero(set, scalarx));
5332  assert(!SCIPsetIsZero(set, scalary));
5333 
5334  *infeasible = FALSE;
5335  *aggregated = FALSE;
5336 
5337  absquot = REALABS(scalarx / scalary);
5338  maxscalar = SCIPsetFeastol(set) / SCIPsetEpsilon(set);
5339  maxscalar = MAX(maxscalar, 1.0);
5340 
5341  if( absquot > maxscalar || absquot < 1 / maxscalar )
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 that means:
5370  *
5371  * a*x + b*y == c -> x == -b/a * y + c/a iff |b/a| > feastol and |a/b| > feastol
5372  */
5373  if( !SCIPsetIsFeasZero(set, scalary/scalarx) && !SCIPsetIsFeasZero(set, scalarx/scalary) )
5374  {
5376  {
5377  easyaggr = TRUE;
5378  }
5379  else if( SCIPsetIsFeasIntegral(set, scalary/scalarx) )
5380  {
5381  easyaggr = TRUE;
5382  }
5383  else if( SCIPsetIsFeasIntegral(set, scalarx/scalary) && SCIPvarGetType(vary) == SCIPvarGetType(varx) )
5384  {
5385  /* we have an easy aggregation if we flip the variables x and y */
5386  SCIP_VAR* var;
5387  SCIP_Real scalar;
5388 
5389  /* switch the variables, such that varx is the aggregated variable */
5390  var = vary;
5391  vary = varx;
5392  varx = var;
5393  scalar = scalary;
5394  scalary = scalarx;
5395  scalarx = scalar;
5396  easyaggr = TRUE;
5397  }
5398  else if( SCIPvarGetType(varx) == SCIP_VARTYPE_CONTINUOUS )
5399  {
5400  /* the aggregation is still easy if both variables are continuous */
5401  assert(SCIPvarGetType(vary) == SCIP_VARTYPE_CONTINUOUS); /* otherwise we are in the first case */
5402  easyaggr = TRUE;
5403  }
5404  }
5405 
5406  /* did we find an "easy" aggregation? */
5407  if( easyaggr )
5408  {
5409  SCIP_Real scalar;
5410  SCIP_Real constant;
5411 
5412  assert(SCIPvarGetType(varx) >= SCIPvarGetType(vary));
5413 
5414  /* calculate aggregation scalar and constant: a*x + b*y == c => x == -b/a * y + c/a */
5415  scalar = -scalary/scalarx;
5416  constant = rhs/scalarx;
5417 
5418  if( REALABS(constant) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
5419  return SCIP_OKAY;
5420 
5421  /* check aggregation for integer feasibility */
5424  && SCIPsetIsFeasIntegral(set, scalar) && !SCIPsetIsFeasIntegral(set, constant) )
5425  {
5426  *infeasible = TRUE;
5427  return SCIP_OKAY;
5428  }
5429 
5430  /* if the aggregation scalar is fractional, we cannot (for technical reasons) and do not want to aggregate implicit integer variables,
5431  * since then we would loose the corresponding divisibility property
5432  */
5433  assert(SCIPvarGetType(varx) != SCIP_VARTYPE_IMPLINT || SCIPsetIsFeasIntegral(set, scalar));
5434 
5435  /* aggregate the variable */
5436  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5437  branchcand, eventfilter, eventqueue, vary, scalar, constant, infeasible, aggregated) );
5438  assert(*aggregated || *infeasible || SCIPvarDoNotAggr(varx));
5439  }
5442  {
5443  /* the variables are both integral: we have to try to find an integer aggregation */
5444  SCIP_CALL( tryAggregateIntVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5445  branchcand, eventfilter, eventqueue, varx, vary, scalarx, scalary, rhs, infeasible, aggregated) );
5446  }
5447 
5448  return SCIP_OKAY;
5449 }
5450 
5451 /** converts variable into multi-aggregated variable */
5453  SCIP_VAR* var, /**< problem variable */
5454  BMS_BLKMEM* blkmem, /**< block memory */
5455  SCIP_SET* set, /**< global SCIP settings */
5456  SCIP_STAT* stat, /**< problem statistics */
5457  SCIP_PROB* transprob, /**< tranformed problem data */
5458  SCIP_PROB* origprob, /**< original problem data */
5459  SCIP_PRIMAL* primal, /**< primal data */
5460  SCIP_TREE* tree, /**< branch and bound tree */
5461  SCIP_REOPT* reopt, /**< reoptimization data structure */
5462  SCIP_LP* lp, /**< current LP data */
5463  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5464  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5465  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
5466  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5467  int naggvars, /**< number n of variables in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5468  SCIP_VAR** aggvars, /**< variables y_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5469  SCIP_Real* scalars, /**< multipliers a_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5470  SCIP_Real constant, /**< constant shift c in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5471  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
5472  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
5473  )
5474 {
5475  SCIP_VAR** tmpvars;
5476  SCIP_Real* tmpscalars;
5477  SCIP_Real obj;
5478  SCIP_Real branchfactor;
5479  int branchpriority;
5480  SCIP_BRANCHDIR branchdirection;
5481  int nlocksdown[NLOCKTYPES];
5482  int nlocksup[NLOCKTYPES];
5483  int v;
5484  SCIP_Real tmpconstant;
5485  SCIP_Real tmpscalar;
5486  int ntmpvars;
5487  int tmpvarssize;
5488  int tmprequiredsize;
5489  int i;
5490 
5491  assert(var != NULL);
5492  assert(var->scip == set->scip);
5493  assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
5494  assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
5495  assert(naggvars == 0 || aggvars != NULL);
5496  assert(naggvars == 0 || scalars != NULL);
5497  assert(infeasible != NULL);
5498  assert(aggregated != NULL);
5499 
5500  SCIPsetDebugMsg(set, "trying multi-aggregating variable <%s> == ...%d vars... %+g\n", var->name, naggvars, constant);
5501 
5502  *infeasible = FALSE;
5503  *aggregated = FALSE;
5504 
5505  switch( SCIPvarGetStatus(var) )
5506  {
5508  if( var->data.original.transvar == NULL )
5509  {
5510  SCIPerrorMessage("cannot multi-aggregate an untransformed original variable\n");
5511  return SCIP_INVALIDDATA;
5512  }
5513  SCIP_CALL( SCIPvarMultiaggregate(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
5514  reopt, lp, cliquetable, branchcand, eventfilter, eventqueue, naggvars, aggvars, scalars, constant, infeasible, aggregated) );
5515  break;
5516 
5517  case SCIP_VARSTATUS_LOOSE:
5518  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
5519 
5520  /* check if we would create a self-reference */
5521  ntmpvars = naggvars;
5522  tmpvarssize = naggvars;
5523  tmpconstant = constant;
5524  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpvars, aggvars, ntmpvars) );
5525  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpscalars, scalars, ntmpvars) );
5526 
5527  /* get all active variables for multi-aggregation */
5528  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize, FALSE) );
5529  if( tmprequiredsize > tmpvarssize )
5530  {
5531  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpvars, tmpvarssize, tmprequiredsize) );
5532  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize, tmprequiredsize) );
5533  tmpvarssize = tmprequiredsize;
5534  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize, FALSE) );
5535  assert( tmprequiredsize <= tmpvarssize );
5536  }
5537 
5538  tmpscalar = 0.0;
5539 
5540  /* iterate over all active variables of the multi-aggregation and filter all variables which are equal to the
5541  * possible multi-aggregated variable
5542  */
5543  for( v = ntmpvars - 1; v >= 0; --v )
5544  {
5545  assert(tmpvars[v] != NULL);
5546  assert(SCIPvarGetStatus(tmpvars[v]) == SCIP_VARSTATUS_LOOSE);
5547 
5548  if( tmpvars[v]->index == var->index )
5549  {
5550  tmpscalar += tmpscalars[v];
5551  tmpvars[v] = tmpvars[ntmpvars - 1];
5552  tmpscalars[v] = tmpscalars[ntmpvars - 1];
5553  --ntmpvars;
5554  }
5555  }
5556 
5557  /* this means that x = x + a_1*y_1 + ... + a_n*y_n + c */
5558  if( SCIPsetIsEQ(set, tmpscalar, 1.0) )
5559  {
5560  if( ntmpvars == 0 )
5561  {
5562  if( SCIPsetIsZero(set, tmpconstant) ) /* x = x */
5563  {
5564  SCIPsetDebugMsg(set, "Possible multi-aggregation was completely resolved and detected to be redundant.\n");
5565  goto TERMINATE;
5566  }
5567  else /* 0 = c and c != 0 */
5568  {
5569  SCIPsetDebugMsg(set, "Multi-aggregation was completely resolved and led to infeasibility.\n");
5570  *infeasible = TRUE;
5571  goto TERMINATE;
5572  }
5573  }
5574  else if( ntmpvars == 1 ) /* 0 = a*y + c => y = -c/a */
5575  {
5576  assert(tmpscalars[0] != 0.0);
5577  assert(tmpvars[0] != NULL);
5578 
5579  SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(tmpvars[0]), -constant/tmpscalars[0]);
5580  SCIP_CALL( SCIPvarFix(tmpvars[0], blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5581  branchcand, eventfilter, eventqueue, cliquetable, -constant/tmpscalars[0], infeasible, aggregated) );
5582  goto TERMINATE;
5583  }
5584  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 */
5585  {
5586  /* both variables are different active problem variables, and both scalars are non-zero: try to aggregate them */
5587  SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
5588  SCIPvarGetName(tmpvars[0]), SCIPvarGetName(tmpvars[1]), tmpscalars[0], tmpscalars[1], -tmpconstant);
5589 
5590  SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
5591  cliquetable, branchcand, eventfilter, eventqueue, tmpvars[0], tmpvars[1], tmpscalars[0],
5592  tmpscalars[1], -tmpconstant, infeasible, aggregated) );
5593 
5594  goto TERMINATE;
5595  }
5596  else
5597  /* @todo: it is possible to multi-aggregate another variable, does it make sense?,
5598  * rest looks like 0 = a_1*y_1 + ... + a_n*y_n + c and has at least three variables
5599  */
5600  goto TERMINATE;
5601  }
5602  /* this means that x = b*x + a_1*y_1 + ... + a_n*y_n + c */
5603  else if( !SCIPsetIsZero(set, tmpscalar) )
5604  {
5605  tmpscalar = 1 - tmpscalar;
5606  tmpconstant /= tmpscalar;
5607  for( v = ntmpvars - 1; v >= 0; --v )
5608  tmpscalars[v] /= tmpscalar;
5609  }
5610 
5611  /* check, if we are in one of the simple cases */
5612  if( ntmpvars == 0 )
5613  {
5614  SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(var), tmpconstant);
5615  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
5616  eventfilter, eventqueue, cliquetable, tmpconstant, infeasible, aggregated) );
5617  goto TERMINATE;
5618  }
5619 
5620  /* if only one aggregation variable is left, we perform a normal aggregation instead of a multi-aggregation */
5621  if( ntmpvars == 1 )
5622  {
5623  SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
5624  SCIPvarGetName(var), SCIPvarGetName(tmpvars[0]), 1.0, -tmpscalars[0], tmpconstant);
5625 
5626  SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
5627  cliquetable, branchcand, eventfilter, eventqueue, var, tmpvars[0], 1.0, -tmpscalars[0], tmpconstant,
5628  infeasible, aggregated) );
5629 
5630  goto TERMINATE;
5631  }
5632 
5633  /**@todo currently we don't perform the multi aggregation if the multi aggregation variable has a non
5634  * empty hole list; this should be changed in the future */
5635  if( SCIPvarGetHolelistGlobal(var) != NULL )
5636  goto TERMINATE;
5637 
5638  /* if the variable is not allowed to be multi-aggregated */
5639  if( SCIPvarDoNotMultaggr(var) )
5640  {
5641  SCIPsetDebugMsg(set, "variable is not allowed to be multi-aggregated.\n");
5642  goto TERMINATE;
5643  }
5644 
5645  /* if the variable to be multi-aggregated has implications or variable bounds (i.e. is the implied variable or
5646  * variable bound variable of another variable), we have to remove it from the other variables implications or
5647  * variable bounds
5648  */
5649  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
5650  assert(var->vlbs == NULL);
5651  assert(var->vubs == NULL);
5652  assert(var->implics == NULL);
5653  assert(var->cliquelist == NULL);
5654 
5655  /* set the aggregated variable's objective value to 0.0 */
5656  obj = var->obj;
5657  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
5658 
5659  /* since we change the variable type form loose to multi aggregated, we have to adjust the number of loose
5660  * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
5661  * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
5662  * objective of this variable is set to zero
5663  */
5664  SCIPlpDecNLoosevars(lp);
5665 
5666  /* unlock all rounding locks */
5667  for( i = 0; i < NLOCKTYPES; i++ )
5668  {
5669  nlocksdown[i] = var->nlocksdown[i];
5670  nlocksup[i] = var->nlocksup[i];
5671 
5672  var->nlocksdown[i] = 0;
5673  var->nlocksup[i] = 0;
5674  }
5675 
5676  /* convert variable into multi-aggregated variable */
5677  var->varstatus = SCIP_VARSTATUS_MULTAGGR; /*lint !e641*/
5678  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.vars, tmpvars, ntmpvars) );
5679  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.scalars, tmpscalars, ntmpvars) );
5680  var->data.multaggr.constant = tmpconstant;
5681  var->data.multaggr.nvars = ntmpvars;
5682  var->data.multaggr.varssize = ntmpvars;
5683 
5684  /* mark variable to be non-deletable */
5686 
5687  /* relock the variable, thus increasing the locks of the aggregation variables */
5688  for( i = 0; i < NLOCKTYPES; i++ )
5689  {
5690  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
5691  }
5692 
5693  /* update flags and branching factors and priorities of aggregation variables;
5694  * update preferred branching direction of all aggregation variables that don't have a preferred direction yet
5695  */
5696  branchfactor = var->branchfactor;
5697  branchpriority = var->branchpriority;
5698  branchdirection = (SCIP_BRANCHDIR)var->branchdirection;
5699 
5700  for( v = 0; v < ntmpvars; ++v )
5701  {
5702  assert(tmpvars[v] != NULL);
5703  tmpvars[v]->removable &= var->removable;
5704  branchfactor = MAX(tmpvars[v]->branchfactor, branchfactor);
5705  branchpriority = MAX(tmpvars[v]->branchpriority, branchpriority);
5706 
5707  /* mark variable to be non-deletable */
5708  SCIPvarMarkNotDeletable(tmpvars[v]);
5709  }
5710  for( v = 0; v < ntmpvars; ++v )
5711  {
5712  SCIP_CALL( SCIPvarChgBranchFactor(tmpvars[v], set, branchfactor) );
5713  SCIP_CALL( SCIPvarChgBranchPriority(tmpvars[v], branchpriority) );
5714  if( (SCIP_BRANCHDIR)tmpvars[v]->branchdirection == SCIP_BRANCHDIR_AUTO )
5715  {
5716  if( tmpscalars[v] >= 0.0 )
5717  {
5718  SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], branchdirection) );
5719  }
5720  else
5721  {
5722  SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], SCIPbranchdirOpposite(branchdirection)) );
5723  }
5724  }
5725  }
5726  SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
5727  SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
5728 
5729  if( var->probindex != -1 )
5730  {
5731  /* inform problem about the variable's status change */
5732  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
5733  }
5734 
5735  /* issue VARFIXED event */
5736  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 2) );
5737 
5738  /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
5739  * variables and the problem's objective offset
5740  */
5741  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventfilter, eventqueue, obj) );
5742 
5743  *aggregated = TRUE;
5744 
5745  TERMINATE:
5746  BMSfreeBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize);
5747  BMSfreeBlockMemoryArray(blkmem, &tmpvars, tmpvarssize);
5748 
5749  break;
5750 
5751  case SCIP_VARSTATUS_COLUMN:
5752  SCIPerrorMessage("cannot multi-aggregate a column variable\n");
5753  return SCIP_INVALIDDATA;
5754 
5755  case SCIP_VARSTATUS_FIXED:
5756  SCIPerrorMessage("cannot multi-aggregate a fixed variable\n");
5757  return SCIP_INVALIDDATA;
5758 
5760  SCIPerrorMessage("cannot multi-aggregate an aggregated variable\n");
5761  return SCIP_INVALIDDATA;
5762 
5764  SCIPerrorMessage("cannot multi-aggregate a multiple aggregated variable again\n");
5765  return SCIP_INVALIDDATA;
5766 
5768  /* aggregate negation variable x in x' = offset - x, instead of aggregating x' directly:
5769  * x' = a_1*y_1 + ... + a_n*y_n + c -> x = offset - x' = offset - a_1*y_1 - ... - a_n*y_n - c
5770  */
5771  assert(SCIPsetIsZero(set, var->obj));
5772  assert(var->negatedvar != NULL);
5774  assert(var->negatedvar->negatedvar == var);
5775 
5776  /* switch the signs of the aggregation scalars */
5777  for( v = 0; v < naggvars; ++v )
5778  scalars[v] *= -1.0;
5779 
5780  /* perform the multi aggregation on the negation variable */
5781  SCIP_CALL( SCIPvarMultiaggregate(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5782  cliquetable, branchcand, eventfilter, eventqueue, naggvars, aggvars, scalars,
5783  var->data.negate.constant - constant, infeasible, aggregated) );
5784 
5785  /* switch the signs of the aggregation scalars again, to reset them to their original values */
5786  for( v = 0; v < naggvars; ++v )
5787  scalars[v] *= -1.0;
5788  break;
5789 
5790  default:
5791  SCIPerrorMessage("unknown variable status\n");
5792  return SCIP_INVALIDDATA;
5793  }
5794 
5795  /* check multi-aggregation on debugging solution */
5796  if( *infeasible || *aggregated )
5797  SCIP_CALL( SCIPdebugCheckAggregation(set, var, aggvars, scalars, constant, naggvars) ); /*lint !e506 !e774*/
5798 
5799  return SCIP_OKAY;
5800 }
5801 
5802 /** transformed variables are resolved to their active, fixed, or multi-aggregated problem variable of a variable,
5803  * or for original variables the same variable is returned
5804  */
5805 static
5807  SCIP_VAR* var /**< problem variable */
5808  )
5809 {
5810  SCIP_VAR* retvar;
5811 
5812  assert(var != NULL);
5813 
5814  retvar = var;
5815 
5816  SCIPdebugMessage("get active variable of <%s>\n", var->name);
5817 
5818  while( TRUE ) /*lint !e716 */
5819  {
5820  assert(retvar != NULL);
5821 
5822  switch( SCIPvarGetStatus(retvar) )
5823  {
5825  case SCIP_VARSTATUS_LOOSE:
5826  case SCIP_VARSTATUS_COLUMN:
5827  case SCIP_VARSTATUS_FIXED:
5828  return retvar;
5829 
5831  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
5832  if ( retvar->data.multaggr.nvars == 1 )
5833  retvar = retvar->data.multaggr.vars[0];
5834  else
5835  return retvar;
5836  break;
5837 
5839  retvar = retvar->data.aggregate.var;
5840  break;
5841 
5843  retvar = retvar->negatedvar;
5844  break;
5845 
5846  default:
5847  SCIPerrorMessage("unknown variable status\n");
5848  SCIPABORT();
5849  return NULL; /*lint !e527*/
5850  }
5851  }
5852 }
5853 
5854 /** returns whether variable is not allowed to be aggregated */
5856  SCIP_VAR* var /**< problem variable */
5857  )
5858 {
5859  SCIP_VAR* retvar;
5860 
5861  assert(var != NULL);
5862 
5863  retvar = varGetActiveVar(var);
5864  assert(retvar != NULL);
5865 
5866  switch( SCIPvarGetStatus(retvar) )
5867  {
5869  case SCIP_VARSTATUS_LOOSE:
5870  case SCIP_VARSTATUS_COLUMN:
5871  case SCIP_VARSTATUS_FIXED:
5872  return retvar->donotaggr;
5873 
5875  return FALSE;
5876 
5879  default:
5880  /* aggregated and negated variables should be resolved by varGetActiveVar() */
5881  SCIPerrorMessage("wrong variable status\n");
5882  SCIPABORT();
5883  return FALSE; /*lint !e527 */
5884  }
5885 }
5886 
5887 /** returns whether variable is not allowed to be multi-aggregated */
5889  SCIP_VAR* var /**< problem variable */
5890  )
5891 {
5892  SCIP_VAR* retvar;
5893 
5894  assert(var != NULL);
5895 
5896  retvar = varGetActiveVar(var);
5897  assert(retvar != NULL);
5898 
5899  switch( SCIPvarGetStatus(retvar) )
5900  {
5902  case SCIP_VARSTATUS_LOOSE:
5903  case SCIP_VARSTATUS_COLUMN:
5904  case SCIP_VARSTATUS_FIXED:
5905  return retvar->donotmultaggr;
5906 
5908  return FALSE;
5909 
5912  default:
5913  /* aggregated and negated variables should be resolved by varGetActiveVar() */
5914  SCIPerrorMessage("wrong variable status\n");
5915  SCIPABORT();
5916  return FALSE; /*lint !e527 */
5917  }
5918 }
5919 
5920 /** gets negated variable x' = offset - x of problem variable x; the negated variable is created if not yet existing;
5921  * the negation offset of binary variables is always 1, the offset of other variables is fixed to lb + ub when the
5922  * negated variable is created
5923  */
5925  SCIP_VAR* var, /**< problem variable to negate */
5926  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
5927  SCIP_SET* set, /**< global SCIP settings */
5928  SCIP_STAT* stat, /**< problem statistics */
5929  SCIP_VAR** negvar /**< pointer to store the negated variable */
5930  )
5931 {
5932  assert(var != NULL);
5933  assert(var->scip == set->scip);
5934  assert(negvar != NULL);
5935 
5936  /* check, if we already created the negated variable */
5937  if( var->negatedvar == NULL )
5938  {
5939  char negvarname[SCIP_MAXSTRLEN];
5940 
5941  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED);
5942 
5943  SCIPsetDebugMsg(set, "creating negated variable of <%s>\n", var->name);
5944 
5945  /* negation is only possible for bounded variables */
5946  if( SCIPsetIsInfinity(set, -var->glbdom.lb) || SCIPsetIsInfinity(set, var->glbdom.ub) )
5947  {
5948  SCIPerrorMessage("cannot negate unbounded variable\n");
5949  return SCIP_INVALIDDATA;
5950  }
5951 
5952  (void) SCIPsnprintf(negvarname, SCIP_MAXSTRLEN, "%s_neg", var->name);
5953 
5954  /* create negated variable */
5955  SCIP_CALL( varCreate(negvar, blkmem, set, stat, negvarname, var->glbdom.lb, var->glbdom.ub, 0.0,
5956  SCIPvarGetType(var), var->initial, var->removable, NULL, NULL, NULL, NULL, NULL) );
5957  (*negvar)->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
5958  if( SCIPvarIsBinary(var) )
5959  (*negvar)->data.negate.constant = 1.0;
5960  else
5961  (*negvar)->data.negate.constant = var->glbdom.lb + var->glbdom.ub;
5962 
5963  /* create event filter for transformed variable */
5964  if( SCIPvarIsTransformed(var) )
5965  {
5966  SCIP_CALL( SCIPeventfilterCreate(&(*negvar)->eventfilter, blkmem) );
5967  }
5968 
5969  /* set the bounds corresponding to the negation variable */
5970  (*negvar)->glbdom.lb = (*negvar)->data.negate.constant - var->glbdom.ub;
5971  (*negvar)->glbdom.ub = (*negvar)->data.negate.constant - var->glbdom.lb;
5972  (*negvar)->locdom.lb = (*negvar)->data.negate.constant - var->locdom.ub;
5973  (*negvar)->locdom.ub = (*negvar)->data.negate.constant - var->locdom.lb;
5974  /**@todo create holes in the negated variable corresponding to the holes of the negation variable */
5975 
5976  /* link the variables together */
5977  var->negatedvar = *negvar;
5978  (*negvar)->negatedvar = var;
5979 
5980  /* mark both variables to be non-deletable */
5982  SCIPvarMarkNotDeletable(*negvar);
5983 
5984  /* copy the branch factor and priority, and use the negative preferred branching direction */
5985  (*negvar)->branchfactor = var->branchfactor;
5986  (*negvar)->branchpriority = var->branchpriority;
5987  (*negvar)->branchdirection = SCIPbranchdirOpposite((SCIP_BRANCHDIR)var->branchdirection); /*lint !e641*/
5988 
5989  /* copy donot(mult)aggr status */
5990  (*negvar)->donotaggr = var->donotaggr;
5991  (*negvar)->donotmultaggr = var->donotmultaggr;
5992 
5993  /* copy lazy bounds (they have to be flipped) */
5994  (*negvar)->lazylb = (*negvar)->data.negate.constant - var->lazyub;
5995  (*negvar)->lazyub = (*negvar)->data.negate.constant - var->lazylb;
5996 
5997  /* make negated variable a parent of the negation variable (negated variable is captured as a parent) */
5998  SCIP_CALL( varAddParent(var, blkmem, set, *negvar) );
5999  assert((*negvar)->nuses == 1);
6000  }
6001  assert(var->negatedvar != NULL);
6002 
6003  /* return the negated variable */
6004  *negvar = var->negatedvar;
6005 
6006  /* exactly one variable of the negation pair has to be marked as negated variable */
6008 
6009  return SCIP_OKAY;
6010 }
6011 
6012 /** informs variable that its position in problem's vars array changed */
6013 static
6014 void varSetProbindex(
6015  SCIP_VAR* var, /**< problem variable */
6016  int probindex /**< new problem index of variable (-1 for removal) */
6017  )
6018 {
6019  assert(var != NULL);
6020  assert(probindex >= 0 || var->vlbs == NULL);
6021  assert(probindex >= 0 || var->vubs == NULL);
6022  assert(probindex >= 0 || var->implics == NULL);
6023 
6024  var->probindex = probindex;
6026  {
6027  assert(var->data.col != NULL);
6028  var->data.col->var_probindex = probindex;
6029  }
6030 }
6031 
6032 /** informs variable that its position in problem's vars array changed */
6033 void SCIPvarSetProbindex(
6034  SCIP_VAR* var, /**< problem variable */
6035  int probindex /**< new problem index of variable */
6036  )
6037 {
6038  assert(var != NULL);
6039  assert(probindex >= 0);
6040 
6041  varSetProbindex(var, probindex);
6042 }
6043 
6044 /** gives the variable a new name
6045  *
6046  * @note the old pointer is overwritten, which might result in a memory leakage
6047  */
6049  SCIP_VAR* var, /**< problem variable */
6050  const char* name /**< new name of variable */
6051  )
6052 {
6053  assert(var != NULL);
6054  assert(name != NULL);
6055 
6056  var->name = (char*)name;
6057 }
6058 
6059 /** informs variable that it will be removed from the problem; adjusts probindex and removes variable from the
6060  * implication graph;
6061  * If 'final' is TRUE, the thorough implication graph removal is not performed. Instead, only the
6062  * variable bounds and implication data structures of the variable are freed. Since in the final removal
6063  * of all variables from the transformed problem, this deletes the implication graph completely and is faster
6064  * than removing the variables one by one, each time updating all lists of the other variables.
6065  */
6067  SCIP_VAR* var, /**< problem variable */
6068  BMS_BLKMEM* blkmem, /**< block memory buffer */
6069  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6070  SCIP_SET* set, /**< global SCIP settings */
6071  SCIP_Bool final /**< is this the final removal of all problem variables? */
6072  )
6073 {
6074  assert(SCIPvarGetProbindex(var) >= 0);
6075  assert(var->scip == set->scip);
6076 
6077  /* if the variable is active in the transformed problem, remove it from the implication graph */
6078  if( SCIPvarIsTransformed(var)
6080  {
6081  if( final )
6082  {
6083  /* just destroy the data structures */
6084  SCIPvboundsFree(&var->vlbs, blkmem);
6085  SCIPvboundsFree(&var->vubs, blkmem);
6086  SCIPimplicsFree(&var->implics, blkmem);
6087  }
6088  else
6089  {
6090  /* unlink the variable from all other variables' lists and free the data structures */
6091  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
6092  }
6093  }
6094 
6095  /* mark the variable to be no longer a member of the problem */
6096  varSetProbindex(var, -1);
6097 
6098  return SCIP_OKAY;
6099 }
6100 
6101 /** marks the variable to be deleted from the problem */
6102 void SCIPvarMarkDeleted(
6103  SCIP_VAR* var /**< problem variable */
6104  )
6105 {
6106  assert(var != NULL);
6107  assert(var->probindex != -1);
6108 
6109  var->deleted = TRUE;
6110 }
6111 
6112 /** marks the variable to not to be aggregated */
6114  SCIP_VAR* var /**< problem variable */
6115  )
6116 {
6117  SCIP_VAR* retvar;
6118 
6119  assert(var != NULL);
6120 
6121  retvar = varGetActiveVar(var);
6122  assert(retvar != NULL);
6123 
6124  switch( SCIPvarGetStatus(retvar) )
6125  {
6127  case SCIP_VARSTATUS_LOOSE:
6128  case SCIP_VARSTATUS_COLUMN:
6129  case SCIP_VARSTATUS_FIXED:
6130  retvar->donotaggr = TRUE;
6131  break;
6132 
6134  SCIPerrorMessage("cannot mark a multi-aggregated variable to not be aggregated.\n");
6135  return SCIP_INVALIDDATA;
6136 
6139  default:
6140  /* aggregated and negated variables should be resolved by varGetActiveVar() */
6141  SCIPerrorMessage("wrong variable status\n");
6142  return SCIP_INVALIDDATA;
6143  }
6144 
6145  return SCIP_OKAY;
6146 }
6147 
6148 /** marks the variable to not to be multi-aggregated */
6150  SCIP_VAR* var /**< problem variable */
6151  )
6152 {
6153  SCIP_VAR* retvar;
6154 
6155  assert(var != NULL);
6156 
6157  retvar = varGetActiveVar(var);
6158  assert(retvar != NULL);
6159 
6160  switch( SCIPvarGetStatus(retvar) )
6161  {
6163  case SCIP_VARSTATUS_LOOSE:
6164  case SCIP_VARSTATUS_COLUMN:
6165  case SCIP_VARSTATUS_FIXED:
6166  retvar->donotmultaggr = TRUE;
6167  break;
6168 
6170  SCIPerrorMessage("cannot mark a multi-aggregated variable to not be multi-aggregated.\n");
6171  return SCIP_INVALIDDATA;
6172 
6175  default:
6176  /* aggregated and negated variables should be resolved by varGetActiveVar() */
6177  SCIPerrorMessage("wrong variable status\n");
6178  return SCIP_INVALIDDATA;
6179  }
6180 
6181  return SCIP_OKAY;
6182 }
6183 
6184 /** changes type of variable; cannot be called, if var belongs to a problem */
6186  SCIP_VAR* var, /**< problem variable to change */
6187  BMS_BLKMEM* blkmem, /**< block memory */
6188  SCIP_SET* set, /**< global SCIP settings */
6189  SCIP_PRIMAL* primal, /**< primal data */
6190  SCIP_LP* lp, /**< current LP data */
6191  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6192  SCIP_VARTYPE vartype /**< new type of variable */
6193  )
6194 {
6195  SCIP_EVENT* event;
6196  SCIP_VARTYPE oldtype;
6197 
6198  assert(var != NULL);
6199 
6200  SCIPdebugMessage("change type of <%s> from %d to %d\n", var->name, SCIPvarGetType(var), vartype);
6201 
6202  if( var->probindex >= 0 )
6203  {
6204  SCIPerrorMessage("cannot change type of variable already in the problem\n");
6205  return SCIP_INVALIDDATA;
6206  }
6207 
6208  oldtype = (SCIP_VARTYPE)var->vartype;
6209  var->vartype = vartype; /*lint !e641*/
6210 
6212  {
6213  SCIP_CALL( SCIPeventCreateTypeChanged(&event, blkmem, var, oldtype, vartype) );
6214  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
6215  }
6216 
6217  if( var->negatedvar != NULL )
6218  {
6219  assert(oldtype == (SCIP_VARTYPE)var->negatedvar->vartype
6220  || SCIPvarIsBinary(var) == SCIPvarIsBinary(var->negatedvar));
6221 
6222 
6223  var->negatedvar->vartype = vartype; /*lint !e641*/
6224 
6226  {
6227  SCIP_CALL( SCIPeventCreateTypeChanged(&event, blkmem, var->negatedvar, oldtype, vartype) );
6228  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
6229  }
6230  }
6231 
6232  return SCIP_OKAY;
6233 }
6234 
6235 /** appends OBJCHANGED event to the event queue */
6236 static
6238  SCIP_VAR* var, /**< problem variable to change */
6239  BMS_BLKMEM* blkmem, /**< block memory */
6240  SCIP_SET* set, /**< global SCIP settings */
6241  SCIP_PRIMAL* primal, /**< primal data */
6242  SCIP_LP* lp, /**< current LP data */
6243  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6244  SCIP_Real oldobj, /**< old objective value for variable */
6245  SCIP_Real newobj /**< new objective value for variable */
6246  )
6247 {
6248  SCIP_EVENT* event;
6249 
6250  assert(var != NULL);
6251  assert(var->scip == set->scip);
6252  assert(var->eventfilter != NULL);
6254  assert(SCIPvarIsTransformed(var));
6255 
6256  /* In the case where the objcetive value of a variable is very close to epsilon, and it is aggregated
6257  * into a variable with a big objective value, round-off errors might make the assert oldobj != newobj fail.
6258  * Hence, we relax it by letting it pass if the variables are percieved the same and we use very large values
6259  * that make comparison with values close to epsilon inaccurate.
6260  */
6261  assert(!SCIPsetIsEQ(set, oldobj, newobj) ||
6262  (SCIPsetIsEQ(set, oldobj, newobj) && REALABS(newobj) > 1e+15 * SCIPsetEpsilon(set))
6263  );
6264 
6265  SCIP_CALL( SCIPeventCreateObjChanged(&event, blkmem, var, oldobj, newobj) );
6266  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
6267 
6268  return SCIP_OKAY;
6269 }
6270 
6271 /** changes objective value of variable */
6273  SCIP_VAR* var, /**< variable to change */
6274  BMS_BLKMEM* blkmem, /**< block memory */
6275  SCIP_SET* set, /**< global SCIP settings */
6276  SCIP_PROB* prob, /**< problem data */
6277  SCIP_PRIMAL* primal, /**< primal data */
6278  SCIP_LP* lp, /**< current LP data */
6279  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6280  SCIP_Real newobj /**< new objective value for variable */
6281  )
6282 {
6283  SCIP_Real oldobj;
6284 
6285  assert(var != NULL);
6286  assert(set != NULL);
6287  assert(var->scip == set->scip);
6288 
6289  SCIPsetDebugMsg(set, "changing objective value of <%s> from %g to %g\n", var->name, var->obj, newobj);
6290 
6291  if( !SCIPsetIsEQ(set, var->obj, newobj) )
6292  {
6293  switch( SCIPvarGetStatus(var) )
6294  {
6296  if( var->data.original.transvar != NULL )
6297  {
6298  assert(SCIPprobIsTransformed(prob));
6299 
6300  SCIP_CALL( SCIPvarChgObj(var->data.original.transvar, blkmem, set, prob, primal, lp, eventqueue,
6301  (SCIP_Real) prob->objsense * newobj/prob->objscale) );
6302  }
6303  else
6304  assert(set->stage == SCIP_STAGE_PROBLEM);
6305 
6306  var->obj = newobj;
6307  var->unchangedobj = newobj;
6308 
6309  break;
6310 
6311  case SCIP_VARSTATUS_LOOSE:
6312  case SCIP_VARSTATUS_COLUMN:
6313  oldobj = var->obj;
6314  var->obj = newobj;
6315 
6316  /* update unchanged objective value of variable */
6317  if( !lp->divingobjchg )
6318  var->unchangedobj = newobj;
6319 
6320  /* update the number of variables with non-zero objective coefficient;
6321  * we only want to do the update, if the variable is added to the problem;
6322  * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
6323  */
6324  if( SCIPvarIsActive(var) )
6325  SCIPprobUpdateNObjVars(prob, set, oldobj, var->obj);
6326 
6327  SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
6328  break;
6329 
6330  case SCIP_VARSTATUS_FIXED:
6334  SCIPerrorMessage("cannot change objective value of a fixed, aggregated, multi-aggregated, or negated variable\n");
6335  return SCIP_INVALIDDATA;
6336 
6337  default:
6338  SCIPerrorMessage("unknown variable status\n");
6339  return SCIP_INVALIDDATA;
6340  }
6341  }
6342 
6343  return SCIP_OKAY;
6344 }
6345 
6346 /** adds value to objective value of variable */
6348  SCIP_VAR* var, /**< variable to change */
6349  BMS_BLKMEM* blkmem, /**< block memory */
6350  SCIP_SET* set, /**< global SCIP settings */
6351  SCIP_STAT* stat, /**< problem statistics */
6352  SCIP_PROB* transprob, /**< transformed problem data */
6353  SCIP_PROB* origprob, /**< original problem data */
6354  SCIP_PRIMAL* primal, /**< primal data */
6355  SCIP_TREE* tree, /**< branch and bound tree */
6356  SCIP_REOPT* reopt, /**< reoptimization data structure */
6357  SCIP_LP* lp, /**< current LP data */
6358  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
6359  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6360  SCIP_Real addobj /**< additional objective value for variable */
6361  )
6362 {
6363  assert(var != NULL);
6364  assert(set != NULL);
6365  assert(var->scip == set->scip);
6366  assert(set->stage < SCIP_STAGE_INITSOLVE);
6367 
6368  SCIPsetDebugMsg(set, "adding %g to objective value %g of <%s>\n", addobj, var->obj, var->name);
6369 
6370  if( !SCIPsetIsZero(set, addobj) )
6371  {
6372  SCIP_Real oldobj;
6373  int i;
6374 
6375  switch( SCIPvarGetStatus(var) )
6376  {
6378  if( var->data.original.transvar != NULL )
6379  {
6380  SCIP_CALL( SCIPvarAddObj(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
6381  reopt, lp, eventfilter, eventqueue, (SCIP_Real) transprob->objsense * addobj/transprob->objscale) );
6382  }
6383  else
6384  assert(set->stage == SCIP_STAGE_PROBLEM);
6385 
6386  var->obj += addobj;
6387  var->unchangedobj += addobj;
6388  assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
6389 
6390  break;
6391 
6392  case SCIP_VARSTATUS_LOOSE:
6393  case SCIP_VARSTATUS_COLUMN:
6394  oldobj = var->obj;
6395  var->obj += addobj;
6396 
6397  /* update unchanged objective value of variable */
6398  if( !lp->divingobjchg )
6399  {
6400  var->unchangedobj += addobj;
6401  assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
6402  }
6403 
6404  /* update the number of variables with non-zero objective coefficient;
6405  * we only want to do the update, if the variable is added to the problem;
6406  * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
6407  */
6408  if( SCIPvarIsActive(var) )
6409  SCIPprobUpdateNObjVars(transprob, set, oldobj, var->obj);
6410 
6411  SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
6412  break;
6413 
6414  case SCIP_VARSTATUS_FIXED:
6415  assert(SCIPsetIsEQ(set, var->locdom.lb, var->locdom.ub));
6416  SCIPprobAddObjoffset(transprob, var->locdom.lb * addobj);
6417  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6418  break;
6419 
6421  assert(!var->donotaggr);
6422  /* x = a*y + c -> add a*addobj to obj. val. of y, and c*addobj to obj. offset of problem */
6423  SCIPprobAddObjoffset(transprob, var->data.aggregate.constant * addobj);
6424  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6425  SCIP_CALL( SCIPvarAddObj(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
6426  lp, eventfilter, eventqueue, var->data.aggregate.scalar * addobj) );
6427  break;
6428 
6430  assert(!var->donotmultaggr);
6431  /* 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 */
6432  SCIPprobAddObjoffset(transprob, var->data.multaggr.constant * addobj);
6433  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6434  for( i = 0; i < var->data.multaggr.nvars; ++i )
6435  {
6436  SCIP_CALL( SCIPvarAddObj(var->data.multaggr.vars[i], blkmem, set, stat, transprob, origprob, primal, tree,
6437  reopt, lp, eventfilter, eventqueue, var->data.multaggr.scalars[i] * addobj) );
6438  }
6439  break;
6440 
6442  /* x' = offset - x -> add -addobj to obj. val. of x and offset*addobj to obj. offset of problem */
6443  assert(var->negatedvar != NULL);
6445  assert(var->negatedvar->negatedvar == var);
6446  SCIPprobAddObjoffset(transprob, var->data.negate.constant * addobj);
6447  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6448  SCIP_CALL( SCIPvarAddObj(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
6449  eventfilter, eventqueue, -addobj) );
6450  break;
6451 
6452  default:
6453  SCIPerrorMessage("unknown variable status\n");
6454  return SCIP_INVALIDDATA;
6455  }
6456  }
6457 
6458  return SCIP_OKAY;
6459 }
6460 
6461 /** changes objective value of variable in current dive */
6463  SCIP_VAR* var, /**< problem variable to change */
6464  SCIP_SET* set, /**< global SCIP settings */
6465  SCIP_LP* lp, /**< current LP data */
6466  SCIP_Real newobj /**< new objective value for variable */
6467  )
6468 {
6469  assert(var != NULL);
6470  assert(set != NULL);
6471  assert(var->scip == set->scip);
6472  assert(lp != NULL);
6473 
6474  SCIPsetDebugMsg(set, "changing objective of <%s> to %g in current dive\n", var->name, newobj);
6475 
6476  if( SCIPsetIsZero(set, newobj) )
6477  newobj = 0.0;
6478 
6479  /* change objective value of attached variables */
6480  switch( SCIPvarGetStatus(var) )
6481  {
6483  assert(var->data.original.transvar != NULL);
6484  SCIP_CALL( SCIPvarChgObjDive(var->data.original.transvar, set, lp, newobj) );
6485  break;
6486 
6487  case SCIP_VARSTATUS_COLUMN:
6488  assert(var->data.col != NULL);
6489  SCIP_CALL( SCIPcolChgObj(var->data.col, set, lp, newobj) );
6490  break;
6491 
6492  case SCIP_VARSTATUS_LOOSE:
6493  case SCIP_VARSTATUS_FIXED:
6494  /* nothing to do here: only the constant shift in objective function would change */
6495  break;
6496 
6497  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6498  assert(var->data.aggregate.var != NULL);
6499  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
6500  SCIP_CALL( SCIPvarChgObjDive(var->data.aggregate.var, set, lp, newobj / var->data.aggregate.scalar) );
6501  /* the constant can be ignored, because it would only affect the objective shift */
6502  break;
6503 
6505  SCIPerrorMessage("cannot change diving objective value of a multi-aggregated variable\n");
6506  return SCIP_INVALIDDATA;
6507 
6508  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6509  assert(var->negatedvar != NULL);
6511  assert(var->negatedvar->negatedvar == var);
6512  SCIP_CALL( SCIPvarChgObjDive(var->negatedvar, set, lp, -newobj) );
6513  /* the offset can be ignored, because it would only affect the objective shift */
6514  break;
6515 
6516  default:
6517  SCIPerrorMessage("unknown variable status\n");
6518  return SCIP_INVALIDDATA;
6519  }
6520 
6521  return SCIP_OKAY;
6522 }
6523 
6524 /** adjust lower bound to integral value, if variable is integral */
6525 void SCIPvarAdjustLb(
6526  SCIP_VAR* var, /**< problem variable */
6527  SCIP_SET* set, /**< global SCIP settings */
6528  SCIP_Real* lb /**< pointer to lower bound to adjust */
6529  )
6530 {
6531  assert(var != NULL);
6532  assert(set != NULL);
6533  assert(var->scip == set->scip);
6534  assert(lb != NULL);
6535 
6536  SCIPsetDebugMsg(set, "adjust lower bound %g of <%s>\n", *lb, var->name);
6537 
6538  *lb = adjustedLb(set, SCIPvarGetType(var), *lb);
6539 }
6540 
6541 /** adjust upper bound to integral value, if variable is integral */
6542 void SCIPvarAdjustUb(
6543  SCIP_VAR* var, /**< problem variable */
6544  SCIP_SET* set, /**< global SCIP settings */
6545  SCIP_Real* ub /**< pointer to upper bound to adjust */
6546  )
6547 {
6548  assert(var != NULL);
6549  assert(set != NULL);
6550  assert(var->scip == set->scip);
6551  assert(ub != NULL);
6552 
6553  SCIPsetDebugMsg(set, "adjust upper bound %g of <%s>\n", *ub, var->name);
6554 
6555  *ub = adjustedUb(set, SCIPvarGetType(var), *ub);
6556 }
6557 
6558 /** adjust lower or upper bound to integral value, if variable is integral */
6559 void SCIPvarAdjustBd(
6560  SCIP_VAR* var, /**< problem variable */
6561  SCIP_SET* set, /**< global SCIP settings */
6562  SCIP_BOUNDTYPE boundtype, /**< type of bound to adjust */
6563  SCIP_Real* bd /**< pointer to bound to adjust */
6564  )
6565 {
6566  assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
6567 
6568  if( boundtype == SCIP_BOUNDTYPE_LOWER )
6569  SCIPvarAdjustLb(var, set, bd);
6570  else
6571  SCIPvarAdjustUb(var, set, bd);
6572 }
6573 
6574 /** changes lower bound of original variable in original problem */
6576  SCIP_VAR* var, /**< problem variable to change */
6577  SCIP_SET* set, /**< global SCIP settings */
6578  SCIP_Real newbound /**< new bound for variable */
6579  )
6580 {
6581  int i;
6582 
6583  assert(var != NULL);
6584  assert(!SCIPvarIsTransformed(var));
6586  assert(set != NULL);
6587  assert(var->scip == set->scip);
6588  assert(set->stage == SCIP_STAGE_PROBLEM);
6589 
6590  /* check that the bound is feasible */
6591  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsLE(set, newbound, SCIPvarGetUbOriginal(var)));
6592  /* adjust bound to integral value if variable is of integral type */
6593  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6594 
6595  if( SCIPsetIsZero(set, newbound) )
6596  newbound = 0.0;
6597 
6598  /* original domains are only stored for ORIGINAL variables, not for NEGATED */
6600  {
6601  SCIPsetDebugMsg(set, "changing original lower bound of <%s> from %g to %g\n",
6602  var->name, var->data.original.origdom.lb, newbound);
6603 
6604  if( SCIPsetIsEQ(set, var->data.original.origdom.lb, newbound) )
6605  return SCIP_OKAY;
6606 
6607  /* change the bound */
6608  var->data.original.origdom.lb = newbound;
6609  }
6610  else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
6611  {
6612  assert( var->negatedvar != NULL );
6613  SCIP_CALL( SCIPvarChgUbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
6614  }
6615 
6616  /* process parent variables */
6617  for( i = 0; i < var->nparentvars; ++i )
6618  {
6619  SCIP_VAR* parentvar;
6620 
6621  parentvar = var->parentvars[i];
6622  assert(parentvar != NULL);
6623  assert(SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_NEGATED);
6624  assert(parentvar->negatedvar == var);
6625  assert(var->negatedvar == parentvar);
6626 
6627  SCIP_CALL( SCIPvarChgUbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
6628  }
6629 
6630  return SCIP_OKAY;
6631 }
6632 
6633 /** changes upper bound of original variable in original problem */
6635  SCIP_VAR* var, /**< problem variable to change */
6636  SCIP_SET* set, /**< global SCIP settings */
6637  SCIP_Real newbound /**< new bound for variable */
6638  )
6639 {
6640  int i;
6641 
6642  assert(var != NULL);
6643  assert(!SCIPvarIsTransformed(var));
6645  assert(set != NULL);
6646  assert(var->scip == set->scip);
6647  assert(set->stage == SCIP_STAGE_PROBLEM);
6648 
6649  /* check that the bound is feasible */
6650  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsGE(set, newbound, SCIPvarGetLbOriginal(var)));
6651  /* adjust bound to integral value if variable is of integral type */
6652  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
6653 
6654  if( SCIPsetIsZero(set, newbound) )
6655  newbound = 0.0;
6656 
6657  /* original domains are only stored for ORIGINAL variables, not for NEGATED */
6659  {
6660  SCIPsetDebugMsg(set, "changing original upper bound of <%s> from %g to %g\n",
6661  var->name, var->data.original.origdom.ub, newbound);
6662 
6663  if( SCIPsetIsEQ(set, var->data.original.origdom.ub, newbound) )
6664  return SCIP_OKAY;
6665 
6666  /* change the bound */
6667  var->data.original.origdom.ub = newbound;
6668  }
6669  else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
6670  {
6671  assert( var->negatedvar != NULL );
6672  SCIP_CALL( SCIPvarChgLbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
6673  }
6674 
6675  /* process parent variables */
6676  for( i = 0; i < var->nparentvars; ++i )
6677  {
6678  SCIP_VAR* parentvar;
6679 
6680  parentvar = var->parentvars[i];
6681  assert(parentvar != NULL);
6682  assert(SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_NEGATED);
6683  assert(parentvar->negatedvar == var);
6684  assert(var->negatedvar == parentvar);
6685 
6686  SCIP_CALL( SCIPvarChgLbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
6687  }
6688 
6689  return SCIP_OKAY;
6690 }
6691 
6692 /** appends GLBCHANGED event to the event queue */
6693 static
6695  SCIP_VAR* var, /**< problem variable to change */
6696  BMS_BLKMEM* blkmem, /**< block memory */
6697  SCIP_SET* set, /**< global SCIP settings */
6698  SCIP_LP* lp, /**< current LP data */
6699  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6700  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6701  SCIP_Real oldbound, /**< old lower bound for variable */
6702  SCIP_Real newbound /**< new lower bound for variable */
6703  )
6704 {
6705  assert(var != NULL);
6706  assert(var->eventfilter != NULL);
6707  assert(SCIPvarIsTransformed(var));
6708  assert(!SCIPsetIsEQ(set, oldbound, newbound) || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
6709  assert(set != NULL);
6710  assert(var->scip == set->scip);
6711 
6712  /* check, if the variable is being tracked for bound changes
6713  * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
6714  */
6715  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GLBCHANGED) != 0)
6718  {
6719  SCIP_EVENT* event;
6720 
6721  SCIPsetDebugMsg(set, "issue GLBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
6722 
6723  SCIP_CALL( SCIPeventCreateGlbChanged(&event, blkmem, var, oldbound, newbound) );
6724  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
6725  }
6726 
6727  return SCIP_OKAY;
6728 }
6729 
6730 /** appends GUBCHANGED event to the event queue */
6731 static
6733  SCIP_VAR* var, /**< problem variable to change */
6734  BMS_BLKMEM* blkmem, /**< block memory */
6735  SCIP_SET* set, /**< global SCIP settings */
6736  SCIP_LP* lp, /**< current LP data */
6737  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6738  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6739  SCIP_Real oldbound, /**< old lower bound for variable */
6740  SCIP_Real newbound /**< new lower bound for variable */
6741  )
6742 {
6743  assert(var != NULL);
6744  assert(var->eventfilter != NULL);
6745  assert(SCIPvarIsTransformed(var));
6746  assert(!SCIPsetIsEQ(set, oldbound, newbound) || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
6747  assert(set != NULL);
6748  assert(var->scip == set->scip);
6749 
6750  /* check, if the variable is being tracked for bound changes
6751  * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
6752  */
6753  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GUBCHANGED) != 0)
6756  {
6757  SCIP_EVENT* event;
6758 
6759  SCIPsetDebugMsg(set, "issue GUBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
6760 
6761  SCIP_CALL( SCIPeventCreateGubChanged(&event, blkmem, var, oldbound, newbound) );
6762  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
6763  }
6764 
6765  return SCIP_OKAY;
6766 }
6767 
6768 /** appends GHOLEADDED event to the event queue */
6769 static
6771  SCIP_VAR* var, /**< problem variable to change */
6772  BMS_BLKMEM* blkmem, /**< block memory */
6773  SCIP_SET* set, /**< global SCIP settings */
6774  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6775  SCIP_Real left, /**< left bound of open interval in new hole */
6776  SCIP_Real right /**< right bound of open interval in new hole */
6777  )
6778 {
6779  assert(var != NULL);
6780  assert(var->eventfilter != NULL);
6781  assert(SCIPvarIsTransformed(var));
6782  assert(set != NULL);
6783  assert(var->scip == set->scip);
6784  assert(SCIPsetIsLT(set, left, right));
6785 
6786  /* check, if the variable is being tracked for bound changes */
6787  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GHOLEADDED) != 0) )
6788  {
6789  SCIP_EVENT* event;
6790 
6791  SCIPsetDebugMsg(set, "issue GHOLEADDED event for variable <%s>: (%.15g,%.15g)\n", var->name, left, right);
6792 
6793  SCIP_CALL( SCIPeventCreateGholeAdded(&event, blkmem, var, left, right) );
6794  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
6795  }
6796 
6797  return SCIP_OKAY;
6798 }
6799 
6800 /** increases root bound change statistics after a global bound change */
6801 static
6802 void varIncRootboundchgs(
6803  SCIP_VAR* var, /**< problem variable to change */
6804  SCIP_SET* set, /**< global SCIP settings */
6805  SCIP_STAT* stat /**< problem statistics */
6806  )
6807 {
6808  assert(var != NULL);
6809  assert(set != NULL);
6810  assert(var->scip == set->scip);
6811  assert(stat != NULL);
6812 
6813  if( SCIPvarIsActive(var) && SCIPvarIsTransformed(var) && set->stage == SCIP_STAGE_SOLVING )
6814  {
6815  stat->nrootboundchgs++;
6816  stat->nrootboundchgsrun++;
6817  if( SCIPvarIsIntegral(var) && SCIPvarGetLbGlobal(var) + 0.5 > SCIPvarGetUbGlobal(var) )
6818  {
6819  stat->nrootintfixings++;
6820  stat->nrootintfixingsrun++;
6821  }
6822  }
6823 }
6824 
6825 /* forward declaration, because both methods call each other recursively */
6826 
6827 /* performs the current change in upper bound, changes all parents accordingly */
6828 static
6830  SCIP_VAR* var, /**< problem variable to change */
6831  BMS_BLKMEM* blkmem, /**< block memory */
6832  SCIP_SET* set, /**< global SCIP settings */
6833  SCIP_STAT* stat, /**< problem statistics */
6834  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6835  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6836  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6837  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6838  SCIP_Real newbound /**< new bound for variable */
6839  );
6840 
6841 /** performs the current change in lower bound, changes all parents accordingly */
6842 static
6844  SCIP_VAR* var, /**< problem variable to change */
6845  BMS_BLKMEM* blkmem, /**< block memory */
6846  SCIP_SET* set, /**< global SCIP settings */
6847  SCIP_STAT* stat, /**< problem statistics */
6848  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6849  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6850  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6851  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6852  SCIP_Real newbound /**< new bound for variable */
6853  )
6854 {
6855  SCIP_VAR* parentvar;
6856  SCIP_Real oldbound;
6857  int i;
6858 
6859  assert(var != NULL);
6860  /* local domains can violate global bounds but not more than feasibility epsilon */
6861  assert(SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb));
6862  assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
6863  assert(blkmem != NULL);
6864  assert(set != NULL);
6865  assert(var->scip == set->scip);
6866  assert(stat != NULL);
6867 
6868  /* adjust bound to integral value if variable is of integral type */
6869  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6870 
6871  /* check that the bound is feasible */
6872  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound > var->glbdom.ub )
6873  {
6874  /* due to numerics we only want to be feasible in feasibility tolerance */
6875  assert(SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
6876  newbound = var->glbdom.ub;
6877  }
6878  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6879 
6880  assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
6881 
6882  SCIPsetDebugMsg(set, "process changing global lower bound of <%s> from %f to %f\n", var->name, var->glbdom.lb, newbound);
6883 
6884  if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) && !(newbound != var->glbdom.lb && newbound * var->glbdom.lb <= 0.0) ) /*lint !e777*/
6885  return SCIP_OKAY;
6886 
6887  /* check bound on debugging solution */
6888  SCIP_CALL( SCIPdebugCheckLbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
6889 
6890  /* change the bound */
6891  oldbound = var->glbdom.lb;
6892  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
6893  var->glbdom.lb = newbound;
6894  assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
6895  assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
6896 
6897  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6898  {
6899  /* merges overlapping holes into single holes, moves bounds respectively */
6900  domMerge(&var->glbdom, blkmem, set, &newbound, NULL);
6901  }
6902 
6903  /* update the root bound changes counters */
6904  varIncRootboundchgs(var, set, stat);
6905 
6906  /* update the lbchginfos array by replacing worse local bounds with the new global bound and changing the
6907  * redundant bound changes to be branching decisions
6908  */
6909  for( i = 0; i < var->nlbchginfos; ++i )
6910  {
6911  assert(var->lbchginfos[i].var == var);
6912 
6913  if( var->lbchginfos[i].oldbound < var->glbdom.lb )
6914  {
6915  SCIPsetDebugMsg(set, " -> adjust lower bound change <%s>: %g -> %g due to new global lower bound %g\n",
6916  SCIPvarGetName(var), var->lbchginfos[i].oldbound, var->lbchginfos[i].newbound, var->glbdom.lb);
6917  var->lbchginfos[i].oldbound = var->glbdom.lb;
6918  if( SCIPsetIsLE(set, var->lbchginfos[i].newbound, var->glbdom.lb) )
6919  {
6920  /* this bound change is redundant due to the new global bound */
6921  var->lbchginfos[i].newbound = var->glbdom.lb;
6922  var->lbchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
6923  var->lbchginfos[i].redundant = TRUE;
6924  }
6925  else
6926  break; /* from now on, the remaining local bound changes are not redundant */
6927  }
6928  else
6929  break; /* from now on, the remaining local bound changes are not redundant */
6930  }
6931 
6932  /* remove redundant implications and variable bounds */
6934  && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
6935  {
6936  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
6937  }
6938 
6939  /* issue bound change event */
6940  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
6941  if( var->eventfilter != NULL )
6942  {
6943  SCIP_CALL( varEventGlbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
6944  }
6945 
6946  /* process parent variables */
6947  for( i = 0; i < var->nparentvars; ++i )
6948  {
6949  parentvar = var->parentvars[i];
6950  assert(parentvar != NULL);
6951 
6952  switch( SCIPvarGetStatus(parentvar) )
6953  {
6955  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6956  break;
6957 
6958  case SCIP_VARSTATUS_COLUMN:
6959  case SCIP_VARSTATUS_LOOSE:
6960  case SCIP_VARSTATUS_FIXED:
6962  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
6963  return SCIP_INVALIDDATA;
6964 
6965  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6966  assert(parentvar->data.aggregate.var == var);
6967  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
6968  {
6969  SCIP_Real parentnewbound;
6970 
6971  /* a > 0 -> change lower bound of y */
6972  assert(SCIPsetIsInfinity(set, -parentvar->glbdom.lb) || SCIPsetIsInfinity(set, -oldbound)
6973  || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
6974  || (SCIPsetIsZero(set, parentvar->glbdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
6975 
6976  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6977  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6978  else
6979  parentnewbound = newbound;
6980  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6981  }
6982  else
6983  {
6984  SCIP_Real parentnewbound;
6985 
6986  /* a < 0 -> change upper bound of y */
6987  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
6988  assert(SCIPsetIsInfinity(set, parentvar->glbdom.ub) || SCIPsetIsInfinity(set, -oldbound)
6989  || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
6990  || (SCIPsetIsZero(set, parentvar->glbdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
6991 
6992  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6993  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6994  else
6995  parentnewbound = -newbound;
6996  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6997  }
6998  break;
6999 
7000  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7001  assert(parentvar->negatedvar != NULL);
7002  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7003  assert(parentvar->negatedvar->negatedvar == parentvar);
7004  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7005  parentvar->data.negate.constant - newbound) );
7006  break;
7007 
7008  default:
7009  SCIPerrorMessage("unknown variable status\n");
7010  return SCIP_INVALIDDATA;
7011  }
7012  }
7013 
7014  return SCIP_OKAY;
7015 }
7016 
7017 /** performs the current change in upper bound, changes all parents accordingly */
7018 static
7020  SCIP_VAR* var, /**< problem variable to change */
7021  BMS_BLKMEM* blkmem, /**< block memory */
7022  SCIP_SET* set, /**< global SCIP settings */
7023  SCIP_STAT* stat, /**< problem statistics */
7024  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7025  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7026  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7027  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7028  SCIP_Real newbound /**< new bound for variable */
7029  )
7030 {
7031  SCIP_VAR* parentvar;
7032  SCIP_Real oldbound;
7033  int i;
7034 
7035  assert(var != NULL);
7036  /* local domains can violate global bounds but not more than feasibility epsilon */
7037  assert(SCIPsetIsFeasLE(set, var->glbdom.lb , var->locdom.lb));
7038  assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
7039  assert(blkmem != NULL);
7040  assert(set != NULL);
7041  assert(var->scip == set->scip);
7042  assert(stat != NULL);
7043 
7044  /* adjust bound to integral value if variable is of integral type */
7045  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7046 
7047  /* check that the bound is feasible */
7048  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound < var->glbdom.lb )
7049  {
7050  /* due to numerics we only want to be feasible in feasibility tolerance */
7051  assert(SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
7052  newbound = var->glbdom.lb;
7053  }
7054  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7055 
7056  assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
7057 
7058  SCIPsetDebugMsg(set, "process changing global upper bound of <%s> from %f to %f\n", var->name, var->glbdom.ub, newbound);
7059 
7060  if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) && !(newbound != var->glbdom.ub && newbound * var->glbdom.ub <= 0.0) ) /*lint !e777*/
7061  return SCIP_OKAY;
7062 
7063  /* check bound on debugging solution */
7064  SCIP_CALL( SCIPdebugCheckUbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
7065 
7066  /* change the bound */
7067  oldbound = var->glbdom.ub;
7068  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
7069  var->glbdom.ub = newbound;
7070  assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
7071  assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
7072 
7073  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7074  {
7075  /* merges overlapping holes into single holes, moves bounds respectively */
7076  domMerge(&var->glbdom, blkmem, set, NULL, &newbound);
7077  }
7078 
7079  /* update the root bound changes counters */
7080  varIncRootboundchgs(var, set, stat);
7081 
7082  /* update the ubchginfos array by replacing worse local bounds with the new global bound and changing the
7083  * redundant bound changes to be branching decisions
7084  */
7085  for( i = 0; i < var->nubchginfos; ++i )
7086  {
7087  assert(var->ubchginfos[i].var == var);
7088  if( var->ubchginfos[i].oldbound > var->glbdom.ub )
7089  {
7090  SCIPsetDebugMsg(set, " -> adjust upper bound change <%s>: %g -> %g due to new global upper bound %g\n",
7091  SCIPvarGetName(var), var->ubchginfos[i].oldbound, var->ubchginfos[i].newbound, var->glbdom.ub);
7092  var->ubchginfos[i].oldbound = var->glbdom.ub;
7093  if( SCIPsetIsGE(set, var->ubchginfos[i].newbound, var->glbdom.ub) )
7094  {
7095  /* this bound change is redundant due to the new global bound */
7096  var->ubchginfos[i].newbound = var->glbdom.ub;
7097  var->ubchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
7098  var->ubchginfos[i].redundant = TRUE;
7099  }
7100  else
7101  break; /* from now on, the remaining local bound changes are not redundant */
7102  }
7103  else
7104  break; /* from now on, the remaining local bound changes are not redundant */
7105  }
7106 
7107  /* remove redundant implications and variable bounds */
7109  && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
7110  {
7111  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
7112  }
7113 
7114  /* issue bound change event */
7115  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7116  if( var->eventfilter != NULL )
7117  {
7118  SCIP_CALL( varEventGubChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7119  }
7120 
7121  /* process parent variables */
7122  for( i = 0; i < var->nparentvars; ++i )
7123  {
7124  parentvar = var->parentvars[i];
7125  assert(parentvar != NULL);
7126 
7127  switch( SCIPvarGetStatus(parentvar) )
7128  {
7130  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7131  break;
7132 
7133  case SCIP_VARSTATUS_COLUMN:
7134  case SCIP_VARSTATUS_LOOSE:
7135  case SCIP_VARSTATUS_FIXED:
7137  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7138  return SCIP_INVALIDDATA;
7139 
7140  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7141  assert(parentvar->data.aggregate.var == var);
7142  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7143  {
7144  SCIP_Real parentnewbound;
7145 
7146  /* a > 0 -> change upper bound of y */
7147  assert(SCIPsetIsInfinity(set, parentvar->glbdom.ub) || SCIPsetIsInfinity(set, oldbound)
7148  || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub,
7149  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7150  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7151  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7152  else
7153  parentnewbound = newbound;
7154  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
7155  }
7156  else
7157  {
7158  SCIP_Real parentnewbound;
7159 
7160  /* a < 0 -> change lower bound of y */
7161  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7162  assert(SCIPsetIsInfinity(set, -parentvar->glbdom.lb) || SCIPsetIsInfinity(set, oldbound)
7163  || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb,
7164  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7165  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7166  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7167  else
7168  parentnewbound = -newbound;
7169  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
7170  }
7171  break;
7172 
7173  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7174  assert(parentvar->negatedvar != NULL);
7175  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7176  assert(parentvar->negatedvar->negatedvar == parentvar);
7177  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7178  parentvar->data.negate.constant - newbound) );
7179  break;
7180 
7181  default:
7182  SCIPerrorMessage("unknown variable status\n");
7183  return SCIP_INVALIDDATA;
7184  }
7185  }
7186 
7187  return SCIP_OKAY;
7188 }
7189 
7190 /** changes global lower bound of variable; if possible, adjusts bound to integral value;
7191  * updates local lower bound if the global bound is tighter
7192  */
7194  SCIP_VAR* var, /**< problem variable to change */
7195  BMS_BLKMEM* blkmem, /**< block memory */
7196  SCIP_SET* set, /**< global SCIP settings */
7197  SCIP_STAT* stat, /**< problem statistics */
7198  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7199  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7200  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7201  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7202  SCIP_Real newbound /**< new bound for variable */
7203  )
7204 {
7205  assert(var != NULL);
7206  assert(blkmem != NULL);
7207  assert(set != NULL);
7208  assert(var->scip == set->scip);
7209 
7210  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7211  * of the domain within feastol
7212  */
7213  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
7214 
7215  /* adjust bound to integral value if variable is of integral type */
7216  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7217 
7218  /* check that the adjusted bound is feasible
7219  * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
7220  * here because we reset bounds to their original value!
7221  */
7222  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
7223 
7224  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7225  {
7226  /* we do not want to exceed the upperbound, which could have happened due to numerics */
7227  newbound = MIN(newbound, var->glbdom.ub);
7228  }
7229  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7230 
7231  /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
7232  * SCIPvarFix() allows fixings that are outside of the domain within feastol
7233  */
7234  assert(lp == NULL || SCIPsetIsFeasLE(set, var->glbdom.lb, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
7235 
7236  SCIPsetDebugMsg(set, "changing global lower bound of <%s> from %g to %g\n", var->name, var->glbdom.lb, newbound);
7237 
7238  if( SCIPsetIsEQ(set, var->glbdom.lb, newbound) && !(newbound != var->glbdom.lb && newbound * var->glbdom.lb <= 0.0) ) /*lint !e777*/
7239  return SCIP_OKAY;
7240 
7241  /* change bounds of attached variables */
7242  switch( SCIPvarGetStatus(var) )
7243  {
7245  if( var->data.original.transvar != NULL )
7246  {
7247  SCIP_CALL( SCIPvarChgLbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
7248  cliquetable, newbound) );
7249  }
7250  else
7251  {
7252  assert(set->stage == SCIP_STAGE_PROBLEM);
7253  if( newbound > SCIPvarGetLbLocal(var) )
7254  {
7255  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7256  }
7257  SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7258  }
7259  break;
7260 
7261  case SCIP_VARSTATUS_COLUMN:
7262  case SCIP_VARSTATUS_LOOSE:
7263  if( newbound > SCIPvarGetLbLocal(var) )
7264  {
7265  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7266  }
7267  SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7268  break;
7269 
7270  case SCIP_VARSTATUS_FIXED:
7271  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7272  return SCIP_INVALIDDATA;
7273 
7274  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7275  assert(var->data.aggregate.var != NULL);
7276  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7277  {
7278  SCIP_Real childnewbound;
7279 
7280  /* a > 0 -> change lower bound of y */
7281  assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, -var->data.aggregate.var->glbdom.lb))
7282  || SCIPsetIsFeasEQ(set, var->glbdom.lb,
7284  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7285  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7286  else
7287  childnewbound = newbound;
7288  SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7289  childnewbound) );
7290  }
7291  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7292  {
7293  SCIP_Real childnewbound;
7294 
7295  /* a < 0 -> change upper bound of y */
7296  assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
7297  || SCIPsetIsFeasEQ(set, var->glbdom.lb,
7299  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7300  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7301  else
7302  childnewbound = -newbound;
7303  SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7304  childnewbound) );
7305  }
7306  else
7307  {
7308  SCIPerrorMessage("scalar is zero in aggregation\n");
7309  return SCIP_INVALIDDATA;
7310  }
7311  break;
7312 
7314  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7315  return SCIP_INVALIDDATA;
7316 
7317  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7318  assert(var->negatedvar != NULL);
7320  assert(var->negatedvar->negatedvar == var);
7321  SCIP_CALL( SCIPvarChgUbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7322  var->data.negate.constant - newbound) );
7323  break;
7324 
7325  default:
7326  SCIPerrorMessage("unknown variable status\n");
7327  return SCIP_INVALIDDATA;
7328  }
7329 
7330  return SCIP_OKAY;
7331 }
7332 
7333 /** changes global upper bound of variable; if possible, adjusts bound to integral value;
7334  * updates local upper bound if the global bound is tighter
7335  */
7337  SCIP_VAR* var, /**< problem variable to change */
7338  BMS_BLKMEM* blkmem, /**< block memory */
7339  SCIP_SET* set, /**< global SCIP settings */
7340  SCIP_STAT* stat, /**< problem statistics */
7341  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7342  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7343  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7344  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7345  SCIP_Real newbound /**< new bound for variable */
7346  )
7347 {
7348  assert(var != NULL);
7349  assert(blkmem != NULL);
7350  assert(set != NULL);
7351  assert(var->scip == set->scip);
7352 
7353  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7354  * of the domain within feastol
7355  */
7356  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
7357 
7358  /* adjust bound to integral value if variable is of integral type */
7359  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7360 
7361  /* check that the adjusted bound is feasible
7362  * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
7363  * here because we reset bounds to their original value!
7364  */
7365  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
7366 
7367  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7368  {
7369  /* we do not want to undercut the lowerbound, which could have happened due to numerics */
7370  newbound = MAX(newbound, var->glbdom.lb);
7371  }
7372  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7373 
7374  /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
7375  * SCIPvarFix() allows fixings that are outside of the domain within feastol
7376  */
7377  assert(lp == NULL || SCIPsetIsFeasGE(set, var->glbdom.ub, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
7378 
7379  SCIPsetDebugMsg(set, "changing global upper bound of <%s> from %g to %g\n", var->name, var->glbdom.ub, newbound);
7380 
7381  if( SCIPsetIsEQ(set, var->glbdom.ub, newbound) && !(newbound != var->glbdom.ub && newbound * var->glbdom.ub <= 0.0) ) /*lint !e777*/
7382  return SCIP_OKAY;
7383 
7384  /* change bounds of attached variables */
7385  switch( SCIPvarGetStatus(var) )
7386  {
7388  if( var->data.original.transvar != NULL )
7389  {
7390  SCIP_CALL( SCIPvarChgUbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7391  newbound) );
7392  }
7393  else
7394  {
7395  assert(set->stage == SCIP_STAGE_PROBLEM);
7396  if( newbound < SCIPvarGetUbLocal(var) )
7397  {
7398  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7399  }
7400  SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7401  }
7402  break;
7403 
7404  case SCIP_VARSTATUS_COLUMN:
7405  case SCIP_VARSTATUS_LOOSE:
7406  if( newbound < SCIPvarGetUbLocal(var) )
7407  {
7408  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7409  }
7410  SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7411  break;
7412 
7413  case SCIP_VARSTATUS_FIXED:
7414  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7415  return SCIP_INVALIDDATA;
7416 
7417  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7418  assert(var->data.aggregate.var != NULL);
7419  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7420  {
7421  SCIP_Real childnewbound;
7422 
7423  /* a > 0 -> change lower bound of y */
7424  assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
7425  || SCIPsetIsFeasEQ(set, var->glbdom.ub,
7427  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7428  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7429  else
7430  childnewbound = newbound;
7431  SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7432  childnewbound) );
7433  }
7434  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7435  {
7436  SCIP_Real childnewbound;
7437 
7438  /* a < 0 -> change upper bound of y */
7439  assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, -var->data.aggregate.var->glbdom.lb))
7440  || SCIPsetIsFeasEQ(set, var->glbdom.ub,
7442  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7443  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7444  else
7445  childnewbound = -newbound;
7446  SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7447  childnewbound) );
7448  }
7449  else
7450  {
7451  SCIPerrorMessage("scalar is zero in aggregation\n");
7452  return SCIP_INVALIDDATA;
7453  }
7454  break;
7455 
7457  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7458  return SCIP_INVALIDDATA;
7459 
7460  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7461  assert(var->negatedvar != NULL);
7463  assert(var->negatedvar->negatedvar == var);
7464  SCIP_CALL( SCIPvarChgLbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7465  var->data.negate.constant - newbound) );
7466  break;
7467 
7468  default:
7469  SCIPerrorMessage("unknown variable status\n");
7470  return SCIP_INVALIDDATA;
7471  }
7472 
7473  return SCIP_OKAY;
7474 }
7475 
7476 /** changes lazy lower bound of the variable, this is only possible if the variable is not in the LP yet */
7478  SCIP_VAR* var, /**< problem variable */
7479  SCIP_SET* set, /**< global SCIP settings */
7480  SCIP_Real lazylb /**< the lazy lower bound to be set */
7481  )
7482 {
7483  assert(var != NULL);
7484  assert(var->probindex != -1);
7485  assert(SCIPsetIsFeasGE(set, var->glbdom.ub, lazylb));
7486  assert(SCIPsetIsFeasGE(set, var->lazyub, lazylb));
7487  assert(set != NULL);
7488  assert(var->scip == set->scip);
7489 
7490  /* variable should not be in the LP */
7492  return SCIP_INVALIDCALL;
7493 
7494  var->lazylb = lazylb;
7495 
7496  return SCIP_OKAY;
7497 }
7498 
7499 /** changes lazy upper bound of the variable, this is only possible if the variable is not in the LP yet */
7501  SCIP_VAR* var, /**< problem variable */
7502  SCIP_SET* set, /**< global SCIP settings */
7503  SCIP_Real lazyub /**< the lazy lower bound to be set */
7504  )
7505 {
7506  assert(var != NULL);
7507  assert(var->probindex != -1);
7508  assert(SCIPsetIsFeasGE(set, lazyub, var->glbdom.lb));
7509  assert(SCIPsetIsFeasGE(set, lazyub, var->lazylb));
7510  assert(set != NULL);
7511  assert(var->scip == set->scip);
7512 
7513  /* variable should not be in the LP */
7515  return SCIP_INVALIDCALL;
7516 
7517  var->lazyub = lazyub;
7518 
7519  return SCIP_OKAY;
7520 }
7521 
7522 
7523 /** changes global bound of variable; if possible, adjusts bound to integral value;
7524  * updates local bound if the global bound is tighter
7525  */
7527  SCIP_VAR* var, /**< problem variable to change */
7528  BMS_BLKMEM* blkmem, /**< block memory */
7529  SCIP_SET* set, /**< global SCIP settings */
7530  SCIP_STAT* stat, /**< problem statistics */
7531  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7532  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7533  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7534  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7535  SCIP_Real newbound, /**< new bound for variable */
7536  SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
7537  )
7538 {
7539  /* apply bound change to the LP data */
7540  switch( boundtype )
7541  {
7542  case SCIP_BOUNDTYPE_LOWER:
7543  return SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
7544  case SCIP_BOUNDTYPE_UPPER:
7545  return SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
7546  default:
7547  SCIPerrorMessage("unknown bound type\n");
7548  return SCIP_INVALIDDATA;
7549  }
7550 }
7551 
7552 /** appends LBTIGHTENED or LBRELAXED event to the event queue */
7553 static
7555  SCIP_VAR* var, /**< problem variable to change */
7556  BMS_BLKMEM* blkmem, /**< block memory */
7557  SCIP_SET* set, /**< global SCIP settings */
7558  SCIP_LP* lp, /**< current LP data */
7559  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7560  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7561  SCIP_Real oldbound, /**< old lower bound for variable */
7562  SCIP_Real newbound /**< new lower bound for variable */
7563  )
7564 {
7565  assert(var != NULL);
7566  assert(var->eventfilter != NULL);
7567  assert(SCIPvarIsTransformed(var));
7568  assert(!SCIPsetIsEQ(set, oldbound, newbound) || newbound == var->glbdom.lb || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
7569  assert(set != NULL);
7570  assert(var->scip == set->scip);
7571 
7572  /* check, if the variable is being tracked for bound changes
7573  * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
7574  */
7575  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_LBCHANGED) != 0)
7578  {
7579  SCIP_EVENT* event;
7580 
7581  SCIPsetDebugMsg(set, "issue LBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
7582 
7583  SCIP_CALL( SCIPeventCreateLbChanged(&event, blkmem, var, oldbound, newbound) );
7584  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
7585  }
7586 
7587  return SCIP_OKAY;
7588 }
7589 
7590 /** appends UBTIGHTENED or UBRELAXED event to the event queue */
7591 static
7593  SCIP_VAR* var, /**< problem variable to change */
7594  BMS_BLKMEM* blkmem, /**< block memory */
7595  SCIP_SET* set, /**< global SCIP settings */
7596  SCIP_LP* lp, /**< current LP data */
7597  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7598  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7599  SCIP_Real oldbound, /**< old upper bound for variable */
7600  SCIP_Real newbound /**< new upper bound for variable */
7601  )
7602 {
7603  assert(var != NULL);
7604  assert(var->eventfilter != NULL);
7605  assert(SCIPvarIsTransformed(var));
7606  assert(!SCIPsetIsEQ(set, oldbound, newbound) || newbound == var->glbdom.ub || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
7607  assert(set != NULL);
7608  assert(var->scip == set->scip);
7609 
7610  /* check, if the variable is being tracked for bound changes
7611  * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
7612  */
7613  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_UBCHANGED) != 0)
7616  {
7617  SCIP_EVENT* event;
7618 
7619  SCIPsetDebugMsg(set, "issue UBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
7620 
7621  SCIP_CALL( SCIPeventCreateUbChanged(&event, blkmem, var, oldbound, newbound) );
7622  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
7623  }
7624 
7625  return SCIP_OKAY;
7626 }
7627 
7628 /* forward declaration, because both methods call each other recursively */
7629 
7630 /* performs the current change in upper bound, changes all parents accordingly */
7631 static
7633  SCIP_VAR* var, /**< problem variable to change */
7634  BMS_BLKMEM* blkmem, /**< block memory */
7635  SCIP_SET* set, /**< global SCIP settings */
7636  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7637  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7638  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7639  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7640  SCIP_Real newbound /**< new bound for variable */
7641  );
7642 
7643 /** performs the current change in lower bound, changes all parents accordingly */
7644 static
7646  SCIP_VAR* var, /**< problem variable to change */
7647  BMS_BLKMEM* blkmem, /**< block memory */
7648  SCIP_SET* set, /**< global SCIP settings */
7649  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7650  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7651  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7652  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7653  SCIP_Real newbound /**< new bound for variable */
7654  )
7655 {
7656  SCIP_VAR* parentvar;
7657  SCIP_Real oldbound;
7658  int i;
7659 
7660  assert(var != NULL);
7661  assert(set != NULL);
7662  assert(var->scip == set->scip);
7663  assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)
7664  || SCIPsetIsEQ(set, newbound, var->locdom.ub)))
7665  || (SCIPvarGetType(var) < SCIP_VARTYPE_CONTINUOUS && (SCIPsetIsIntegral(set, newbound)
7666  || SCIPsetIsEQ(set, newbound, var->locdom.ub)))
7668 
7669  /* check that the bound is feasible */
7670  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsLE(set, newbound, var->glbdom.ub));
7671  /* adjust bound to integral value if variable is of integral type */
7672  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7673 
7674  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7675  {
7676  /* we do not want to exceed the upper bound, which could have happened due to numerics */
7677  newbound = MIN(newbound, var->locdom.ub);
7678 
7679  /* we do not want to undercut the global lower bound, which could have happened due to numerics */
7680  newbound = MAX(newbound, var->glbdom.lb);
7681  }
7682  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7683 
7684  SCIPsetDebugMsg(set, "process changing lower bound of <%s> from %g to %g\n", var->name, var->locdom.lb, newbound);
7685 
7686  if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) && var->glbdom.lb != var->locdom.lb ) /*lint !e777*/
7687  newbound = var->glbdom.lb;
7688  else if( SCIPsetIsEQ(set, newbound, var->locdom.lb) && !(newbound != var->locdom.lb && newbound * var->locdom.lb <= 0.0) ) /*lint !e777*/
7689  return SCIP_OKAY;
7690 
7691  /* change the bound */
7692  oldbound = var->locdom.lb;
7693  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->locdom.ub));
7694  var->locdom.lb = newbound;
7695 
7696  /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
7697  * once update the statistic
7698  */
7699  if( stat != NULL )
7700  SCIPstatIncrement(stat, set, domchgcount);
7701 
7702  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7703  {
7704  /* merges overlapping holes into single holes, moves bounds respectively */
7705  domMerge(&var->locdom, blkmem, set, &newbound, NULL);
7706  }
7707 
7708  /* issue bound change event */
7709  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7710  if( var->eventfilter != NULL )
7711  {
7712  SCIP_CALL( varEventLbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7713  }
7714 
7715  /* process parent variables */
7716  for( i = 0; i < var->nparentvars; ++i )
7717  {
7718  parentvar = var->parentvars[i];
7719  assert(parentvar != NULL);
7720 
7721  switch( SCIPvarGetStatus(parentvar) )
7722  {
7724  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
7725  break;
7726 
7727  case SCIP_VARSTATUS_COLUMN:
7728  case SCIP_VARSTATUS_LOOSE:
7729  case SCIP_VARSTATUS_FIXED:
7731  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7732  return SCIP_INVALIDDATA;
7733 
7734  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7735  assert(parentvar->data.aggregate.var == var);
7736  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7737  {
7738  SCIP_Real parentnewbound;
7739 
7740  /* a > 0 -> change lower bound of y */
7741  assert(SCIPsetIsInfinity(set, -parentvar->locdom.lb) || SCIPsetIsInfinity(set, -oldbound)
7742  || SCIPsetIsFeasEQ(set, parentvar->locdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
7743  || (SCIPsetIsZero(set, parentvar->locdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
7744 
7745  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7746  {
7747  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7748  /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
7749  * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
7750  * as a result, the parent's lower bound is set to it's upper bound, and not above
7751  */
7752  if( parentnewbound > parentvar->glbdom.ub )
7753  {
7754  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7755  assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
7756  parentnewbound = parentvar->glbdom.ub;
7757  }
7758  }
7759  else
7760  parentnewbound = newbound;
7761  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7762  }
7763  else
7764  {
7765  SCIP_Real parentnewbound;
7766 
7767  /* a < 0 -> change upper bound of y */
7768  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7769  assert(SCIPsetIsInfinity(set, parentvar->locdom.ub) || SCIPsetIsInfinity(set, -oldbound)
7770  || SCIPsetIsFeasEQ(set, parentvar->locdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
7771  || (SCIPsetIsZero(set, parentvar->locdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
7772 
7773  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7774  {
7775  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7776  /* 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
7777  * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
7778  * as a result, the parent's upper bound is set to it's lower bound, and not below
7779  */
7780  if( parentnewbound < parentvar->glbdom.lb )
7781  {
7782  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7783  assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
7784  parentnewbound = parentvar->glbdom.lb;
7785  }
7786  }
7787  else
7788  parentnewbound = -newbound;
7789  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7790  }
7791  break;
7792 
7793  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
7794  assert(parentvar->negatedvar != NULL);
7795  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7796  assert(parentvar->negatedvar->negatedvar == parentvar);
7797  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
7798  parentvar->data.negate.constant - newbound) );
7799  break;
7800 
7801  default:
7802  SCIPerrorMessage("unknown variable status\n");
7803  return SCIP_INVALIDDATA;
7804  }
7805  }
7806 
7807  return SCIP_OKAY;
7808 }
7809 
7810 /** performs the current change in upper bound, changes all parents accordingly */
7811 static
7813  SCIP_VAR* var, /**< problem variable to change */
7814  BMS_BLKMEM* blkmem, /**< block memory */
7815  SCIP_SET* set, /**< global SCIP settings */
7816  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7817  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7818  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7819  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7820  SCIP_Real newbound /**< new bound for variable */
7821  )
7822 {
7823  SCIP_VAR* parentvar;
7824  SCIP_Real oldbound;
7825  int i;
7826 
7827  assert(var != NULL);
7828  assert(set != NULL);
7829  assert(var->scip == set->scip);
7830  assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)
7831  || SCIPsetIsEQ(set, newbound, var->locdom.lb)))
7832  || (SCIPvarGetType(var) < SCIP_VARTYPE_CONTINUOUS && (SCIPsetIsIntegral(set, newbound)
7833  || SCIPsetIsEQ(set, newbound, var->locdom.lb)))
7835 
7836  /* check that the bound is feasible */
7837  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsGE(set, newbound, var->glbdom.lb));
7838  /* adjust bound to integral value if variable is of integral type */
7839  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7840 
7841  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7842  {
7843  /* we do not want to undercut the lower bound, which could have happened due to numerics */
7844  newbound = MAX(newbound, var->locdom.lb);
7845 
7846  /* we do not want to exceed the global upper bound, which could have happened due to numerics */
7847  newbound = MIN(newbound, var->glbdom.ub);
7848  }
7849  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7850 
7851  SCIPsetDebugMsg(set, "process changing upper bound of <%s> from %g to %g\n", var->name, var->locdom.ub, newbound);
7852 
7853  if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) && var->glbdom.ub != var->locdom.ub ) /*lint !e777*/
7854  newbound = var->glbdom.ub;
7855  else if( SCIPsetIsEQ(set, newbound, var->locdom.ub) && !(newbound != var->locdom.ub && newbound * var->locdom.ub <= 0.0) ) /*lint !e777*/
7856  return SCIP_OKAY;
7857 
7858  /* change the bound */
7859  oldbound = var->locdom.ub;
7860  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->locdom.lb));
7861  var->locdom.ub = newbound;
7862 
7863  /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
7864  * once update the statistic
7865  */
7866  if( stat != NULL )
7867  SCIPstatIncrement(stat, set, domchgcount);
7868 
7869  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7870  {
7871  /* merges overlapping holes into single holes, moves bounds respectively */
7872  domMerge(&var->locdom, blkmem, set, NULL, &newbound);
7873  }
7874 
7875  /* issue bound change event */
7876  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7877  if( var->eventfilter != NULL )
7878  {
7879  SCIP_CALL( varEventUbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7880  }
7881 
7882  /* process parent variables */
7883  for( i = 0; i < var->nparentvars; ++i )
7884  {
7885  parentvar = var->parentvars[i];
7886  assert(parentvar != NULL);
7887 
7888  switch( SCIPvarGetStatus(parentvar) )
7889  {
7891  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
7892  break;
7893 
7894  case SCIP_VARSTATUS_COLUMN:
7895  case SCIP_VARSTATUS_LOOSE:
7896  case SCIP_VARSTATUS_FIXED:
7898  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7899  return SCIP_INVALIDDATA;
7900 
7901  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7902  assert(parentvar->data.aggregate.var == var);
7903  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7904  {
7905  SCIP_Real parentnewbound;
7906 
7907  /* a > 0 -> change upper bound of x */
7908  assert(SCIPsetIsInfinity(set, parentvar->locdom.ub) || SCIPsetIsInfinity(set, oldbound)
7909  || SCIPsetIsFeasEQ(set, parentvar->locdom.ub,
7910  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7911  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7912  {
7913  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7914  /* 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
7915  * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
7916  * as a result, the parent's upper bound is set to it's lower bound, and not below
7917  */
7918  if( parentnewbound < parentvar->glbdom.lb )
7919  {
7920  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7921  assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
7922  parentnewbound = parentvar->glbdom.lb;
7923  }
7924  }
7925  else
7926  parentnewbound = newbound;
7927  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7928  }
7929  else
7930  {
7931  SCIP_Real parentnewbound;
7932 
7933  /* a < 0 -> change lower bound of x */
7934  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7935  assert(SCIPsetIsInfinity(set, -parentvar->locdom.lb) || SCIPsetIsInfinity(set, oldbound)
7936  || SCIPsetIsFeasEQ(set, parentvar->locdom.lb,
7937  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7938  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7939  {
7940  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7941  /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
7942  * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
7943  * as a result, the parent's lower bound is set to it's upper bound, and not above
7944  */
7945  if( parentnewbound > parentvar->glbdom.ub )
7946  {
7947  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7948  assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
7949  parentnewbound = parentvar->glbdom.ub;
7950  }
7951  }
7952  else
7953  parentnewbound = -newbound;
7954  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7955  }
7956  break;
7957 
7958  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
7959  assert(parentvar->negatedvar != NULL);
7960  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7961  assert(parentvar->negatedvar->negatedvar == parentvar);
7962  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
7963  parentvar->data.negate.constant - newbound) );
7964  break;
7965 
7966  default:
7967  SCIPerrorMessage("unknown variable status\n");
7968  return SCIP_INVALIDDATA;
7969  }
7970  }
7971 
7972  return SCIP_OKAY;
7973 }
7974 
7975 /** changes current local lower bound of variable; if possible, adjusts bound to integral value; stores inference
7976  * information in variable
7977  */
7979  SCIP_VAR* var, /**< problem variable to change */
7980  BMS_BLKMEM* blkmem, /**< block memory */
7981  SCIP_SET* set, /**< global SCIP settings */
7982  SCIP_STAT* stat, /**< problem statistics */
7983  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7984  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7985  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7986  SCIP_Real newbound /**< new bound for variable */
7987  )
7988 {
7989  assert(var != NULL);
7990  assert(blkmem != NULL);
7991  assert(set != NULL);
7992  assert(var->scip == set->scip);
7993 
7994  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7995  * of the domain within feastol
7996  */
7997  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
7998 
7999  /* adjust bound to integral value if variable is of integral type */
8000  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
8001 
8002  /* check that the adjusted bound is feasible */
8003  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
8004 
8005  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
8006  {
8007  /* we do not want to exceed the upperbound, which could have happened due to numerics */
8008  newbound = MIN(newbound, var->locdom.ub);
8009  }
8010  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
8011 
8012  SCIPsetDebugMsg(set, "changing lower bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
8013 
8014  if( SCIPsetIsEQ(set, var->locdom.lb, newbound) && (!SCIPsetIsEQ(set, var->glbdom.lb, newbound) || var->locdom.lb == newbound) /*lint !e777*/
8015  && !(newbound != var->locdom.lb && newbound * var->locdom.lb <= 0.0) ) /*lint !e777*/
8016  return SCIP_OKAY;
8017 
8018  /* change bounds of attached variables */
8019  switch( SCIPvarGetStatus(var) )
8020  {
8022  if( var->data.original.transvar != NULL )
8023  {
8024  SCIP_CALL( SCIPvarChgLbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
8025  newbound) );
8026  }
8027  else
8028  {
8029  assert(set->stage == SCIP_STAGE_PROBLEM);
8030  SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8031  }
8032  break;
8033 
8034  case SCIP_VARSTATUS_COLUMN:
8035  case SCIP_VARSTATUS_LOOSE:
8036  SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8037  break;
8038 
8039  case SCIP_VARSTATUS_FIXED:
8040  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8041  return SCIP_INVALIDDATA;
8042 
8043  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8044  assert(var->data.aggregate.var != NULL);
8045  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8046  {
8047  SCIP_Real childnewbound;
8048 
8049  /* a > 0 -> change lower bound of y */
8050  assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, -var->data.aggregate.var->locdom.lb))
8051  || SCIPsetIsFeasEQ(set, var->locdom.lb,
8053  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8054  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8055  else
8056  childnewbound = newbound;
8057  SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
8058  childnewbound) );
8059  }
8060  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8061  {
8062  SCIP_Real childnewbound;
8063 
8064  /* a < 0 -> change upper bound of y */
8065  assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->locdom.ub))
8066  || SCIPsetIsFeasEQ(set, var->locdom.lb,
8068  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8069  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8070  else
8071  childnewbound = -newbound;
8072  SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
8073  childnewbound) );
8074  }
8075  else
8076  {
8077  SCIPerrorMessage("scalar is zero in aggregation\n");
8078  return SCIP_INVALIDDATA;
8079  }
8080  break;
8081 
8083  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8084  return SCIP_INVALIDDATA;
8085 
8086  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8087  assert(var->negatedvar != NULL);
8089  assert(var->negatedvar->negatedvar == var);
8090  SCIP_CALL( SCIPvarChgUbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
8091  var->data.negate.constant - newbound) );
8092  break;
8093 
8094  default:
8095  SCIPerrorMessage("unknown variable status\n");
8096  return SCIP_INVALIDDATA;
8097  }
8098 
8099  return SCIP_OKAY;
8100 }
8101 
8102 /** changes current local upper bound of variable; if possible, adjusts bound to integral value; stores inference
8103  * information in variable
8104  */
8106  SCIP_VAR* var, /**< problem variable to change */
8107  BMS_BLKMEM* blkmem, /**< block memory */
8108  SCIP_SET* set, /**< global SCIP settings */
8109  SCIP_STAT* stat, /**< problem statistics */
8110  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
8111  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
8112  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8113  SCIP_Real newbound /**< new bound for variable */
8114  )
8115 {
8116  assert(var != NULL);
8117  assert(blkmem != NULL);
8118  assert(set != NULL);
8119  assert(var->scip == set->scip);
8120 
8121  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
8122  * of the domain within feastol
8123  */
8124  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
8125 
8126  /* adjust bound to integral value if variable is of integral type */
8127  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
8128 
8129  /* check that the adjusted bound is feasible */
8130  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
8131 
8132  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
8133  {
8134  /* we do not want to undercut the lowerbound, which could have happened due to numerics */
8135  newbound = MAX(newbound, var->locdom.lb);
8136  }
8137  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
8138 
8139  SCIPsetDebugMsg(set, "changing upper bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
8140 
8141  if( SCIPsetIsEQ(set, var->locdom.ub, newbound) && (!SCIPsetIsEQ(set, var->glbdom.ub, newbound) || var->locdom.ub == newbound) /*lint !e777*/
8142  && !(newbound != var->locdom.ub && newbound * var->locdom.ub <= 0.0) ) /*lint !e777*/
8143  return SCIP_OKAY;
8144 
8145  /* change bounds of attached variables */
8146  switch( SCIPvarGetStatus(var) )
8147  {
8149  if( var->data.original.transvar != NULL )
8150  {
8151  SCIP_CALL( SCIPvarChgUbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8152  }
8153  else
8154  {
8155  assert(set->stage == SCIP_STAGE_PROBLEM);
8156  SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8157  }
8158  break;
8159 
8160  case SCIP_VARSTATUS_COLUMN:
8161  case SCIP_VARSTATUS_LOOSE:
8162  SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8163  break;
8164 
8165  case SCIP_VARSTATUS_FIXED:
8166  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8167  return SCIP_INVALIDDATA;
8168 
8169  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8170  assert(var->data.aggregate.var != NULL);
8171  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8172  {
8173  SCIP_Real childnewbound;
8174 
8175  /* a > 0 -> change upper bound of y */
8176  assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, var->data.aggregate.var->locdom.ub))
8177  || SCIPsetIsFeasEQ(set, var->locdom.ub,
8179  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8180  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8181  else
8182  childnewbound = newbound;
8183  SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
8184  childnewbound) );
8185  }
8186  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8187  {
8188  SCIP_Real childnewbound;
8189 
8190  /* a < 0 -> change lower bound of y */
8191  assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, -var->data.aggregate.var->locdom.lb))
8192  || SCIPsetIsFeasEQ(set, var->locdom.ub,
8194  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8195  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8196  else
8197  childnewbound = -newbound;
8198  SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
8199  childnewbound) );
8200  }
8201  else
8202  {
8203  SCIPerrorMessage("scalar is zero in aggregation\n");
8204  return SCIP_INVALIDDATA;
8205  }
8206  break;
8207 
8209  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8210  return SCIP_INVALIDDATA;
8211 
8212  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8213  assert(var->negatedvar != NULL);
8215  assert(var->negatedvar->negatedvar == var);
8216  SCIP_CALL( SCIPvarChgLbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
8217  var->data.negate.constant - newbound) );
8218  break;
8219 
8220  default:
8221  SCIPerrorMessage("unknown variable status\n");
8222  return SCIP_INVALIDDATA;
8223  }
8224 
8225  return SCIP_OKAY;
8226 }
8227 
8228 /** changes current local bound of variable; if possible, adjusts bound to integral value; stores inference
8229  * information in variable
8230  */
8232  SCIP_VAR* var, /**< problem variable to change */
8233  BMS_BLKMEM* blkmem, /**< block memory */
8234  SCIP_SET* set, /**< global SCIP settings */
8235  SCIP_STAT* stat, /**< problem statistics */
8236  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
8237  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
8238  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8239  SCIP_Real newbound, /**< new bound for variable */
8240  SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
8241  )
8242 {
8243  /* apply bound change to the LP data */
8244  switch( boundtype )
8245  {
8246  case SCIP_BOUNDTYPE_LOWER:
8247  return SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
8248  case SCIP_BOUNDTYPE_UPPER:
8249  return SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
8250  default:
8251  SCIPerrorMessage("unknown bound type\n");
8252  return SCIP_INVALIDDATA;
8253  }
8254 }
8255 
8256 /** changes lower bound of variable in current dive; if possible, adjusts bound to integral value */
8258  SCIP_VAR* var, /**< problem variable to change */
8259  SCIP_SET* set, /**< global SCIP settings */
8260  SCIP_LP* lp, /**< current LP data */
8261  SCIP_Real newbound /**< new bound for variable */
8262  )
8263 {
8264  assert(var != NULL);
8265  assert(set != NULL);
8266  assert(var->scip == set->scip);
8267  assert(lp != NULL);
8268  assert(SCIPlpDiving(lp));
8269 
8270  /* adjust bound for integral variables */
8271  SCIPvarAdjustLb(var, set, &newbound);
8272 
8273  SCIPsetDebugMsg(set, "changing lower bound of <%s> to %g in current dive\n", var->name, newbound);
8274 
8275  /* change bounds of attached variables */
8276  switch( SCIPvarGetStatus(var) )
8277  {
8279  assert(var->data.original.transvar != NULL);
8280  SCIP_CALL( SCIPvarChgLbDive(var->data.original.transvar, set, lp, newbound) );
8281  break;
8282 
8283  case SCIP_VARSTATUS_COLUMN:
8284  assert(var->data.col != NULL);
8285  SCIP_CALL( SCIPcolChgLb(var->data.col, set, lp, newbound) );
8286  break;
8287 
8288  case SCIP_VARSTATUS_LOOSE:
8289  SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
8290  return SCIP_INVALIDDATA;
8291 
8292  case SCIP_VARSTATUS_FIXED:
8293  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8294  return SCIP_INVALIDDATA;
8295 
8296  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8297  assert(var->data.aggregate.var != NULL);
8298  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8299  {
8300  SCIP_Real childnewbound;
8301 
8302  /* a > 0 -> change lower bound of y */
8303  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8304  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8305  else
8306  childnewbound = newbound;
8307  SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
8308  }
8309  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8310  {
8311  SCIP_Real childnewbound;
8312 
8313  /* a < 0 -> change upper bound of y */
8314  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8315  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8316  else
8317  childnewbound = -newbound;
8318  SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
8319  }
8320  else
8321  {
8322  SCIPerrorMessage("scalar is zero in aggregation\n");
8323  return SCIP_INVALIDDATA;
8324  }
8325  break;
8326 
8328  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8329  return SCIP_INVALIDDATA;
8330 
8331  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8332  assert(var->negatedvar != NULL);
8334  assert(var->negatedvar->negatedvar == var);
8335  SCIP_CALL( SCIPvarChgUbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
8336  break;
8337 
8338  default:
8339  SCIPerrorMessage("unknown variable status\n");
8340  return SCIP_INVALIDDATA;
8341  }
8342 
8343  return SCIP_OKAY;
8344 }
8345 
8346 /** changes upper bound of variable in current dive; if possible, adjusts bound to integral value */
8348  SCIP_VAR* var, /**< problem variable to change */
8349  SCIP_SET* set, /**< global SCIP settings */
8350  SCIP_LP* lp, /**< current LP data */
8351  SCIP_Real newbound /**< new bound for variable */
8352  )
8353 {
8354  assert(var != NULL);
8355  assert(set != NULL);
8356  assert(var->scip == set->scip);
8357  assert(lp != NULL);
8358  assert(SCIPlpDiving(lp));
8359 
8360  /* adjust bound for integral variables */
8361  SCIPvarAdjustUb(var, set, &newbound);
8362 
8363  SCIPsetDebugMsg(set, "changing upper bound of <%s> to %g in current dive\n", var->name, newbound);
8364 
8365  /* change bounds of attached variables */
8366  switch( SCIPvarGetStatus(var) )
8367  {
8369  assert(var->data.original.transvar != NULL);
8370  SCIP_CALL( SCIPvarChgUbDive(var->data.original.transvar, set, lp, newbound) );
8371  break;
8372 
8373  case SCIP_VARSTATUS_COLUMN:
8374  assert(var->data.col != NULL);
8375  SCIP_CALL( SCIPcolChgUb(var->data.col, set, lp, newbound) );
8376  break;
8377 
8378  case SCIP_VARSTATUS_LOOSE:
8379  SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
8380  return SCIP_INVALIDDATA;
8381 
8382  case SCIP_VARSTATUS_FIXED:
8383  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8384  return SCIP_INVALIDDATA;
8385 
8386  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8387  assert(var->data.aggregate.var != NULL);
8388  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8389  {
8390  SCIP_Real childnewbound;
8391 
8392  /* a > 0 -> change upper bound of y */
8393  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8394  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8395  else
8396  childnewbound = newbound;
8397  SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
8398  }
8399  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8400  {
8401  SCIP_Real childnewbound;
8402 
8403  /* a < 0 -> change lower bound of y */
8404  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8405  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8406  else
8407  childnewbound = -newbound;
8408  SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
8409  }
8410  else
8411  {
8412  SCIPerrorMessage("scalar is zero in aggregation\n");
8413  return SCIP_INVALIDDATA;
8414  }
8415  break;
8416 
8418  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8419  return SCIP_INVALIDDATA;
8420 
8421  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8422  assert(var->negatedvar != NULL);
8424  assert(var->negatedvar->negatedvar == var);
8425  SCIP_CALL( SCIPvarChgLbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
8426  break;
8427 
8428  default:
8429  SCIPerrorMessage("unknown variable status\n");
8430  return SCIP_INVALIDDATA;
8431  }
8432 
8433  return SCIP_OKAY;
8434 }
8435 
8436 /** for a multi-aggregated variable, gives the local lower bound computed by adding the local bounds from all
8437  * aggregation variables, this lower bound may be tighter than the one given by SCIPvarGetLbLocal, since the latter is
8438  * not updated if bounds of aggregation variables are changing
8439  *
8440  * calling this function for a non-multi-aggregated variable is not allowed
8441  */
8443  SCIP_VAR* var, /**< problem variable */
8444  SCIP_SET* set /**< global SCIP settings */
8445  )
8446 {
8447  int i;
8448  SCIP_Real lb;
8449  SCIP_Real bnd;
8450  SCIP_VAR* aggrvar;
8451  SCIP_Bool posinf;
8452  SCIP_Bool neginf;
8453 
8454  assert(var != NULL);
8455  assert(set != NULL);
8456  assert(var->scip == set->scip);
8458 
8459  posinf = FALSE;
8460  neginf = FALSE;
8461  lb = var->data.multaggr.constant;
8462  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8463  {
8464  aggrvar = var->data.multaggr.vars[i];
8465  if( var->data.multaggr.scalars[i] > 0.0 )
8466  {
8467  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbLocal(aggrvar, set) : SCIPvarGetLbLocal(aggrvar);
8468 
8469  if( SCIPsetIsInfinity(set, bnd) )
8470  posinf = TRUE;
8471  else if( SCIPsetIsInfinity(set, -bnd) )
8472  neginf = TRUE;
8473  else
8474  lb += var->data.multaggr.scalars[i] * bnd;
8475  }
8476  else
8477  {
8478  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbLocal(aggrvar, set) : SCIPvarGetUbLocal(aggrvar);
8479 
8480  if( SCIPsetIsInfinity(set, -bnd) )
8481  posinf = TRUE;
8482  else if( SCIPsetIsInfinity(set, bnd) )
8483  neginf = TRUE;
8484  else
8485  lb += var->data.multaggr.scalars[i] * bnd;
8486  }
8487 
8488  /* stop if two diffrent infinities (or a -infinity) were found and return local lower bound of multi aggregated
8489  * variable
8490  */
8491  if( neginf )
8492  return SCIPvarGetLbLocal(var);
8493  }
8494 
8495  /* if positive infinity flag was set to true return infinity */
8496  if( posinf )
8497  return SCIPsetInfinity(set);
8498 
8499  return (MAX(lb, SCIPvarGetLbLocal(var))); /*lint !e666*/
8500 }
8501 
8502 /** for a multi-aggregated variable, gives the local upper bound computed by adding the local bounds from all
8503  * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbLocal, since the latter is
8504  * not updated if bounds of aggregation variables are changing
8505  *
8506  * calling this function for a non-multi-aggregated variable is not allowed
8507  */
8509  SCIP_VAR* var, /**< problem variable */
8510  SCIP_SET* set /**< global SCIP settings */
8511  )
8512 {
8513  int i;
8514  SCIP_Real ub;
8515  SCIP_Real bnd;
8516  SCIP_VAR* aggrvar;
8517  SCIP_Bool posinf;
8518  SCIP_Bool neginf;
8519 
8520  assert(var != NULL);
8521  assert(set != NULL);
8522  assert(var->scip == set->scip);
8524 
8525  posinf = FALSE;
8526  neginf = FALSE;
8527  ub = var->data.multaggr.constant;
8528  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8529  {
8530  aggrvar = var->data.multaggr.vars[i];
8531  if( var->data.multaggr.scalars[i] > 0.0 )
8532  {
8533  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbLocal(aggrvar, set) : SCIPvarGetUbLocal(aggrvar);
8534 
8535  if( SCIPsetIsInfinity(set, bnd) )
8536  posinf = TRUE;
8537  else if( SCIPsetIsInfinity(set, -bnd) )
8538  neginf = TRUE;
8539  else
8540  ub += var->data.multaggr.scalars[i] * bnd;
8541  }
8542  else
8543  {
8544  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbLocal(aggrvar, set) : SCIPvarGetLbLocal(aggrvar);
8545 
8546  if( SCIPsetIsInfinity(set, -bnd) )
8547  posinf = TRUE;
8548  else if( SCIPsetIsInfinity(set, bnd) )
8549  neginf = TRUE;
8550  else
8551  ub += var->data.multaggr.scalars[i] * bnd;
8552  }
8553 
8554  /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
8555  * variable
8556  */
8557  if( posinf )
8558  return SCIPvarGetUbLocal(var);
8559  }
8560 
8561  /* if negative infinity flag was set to true return -infinity */
8562  if( neginf )
8563  return -SCIPsetInfinity(set);
8564 
8565  return (MIN(ub, SCIPvarGetUbLocal(var))); /*lint !e666*/
8566 }
8567 
8568 /** for a multi-aggregated variable, gives the global lower bound computed by adding the global bounds from all
8569  * aggregation variables, this global bound may be tighter than the one given by SCIPvarGetLbGlobal, since the latter is
8570  * not updated if bounds of aggregation variables are changing
8571  *
8572  * calling this function for a non-multi-aggregated variable is not allowed
8573  */
8575  SCIP_VAR* var, /**< problem variable */
8576  SCIP_SET* set /**< global SCIP settings */
8577  )
8578 {
8579  int i;
8580  SCIP_Real lb;
8581  SCIP_Real bnd;
8582  SCIP_VAR* aggrvar;
8583  SCIP_Bool posinf;
8584  SCIP_Bool neginf;
8585 
8586  assert(var != NULL);
8587  assert(set != NULL);
8588  assert(var->scip == set->scip);
8590 
8591  posinf = FALSE;
8592  neginf = FALSE;
8593  lb = var->data.multaggr.constant;
8594  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8595  {
8596  aggrvar = var->data.multaggr.vars[i];
8597  if( var->data.multaggr.scalars[i] > 0.0 )
8598  {
8599  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbGlobal(aggrvar, set) : SCIPvarGetLbGlobal(aggrvar);
8600 
8601  if( SCIPsetIsInfinity(set, bnd) )
8602  posinf = TRUE;
8603  else if( SCIPsetIsInfinity(set, -bnd) )
8604  neginf = TRUE;
8605  else
8606  lb += var->data.multaggr.scalars[i] * bnd;
8607  }
8608  else
8609  {
8610  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbGlobal(aggrvar, set) : SCIPvarGetUbGlobal(aggrvar);
8611 
8612  if( SCIPsetIsInfinity(set, -bnd) )
8613  posinf = TRUE;
8614  else if( SCIPsetIsInfinity(set, bnd) )
8615  neginf = TRUE;
8616  else
8617  lb += var->data.multaggr.scalars[i] * bnd;
8618  }
8619 
8620  /* stop if two diffrent infinities (or a -infinity) were found and return global lower bound of multi aggregated
8621  * variable
8622  */
8623  if( neginf )
8624  return SCIPvarGetLbGlobal(var);
8625  }
8626 
8627  /* if positive infinity flag was set to true return infinity */
8628  if( posinf )
8629  return SCIPsetInfinity(set);
8630 
8631  return (MAX(lb, SCIPvarGetLbGlobal(var))); /*lint !e666*/
8632 }
8633 
8634 /** for a multi-aggregated variable, gives the global upper bound computed by adding the global bounds from all
8635  * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbGlobal, since the latter is
8636  * not updated if bounds of aggregation variables are changing
8637  *
8638  * calling this function for a non-multi-aggregated variable is not allowed
8639  */
8641  SCIP_VAR* var, /**< problem variable */
8642  SCIP_SET* set /**< global SCIP settings */
8643  )
8644 {
8645  int i;
8646  SCIP_Real ub;
8647  SCIP_Real bnd;
8648  SCIP_VAR* aggrvar;
8649  SCIP_Bool posinf;
8650  SCIP_Bool neginf;
8651 
8652  assert(var != NULL);
8653  assert(set != NULL);
8654  assert(var->scip == set->scip);
8656 
8657  posinf = FALSE;
8658  neginf = FALSE;
8659  ub = var->data.multaggr.constant;
8660  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8661  {
8662  aggrvar = var->data.multaggr.vars[i];
8663  if( var->data.multaggr.scalars[i] > 0.0 )
8664  {
8665  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbGlobal(aggrvar, set) : SCIPvarGetUbGlobal(aggrvar);
8666 
8667  if( SCIPsetIsInfinity(set, bnd) )
8668  posinf = TRUE;
8669  else if( SCIPsetIsInfinity(set, -bnd) )
8670  neginf = TRUE;
8671  else
8672  ub += var->data.multaggr.scalars[i] * bnd;
8673  }
8674  else
8675  {
8676  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbGlobal(aggrvar, set) : SCIPvarGetLbGlobal(aggrvar);
8677 
8678  if( SCIPsetIsInfinity(set, -bnd) )
8679  posinf = TRUE;
8680  else if( SCIPsetIsInfinity(set, bnd) )
8681  neginf = TRUE;
8682  else
8683  ub += var->data.multaggr.scalars[i] * bnd;
8684  }
8685 
8686  /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
8687  * variable
8688  */
8689  if( posinf )
8690  return SCIPvarGetUbGlobal(var);
8691  }
8692 
8693  /* if negative infinity flag was set to true return -infinity */
8694  if( neginf )
8695  return -SCIPsetInfinity(set);
8696 
8697  return (MIN(ub, SCIPvarGetUbGlobal(var))); /*lint !e666*/
8698 }
8699 
8700 /** adds a hole to the original domain of the variable */
8702  SCIP_VAR* var, /**< problem variable */
8703  BMS_BLKMEM* blkmem, /**< block memory */
8704  SCIP_SET* set, /**< global SCIP settings */
8705  SCIP_Real left, /**< left bound of open interval in new hole */
8706  SCIP_Real right /**< right bound of open interval in new hole */
8707  )
8708 {
8709  SCIP_Bool added;
8710 
8711  assert(var != NULL);
8712  assert(!SCIPvarIsTransformed(var));
8714  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8715  assert(set != NULL);
8716  assert(var->scip == set->scip);
8717  assert(set->stage == SCIP_STAGE_PROBLEM);
8718 
8719  SCIPsetDebugMsg(set, "adding original hole (%g,%g) to <%s>\n", left, right, var->name);
8720 
8721  if( SCIPsetIsEQ(set, left, right) )
8722  return SCIP_OKAY;
8723 
8724  /* the interval should not be empty */
8725  assert(SCIPsetIsLT(set, left, right));
8726 
8727  /* the the interval bound should already be adjusted */
8728  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8729  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8730 
8731  /* the the interval should lay between the lower and upper bound */
8732  assert(SCIPsetIsGE(set, left, SCIPvarGetLbOriginal(var)));
8733  assert(SCIPsetIsLE(set, right, SCIPvarGetUbOriginal(var)));
8734 
8735  /* add domain hole */
8736  SCIP_CALL( domAddHole(&var->data.original.origdom, blkmem, set, left, right, &added) );
8737 
8738  /* merges overlapping holes into single holes, moves bounds respectively if hole was added */
8739  if( added )
8740  {
8741  domMerge(&var->data.original.origdom, blkmem, set, NULL, NULL);
8742  }
8743 
8744  /**@todo add hole in parent and child variables (just like with bound changes);
8745  * warning! original vars' holes are in original blkmem, transformed vars' holes in transformed blkmem
8746  */
8747 
8748  return SCIP_OKAY;
8749 }
8750 
8751 /** performs the current add of domain, changes all parents accordingly */
8752 static
8754  SCIP_VAR* var, /**< problem variable */
8755  BMS_BLKMEM* blkmem, /**< block memory */
8756  SCIP_SET* set, /**< global SCIP settings */
8757  SCIP_STAT* stat, /**< problem statistics */
8758  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8759  SCIP_Real left, /**< left bound of open interval in new hole */
8760  SCIP_Real right, /**< right bound of open interval in new hole */
8761  SCIP_Bool* added /**< pointer to store whether the hole was added */
8762  )
8763 {
8764  SCIP_VAR* parentvar;
8765  SCIP_Real newlb;
8766  SCIP_Real newub;
8767  int i;
8768 
8769  assert(var != NULL);
8770  assert(added != NULL);
8771  assert(blkmem != NULL);
8772 
8773  /* the interval should not be empty */
8774  assert(SCIPsetIsLT(set, left, right));
8775 
8776  /* the interval bound should already be adjusted */
8777  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8778  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8779 
8780  /* the interval should lay between the lower and upper bound */
8781  assert(SCIPsetIsGE(set, left, SCIPvarGetLbGlobal(var)));
8782  assert(SCIPsetIsLE(set, right, SCIPvarGetUbGlobal(var)));
8783 
8784  /* @todo add debugging mechanism for holes when using a debugging solution */
8785 
8786  /* add hole to hole list */
8787  SCIP_CALL( domAddHole(&var->glbdom, blkmem, set, left, right, added) );
8788 
8789  /* check if the hole is redundant */
8790  if( !(*added) )
8791  return SCIP_OKAY;
8792 
8793  /* current bounds */
8794  newlb = var->glbdom.lb;
8795  newub = var->glbdom.ub;
8796 
8797  /* merge domain holes */
8798  domMerge(&var->glbdom, blkmem, set, &newlb, &newub);
8799 
8800  /* the bound should not be changed */
8801  assert(SCIPsetIsEQ(set, newlb, var->glbdom.lb));
8802  assert(SCIPsetIsEQ(set, newub, var->glbdom.ub));
8803 
8804  /* issue bound change event */
8805  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
8806  if( var->eventfilter != NULL )
8807  {
8808  SCIP_CALL( varEventGholeAdded(var, blkmem, set, eventqueue, left, right) );
8809  }
8810 
8811  /* process parent variables */
8812  for( i = 0; i < var->nparentvars; ++i )
8813  {
8814  SCIP_Real parentnewleft;
8815  SCIP_Real parentnewright;
8816  SCIP_Bool localadded;
8817 
8818  parentvar = var->parentvars[i];
8819  assert(parentvar != NULL);
8820 
8821  switch( SCIPvarGetStatus(parentvar) )
8822  {
8824  parentnewleft = left;
8825  parentnewright = right;
8826  break;
8827 
8828  case SCIP_VARSTATUS_COLUMN:
8829  case SCIP_VARSTATUS_LOOSE:
8830  case SCIP_VARSTATUS_FIXED:
8832  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
8833  return SCIP_INVALIDDATA;
8834 
8835  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8836  assert(parentvar->data.aggregate.var == var);
8837 
8838  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
8839  {
8840  /* a > 0 -> change upper bound of x */
8841  parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8842  parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8843  }
8844  else
8845  {
8846  /* a < 0 -> change lower bound of x */
8847  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
8848 
8849  parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8850  parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8851  }
8852  break;
8853 
8854  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
8855  assert(parentvar->negatedvar != NULL);
8856  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
8857  assert(parentvar->negatedvar->negatedvar == parentvar);
8858 
8859  parentnewright = -left + parentvar->data.negate.constant;
8860  parentnewleft = -right + parentvar->data.negate.constant;
8861  break;
8862 
8863  default:
8864  SCIPerrorMessage("unknown variable status\n");
8865  return SCIP_INVALIDDATA;
8866  }
8867 
8868  SCIPsetDebugMsg(set, "add global hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
8869 
8870  /* perform hole added for parent variable */
8871  assert(blkmem != NULL);
8872  assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
8873  SCIP_CALL( varProcessAddHoleGlobal(parentvar, blkmem, set, stat, eventqueue,
8874  parentnewleft, parentnewright, &localadded) );
8875  assert(localadded);
8876  }
8877 
8878  return SCIP_OKAY;
8879 }
8880 
8881 /** adds a hole to the variable's global and local domain */
8883  SCIP_VAR* var, /**< problem variable */
8884  BMS_BLKMEM* blkmem, /**< block memory */
8885  SCIP_SET* set, /**< global SCIP settings */
8886  SCIP_STAT* stat, /**< problem statistics */
8887  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8888  SCIP_Real left, /**< left bound of open interval in new hole */
8889  SCIP_Real right, /**< right bound of open interval in new hole */
8890  SCIP_Bool* added /**< pointer to store whether the hole was added */
8891  )
8892 {
8893  SCIP_Real childnewleft;
8894  SCIP_Real childnewright;
8895 
8896  assert(var != NULL);
8897  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8898  assert(blkmem != NULL);
8899  assert(added != NULL);
8900 
8901  SCIPsetDebugMsg(set, "adding global hole (%g,%g) to <%s>\n", left, right, var->name);
8902 
8903  /* the interval should not be empty */
8904  assert(SCIPsetIsLT(set, left, right));
8905 
8906  /* the the interval bound should already be adjusted */
8907  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8908  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8909 
8910  /* the the interval should lay between the lower and upper bound */
8911  assert(SCIPsetIsGE(set, left, SCIPvarGetLbGlobal(var)));
8912  assert(SCIPsetIsLE(set, right, SCIPvarGetUbGlobal(var)));
8913 
8914  /* change bounds of attached variables */
8915  switch( SCIPvarGetStatus(var) )
8916  {
8918  if( var->data.original.transvar != NULL )
8919  {
8920  SCIP_CALL( SCIPvarAddHoleGlobal(var->data.original.transvar, blkmem, set, stat, eventqueue,
8921  left, right, added) );
8922  }
8923  else
8924  {
8925  assert(set->stage == SCIP_STAGE_PROBLEM);
8926 
8927  SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
8928  if( *added )
8929  {
8930  SCIP_Bool localadded;
8931 
8932  SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
8933  }
8934  }
8935  break;
8936 
8937  case SCIP_VARSTATUS_COLUMN:
8938  case SCIP_VARSTATUS_LOOSE:
8939  SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
8940  if( *added )
8941  {
8942  SCIP_Bool localadded;
8943 
8944  SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
8945  }
8946  break;
8947 
8948  case SCIP_VARSTATUS_FIXED:
8949  SCIPerrorMessage("cannot add hole of a fixed variable\n");
8950  return SCIP_INVALIDDATA;
8951 
8952  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8953  assert(var->data.aggregate.var != NULL);
8954 
8955  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8956  {
8957  /* a > 0 -> change lower bound of y */
8958  childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8959  childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8960  }
8961  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8962  {
8963  childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8964  childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8965  }
8966  else
8967  {
8968  SCIPerrorMessage("scalar is zero in aggregation\n");
8969  return SCIP_INVALIDDATA;
8970  }
8971  SCIP_CALL( SCIPvarAddHoleGlobal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
8972  childnewleft, childnewright, added) );
8973  break;
8974 
8976  SCIPerrorMessage("cannot add a hole of a multi-aggregated variable.\n");
8977  return SCIP_INVALIDDATA;
8978 
8979  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8980  assert(var->negatedvar != NULL);
8982  assert(var->negatedvar->negatedvar == var);
8983 
8984  childnewright = -left + var->data.negate.constant;
8985  childnewleft = -right + var->data.negate.constant;
8986 
8987  SCIP_CALL( SCIPvarAddHoleGlobal(var->negatedvar, blkmem, set, stat, eventqueue,
8988  childnewleft, childnewright, added) );
8989  break;
8990 
8991  default:
8992  SCIPerrorMessage("unknown variable status\n");
8993  return SCIP_INVALIDDATA;
8994  }
8995 
8996  return SCIP_OKAY;
8997 }
8998 
8999 /** performs the current add of domain, changes all parents accordingly */
9000 static
9002  SCIP_VAR* var, /**< problem variable */
9003  BMS_BLKMEM* blkmem, /**< block memory */
9004  SCIP_SET* set, /**< global SCIP settings */
9005  SCIP_STAT* stat, /**< problem statistics */
9006  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
9007  SCIP_Real left, /**< left bound of open interval in new hole */
9008  SCIP_Real right, /**< right bound of open interval in new hole */
9009  SCIP_Bool* added /**< pointer to store whether the hole was added, or NULL */
9010  )
9011 {
9012  SCIP_VAR* parentvar;
9013  SCIP_Real newlb;
9014  SCIP_Real newub;
9015  int i;
9016 
9017  assert(var != NULL);
9018  assert(added != NULL);
9019  assert(blkmem != NULL);
9020 
9021  /* the interval should not be empty */
9022  assert(SCIPsetIsLT(set, left, right));
9023 
9024  /* the the interval bound should already be adjusted */
9025  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
9026  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
9027 
9028  /* the the interval should lay between the lower and upper bound */
9029  assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
9030  assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
9031 
9032  /* add hole to hole list */
9033  SCIP_CALL( domAddHole(&var->locdom, blkmem, set, left, right, added) );
9034 
9035  /* check if the hole is redundant */
9036  if( !(*added) )
9037  return SCIP_OKAY;
9038 
9039  /* current bounds */
9040  newlb = var->locdom.lb;
9041  newub = var->locdom.ub;
9042 
9043  /* merge domain holes */
9044  domMerge(&var->locdom, blkmem, set, &newlb, &newub);
9045 
9046  /* the bound should not be changed */
9047  assert(SCIPsetIsEQ(set, newlb, var->locdom.lb));
9048  assert(SCIPsetIsEQ(set, newub, var->locdom.ub));
9049 
9050 #if 0
9051  /* issue bound change event */
9052  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
9053  if( var->eventfilter != NULL )
9054  {
9055  SCIP_CALL( varEventLholeAdded(var, blkmem, set, lp, branchcand, eventqueue, left, right) );
9056  }
9057 #endif
9058 
9059  /* process parent variables */
9060  for( i = 0; i < var->nparentvars; ++i )
9061  {
9062  SCIP_Real parentnewleft;
9063  SCIP_Real parentnewright;
9064  SCIP_Bool localadded;
9065 
9066  parentvar = var->parentvars[i];
9067  assert(parentvar != NULL);
9068 
9069  switch( SCIPvarGetStatus(parentvar) )
9070  {
9072  parentnewleft = left;
9073  parentnewright = right;
9074  break;
9075 
9076  case SCIP_VARSTATUS_COLUMN:
9077  case SCIP_VARSTATUS_LOOSE:
9078  case SCIP_VARSTATUS_FIXED:
9080  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
9081  return SCIP_INVALIDDATA;
9082 
9083  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
9084  assert(parentvar->data.aggregate.var == var);
9085 
9086  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
9087  {
9088  /* a > 0 -> change upper bound of x */
9089  parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
9090  parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
9091  }
9092  else
9093  {
9094  /* a < 0 -> change lower bound of x */
9095  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
9096 
9097  parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
9098  parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
9099  }
9100  break;
9101 
9102  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
9103  assert(parentvar->negatedvar != NULL);
9104  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
9105  assert(parentvar->negatedvar->negatedvar == parentvar);
9106 
9107  parentnewright = -left + parentvar->data.negate.constant;
9108  parentnewleft = -right + parentvar->data.negate.constant;
9109  break;
9110 
9111  default:
9112  SCIPerrorMessage("unknown variable status\n");
9113  return SCIP_INVALIDDATA;
9114  }
9115 
9116  SCIPsetDebugMsg(set, "add local hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
9117 
9118  /* perform hole added for parent variable */
9119  assert(blkmem != NULL);
9120  assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
9121  SCIP_CALL( varProcessAddHoleLocal(parentvar, blkmem, set, stat, eventqueue,
9122  parentnewleft, parentnewright, &localadded) );
9123  assert(localadded);
9124  }
9125 
9126  return SCIP_OKAY;
9127 }
9128 
9129 /** adds a hole to the variable's current local domain */
9131  SCIP_VAR* var, /**< problem variable */
9132  BMS_BLKMEM* blkmem, /**< block memory */
9133  SCIP_SET* set, /**< global SCIP settings */
9134  SCIP_STAT* stat, /**< problem statistics */
9135  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
9136  SCIP_Real left, /**< left bound of open interval in new hole */
9137  SCIP_Real right, /**< right bound of open interval in new hole */
9138  SCIP_Bool* added /**< pointer to store whether the hole was added */
9139  )
9140 {
9141  SCIP_Real childnewleft;
9142  SCIP_Real childnewright;
9143 
9144  assert(var != NULL);
9145 
9146  SCIPsetDebugMsg(set, "adding local hole (%g,%g) to <%s>\n", left, right, var->name);
9147 
9148  assert(set != NULL);
9149  assert(var->scip == set->scip);
9150  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
9151  assert(blkmem != NULL);
9152  assert(added != NULL);
9153 
9154  /* the interval should not be empty */
9155  assert(SCIPsetIsLT(set, left, right));
9156 
9157  /* the the interval bound should already be adjusted */
9158  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
9159  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
9160 
9161  /* the the interval should lay between the lower and upper bound */
9162  assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
9163  assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
9164 
9165  /* change bounds of attached variables */
9166  switch( SCIPvarGetStatus(var) )
9167  {
9169  if( var->data.original.transvar != NULL )
9170  {
9171  SCIP_CALL( SCIPvarAddHoleLocal(var->data.original.transvar, blkmem, set, stat, eventqueue,
9172  left, right, added) );
9173  }
9174  else
9175  {
9176  assert(set->stage == SCIP_STAGE_PROBLEM);
9177  SCIPstatIncrement(stat, set, domchgcount);
9178  SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
9179  }
9180  break;
9181 
9182  case SCIP_VARSTATUS_COLUMN:
9183  case SCIP_VARSTATUS_LOOSE:
9184  SCIPstatIncrement(stat, set, domchgcount);
9185  SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
9186  break;
9187 
9188  case SCIP_VARSTATUS_FIXED:
9189  SCIPerrorMessage("cannot add domain hole to a fixed variable\n");
9190  return SCIP_INVALIDDATA;
9191 
9192  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
9193  assert(var->data.aggregate.var != NULL);
9194 
9195  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
9196  {
9197  /* a > 0 -> change lower bound of y */
9198  childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
9199  childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
9200  }
9201  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
9202  {
9203  childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
9204  childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
9205  }
9206  else
9207  {
9208  SCIPerrorMessage("scalar is zero in aggregation\n");
9209  return SCIP_INVALIDDATA;
9210  }
9211  SCIP_CALL( SCIPvarAddHoleLocal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
9212  childnewleft, childnewright, added) );
9213  break;
9214 
9216  SCIPerrorMessage("cannot add domain hole to a multi-aggregated variable.\n");
9217  return SCIP_INVALIDDATA;
9218 
9219  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
9220  assert(var->negatedvar != NULL);
9222  assert(var->negatedvar->negatedvar == var);
9223 
9224  childnewright = -left + var->data.negate.constant;
9225  childnewleft = -right + var->data.negate.constant;
9226 
9227  SCIP_CALL( SCIPvarAddHoleLocal(var->negatedvar, blkmem, set, stat, eventqueue, childnewleft, childnewright, added) );
9228  break;
9229 
9230  default:
9231  SCIPerrorMessage("unknown variable status\n");
9232  return SCIP_INVALIDDATA;
9233  }
9234 
9235  return SCIP_OKAY;
9236 }
9237 
9238 /** resets the global and local bounds of original variable to their original values */
9240  SCIP_VAR* var, /**< problem variable */
9241  BMS_BLKMEM* blkmem, /**< block memory */
9242  SCIP_SET* set, /**< global SCIP settings */
9243  SCIP_STAT* stat /**< problem statistics */
9244  )
9245 {
9246  assert(var != NULL);
9247  assert(set != NULL);
9248  assert(var->scip == set->scip);
9249  assert(SCIPvarIsOriginal(var));
9250  /* resetting of bounds on original variables which have a transformed counterpart easily fails if, e.g.,
9251  * the transformed variable has been fixed */
9252  assert(SCIPvarGetTransVar(var) == NULL);
9253 
9254  /* copy the original bounds back to the global and local bounds */
9255  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.lb) );
9256  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.ub) );
9257  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.lb) );
9258  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.ub) );
9259 
9260  /* free the global and local holelists and duplicate the original ones */
9261  /**@todo this has also to be called recursively with methods similar to SCIPvarChgLbGlobal() */
9262  holelistFree(&var->glbdom.holelist, blkmem);
9263  holelistFree(&var->locdom.holelist, blkmem);
9264  SCIP_CALL( holelistDuplicate(&var->glbdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
9265  SCIP_CALL( holelistDuplicate(&var->locdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
9266 
9267  return SCIP_OKAY;
9268 }
9269 
9270 /** issues a IMPLADDED event on the given variable */
9271 static
9273  SCIP_VAR* var, /**< problem variable to change */
9274  BMS_BLKMEM* blkmem, /**< block memory */
9275  SCIP_SET* set, /**< global SCIP settings */
9276  SCIP_EVENTQUEUE* eventqueue /**< event queue */
9277  )
9278 {
9279  SCIP_EVENT* event;
9280 
9281  assert(var != NULL);
9282 
9283  /* issue IMPLADDED event on variable */
9284  SCIP_CALL( SCIPeventCreateImplAdded(&event, blkmem, var) );
9285  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
9286 
9287  return SCIP_OKAY;
9288 }
9289 
9290 /** actually performs the addition of a variable bound to the variable's vbound arrays */
9291 static
9293  SCIP_VAR* var, /**< problem variable x in x <= b*z + d or x >= b*z + d */
9294  BMS_BLKMEM* blkmem, /**< block memory */
9295  SCIP_SET* set, /**< global SCIP settings */
9296  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9297  SCIP_BOUNDTYPE vbtype, /**< type of variable bound (LOWER or UPPER) */
9298  SCIP_VAR* vbvar, /**< variable z in x <= b*z + d or x >= b*z + d */
9299  SCIP_Real vbcoef, /**< coefficient b in x <= b*z + d or x >= b*z + d */
9300  SCIP_Real vbconstant /**< constant d in x <= b*z + d or x >= b*z + d */
9301  )
9302 {
9303  SCIP_Bool added;
9304 
9305  /* It can happen that the variable "var" and the variable "vbvar" are the same variable. For example if a variable
9306  * gets aggregated, the variable bounds (vbound) of that variable are copied to the other variable. A variable bound
9307  * variable of the aggregated variable might be the same as the one its gets aggregated too.
9308  *
9309  * If the variable "var" and the variable "vbvar" are the same, the variable bound which should be added here has to
9310  * be redundant. This is the case since an infeasibility should have be detected in the previous methods. As well as
9311  * the bounds of the variable which should be also already be tightened in the previous methods. Therefore, the
9312  * variable bound can be ignored.
9313  *
9314  * From the way the the variable bound system is implemented (detecting infeasibility, tighten bounds), the
9315  * equivalence of the variables should be checked here.
9316  */
9317  if( var == vbvar )
9318  {
9319  /* in this case the variable bound has to be redundant, this means for possible assignments to this variable; this
9320  * can be checked via the global bounds of the variable */
9321 #ifndef NDEBUG
9322  SCIP_Real lb;
9323  SCIP_Real ub;
9324 
9325  lb = SCIPvarGetLbGlobal(var);
9326  ub = SCIPvarGetUbGlobal(var);
9327 
9328  if(vbtype == SCIP_BOUNDTYPE_LOWER)
9329  {
9330  if( vbcoef > 0.0 )
9331  {
9332  assert(SCIPsetIsGE(set, lb, lb * vbcoef + vbconstant) );
9333  assert(SCIPsetIsGE(set, ub, ub * vbcoef + vbconstant) );
9334  }
9335  else
9336  {
9337  assert(SCIPsetIsGE(set, lb, ub * vbcoef + vbconstant) );
9338  assert(SCIPsetIsGE(set, ub, lb * vbcoef + vbconstant) );
9339  }
9340  }
9341  else
9342  {
9343  assert(vbtype == SCIP_BOUNDTYPE_UPPER);
9344  if( vbcoef > 0.0 )
9345  {
9346  assert(SCIPsetIsLE(set, lb, lb * vbcoef + vbconstant) );
9347  assert(SCIPsetIsLE(set, ub, ub * vbcoef + vbconstant) );
9348  }
9349  else
9350  {
9351  assert(SCIPsetIsLE(set, lb, ub * vbcoef + vbconstant) );
9352  assert(SCIPsetIsLE(set, ub, lb * vbcoef + vbconstant) );
9353  }
9354  }
9355 #endif
9356  SCIPsetDebugMsg(set, "redundant variable bound: <%s> %s %g<%s> %+g\n",
9357  SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
9358 
9359  return SCIP_OKAY;
9360  }
9361 
9362  SCIPsetDebugMsg(set, "adding variable bound: <%s> %s %g<%s> %+g\n",
9363  SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
9364 
9365  /* check variable bound on debugging solution */
9366  SCIP_CALL( SCIPdebugCheckVbound(set, var, vbtype, vbvar, vbcoef, vbconstant) ); /*lint !e506 !e774*/
9367 
9368  /* perform the addition */
9369  if( vbtype == SCIP_BOUNDTYPE_LOWER )
9370  {
9371  SCIP_CALL( SCIPvboundsAdd(&var->vlbs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
9372  }
9373  else
9374  {
9375  SCIP_CALL( SCIPvboundsAdd(&var->vubs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
9376  }
9377  var->closestvblpcount = -1;
9378 
9379  if( added )
9380  {
9381  /* issue IMPLADDED event */
9382  SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
9383  }
9384 
9385  return SCIP_OKAY;
9386 }
9387 
9388 /** checks whether the given implication is redundant or infeasible w.r.t. the implied variables global bounds */
9389 static
9390 void checkImplic(
9391  SCIP_SET* set, /**< global SCIP settings */
9392  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9393  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9394  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9395  SCIP_Bool* redundant, /**< pointer to store whether the implication is redundant */
9396  SCIP_Bool* infeasible /**< pointer to store whether the implication is infeasible */
9397  )
9398 {
9399  SCIP_Real impllb;
9400  SCIP_Real implub;
9401 
9402  assert(redundant != NULL);
9403  assert(infeasible != NULL);
9404 
9405  impllb = SCIPvarGetLbGlobal(implvar);
9406  implub = SCIPvarGetUbGlobal(implvar);
9407  if( impltype == SCIP_BOUNDTYPE_LOWER )
9408  {
9409  *infeasible = SCIPsetIsFeasGT(set, implbound, implub);
9410  *redundant = SCIPsetIsFeasLE(set, implbound, impllb);
9411  }
9412  else
9413  {
9414  *infeasible = SCIPsetIsFeasLT(set, implbound, impllb);
9415  *redundant = SCIPsetIsFeasGE(set, implbound, implub);
9416  }
9417 }
9418 
9419 /** applies the given implication, if it is not redundant */
9420 static
9422  BMS_BLKMEM* blkmem, /**< block memory */
9423  SCIP_SET* set, /**< global SCIP settings */
9424  SCIP_STAT* stat, /**< problem statistics */
9425  SCIP_PROB* transprob, /**< transformed problem */
9426  SCIP_PROB* origprob, /**< original problem */
9427  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9428  SCIP_REOPT* reopt, /**< reoptimization data structure */
9429  SCIP_LP* lp, /**< current LP data */
9430  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9431  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9432  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9433  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9434  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9435  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9436  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9437  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9438  )
9439 {
9440  SCIP_Real implub;
9441  SCIP_Real impllb;
9442 
9443  assert(infeasible != NULL);
9444 
9445  *infeasible = FALSE;
9446 
9447  implub = SCIPvarGetUbGlobal(implvar);
9448  impllb = SCIPvarGetLbGlobal(implvar);
9449  if( impltype == SCIP_BOUNDTYPE_LOWER )
9450  {
9451  if( SCIPsetIsFeasGT(set, implbound, implub) )
9452  {
9453  /* the implication produces a conflict: the problem is infeasible */
9454  *infeasible = TRUE;
9455  }
9456  else if( SCIPsetIsFeasGT(set, implbound, impllb) )
9457  {
9458  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9459  * with the local bound, in this case we need to store the bound change as pending bound change
9460  */
9461  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9462  {
9463  assert(tree != NULL);
9464  assert(transprob != NULL);
9465  assert(SCIPprobIsTransformed(transprob));
9466 
9467  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9468  tree, reopt, lp, branchcand, eventqueue, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
9469  }
9470  else
9471  {
9472  SCIP_CALL( SCIPvarChgLbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
9473  }
9474 
9475  if( nbdchgs != NULL )
9476  (*nbdchgs)++;
9477  }
9478  }
9479  else
9480  {
9481  if( SCIPsetIsFeasLT(set, implbound, impllb) )
9482  {
9483  /* the implication produces a conflict: the problem is infeasible */
9484  *infeasible = TRUE;
9485  }
9486  else if( SCIPsetIsFeasLT(set, implbound, implub) )
9487  {
9488  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9489  * with the local bound, in this case we need to store the bound change as pending bound change
9490  */
9491  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9492  {
9493  assert(tree != NULL);
9494  assert(transprob != NULL);
9495  assert(SCIPprobIsTransformed(transprob));
9496 
9497  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9498  tree, reopt, lp, branchcand, eventqueue, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
9499  }
9500  else
9501  {
9502  SCIP_CALL( SCIPvarChgUbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
9503  }
9504 
9505  if( nbdchgs != NULL )
9506  (*nbdchgs)++;
9507  }
9508  }
9509 
9510  return SCIP_OKAY;
9511 }
9512 
9513 /** actually performs the addition of an implication to the variable's implication arrays,
9514  * and adds the corresponding implication or variable bound to the implied variable;
9515  * if the implication is conflicting, the variable is fixed to the opposite value;
9516  * if the variable is already fixed to the given value, the implication is performed immediately;
9517  * if the implication is redundant with respect to the variables' global bounds, it is ignored
9518  */
9519 static
9521  SCIP_VAR* var, /**< problem variable */
9522  BMS_BLKMEM* blkmem, /**< block memory */
9523  SCIP_SET* set, /**< global SCIP settings */
9524  SCIP_STAT* stat, /**< problem statistics */
9525  SCIP_PROB* transprob, /**< transformed problem */
9526  SCIP_PROB* origprob, /**< original problem */
9527  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9528  SCIP_REOPT* reopt, /**< reoptimization data structure */
9529  SCIP_LP* lp, /**< current LP data */
9530  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9531  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9532  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9533  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9534  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9535  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9536  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9537  SCIP_Bool isshortcut, /**< is the implication a shortcut, i.e., added as part of the transitive closure of another implication? */
9538  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9539  int* nbdchgs, /**< pointer to count the number of performed bound changes, or NULL */
9540  SCIP_Bool* added /**< pointer to store whether an implication was added */
9541  )
9542 {
9543  SCIP_Bool redundant;
9544  SCIP_Bool conflict;
9545 
9546  assert(var != NULL);
9547  assert(SCIPvarIsActive(var));
9549  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
9550  assert(SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED);
9551  assert(infeasible != NULL);
9552  assert(added != NULL);
9553 
9554  /* check implication on debugging solution */
9555  SCIP_CALL( SCIPdebugCheckImplic(set, var, varfixing, implvar, impltype, implbound) ); /*lint !e506 !e774*/
9556 
9557  *infeasible = FALSE;
9558  *added = FALSE;
9559 
9560  /* check, if the implication is redundant or infeasible */
9561  checkImplic(set, implvar, impltype, implbound, &redundant, &conflict);
9562  assert(!redundant || !conflict);
9563  if( redundant )
9564  return SCIP_OKAY;
9565 
9566  if( var == implvar )
9567  {
9568  /* special cases appear were a bound to a variable implies itself to be outside the bounds:
9569  * x == varfixing => x < 0 or x > 1
9570  */
9571  if( SCIPsetIsLT(set, implbound, 0.0) || SCIPsetIsGT(set, implbound, 1.0) )
9572  conflict = TRUE;
9573  else
9574  {
9575  /* variable implies itself: x == varfixing => x == (impltype == SCIP_BOUNDTYPE_LOWER) */
9576  assert(SCIPsetIsZero(set, implbound) || SCIPsetIsEQ(set, implbound, 1.0));
9577  assert(SCIPsetIsZero(set, implbound) == (impltype == SCIP_BOUNDTYPE_UPPER));
9578  assert(SCIPsetIsEQ(set, implbound, 1.0) == (impltype == SCIP_BOUNDTYPE_LOWER));
9579  conflict = conflict || ((varfixing == TRUE) == (impltype == SCIP_BOUNDTYPE_UPPER));
9580  if( !conflict )
9581  return SCIP_OKAY;
9582  }
9583  }
9584 
9585  /* check, if the variable is already fixed */
9586  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
9587  {
9588  /* if the variable is fixed to the given value, perform the implication; otherwise, ignore the implication */
9589  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
9590  {
9591  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
9592  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
9593  }
9594  return SCIP_OKAY;
9595  }
9596 
9597  assert((impltype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, implbound, SCIPvarGetLbGlobal(implvar)))
9598  || (impltype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, implbound, SCIPvarGetUbGlobal(implvar))));
9599 
9600  if( !conflict )
9601  {
9602  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9603 
9604  if( SCIPvarIsBinary(implvar) )
9605  {
9606  SCIP_VAR* vars[2];
9607  SCIP_Bool vals[2];
9608 
9609  assert(SCIPsetIsFeasEQ(set, implbound, 1.0) || SCIPsetIsFeasZero(set, implbound));
9610  assert((impltype == SCIP_BOUNDTYPE_UPPER) == SCIPsetIsFeasZero(set, implbound));
9611 
9612  vars[0] = var;
9613  vars[1] = implvar;
9614  vals[0] = varfixing;
9615  vals[1] = (impltype == SCIP_BOUNDTYPE_UPPER);
9616 
9617  /* add the clique to the clique table */
9618  SCIP_CALL( SCIPcliquetableAdd(cliquetable, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
9619  eventqueue, vars, vals, 2, FALSE, &conflict, nbdchgs) );
9620 
9621  if( !conflict )
9622  return SCIP_OKAY;
9623  }
9624  else
9625  {
9626  /* add implication x == 0/1 -> y <= b / y >= b to the implications list of x */
9627  SCIPsetDebugMsg(set, "adding implication: <%s> == %u ==> <%s> %s %g\n",
9628  SCIPvarGetName(var), varfixing,
9629  SCIPvarGetName(implvar), impltype == SCIP_BOUNDTYPE_UPPER ? "<=" : ">=", implbound);
9630  SCIP_CALL( SCIPimplicsAdd(&var->implics, blkmem, set, stat, varfixing, implvar, impltype, implbound,
9631  isshortcut, &conflict, added) );
9632  }
9633  }
9634  assert(!conflict || !(*added));
9635 
9636  /* on conflict, fix the variable to the opposite value */
9637  if( conflict )
9638  {
9639  SCIPsetDebugMsg(set, " -> implication yields a conflict: fix <%s> == %d\n", SCIPvarGetName(var), !varfixing);
9640 
9641  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9642  * with the local bound, in this case we need to store the bound change as pending bound change
9643  */
9644  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9645  {
9646  assert(tree != NULL);
9647  assert(transprob != NULL);
9648  assert(SCIPprobIsTransformed(transprob));
9649 
9650  if( varfixing )
9651  {
9652  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9653  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
9654  }
9655  else
9656  {
9657  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9658  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
9659  }
9660  }
9661  else
9662  {
9663  if( varfixing )
9664  {
9665  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
9666  }
9667  else
9668  {
9669  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
9670  }
9671  }
9672  if( nbdchgs != NULL )
9673  (*nbdchgs)++;
9674 
9675  return SCIP_OKAY;
9676  }
9677  else if( *added )
9678  {
9679  /* issue IMPLADDED event */
9680  SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
9681  }
9682  else
9683  {
9684  /* the implication was redundant: the inverse is also redundant */
9685  return SCIP_OKAY;
9686  }
9687 
9688  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9689 
9690  /* check, whether implied variable is binary */
9691  if( !SCIPvarIsBinary(implvar) )
9692  {
9693  SCIP_Real lb;
9694  SCIP_Real ub;
9695 
9696  /* add inverse variable bound to the variable bounds of y with global bounds y \in [lb,ub]:
9697  * x == 0 -> y <= b <-> y <= (ub - b)*x + b
9698  * x == 1 -> y <= b <-> y <= (b - ub)*x + ub
9699  * x == 0 -> y >= b <-> y >= (lb - b)*x + b
9700  * x == 1 -> y >= b <-> y >= (b - lb)*x + lb
9701  * for numerical reasons, ignore variable bounds with large absolute coefficient
9702  */
9703  lb = SCIPvarGetLbGlobal(implvar);
9704  ub = SCIPvarGetUbGlobal(implvar);
9705  if( impltype == SCIP_BOUNDTYPE_UPPER )
9706  {
9707  if( REALABS(implbound - ub) <= MAXABSVBCOEF )
9708  {
9709  SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, var,
9710  varfixing ? implbound - ub : ub - implbound, varfixing ? ub : implbound) );
9711  }
9712  }
9713  else
9714  {
9715  if( REALABS(implbound - lb) <= MAXABSVBCOEF )
9716  {
9717  SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, var,
9718  varfixing ? implbound - lb : lb - implbound, varfixing ? lb : implbound) );
9719  }
9720  }
9721  }
9722 
9723  return SCIP_OKAY;
9724 }
9725 
9726 /** adds transitive closure for binary implication x = a -> y = b */
9727 static
9729  SCIP_VAR* var, /**< problem variable */
9730  BMS_BLKMEM* blkmem, /**< block memory */
9731  SCIP_SET* set, /**< global SCIP settings */
9732  SCIP_STAT* stat, /**< problem statistics */
9733  SCIP_PROB* transprob, /**< transformed problem */
9734  SCIP_PROB* origprob, /**< original problem */
9735  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9736  SCIP_REOPT* reopt, /**< reoptimization data structure */
9737  SCIP_LP* lp, /**< current LP data */
9738  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9739  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9740  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9741  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9742  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9743  SCIP_Bool implvarfixing, /**< fixing b in implication */
9744  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9745  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9746  )
9747 {
9748  SCIP_VAR** implvars;
9749  SCIP_BOUNDTYPE* impltypes;
9750  SCIP_Real* implbounds;
9751  int nimpls;
9752  int i;
9753 
9754  *infeasible = FALSE;
9755 
9756  /* binary variable: implications of implvar */
9757  nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
9758  implvars = SCIPimplicsGetVars(implvar->implics, implvarfixing);
9759  impltypes = SCIPimplicsGetTypes(implvar->implics, implvarfixing);
9760  implbounds = SCIPimplicsGetBounds(implvar->implics, implvarfixing);
9761 
9762  /* if variable has too many implications, the implication graph may become too dense */
9763  i = MIN(nimpls, MAXIMPLSCLOSURE) - 1;
9764 
9765  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9766  * implvars[i] is fixed, s.t. the implication y == varfixing -> z <= b / z >= b is deleted; this affects the
9767  * array over which we currently iterate; the only thing that can happen, is that elements of the array are
9768  * deleted; in this case, the subsequent elements are moved to the front; if we iterate from back to front, the
9769  * only thing that can happen is that we add the same implication twice - this does no harm
9770  */
9771  while ( i >= 0 && !(*infeasible) )
9772  {
9773  SCIP_Bool added;
9774 
9775  assert(implvars[i] != implvar);
9776 
9777  /* we have x == varfixing -> y == implvarfixing -> z <= b / z >= b:
9778  * add implication x == varfixing -> z <= b / z >= b to the implications list of x
9779  */
9780  if( SCIPvarIsActive(implvars[i]) )
9781  {
9782  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
9783  eventqueue, varfixing, implvars[i], impltypes[i], implbounds[i], TRUE, infeasible, nbdchgs, &added) );
9784  assert(SCIPimplicsGetNImpls(implvar->implics, implvarfixing) <= nimpls);
9785  nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
9786  i = MIN(i, nimpls); /* some elements from the array could have been removed */
9787  }
9788  --i;
9789  }
9790 
9791  return SCIP_OKAY;
9792 }
9793 
9794 /** adds given implication to the variable's implication list, and adds all implications directly implied by this
9795  * implication to the variable's implication list;
9796  * if the implication is conflicting, the variable is fixed to the opposite value;
9797  * if the variable is already fixed to the given value, the implication is performed immediately;
9798  * if the implication is redundant with respect to the variables' global bounds, it is ignored
9799  */
9800 static
9802  SCIP_VAR* var, /**< problem variable */
9803  BMS_BLKMEM* blkmem, /**< block memory */
9804  SCIP_SET* set, /**< global SCIP settings */
9805  SCIP_STAT* stat, /**< problem statistics */
9806  SCIP_PROB* transprob, /**< transformed problem */
9807  SCIP_PROB* origprob, /**< original problem */
9808  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9809  SCIP_REOPT* reopt, /**< reoptimization data structure */
9810  SCIP_LP* lp, /**< current LP data */
9811  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9812  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9813  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9814  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9815  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9816  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9817  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9818  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
9819  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9820  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9821  )
9822 {
9823  SCIP_Bool added;
9824 
9825  assert(var != NULL);
9826  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
9827  assert(SCIPvarIsActive(var));
9828  assert(implvar != NULL);
9829  assert(SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED);
9830  assert(infeasible != NULL);
9831 
9832  /* add implication x == varfixing -> y <= b / y >= b to the implications list of x */
9833  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
9834  eventqueue, varfixing, implvar, impltype, implbound, FALSE, infeasible, nbdchgs, &added) );
9835 
9836  if( *infeasible || var == implvar || !transitive || !added )
9837  return SCIP_OKAY;
9838 
9839  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9840 
9841  /* add transitive closure */
9842  if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
9843  {
9844  SCIP_Bool implvarfixing;
9845 
9846  implvarfixing = (impltype == SCIP_BOUNDTYPE_LOWER);
9847 
9848  /* binary variable: implications of implvar */
9849  SCIP_CALL( varAddTransitiveBinaryClosureImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9850  cliquetable, branchcand, eventqueue, varfixing, implvar, implvarfixing, infeasible, nbdchgs) );
9851 
9852  /* inverse implication */
9853  if( !(*infeasible) )
9854  {
9855  SCIP_CALL( varAddTransitiveBinaryClosureImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9856  cliquetable, branchcand, eventqueue, !implvarfixing, var, !varfixing, infeasible, nbdchgs) );
9857  }
9858  }
9859  else
9860  {
9861  /* non-binary variable: variable lower bounds of implvar */
9862  if( impltype == SCIP_BOUNDTYPE_UPPER && implvar->vlbs != NULL )
9863  {
9864  SCIP_VAR** vlbvars;
9865  SCIP_Real* vlbcoefs;
9866  SCIP_Real* vlbconstants;
9867  int nvlbvars;
9868  int i;
9869 
9870  nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
9871  vlbvars = SCIPvboundsGetVars(implvar->vlbs);
9872  vlbcoefs = SCIPvboundsGetCoefs(implvar->vlbs);
9873  vlbconstants = SCIPvboundsGetConstants(implvar->vlbs);
9874 
9875  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9876  * vlbvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
9877  * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
9878  * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
9879  * is that we add the same implication twice - this does no harm
9880  */
9881  i = nvlbvars-1;
9882  while ( i >= 0 && !(*infeasible) )
9883  {
9884  assert(vlbvars[i] != implvar);
9885  assert(!SCIPsetIsZero(set, vlbcoefs[i]));
9886 
9887  /* we have x == varfixing -> y <= b and y >= c*z + d:
9888  * c > 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
9889  * c < 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
9890  *
9891  * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
9892  * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
9893  * aggregation variable (the one which will stay active);
9894  *
9895  * W.l.o.g. we consider the variable upper bounds for now. Let "vubvar" be a variable upper bound of
9896  * the aggregated variable "aggvar"; During that copying of that variable upper bound variable
9897  * "vubvar" the variable lower and upper bounds of this variable "vubvar" are also considered; note
9898  * that the "aggvar" can be a variable lower bound variable of the variable "vubvar"; Due to that
9899  * situation it can happen that we reach that code place where "vlbvars[i] == aggvar". In particular
9900  * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
9901  * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
9902  * have to explicitly check that the active variable has not a variable status
9903  * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
9904  */
9905  if( SCIPvarIsActive(vlbvars[i]) && SCIPvarGetStatus(vlbvars[i]) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(vlbvars[i]) != SCIP_VARSTATUS_NEGATED )
9906  {
9907  SCIP_Real vbimplbound;
9908 
9909  vbimplbound = (implbound - vlbconstants[i])/vlbcoefs[i];
9910  if( vlbcoefs[i] >= 0.0 )
9911  {
9912  vbimplbound = adjustedUb(set, SCIPvarGetType(vlbvars[i]), vbimplbound);
9913  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9914  branchcand, eventqueue, varfixing, vlbvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
9915  infeasible, nbdchgs, &added) );
9916  }
9917  else
9918  {
9919  vbimplbound = adjustedLb(set, SCIPvarGetType(vlbvars[i]), vbimplbound);
9920  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9921  branchcand, eventqueue, varfixing, vlbvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
9922  infeasible, nbdchgs, &added) );
9923  }
9924  nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
9925  i = MIN(i, nvlbvars); /* some elements from the array could have been removed */
9926  }
9927  --i;
9928  }
9929  }
9930 
9931  /* non-binary variable: variable upper bounds of implvar */
9932  if( impltype == SCIP_BOUNDTYPE_LOWER && implvar->vubs != NULL )
9933  {
9934  SCIP_VAR** vubvars;
9935  SCIP_Real* vubcoefs;
9936  SCIP_Real* vubconstants;
9937  int nvubvars;
9938  int i;
9939 
9940  nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
9941  vubvars = SCIPvboundsGetVars(implvar->vubs);
9942  vubcoefs = SCIPvboundsGetCoefs(implvar->vubs);
9943  vubconstants = SCIPvboundsGetConstants(implvar->vubs);
9944 
9945  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9946  * vubvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
9947  * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
9948  * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
9949  * is that we add the same implication twice - this does no harm
9950  */
9951  i = nvubvars-1;
9952  while ( i >= 0 && !(*infeasible) )
9953  {
9954  assert(vubvars[i] != implvar);
9955  assert(!SCIPsetIsZero(set, vubcoefs[i]));
9956 
9957  /* we have x == varfixing -> y >= b and y <= c*z + d:
9958  * c > 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
9959  * c < 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
9960  *
9961  * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
9962  * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
9963  * aggregation variable (the one which will stay active);
9964  *
9965  * W.l.o.g. we consider the variable lower bounds for now. Let "vlbvar" be a variable lower bound of
9966  * the aggregated variable "aggvar"; During that copying of that variable lower bound variable
9967  * "vlbvar" the variable lower and upper bounds of this variable "vlbvar" are also considered; note
9968  * that the "aggvar" can be a variable upper bound variable of the variable "vlbvar"; Due to that
9969  * situation it can happen that we reach that code place where "vubvars[i] == aggvar". In particular
9970  * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
9971  * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
9972  * have to explicitly check that the active variable has not a variable status
9973  * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
9974  */
9975  if( SCIPvarIsActive(vubvars[i]) && SCIPvarGetStatus(vubvars[i]) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(vubvars[i]) != SCIP_VARSTATUS_NEGATED )
9976  {
9977  SCIP_Real vbimplbound;
9978 
9979  vbimplbound = (implbound - vubconstants[i])/vubcoefs[i];
9980  if( vubcoefs[i] >= 0.0 )
9981  {
9982  vbimplbound = adjustedLb(set, SCIPvarGetType(vubvars[i]), vbimplbound);
9983  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9984  branchcand, eventqueue, varfixing, vubvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
9985  infeasible, nbdchgs, &added) );
9986  }
9987  else
9988  {
9989  vbimplbound = adjustedUb(set, SCIPvarGetType(vubvars[i]), vbimplbound);
9990  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9991  branchcand, eventqueue, varfixing, vubvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
9992  infeasible, nbdchgs, &added) );
9993  }
9994  nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
9995  i = MIN(i, nvubvars); /* some elements from the array could have been removed */
9996  }
9997  --i;
9998  }
9999  }
10000  }
10001 
10002  return SCIP_OKAY;
10003 }
10004 
10005 /** informs variable x about a globally valid variable lower bound x >= b*z + d with integer variable z;
10006  * if z is binary, the corresponding valid implication for z is also added;
10007  * improves the global bounds of the variable and the vlb variable if possible
10008  */
10010  SCIP_VAR* var, /**< problem variable */
10011  BMS_BLKMEM* blkmem, /**< block memory */
10012  SCIP_SET* set, /**< global SCIP settings */
10013  SCIP_STAT* stat, /**< problem statistics */
10014  SCIP_PROB* transprob, /**< transformed problem */
10015  SCIP_PROB* origprob, /**< original problem */
10016  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10017  SCIP_REOPT* reopt, /**< reoptimization data structure */
10018  SCIP_LP* lp, /**< current LP data */
10019  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10020  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10021  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10022  SCIP_VAR* vlbvar, /**< variable z in x >= b*z + d */
10023  SCIP_Real vlbcoef, /**< coefficient b in x >= b*z + d */
10024  SCIP_Real vlbconstant, /**< constant d in x >= b*z + d */
10025  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
10026  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10027  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
10028  )
10029 {
10030  assert(var != NULL);
10031  assert(set != NULL);
10032  assert(var->scip == set->scip);
10033  assert(SCIPvarGetType(vlbvar) != SCIP_VARTYPE_CONTINUOUS);
10034  assert(infeasible != NULL);
10035 
10036  SCIPsetDebugMsg(set, "adding variable lower bound <%s> >= %g<%s> + %g\n", SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
10037 
10038  *infeasible = FALSE;
10039  if( nbdchgs != NULL )
10040  *nbdchgs = 0;
10041 
10042  switch( SCIPvarGetStatus(var) )
10043  {
10045  assert(var->data.original.transvar != NULL);
10046  SCIP_CALL( SCIPvarAddVlb(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10047  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef, vlbconstant, transitive, infeasible, nbdchgs) );
10048  break;
10049 
10050  case SCIP_VARSTATUS_COLUMN:
10051  case SCIP_VARSTATUS_LOOSE:
10052  case SCIP_VARSTATUS_FIXED:
10053  /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
10054  SCIP_CALL( SCIPvarGetProbvarSum(&vlbvar, set, &vlbcoef, &vlbconstant) );
10055  SCIPsetDebugMsg(set, " -> transformed to variable lower bound <%s> >= %g<%s> + %g\n", SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
10056 
10057  /* if the vlb coefficient is zero, just update the lower bound of the variable */
10058  if( SCIPsetIsZero(set, vlbcoef) )
10059  {
10060  if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetUbGlobal(var)) )
10061  *infeasible = TRUE;
10062  else if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetLbGlobal(var)) )
10063  {
10064  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10065  * with the local bound, in this case we need to store the bound change as pending bound change
10066  */
10067  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10068  {
10069  assert(tree != NULL);
10070  assert(transprob != NULL);
10071  assert(SCIPprobIsTransformed(transprob));
10072 
10073  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10074  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vlbconstant, SCIP_BOUNDTYPE_LOWER, FALSE) );
10075  }
10076  else
10077  {
10078  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vlbconstant) );
10079  }
10080 
10081  if( nbdchgs != NULL )
10082  (*nbdchgs)++;
10083  }
10084  }
10085  else if( var == vlbvar )
10086  {
10087  /* the variables cancels out, the variable bound constraint is either redundant or proves global infeasibility */
10088  if( SCIPsetIsEQ(set, vlbcoef, 1.0) )
10089  {
10090  if( SCIPsetIsPositive(set, vlbconstant) )
10091  *infeasible = TRUE;
10092  return SCIP_OKAY;
10093  }
10094  else
10095  {
10096  SCIP_Real lb = SCIPvarGetLbGlobal(var);
10097  SCIP_Real ub = SCIPvarGetUbGlobal(var);
10098 
10099  /* the variable bound constraint defines a new upper bound */
10100  if( SCIPsetIsGT(set, vlbcoef, 1.0) )
10101  {
10102  SCIP_Real newub = vlbconstant / (1.0 - vlbcoef);
10103 
10104  if( SCIPsetIsFeasLT(set, newub, lb) )
10105  {
10106  *infeasible = TRUE;
10107  return SCIP_OKAY;
10108  }
10109  else if( SCIPsetIsFeasLT(set, newub, ub) )
10110  {
10111  /* bound might be adjusted due to integrality condition */
10112  newub = adjustedUb(set, SCIPvarGetType(var), newub);
10113 
10114  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10115  * with the local bound, in this case we need to store the bound change as pending bound change
10116  */
10117  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10118  {
10119  assert(tree != NULL);
10120  assert(transprob != NULL);
10121  assert(SCIPprobIsTransformed(transprob));
10122 
10123  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10124  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10125  }
10126  else
10127  {
10128  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newub) );
10129  }
10130 
10131  if( nbdchgs != NULL )
10132  (*nbdchgs)++;
10133  }
10134  }
10135  /* the variable bound constraint defines a new lower bound */
10136  else
10137  {
10138  SCIP_Real newlb;
10139 
10140  assert(SCIPsetIsLT(set, vlbcoef, 1.0));
10141 
10142  newlb = vlbconstant / (1.0 - vlbcoef);
10143 
10144  if( SCIPsetIsFeasGT(set, newlb, ub) )
10145  {
10146  *infeasible = TRUE;
10147  return SCIP_OKAY;
10148  }
10149  else if( SCIPsetIsFeasGT(set, newlb, lb) )
10150  {
10151  /* bound might be adjusted due to integrality condition */
10152  newlb = adjustedLb(set, SCIPvarGetType(var), newlb);
10153 
10154  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10155  * with the local bound, in this case we need to store the bound change as pending bound change
10156  */
10157  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10158  {
10159  assert(tree != NULL);
10160  assert(transprob != NULL);
10161  assert(SCIPprobIsTransformed(transprob));
10162 
10163  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10164  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10165  }
10166  else
10167  {
10168  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newlb) );
10169  }
10170 
10171  if( nbdchgs != NULL )
10172  (*nbdchgs)++;
10173  }
10174  }
10175  }
10176  }
10177  else if( SCIPvarIsActive(vlbvar) )
10178  {
10179  SCIP_Real xlb;
10180  SCIP_Real xub;
10181  SCIP_Real zlb;
10182  SCIP_Real zub;
10183  SCIP_Real minvlb;
10184  SCIP_Real maxvlb;
10185 
10187  assert(vlbcoef != 0.0);
10188 
10189  minvlb = -SCIPsetInfinity(set);
10190  maxvlb = SCIPsetInfinity(set);
10191 
10192  xlb = SCIPvarGetLbGlobal(var);
10193  xub = SCIPvarGetUbGlobal(var);
10194  zlb = SCIPvarGetLbGlobal(vlbvar);
10195  zub = SCIPvarGetUbGlobal(vlbvar);
10196 
10197  /* improve global bounds of vlb variable, and calculate minimal and maximal value of variable bound */
10198  if( vlbcoef >= 0.0 )
10199  {
10200  SCIP_Real newzub;
10201 
10202  if( !SCIPsetIsInfinity(set, xub) )
10203  {
10204  /* x >= b*z + d -> z <= (x-d)/b */
10205  newzub = (xub - vlbconstant)/vlbcoef;
10206 
10207  /* return if the new bound is less than -infinity */
10208  if( SCIPsetIsInfinity(set, REALABS(newzub)) )
10209  return SCIP_OKAY;
10210 
10211  if( SCIPsetIsFeasLT(set, newzub, zlb) )
10212  {
10213  *infeasible = TRUE;
10214  return SCIP_OKAY;
10215  }
10216  if( SCIPsetIsFeasLT(set, newzub, zub) )
10217  {
10218  /* bound might be adjusted due to integrality condition */
10219  newzub = adjustedUb(set, SCIPvarGetType(vlbvar), newzub);
10220 
10221  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10222  * with the local bound, in this case we need to store the bound change as pending bound change
10223  */
10224  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10225  {
10226  assert(tree != NULL);
10227  assert(transprob != NULL);
10228  assert(SCIPprobIsTransformed(transprob));
10229 
10230  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10231  tree, reopt, lp, branchcand, eventqueue, cliquetable, vlbvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10232  }
10233  else
10234  {
10235  SCIP_CALL( SCIPvarChgUbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
10236  }
10237  zub = newzub;
10238 
10239  if( nbdchgs != NULL )
10240  (*nbdchgs)++;
10241  }
10242  maxvlb = vlbcoef * zub + vlbconstant;
10243  if( !SCIPsetIsInfinity(set, -zlb) )
10244  minvlb = vlbcoef * zlb + vlbconstant;
10245  }
10246  else
10247  {
10248  if( !SCIPsetIsInfinity(set, zub) )
10249  maxvlb = vlbcoef * zub + vlbconstant;
10250  if( !SCIPsetIsInfinity(set, -zlb) )
10251  minvlb = vlbcoef * zlb + vlbconstant;
10252  }
10253  }
10254  else
10255  {
10256  SCIP_Real newzlb;
10257 
10258  if( !SCIPsetIsInfinity(set, xub) )
10259  {
10260  /* x >= b*z + d -> z >= (x-d)/b */
10261  newzlb = (xub - vlbconstant)/vlbcoef;
10262 
10263  /* return if the new bound is larger than infinity */
10264  if( SCIPsetIsInfinity(set, REALABS(newzlb)) )
10265  return SCIP_OKAY;
10266 
10267  if( SCIPsetIsFeasGT(set, newzlb, zub) )
10268  {
10269  *infeasible = TRUE;
10270  return SCIP_OKAY;
10271  }
10272  if( SCIPsetIsFeasGT(set, newzlb, zlb) )
10273  {
10274  /* bound might be adjusted due to integrality condition */
10275  newzlb = adjustedLb(set, SCIPvarGetType(vlbvar), newzlb);
10276 
10277  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10278  * with the local bound, in this case we need to store the bound change as pending bound change
10279  */
10280  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10281  {
10282  assert(tree != NULL);
10283  assert(transprob != NULL);
10284  assert(SCIPprobIsTransformed(transprob));
10285 
10286  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10287  tree, reopt, lp, branchcand, eventqueue, cliquetable, vlbvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10288  }
10289  else
10290  {
10291  SCIP_CALL( SCIPvarChgLbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
10292  }
10293  zlb = newzlb;
10294 
10295  if( nbdchgs != NULL )
10296  (*nbdchgs)++;
10297  }
10298  maxvlb = vlbcoef * zlb + vlbconstant;
10299  if( !SCIPsetIsInfinity(set, zub) )
10300  minvlb = vlbcoef * zub + vlbconstant;
10301  }
10302  else
10303  {
10304  if( !SCIPsetIsInfinity(set, -zlb) )
10305  maxvlb = vlbcoef * zlb + vlbconstant;
10306  if( !SCIPsetIsInfinity(set, zub) )
10307  minvlb = vlbcoef * zub + vlbconstant;
10308  }
10309  }
10310  if( maxvlb < minvlb )
10311  maxvlb = minvlb;
10312 
10313  /* adjust bounds due to integrality of variable */
10314  minvlb = adjustedLb(set, SCIPvarGetType(var), minvlb);
10315  maxvlb = adjustedLb(set, SCIPvarGetType(var), maxvlb);
10316 
10317  /* check bounds for feasibility */
10318  if( SCIPsetIsFeasGT(set, minvlb, xub) || (var == vlbvar && SCIPsetIsEQ(set, vlbcoef, 1.0) && SCIPsetIsFeasPositive(set, vlbconstant)) )
10319  {
10320  *infeasible = TRUE;
10321  return SCIP_OKAY;
10322  }
10323  /* improve global lower bound of variable */
10324  if( SCIPsetIsFeasGT(set, minvlb, xlb) )
10325  {
10326  /* bound might be adjusted due to integrality condition */
10327  minvlb = adjustedLb(set, SCIPvarGetType(var), minvlb);
10328 
10329  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10330  * with the local bound, in this case we need to store the bound change as pending bound change
10331  */
10332  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10333  {
10334  assert(tree != NULL);
10335  assert(transprob != NULL);
10336  assert(SCIPprobIsTransformed(transprob));
10337 
10338  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10339  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, minvlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10340  }
10341  else
10342  {
10343  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, minvlb) );
10344  }
10345  xlb = minvlb;
10346 
10347  if( nbdchgs != NULL )
10348  (*nbdchgs)++;
10349  }
10350  minvlb = xlb;
10351 
10352  /* improve variable bound for binary z by moving the variable's global bound to the vlb constant */
10353  if( SCIPvarGetType(vlbvar) == SCIP_VARTYPE_BINARY )
10354  {
10355  /* b > 0: x >= (maxvlb - minvlb) * z + minvlb
10356  * b < 0: x >= (minvlb - maxvlb) * z + maxvlb
10357  */
10358 
10359  assert(!SCIPsetIsInfinity(set, maxvlb) && !SCIPsetIsInfinity(set, -minvlb));
10360 
10361  if( vlbcoef >= 0.0 )
10362  {
10363  vlbcoef = maxvlb - minvlb;
10364  vlbconstant = minvlb;
10365  }
10366  else
10367  {
10368  vlbcoef = minvlb - maxvlb;
10369  vlbconstant = maxvlb;
10370  }
10371  }
10372 
10373  /* add variable bound to the variable bounds list */
10374  if( SCIPsetIsFeasGT(set, maxvlb, xlb) )
10375  {
10376  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED);
10377  assert(!SCIPsetIsZero(set, vlbcoef));
10378 
10379  /* if one of the variables is binary, add the corresponding implication to the variable's implication
10380  * list, thereby also adding the variable bound (or implication) to the other variable
10381  */
10382  if( SCIPvarGetType(vlbvar) == SCIP_VARTYPE_BINARY )
10383  {
10384  /* add corresponding implication:
10385  * b > 0, x >= b*z + d <-> z == 1 -> x >= b+d
10386  * b < 0, x >= b*z + d <-> z == 0 -> x >= d
10387  */
10388  SCIP_CALL( varAddTransitiveImplic(vlbvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10389  cliquetable, branchcand, eventqueue, (vlbcoef >= 0.0), var, SCIP_BOUNDTYPE_LOWER, maxvlb, transitive,
10390  infeasible, nbdchgs) );
10391  }
10392  else if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
10393  {
10394  /* add corresponding implication:
10395  * b > 0, x >= b*z + d <-> x == 0 -> z <= -d/b
10396  * b < 0, x >= b*z + d <-> x == 0 -> z >= -d/b
10397  */
10398  SCIP_Real implbound;
10399  implbound = -vlbconstant/vlbcoef;
10400 
10401  /* tighten the implication bound if the variable is integer */
10402  if( SCIPvarIsIntegral(vlbvar) )
10403  {
10404  if( vlbcoef >= 0 )
10405  implbound = SCIPsetFloor(set, implbound);
10406  else
10407  implbound = SCIPsetCeil(set, implbound);
10408  }
10409  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10410  cliquetable, branchcand, eventqueue, FALSE, vlbvar, (vlbcoef >= 0.0 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER),
10411  implbound, transitive, infeasible, nbdchgs) );
10412  }
10413  else
10414  {
10415  SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, vlbvar, vlbcoef, vlbconstant) );
10416  }
10417  }
10418  }
10419  break;
10420 
10422  /* x = a*y + c: x >= b*z + d <=> a*y + c >= b*z + d <=> y >= b/a * z + (d-c)/a, if a > 0
10423  * y <= b/a * z + (d-c)/a, if a < 0
10424  */
10425  assert(var->data.aggregate.var != NULL);
10426  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
10427  {
10428  /* a > 0 -> add variable lower bound */
10429  SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10430  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef/var->data.aggregate.scalar,
10431  (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10432  }
10433  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
10434  {
10435  /* a < 0 -> add variable upper bound */
10436  SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10437  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef/var->data.aggregate.scalar,
10438  (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10439  }
10440  else
10441  {
10442  SCIPerrorMessage("scalar is zero in aggregation\n");
10443  return SCIP_INVALIDDATA;
10444  }
10445  break;
10446 
10448  /* nothing to do here */
10449  break;
10450 
10452  /* x = offset - x': x >= b*z + d <=> offset - x' >= b*z + d <=> x' <= -b*z + (offset-d) */
10453  assert(var->negatedvar != NULL);
10455  assert(var->negatedvar->negatedvar == var);
10456  SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10457  branchcand, eventqueue, vlbvar, -vlbcoef, var->data.negate.constant - vlbconstant, transitive, infeasible,
10458  nbdchgs) );
10459  break;
10460 
10461  default:
10462  SCIPerrorMessage("unknown variable status\n");
10463  return SCIP_INVALIDDATA;
10464  }
10465 
10466  return SCIP_OKAY;
10467 }
10468 
10469 /** informs variable x about a globally valid variable upper bound x <= b*z + d with integer variable z;
10470  * if z is binary, the corresponding valid implication for z is also added;
10471  * updates the global bounds of the variable and the vub variable correspondingly
10472  */
10474  SCIP_VAR* var, /**< problem variable */
10475  BMS_BLKMEM* blkmem, /**< block memory */
10476  SCIP_SET* set, /**< global SCIP settings */
10477  SCIP_STAT* stat, /**< problem statistics */
10478  SCIP_PROB* transprob, /**< transformed problem */
10479  SCIP_PROB* origprob, /**< original problem */
10480  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10481  SCIP_REOPT* reopt, /**< reoptimization data structure */
10482  SCIP_LP* lp, /**< current LP data */
10483  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10484  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10485  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10486  SCIP_VAR* vubvar, /**< variable z in x <= b*z + d */
10487  SCIP_Real vubcoef, /**< coefficient b in x <= b*z + d */
10488  SCIP_Real vubconstant, /**< constant d in x <= b*z + d */
10489  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
10490  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10491  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
10492  )
10493 {
10494  assert(var != NULL);
10495  assert(set != NULL);
10496  assert(var->scip == set->scip);
10497  assert(SCIPvarGetType(vubvar) != SCIP_VARTYPE_CONTINUOUS);
10498  assert(infeasible != NULL);
10499 
10500  SCIPsetDebugMsg(set, "adding variable upper bound <%s> <= %g<%s> + %g\n", SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
10501 
10502  *infeasible = FALSE;
10503  if( nbdchgs != NULL )
10504  *nbdchgs = 0;
10505 
10506  switch( SCIPvarGetStatus(var) )
10507  {
10509  assert(var->data.original.transvar != NULL);
10510  SCIP_CALL( SCIPvarAddVub(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10511  cliquetable, branchcand, eventqueue, vubvar, vubcoef, vubconstant, transitive, infeasible, nbdchgs) );
10512  break;
10513 
10514  case SCIP_VARSTATUS_COLUMN:
10515  case SCIP_VARSTATUS_LOOSE:
10516  case SCIP_VARSTATUS_FIXED:
10517  /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
10518  SCIP_CALL( SCIPvarGetProbvarSum(&vubvar, set, &vubcoef, &vubconstant) );
10519  SCIPsetDebugMsg(set, " -> transformed to variable upper bound <%s> <= %g<%s> + %g\n",
10520  SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
10521 
10522  /* if the vub coefficient is zero, just update the upper bound of the variable */
10523  if( SCIPsetIsZero(set, vubcoef) )
10524  {
10525  if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetLbGlobal(var)) )
10526  *infeasible = TRUE;
10527  else if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetUbGlobal(var)) )
10528  {
10529  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10530  * with the local bound, in this case we need to store the bound change as pending bound change
10531  */
10532  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10533  {
10534  assert(tree != NULL);
10535  assert(transprob != NULL);
10536  assert(SCIPprobIsTransformed(transprob));
10537 
10538  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10539  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vubconstant, SCIP_BOUNDTYPE_UPPER, FALSE) );
10540  }
10541  else
10542  {
10543  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vubconstant) );
10544  }
10545 
10546  if( nbdchgs != NULL )
10547  (*nbdchgs)++;
10548  }
10549  }
10550  else if( var == vubvar )
10551  {
10552  /* the variables cancels out, the variable bound constraint is either redundant or proves global infeasibility */
10553  if( SCIPsetIsEQ(set, vubcoef, 1.0) )
10554  {
10555  if( SCIPsetIsNegative(set, vubconstant) )
10556  *infeasible = TRUE;
10557  return SCIP_OKAY;
10558  }
10559  else
10560  {
10561  SCIP_Real lb = SCIPvarGetLbGlobal(var);
10562  SCIP_Real ub = SCIPvarGetUbGlobal(var);
10563 
10564  /* the variable bound constraint defines a new lower bound */
10565  if( SCIPsetIsGT(set, vubcoef, 1.0) )
10566  {
10567  SCIP_Real newlb = vubconstant / (1.0 - vubcoef);
10568 
10569  if( SCIPsetIsFeasGT(set, newlb, ub) )
10570  {
10571  *infeasible = TRUE;
10572  return SCIP_OKAY;
10573  }
10574  else if( SCIPsetIsFeasGT(set, newlb, lb) )
10575  {
10576  /* bound might be adjusted due to integrality condition */
10577  newlb = adjustedLb(set, SCIPvarGetType(var), newlb);
10578 
10579  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10580  * with the local bound, in this case we need to store the bound change as pending bound change
10581  */
10582  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10583  {
10584  assert(tree != NULL);
10585  assert(transprob != NULL);
10586  assert(SCIPprobIsTransformed(transprob));
10587 
10588  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10589  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10590  }
10591  else
10592  {
10593  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newlb) );
10594  }
10595 
10596  if( nbdchgs != NULL )
10597  (*nbdchgs)++;
10598  }
10599  }
10600  /* the variable bound constraint defines a new upper bound */
10601  else
10602  {
10603  SCIP_Real newub;
10604 
10605  assert(SCIPsetIsLT(set, vubcoef, 1.0));
10606 
10607  newub = vubconstant / (1.0 - vubcoef);
10608 
10609  if( SCIPsetIsFeasLT(set, newub, lb) )
10610  {
10611  *infeasible = TRUE;
10612  return SCIP_OKAY;
10613  }
10614  else if( SCIPsetIsFeasLT(set, newub, ub) )
10615  {
10616  /* bound might be adjusted due to integrality condition */
10617  newub = adjustedUb(set, SCIPvarGetType(var), newub);
10618 
10619  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10620  * with the local bound, in this case we need to store the bound change as pending bound change
10621  */
10622  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10623  {
10624  assert(tree != NULL);
10625  assert(transprob != NULL);
10626  assert(SCIPprobIsTransformed(transprob));
10627 
10628  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10629  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10630  }
10631  else
10632  {
10633  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newub) );
10634  }
10635 
10636  if( nbdchgs != NULL )
10637  (*nbdchgs)++;
10638  }
10639  }
10640  }
10641  }
10642  else if( SCIPvarIsActive(vubvar) )
10643  {
10644  SCIP_Real xlb;
10645  SCIP_Real xub;
10646  SCIP_Real zlb;
10647  SCIP_Real zub;
10648  SCIP_Real minvub;
10649  SCIP_Real maxvub;
10650 
10652  assert(vubcoef != 0.0);
10653 
10654  minvub = -SCIPsetInfinity(set);
10655  maxvub = SCIPsetInfinity(set);
10656 
10657  xlb = SCIPvarGetLbGlobal(var);
10658  xub = SCIPvarGetUbGlobal(var);
10659  zlb = SCIPvarGetLbGlobal(vubvar);
10660  zub = SCIPvarGetUbGlobal(vubvar);
10661 
10662  /* improve global bounds of vub variable, and calculate minimal and maximal value of variable bound */
10663  if( vubcoef >= 0.0 )
10664  {
10665  SCIP_Real newzlb;
10666 
10667  if( !SCIPsetIsInfinity(set, -xlb) )
10668  {
10669  /* x <= b*z + d -> z >= (x-d)/b */
10670  newzlb = (xlb - vubconstant)/vubcoef;
10671  if( SCIPsetIsFeasGT(set, newzlb, zub) )
10672  {
10673  *infeasible = TRUE;
10674  return SCIP_OKAY;
10675  }
10676  if( SCIPsetIsFeasGT(set, newzlb, zlb) )
10677  {
10678  /* bound might be adjusted due to integrality condition */
10679  newzlb = adjustedLb(set, SCIPvarGetType(vubvar), newzlb);
10680 
10681  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10682  * with the local bound, in this case we need to store the bound change as pending bound change
10683  */
10684  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10685  {
10686  assert(tree != NULL);
10687  assert(transprob != NULL);
10688  assert(SCIPprobIsTransformed(transprob));
10689 
10690  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10691  tree, reopt, lp, branchcand, eventqueue, cliquetable, vubvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10692  }
10693  else
10694  {
10695  SCIP_CALL( SCIPvarChgLbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
10696  }
10697  zlb = newzlb;
10698 
10699  if( nbdchgs != NULL )
10700  (*nbdchgs)++;
10701  }
10702  minvub = vubcoef * zlb + vubconstant;
10703  if( !SCIPsetIsInfinity(set, zub) )
10704  maxvub = vubcoef * zub + vubconstant;
10705  }
10706  else
10707  {
10708  if( !SCIPsetIsInfinity(set, zub) )
10709  maxvub = vubcoef * zub + vubconstant;
10710  if( !SCIPsetIsInfinity(set, -zlb) )
10711  minvub = vubcoef * zlb + vubconstant;
10712  }
10713  }
10714  else
10715  {
10716  SCIP_Real newzub;
10717 
10718  if( !SCIPsetIsInfinity(set, -xlb) )
10719  {
10720  /* x <= b*z + d -> z <= (x-d)/b */
10721  newzub = (xlb - vubconstant)/vubcoef;
10722  if( SCIPsetIsFeasLT(set, newzub, zlb) )
10723  {
10724  *infeasible = TRUE;
10725  return SCIP_OKAY;
10726  }
10727  if( SCIPsetIsFeasLT(set, newzub, zub) )
10728  {
10729  /* bound might be adjusted due to integrality condition */
10730  newzub = adjustedUb(set, SCIPvarGetType(vubvar), newzub);
10731 
10732  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10733  * with the local bound, in this case we need to store the bound change as pending bound change
10734  */
10735  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10736  {
10737  assert(tree != NULL);
10738  assert(transprob != NULL);
10739  assert(SCIPprobIsTransformed(transprob));
10740 
10741  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10742  tree, reopt, lp, branchcand, eventqueue, cliquetable, vubvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10743  }
10744  else
10745  {
10746  SCIP_CALL( SCIPvarChgUbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
10747  }
10748  zub = newzub;
10749 
10750  if( nbdchgs != NULL )
10751  (*nbdchgs)++;
10752  }
10753  minvub = vubcoef * zub + vubconstant;
10754  if( !SCIPsetIsInfinity(set, -zlb) )
10755  maxvub = vubcoef * zlb + vubconstant;
10756  }
10757  else
10758  {
10759  if( !SCIPsetIsInfinity(set, zub) )
10760  minvub = vubcoef * zub + vubconstant;
10761  if( !SCIPsetIsInfinity(set, -zlb) )
10762  maxvub = vubcoef * zlb + vubconstant;
10763  }
10764  }
10765  if( minvub > maxvub )
10766  minvub = maxvub;
10767 
10768  /* adjust bounds due to integrality of vub variable */
10769  minvub = adjustedUb(set, SCIPvarGetType(var), minvub);
10770  maxvub = adjustedUb(set, SCIPvarGetType(var), maxvub);
10771 
10772  /* check bounds for feasibility */
10773  if( SCIPsetIsFeasLT(set, maxvub, xlb) || (var == vubvar && SCIPsetIsEQ(set, vubcoef, 1.0) && SCIPsetIsFeasNegative(set, vubconstant)) )
10774  {
10775  *infeasible = TRUE;
10776  return SCIP_OKAY;
10777  }
10778 
10779  /* improve global upper bound of variable */
10780  if( SCIPsetIsFeasLT(set, maxvub, xub) )
10781  {
10782  /* bound might be adjusted due to integrality condition */
10783  maxvub = adjustedUb(set, SCIPvarGetType(var), maxvub);
10784 
10785  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10786  * with the local bound, in this case we need to store the bound change as pending bound change
10787  */
10788  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10789  {
10790  assert(tree != NULL);
10791  assert(transprob != NULL);
10792  assert(SCIPprobIsTransformed(transprob));
10793 
10794  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10795  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, maxvub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10796  }
10797  else
10798  {
10799  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, maxvub) );
10800  }
10801  xub = maxvub;
10802 
10803  if( nbdchgs != NULL )
10804  (*nbdchgs)++;
10805  }
10806  maxvub = xub;
10807 
10808  /* improve variable bound for binary z by moving the variable's global bound to the vub constant */
10809  if( SCIPvarIsBinary(vubvar) )
10810  {
10811  /* b > 0: x <= (maxvub - minvub) * z + minvub
10812  * b < 0: x <= (minvub - maxvub) * z + maxvub
10813  */
10814 
10815  assert(!SCIPsetIsInfinity(set, maxvub) && !SCIPsetIsInfinity(set, -minvub));
10816 
10817  if( vubcoef >= 0.0 )
10818  {
10819  vubcoef = maxvub - minvub;
10820  vubconstant = minvub;
10821  }
10822  else
10823  {
10824  vubcoef = minvub - maxvub;
10825  vubconstant = maxvub;
10826  }
10827  }
10828 
10829  /* add variable bound to the variable bounds list */
10830  if( SCIPsetIsFeasLT(set, minvub, xub) )
10831  {
10832  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED);
10833  assert(!SCIPsetIsZero(set, vubcoef));
10834 
10835  /* if one of the variables is binary, add the corresponding implication to the variable's implication
10836  * list, thereby also adding the variable bound (or implication) to the other variable
10837  */
10838  if( SCIPvarGetType(vubvar) == SCIP_VARTYPE_BINARY )
10839  {
10840  /* add corresponding implication:
10841  * b > 0, x <= b*z + d <-> z == 0 -> x <= d
10842  * b < 0, x <= b*z + d <-> z == 1 -> x <= b+d
10843  */
10844  SCIP_CALL( varAddTransitiveImplic(vubvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10845  cliquetable, branchcand, eventqueue, (vubcoef < 0.0), var, SCIP_BOUNDTYPE_UPPER, minvub, transitive,
10846  infeasible, nbdchgs) );
10847  }
10848  else if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
10849  {
10850  /* add corresponding implication:
10851  * b > 0, x <= b*z + d <-> x == 1 -> z >= (1-d)/b
10852  * b < 0, x <= b*z + d <-> x == 1 -> z <= (1-d)/b
10853  */
10854  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10855  cliquetable, branchcand, eventqueue, TRUE, vubvar, (vubcoef >= 0.0 ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER),
10856  (1.0-vubconstant)/vubcoef, transitive, infeasible, nbdchgs) );
10857  }
10858  else
10859  {
10860  SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, vubvar, vubcoef, vubconstant) );
10861  }
10862  }
10863  }
10864  break;
10865 
10867  /* x = a*y + c: x <= b*z + d <=> a*y + c <= b*z + d <=> y <= b/a * z + (d-c)/a, if a > 0
10868  * y >= b/a * z + (d-c)/a, if a < 0
10869  */
10870  assert(var->data.aggregate.var != NULL);
10871  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
10872  {
10873  /* a > 0 -> add variable upper bound */
10874  SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10875  cliquetable, branchcand, eventqueue, vubvar, vubcoef/var->data.aggregate.scalar,
10876  (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10877  }
10878  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
10879  {
10880  /* a < 0 -> add variable lower bound */
10881  SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10882  cliquetable, branchcand, eventqueue, vubvar, vubcoef/var->data.aggregate.scalar,
10883  (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10884  }
10885  else
10886  {
10887  SCIPerrorMessage("scalar is zero in aggregation\n");
10888  return SCIP_INVALIDDATA;
10889  }
10890  break;
10891 
10893  /* nothing to do here */
10894  break;
10895 
10897  /* x = offset - x': x <= b*z + d <=> offset - x' <= b*z + d <=> x' >= -b*z + (offset-d) */
10898  assert(var->negatedvar != NULL);
10900  assert(var->negatedvar->negatedvar == var);
10901  SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10902  branchcand, eventqueue, vubvar, -vubcoef, var->data.negate.constant - vubconstant, transitive, infeasible,
10903  nbdchgs) );
10904  break;
10905 
10906  default:
10907  SCIPerrorMessage("unknown variable status\n");
10908  return SCIP_INVALIDDATA;
10909  }
10910 
10911  return SCIP_OKAY;
10912 }
10913 
10914 /** informs binary variable x about a globally valid implication: x == 0 or x == 1 ==> y <= b or y >= b;
10915  * also adds the corresponding implication or variable bound to the implied variable;
10916  * if the implication is conflicting, the variable is fixed to the opposite value;
10917  * if the variable is already fixed to the given value, the implication is performed immediately;
10918  * if the implication is redundant with respect to the variables' global bounds, it is ignored
10919  */
10921  SCIP_VAR* var, /**< problem variable */
10922  BMS_BLKMEM* blkmem, /**< block memory */
10923  SCIP_SET* set, /**< global SCIP settings */
10924  SCIP_STAT* stat, /**< problem statistics */
10925  SCIP_PROB* transprob, /**< transformed problem */
10926  SCIP_PROB* origprob, /**< original problem */
10927  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10928  SCIP_REOPT* reopt, /**< reoptimization data structure */
10929  SCIP_LP* lp, /**< current LP data */
10930  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10931  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10932  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10933  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
10934  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
10935  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
10936  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
10937  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
10938  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10939  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
10940  )
10941 {
10942  assert(var != NULL);
10943  assert(set != NULL);
10944  assert(var->scip == set->scip);
10945  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
10946  assert(infeasible != NULL);
10947 
10948  *infeasible = FALSE;
10949  if( nbdchgs != NULL )
10950  *nbdchgs = 0;
10951 
10952  switch( SCIPvarGetStatus(var) )
10953  {
10955  assert(var->data.original.transvar != NULL);
10956  SCIP_CALL( SCIPvarAddImplic(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10957  cliquetable, branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible,
10958  nbdchgs) );
10959  break;
10960 
10961  case SCIP_VARSTATUS_COLUMN:
10962  case SCIP_VARSTATUS_LOOSE:
10963  /* if the variable is fixed (although it has no FIXED status), and varfixing corresponds to the fixed value of
10964  * the variable, the implication can be applied directly;
10965  * otherwise, add implication to the implications list (and add inverse of implication to the implied variable)
10966  */
10967  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
10968  {
10969  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
10970  {
10971  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
10972  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
10973  }
10974  }
10975  else
10976  {
10977  SCIP_CALL( SCIPvarGetProbvarBound(&implvar, &implbound, &impltype) );
10978  SCIPvarAdjustBd(implvar, set, impltype, &implbound);
10979  if( SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED )
10980  {
10981  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10982  branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
10983  }
10984  }
10985  break;
10986 
10987  case SCIP_VARSTATUS_FIXED:
10988  /* if varfixing corresponds to the fixed value of the variable, the implication can be applied directly */
10989  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
10990  {
10991  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
10992  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
10993  }
10994  break;
10995 
10997  /* implication added for x == 1:
10998  * x == 1 && x = 1*z + 0 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10999  * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
11000  * implication added for x == 0:
11001  * x == 0 && x = 1*z + 0 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
11002  * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
11003  *
11004  * use only binary variables z
11005  */
11006  assert(var->data.aggregate.var != NULL);
11007  if( SCIPvarIsBinary(var->data.aggregate.var) )
11008  {
11009  assert( (SCIPsetIsEQ(set, var->data.aggregate.scalar, 1.0) && SCIPsetIsZero(set, var->data.aggregate.constant))
11010  || (SCIPsetIsEQ(set, var->data.aggregate.scalar, -1.0) && SCIPsetIsEQ(set, var->data.aggregate.constant, 1.0)) );
11011 
11012  if( var->data.aggregate.scalar > 0 )
11013  {
11014  SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11015  cliquetable, branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible,
11016  nbdchgs) );
11017  }
11018  else
11019  {
11020  SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11021  cliquetable, branchcand, eventqueue, !varfixing, implvar, impltype, implbound, transitive, infeasible,
11022  nbdchgs) );
11023  }
11024  }
11025  break;
11026 
11028  /* nothing to do here */
11029  break;
11030 
11032  /* implication added for x == 1:
11033  * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
11034  * implication added for x == 0:
11035  * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
11036  */
11037  assert(var->negatedvar != NULL);
11039  assert(var->negatedvar->negatedvar == var);
11040  assert(SCIPvarIsBinary(var->negatedvar));
11041 
11043  {
11044  SCIP_CALL( SCIPvarAddImplic(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11045  cliquetable, branchcand, eventqueue, !varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
11046  }
11047  /* in case one both variables are not of binary type we have to add the implication as variable bounds */
11048  else
11049  {
11050  /* if the implied variable is of binary type exchange the variables */
11051  if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
11052  {
11053  SCIP_CALL( SCIPvarAddImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
11054  branchcand, eventqueue, (impltype == SCIP_BOUNDTYPE_UPPER) ? TRUE : FALSE, var->negatedvar,
11055  varfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER, varfixing ? 1.0 : 0.0, transitive,
11056  infeasible, nbdchgs) );
11057  }
11058  else
11059  {
11060  /* both variables are not of binary type but are implicit binary; in that case we can only add this
11061  * implication as variable bounds
11062  */
11063 
11064  /* add variable lower bound on the negation of var */
11065  if( varfixing )
11066  {
11067  /* (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
11068  * as variable lower bound
11069  */
11070  SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11071  cliquetable, branchcand, eventqueue, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : -1.0,
11072  (impltype == SCIP_BOUNDTYPE_UPPER) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
11073  }
11074  else
11075  {
11076  /* (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
11077  * as variable upper bound
11078  */
11079  SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11080  cliquetable, branchcand, eventqueue, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? -1.0 : 1.0,
11081  (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : 0.0, transitive, infeasible, nbdchgs) );
11082  }
11083 
11084  /* add variable bound on implvar */
11085  if( impltype == SCIP_BOUNDTYPE_UPPER )
11086  {
11087  /* (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
11088  * as variable upper bound
11089  */
11090  SCIP_CALL( SCIPvarAddVub(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
11091  branchcand, eventqueue, var->negatedvar, (varfixing) ? 1.0 : -1.0,
11092  (varfixing) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
11093  }
11094  else
11095  {
11096  /* (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
11097  * as variable upper bound
11098  */
11099  SCIP_CALL( SCIPvarAddVlb(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
11100  branchcand, eventqueue, var->negatedvar, (varfixing) ? -1.0 : 1.0, (varfixing) ? 1.0 : 0.0,
11101  transitive, infeasible, nbdchgs) );
11102  }
11103  }
11104  }
11105  break;
11106 
11107  default:
11108  SCIPerrorMessage("unknown variable status\n");
11109  return SCIP_INVALIDDATA;
11110  }
11111 
11112  return SCIP_OKAY;
11113 }
11114 
11115 /** returns whether there is an implication x == varfixing -> y <= b or y >= b in the implication graph;
11116  * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
11117  * both variables must be active, variable x must be binary
11118  */
11120  SCIP_VAR* var, /**< problem variable x */
11121  SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
11122  SCIP_VAR* implvar, /**< variable y to search for */
11123  SCIP_BOUNDTYPE impltype /**< type of implication y <=/>= b to search for */
11124  )
11125 {
11126  assert(var != NULL);
11127  assert(implvar != NULL);
11128  assert(SCIPvarIsActive(var));
11129  assert(SCIPvarIsActive(implvar));
11130  assert(SCIPvarIsBinary(var));
11131 
11132  return var->implics != NULL && SCIPimplicsContainsImpl(var->implics, varfixing, implvar, impltype);
11133 }
11134 
11135 /** returns whether there is an implication x == varfixing -> y == implvarfixing in the implication graph;
11136  * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
11137  * both variables must be active binary variables
11138  */
11140  SCIP_VAR* var, /**< problem variable x */
11141  SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
11142  SCIP_VAR* implvar, /**< variable y to search for */
11143  SCIP_Bool implvarfixing /**< value of the implied variable to search for */
11144  )
11145 {
11146  assert(SCIPvarIsBinary(implvar));
11147 
11148  return SCIPvarHasImplic(var, varfixing, implvar, implvarfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER);
11149 }
11150 
11151 /** gets the values of b in implications x == varfixing -> y <= b or y >= b in the implication graph;
11152  * the values are set to SCIP_INVALID if there is no implied bound
11153  */
11155  SCIP_VAR* var, /**< problem variable x */
11156  SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
11157  SCIP_VAR* implvar, /**< variable y to search for */
11158  SCIP_Real* lb, /**< buffer to store the value of the implied lower bound */
11159  SCIP_Real* ub /**< buffer to store the value of the implied upper bound */
11160  )
11161 {
11162  int lowerpos;
11163  int upperpos;
11164  SCIP_Real* bounds;
11165 
11166  assert(lb != NULL);
11167  assert(ub != NULL);
11168 
11169  *lb = SCIP_INVALID;
11170  *ub = SCIP_INVALID;
11171 
11172  if( var->implics == NULL )
11173  return;
11174 
11175  SCIPimplicsGetVarImplicPoss(var->implics, varfixing, implvar, &lowerpos, &upperpos);
11176  bounds = SCIPvarGetImplBounds(var, varfixing);
11177 
11178  if( bounds == NULL )
11179  return;
11180 
11181  if( lowerpos >= 0 )
11182  *lb = bounds[lowerpos];
11183 
11184  if( upperpos >= 0 )
11185  *ub = bounds[upperpos];
11186 }
11187 
11188 
11189 /** fixes the bounds of a binary variable to the given value, counting bound changes and detecting infeasibility */
11191  SCIP_VAR* var, /**< problem variable */
11192  BMS_BLKMEM* blkmem, /**< block memory */
11193  SCIP_SET* set, /**< global SCIP settings */
11194  SCIP_STAT* stat, /**< problem statistics */
11195  SCIP_PROB* transprob, /**< transformed problem */
11196  SCIP_PROB* origprob, /**< original problem */
11197  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
11198  SCIP_REOPT* reopt, /**< reoptimization data structure */
11199  SCIP_LP* lp, /**< current LP data */
11200  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
11201  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
11202  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11203  SCIP_Bool value, /**< value to fix variable to */
11204  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
11205  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
11206  )
11207 {
11208  assert(var != NULL);
11209  assert(set != NULL);
11210  assert(var->scip == set->scip);
11211  assert(infeasible != NULL);
11212 
11213  *infeasible = FALSE;
11214 
11215  if( value == FALSE )
11216  {
11217  if( var->glbdom.lb > 0.5 )
11218  *infeasible = TRUE;
11219  else if( var->glbdom.ub > 0.5 )
11220  {
11221  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
11222  * with the local bound, in this case we need to store the bound change as pending bound change
11223  */
11224  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
11225  {
11226  assert(tree != NULL);
11227  assert(transprob != NULL);
11228  assert(SCIPprobIsTransformed(transprob));
11229 
11230  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
11231  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
11232  }
11233  else
11234  {
11235  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
11236  }
11237 
11238  if( nbdchgs != NULL )
11239  (*nbdchgs)++;
11240  }
11241  }
11242  else
11243  {
11244  if( var->glbdom.ub < 0.5 )
11245  *infeasible = TRUE;
11246  else if( var->glbdom.lb < 0.5 )
11247  {
11248  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
11249  * with the local bound, in this case we need to store the bound change as pending bound change
11250  */
11251  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
11252  {
11253  assert(tree != NULL);
11254  assert(transprob != NULL);
11255  assert(SCIPprobIsTransformed(transprob));
11256 
11257  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
11258  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
11259  }
11260  else
11261  {
11262  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
11263  }
11264 
11265  if( nbdchgs != NULL )
11266  (*nbdchgs)++;
11267  }
11268  }
11269 
11270  /* during presolving, the variable should have been removed immediately from all its cliques */
11271  assert(SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING || var->cliquelist == NULL);
11272 
11273  return SCIP_OKAY;
11274 }
11275 
11276 /** adds the variable to the given clique and updates the list of cliques the binary variable is member of;
11277  * if the variable now appears twice in the clique with the same value, it is fixed to the opposite value;
11278  * if the variable now appears twice in the clique with opposite values, all other variables are fixed to
11279  * the opposite of the value they take in the clique
11280  */
11282  SCIP_VAR* var, /**< problem variable */
11283  BMS_BLKMEM* blkmem, /**< block memory */
11284  SCIP_SET* set, /**< global SCIP settings */
11285  SCIP_STAT* stat, /**< problem statistics */
11286  SCIP_PROB* transprob, /**< transformed problem */
11287  SCIP_PROB* origprob, /**< original problem */
11288  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
11289  SCIP_REOPT* reopt, /**< reoptimization data structure */
11290  SCIP_LP* lp, /**< current LP data */
11291  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
11292  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
11293  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11294  SCIP_Bool value, /**< value of the variable in the clique */
11295  SCIP_CLIQUE* clique, /**< clique the variable should be added to */
11296  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
11297  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
11298  )
11299 {
11300  assert(var != NULL);
11301  assert(set != NULL);
11302  assert(var->scip == set->scip);
11303  assert(SCIPvarIsBinary(var));
11304  assert(infeasible != NULL);
11305 
11306  *infeasible = FALSE;
11307 
11308  /* get corresponding active problem variable */
11309  SCIP_CALL( SCIPvarGetProbvarBinary(&var, &value) );
11314  assert(SCIPvarIsBinary(var));
11315 
11316  /* only column and loose variables may be member of a clique */
11318  {
11319  SCIP_Bool doubleentry;
11320  SCIP_Bool oppositeentry;
11321 
11322  /* add variable to clique */
11323  SCIP_CALL( SCIPcliqueAddVar(clique, blkmem, set, var, value, &doubleentry, &oppositeentry) );
11324 
11325  /* add clique to variable's clique list */
11326  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
11327 
11328  /* check consistency of cliquelist */
11329  SCIPcliquelistCheck(var->cliquelist, var);
11330 
11331  /* if the variable now appears twice with the same value in the clique, it can be fixed to the opposite value */
11332  if( doubleentry )
11333  {
11334  SCIP_CALL( SCIPvarFixBinary(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
11335  eventqueue, cliquetable, !value, infeasible, nbdchgs) );
11336  }
11337 
11338  /* if the variable appears with both values in the clique, all other variables of the clique can be fixed
11339  * to the opposite of the value they take in the clique
11340  */
11341  if( oppositeentry )
11342  {
11343  SCIP_VAR** vars;
11344  SCIP_Bool* values;
11345  int nvars;
11346  int i;
11347 
11348  nvars = SCIPcliqueGetNVars(clique);
11349  vars = SCIPcliqueGetVars(clique);
11350  values = SCIPcliqueGetValues(clique);
11351  for( i = 0; i < nvars && !(*infeasible); ++i )
11352  {
11353  if( vars[i] == var )
11354  continue;
11355 
11356  SCIP_CALL( SCIPvarFixBinary(vars[i], blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
11357  eventqueue, cliquetable, !values[i], infeasible, nbdchgs) );
11358  }
11359  }
11360  }
11361 
11362  return SCIP_OKAY;
11363 }
11364 
11365 /** adds a filled clique to the cliquelists of all corresponding variables */
11367  SCIP_VAR** vars, /**< problem variables */
11368  SCIP_Bool* values, /**< values of the variables in the clique */
11369  int nvars, /**< number of problem variables */
11370  BMS_BLKMEM* blkmem, /**< block memory */
11371  SCIP_SET* set, /**< global SCIP settings */
11372  SCIP_CLIQUE* clique /**< clique that contains all given variables and values */
11373  )
11374 {
11375  SCIP_VAR* var;
11376  int v;
11377 
11378  assert(vars != NULL);
11379  assert(values != NULL);
11380  assert(nvars > 0);
11381  assert(set != NULL);
11382  assert(blkmem != NULL);
11383  assert(clique != NULL);
11384 
11385  for( v = nvars - 1; v >= 0; --v )
11386  {
11387  var = vars[v];
11388  assert(SCIPvarIsBinary(var));
11390 
11391  /* add clique to variable's clique list */
11392  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, values[v], clique) );
11393 
11394  /* check consistency of cliquelist */
11395  SCIPcliquelistCheck(var->cliquelist, var);
11396  }
11397 
11398  return SCIP_OKAY;
11399 }
11400 
11401 /** adds a clique to the list of cliques of the given binary variable, but does not change the clique
11402  * itself
11403  */
11405  SCIP_VAR* var, /**< problem variable */
11406  BMS_BLKMEM* blkmem, /**< block memory */
11407  SCIP_SET* set, /**< global SCIP settings */
11408  SCIP_Bool value, /**< value of the variable in the clique */
11409  SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
11410  )
11411 {
11412  assert(var != NULL);
11413  assert(SCIPvarIsBinary(var));
11415 
11416  /* add clique to variable's clique list */
11417  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
11418 
11419  return SCIP_OKAY;
11420 }
11421 
11422 
11423 /** deletes a clique from the list of cliques the binary variable is member of, but does not change the clique
11424  * itself
11425  */
11427  SCIP_VAR* var, /**< problem variable */
11428  BMS_BLKMEM* blkmem, /**< block memory */
11429  SCIP_Bool value, /**< value of the variable in the clique */
11430  SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
11431  )
11432 {
11433  assert(var != NULL);
11434  assert(SCIPvarIsBinary(var));
11435 
11436  /* delete clique from variable's clique list */
11437  SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
11438 
11439  return SCIP_OKAY;
11440 }
11441 
11442 /** deletes the variable from the given clique and updates the list of cliques the binary variable is member of */
11444  SCIP_VAR* var, /**< problem variable */
11445  BMS_BLKMEM* blkmem, /**< block memory */
11446  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11447  SCIP_Bool value, /**< value of the variable in the clique */
11448  SCIP_CLIQUE* clique /**< clique the variable should be removed from */
11449  )
11450 {
11451  assert(var != NULL);
11452  assert(SCIPvarIsBinary(var));
11453 
11454  /* get corresponding active problem variable */
11455  SCIP_CALL( SCIPvarGetProbvarBinary(&var, &value) );
11460  assert(SCIPvarIsBinary(var));
11461 
11462  /* only column and loose variables may be member of a clique */
11464  {
11465  /* delete clique from variable's clique list */
11466  SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
11467 
11468  /* delete variable from clique */
11469  SCIPcliqueDelVar(clique, cliquetable, var, value);
11470 
11471  /* check consistency of cliquelist */
11472  SCIPcliquelistCheck(var->cliquelist, var);
11473  }
11474 
11475  return SCIP_OKAY;
11476 }
11477 
11478 /** returns whether there is a clique that contains both given variable/value pairs;
11479  * the variables must be active binary variables;
11480  * if regardimplics is FALSE, only the cliques in the clique table are looked at;
11481  * if regardimplics is TRUE, both the cliques and the implications of the implication graph are regarded
11482  *
11483  * @note a variable with it's negated variable are NOT! in a clique
11484  * @note a variable with itself are in a clique
11485  */
11487  SCIP_VAR* var1, /**< first variable */
11488  SCIP_Bool value1, /**< value of first variable */
11489  SCIP_VAR* var2, /**< second variable */
11490  SCIP_Bool value2, /**< value of second variable */
11491  SCIP_Bool regardimplics /**< should the implication graph also be searched for a clique? */
11492  )
11493 {
11494  assert(var1 != NULL);
11495  assert(var2 != NULL);
11496  assert(SCIPvarIsActive(var1));
11497  assert(SCIPvarIsActive(var2));
11498  assert(SCIPvarIsBinary(var1));
11499  assert(SCIPvarIsBinary(var2));
11500 
11501  return (SCIPcliquelistsHaveCommonClique(var1->cliquelist, value1, var2->cliquelist, value2)
11502  || (regardimplics && SCIPvarHasImplic(var1, value1, var2, value2 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER)));
11503 }
11504 
11505 /** actually changes the branch factor of the variable and of all parent variables */
11506 static
11508  SCIP_VAR* var, /**< problem variable */
11509  SCIP_SET* set, /**< global SCIP settings */
11510  SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
11511  )
11512 {
11513  SCIP_VAR* parentvar;
11514  SCIP_Real eps;
11515  int i;
11516 
11517  assert(var != NULL);
11518  assert(set != NULL);
11519  assert(var->scip == set->scip);
11520 
11521  /* only use positive values */
11522  eps = SCIPsetEpsilon(set);
11523  branchfactor = MAX(branchfactor, eps);
11524 
11525  SCIPsetDebugMsg(set, "process changing branch factor of <%s> from %f to %f\n", var->name, var->branchfactor, branchfactor);
11526 
11527  if( SCIPsetIsEQ(set, branchfactor, var->branchfactor) )
11528  return SCIP_OKAY;
11529 
11530  /* change the branch factor */
11531  var->branchfactor = branchfactor;
11532 
11533  /* process parent variables */
11534  for( i = 0; i < var->nparentvars; ++i )
11535  {
11536  parentvar = var->parentvars[i];
11537  assert(parentvar != NULL);
11538 
11539  switch( SCIPvarGetStatus(parentvar) )
11540  {
11542  /* do not change priorities across the border between transformed and original problem */
11543  break;
11544 
11545  case SCIP_VARSTATUS_COLUMN:
11546  case SCIP_VARSTATUS_LOOSE:
11547  case SCIP_VARSTATUS_FIXED:
11549  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11550  SCIPABORT();
11551  return SCIP_INVALIDDATA; /*lint !e527*/
11552 
11555  SCIP_CALL( varProcessChgBranchFactor(parentvar, set, branchfactor) );
11556  break;
11557 
11558  default:
11559  SCIPerrorMessage("unknown variable status\n");
11560  SCIPABORT();
11561  return SCIP_ERROR; /*lint !e527*/
11562  }
11563  }
11564 
11565  return SCIP_OKAY;
11566 }
11567 
11568 /** sets the branch factor of the variable; this value can be used in the branching methods to scale the score
11569  * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
11570  */
11572  SCIP_VAR* var, /**< problem variable */
11573  SCIP_SET* set, /**< global SCIP settings */
11574  SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
11575  )
11576 {
11577  int v;
11578 
11579  assert(var != NULL);
11580  assert(set != NULL);
11581  assert(var->scip == set->scip);
11582  assert(branchfactor >= 0.0);
11583 
11584  SCIPdebugMessage("changing branch factor of <%s> from %g to %g\n", var->name, var->branchfactor, branchfactor);
11585 
11586  if( SCIPsetIsEQ(set, var->branchfactor, branchfactor) )
11587  return SCIP_OKAY;
11588 
11589  /* change priorities of attached variables */
11590  switch( SCIPvarGetStatus(var) )
11591  {
11593  if( var->data.original.transvar != NULL )
11594  {
11595  SCIP_CALL( SCIPvarChgBranchFactor(var->data.original.transvar, set, branchfactor) );
11596  }
11597  else
11598  {
11599  assert(set->stage == SCIP_STAGE_PROBLEM);
11600  var->branchfactor = branchfactor;
11601  }
11602  break;
11603 
11604  case SCIP_VARSTATUS_COLUMN:
11605  case SCIP_VARSTATUS_LOOSE:
11606  case SCIP_VARSTATUS_FIXED:
11607  SCIP_CALL( varProcessChgBranchFactor(var, set, branchfactor) );
11608  break;
11609 
11611  assert(!var->donotaggr);
11612  assert(var->data.aggregate.var != NULL);
11613  SCIP_CALL( SCIPvarChgBranchFactor(var->data.aggregate.var, set, branchfactor) );
11614  break;
11615 
11617  assert(!var->donotmultaggr);
11618  for( v = 0; v < var->data.multaggr.nvars; ++v )
11619  {
11620  SCIP_CALL( SCIPvarChgBranchFactor(var->data.multaggr.vars[v], set, branchfactor) );
11621  }
11622  break;
11623 
11625  assert(var->negatedvar != NULL);
11627  assert(var->negatedvar->negatedvar == var);
11628  SCIP_CALL( SCIPvarChgBranchFactor(var->negatedvar, set, branchfactor) );
11629  break;
11630 
11631  default:
11632  SCIPerrorMessage("unknown variable status\n");
11633  SCIPABORT();
11634  return SCIP_ERROR; /*lint !e527*/
11635  }
11636 
11637  return SCIP_OKAY;
11638 }
11639 
11640 /** actually changes the branch priority of the variable and of all parent variables */
11641 static
11643  SCIP_VAR* var, /**< problem variable */
11644  int branchpriority /**< branching priority of the variable */
11645  )
11646 {
11647  SCIP_VAR* parentvar;
11648  int i;
11649 
11650  assert(var != NULL);
11651 
11652  SCIPdebugMessage("process changing branch priority of <%s> from %d to %d\n",
11653  var->name, var->branchpriority, branchpriority);
11654 
11655  if( branchpriority == var->branchpriority )
11656  return SCIP_OKAY;
11657 
11658  /* change the branch priority */
11659  var->branchpriority = branchpriority;
11660 
11661  /* process parent variables */
11662  for( i = 0; i < var->nparentvars; ++i )
11663  {
11664  parentvar = var->parentvars[i];
11665  assert(parentvar != NULL);
11666 
11667  switch( SCIPvarGetStatus(parentvar) )
11668  {
11670  /* do not change priorities across the border between transformed and original problem */
11671  break;
11672 
11673  case SCIP_VARSTATUS_COLUMN:
11674  case SCIP_VARSTATUS_LOOSE:
11675  case SCIP_VARSTATUS_FIXED:
11677  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11678  SCIPABORT();
11679  return SCIP_INVALIDDATA; /*lint !e527*/
11680 
11683  SCIP_CALL( varProcessChgBranchPriority(parentvar, branchpriority) );
11684  break;
11685 
11686  default:
11687  SCIPerrorMessage("unknown variable status\n");
11688  return SCIP_ERROR;
11689  }
11690  }
11691 
11692  return SCIP_OKAY;
11693 }
11694 
11695 /** sets the branch priority of the variable; variables with higher branch priority are always preferred to variables
11696  * with lower priority in selection of branching variable
11697  */
11699  SCIP_VAR* var, /**< problem variable */
11700  int branchpriority /**< branching priority of the variable */
11701  )
11702 {
11703  int v;
11704 
11705  assert(var != NULL);
11706 
11707  SCIPdebugMessage("changing branch priority of <%s> from %d to %d\n", var->name, var->branchpriority, branchpriority);
11708 
11709  if( var->branchpriority == branchpriority )
11710  return SCIP_OKAY;
11711 
11712  /* change priorities of attached variables */
11713  switch( SCIPvarGetStatus(var) )
11714  {
11716  if( var->data.original.transvar != NULL )
11717  {
11718  SCIP_CALL( SCIPvarChgBranchPriority(var->data.original.transvar, branchpriority) );
11719  }
11720  else
11721  var->branchpriority = branchpriority;
11722  break;
11723 
11724  case SCIP_VARSTATUS_COLUMN:
11725  case SCIP_VARSTATUS_LOOSE:
11726  case SCIP_VARSTATUS_FIXED:
11727  SCIP_CALL( varProcessChgBranchPriority(var, branchpriority) );
11728  break;
11729 
11731  assert(!var->donotaggr);
11732  assert(var->data.aggregate.var != NULL);
11733  SCIP_CALL( SCIPvarChgBranchPriority(var->data.aggregate.var, branchpriority) );
11734  break;
11735 
11737  assert(!var->donotmultaggr);
11738  for( v = 0; v < var->data.multaggr.nvars; ++v )
11739  {
11740  SCIP_CALL( SCIPvarChgBranchPriority(var->data.multaggr.vars[v], branchpriority) );
11741  }
11742  break;
11743 
11745  assert(var->negatedvar != NULL);
11747  assert(var->negatedvar->negatedvar == var);
11748  SCIP_CALL( SCIPvarChgBranchPriority(var->negatedvar, branchpriority) );
11749  break;
11750 
11751  default:
11752  SCIPerrorMessage("unknown variable status\n");
11753  SCIPABORT();
11754  return SCIP_ERROR; /*lint !e527*/
11755  }
11756 
11757  return SCIP_OKAY;
11758 }
11759 
11760 /** actually changes the branch direction of the variable and of all parent variables */
11761 static
11763  SCIP_VAR* var, /**< problem variable */
11764  SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
11765  )
11766 {
11767  SCIP_VAR* parentvar;
11768  int i;
11769 
11770  assert(var != NULL);
11771 
11772  SCIPdebugMessage("process changing branch direction of <%s> from %u to %d\n",
11773  var->name, var->branchdirection, branchdirection);
11774 
11775  if( branchdirection == (SCIP_BRANCHDIR)var->branchdirection )
11776  return SCIP_OKAY;
11777 
11778  /* change the branch direction */
11779  var->branchdirection = branchdirection; /*lint !e641*/
11780 
11781  /* process parent variables */
11782  for( i = 0; i < var->nparentvars; ++i )
11783  {
11784  parentvar = var->parentvars[i];
11785  assert(parentvar != NULL);
11786 
11787  switch( SCIPvarGetStatus(parentvar) )
11788  {
11790  /* do not change directions across the border between transformed and original problem */
11791  break;
11792 
11793  case SCIP_VARSTATUS_COLUMN:
11794  case SCIP_VARSTATUS_LOOSE:
11795  case SCIP_VARSTATUS_FIXED:
11797  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11798  SCIPABORT();
11799  return SCIP_INVALIDDATA; /*lint !e527*/
11800 
11802  if( parentvar->data.aggregate.scalar > 0.0 )
11803  {
11804  SCIP_CALL( varProcessChgBranchDirection(parentvar, branchdirection) );
11805  }
11806  else
11807  {
11808  SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
11809  }
11810  break;
11811 
11813  SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
11814  break;
11815 
11816  default:
11817  SCIPerrorMessage("unknown variable status\n");
11818  SCIPABORT();
11819  return SCIP_ERROR; /*lint !e527*/
11820  }
11821  }
11822 
11823  return SCIP_OKAY;
11824 }
11825 
11826 /** sets the branch direction of the variable; variables with higher branch direction are always preferred to variables
11827  * with lower direction in selection of branching variable
11828  */
11830  SCIP_VAR* var, /**< problem variable */
11831  SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
11832  )
11833 {
11834  int v;
11835 
11836  assert(var != NULL);
11837 
11838  SCIPdebugMessage("changing branch direction of <%s> from %u to %d\n", var->name, var->branchdirection, branchdirection);
11839 
11840  if( (SCIP_BRANCHDIR)var->branchdirection == branchdirection )
11841  return SCIP_OKAY;
11842 
11843  /* change directions of attached variables */
11844  switch( SCIPvarGetStatus(var) )
11845  {
11847  if( var->data.original.transvar != NULL )
11848  {
11849  SCIP_CALL( SCIPvarChgBranchDirection(var->data.original.transvar, branchdirection) );
11850  }
11851  else
11852  var->branchdirection = branchdirection; /*lint !e641*/
11853  break;
11854 
11855  case SCIP_VARSTATUS_COLUMN:
11856  case SCIP_VARSTATUS_LOOSE:
11857  case SCIP_VARSTATUS_FIXED:
11858  SCIP_CALL( varProcessChgBranchDirection(var, branchdirection) );
11859  break;
11860 
11862  assert(!var->donotaggr);
11863  assert(var->data.aggregate.var != NULL);
11864  if( var->data.aggregate.scalar > 0.0 )
11865  {
11866  SCIP_CALL( SCIPvarChgBranchDirection(var->data.aggregate.var, branchdirection) );
11867  }
11868  else
11869  {
11871  }
11872  break;
11873 
11875  assert(!var->donotmultaggr);
11876  for( v = 0; v < var->data.multaggr.nvars; ++v )
11877  {
11878  /* only update branching direction of aggregation variables, if they don't have a preferred direction yet */
11879  assert(var->data.multaggr.vars[v] != NULL);
11881  {
11882  if( var->data.multaggr.scalars[v] > 0.0 )
11883  {
11884  SCIP_CALL( SCIPvarChgBranchDirection(var->data.multaggr.vars[v], branchdirection) );
11885  }
11886  else
11887  {
11889  }
11890  }
11891  }
11892  break;
11893 
11895  assert(var->negatedvar != NULL);
11897  assert(var->negatedvar->negatedvar == var);
11899  break;
11900 
11901  default:
11902  SCIPerrorMessage("unknown variable status\n");
11903  SCIPABORT();
11904  return SCIP_ERROR; /*lint !e527*/
11905  }
11906 
11907  return SCIP_OKAY;
11908 }
11909 
11910 /** compares the index of two variables, only active, fixed or negated variables are allowed, if a variable
11911  * is negated then the index of the corresponding active variable is taken, returns -1 if first is
11912  * smaller than, and +1 if first is greater than second variable index; returns 0 if both indices
11913  * are equal, which means both variables are equal
11914  */
11916  SCIP_VAR* var1, /**< first problem variable */
11917  SCIP_VAR* var2 /**< second problem variable */
11918  )
11919 {
11920  assert(var1 != NULL);
11921  assert(var2 != NULL);
11924 
11926  var1 = SCIPvarGetNegatedVar(var1);
11928  var2 = SCIPvarGetNegatedVar(var2);
11929 
11930  assert(var1 != NULL);
11931  assert(var2 != NULL);
11932 
11933  if( SCIPvarGetIndex(var1) < SCIPvarGetIndex(var2) )
11934  return -1;
11935  else if( SCIPvarGetIndex(var1) > SCIPvarGetIndex(var2) )
11936  return +1;
11937 
11938  assert(var1 == var2);
11939  return 0;
11940 }
11941 
11942 /** comparison method for sorting active and negated variables by non-decreasing index, active and negated
11943  * variables are handled as the same variables
11944  */
11945 SCIP_DECL_SORTPTRCOMP(SCIPvarCompActiveAndNegated)
11947  return SCIPvarCompareActiveAndNegated((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
11948 }
11949 
11950 /** compares the index of two variables, returns -1 if first is smaller than, and +1 if first is greater than second
11951  * variable index; returns 0 if both indices are equal, which means both variables are equal
11952  */
11953 int SCIPvarCompare(
11954  SCIP_VAR* var1, /**< first problem variable */
11955  SCIP_VAR* var2 /**< second problem variable */
11956  )
11957 {
11958  assert(var1 != NULL);
11959  assert(var2 != NULL);
11960 
11961  if( var1->index < var2->index )
11962  return -1;
11963  else if( var1->index > var2->index )
11964  return +1;
11965  else
11966  {
11967  assert(var1 == var2);
11968  return 0;
11969  }
11970 }
11971 
11972 /** comparison method for sorting variables by non-decreasing index */
11973 SCIP_DECL_SORTPTRCOMP(SCIPvarComp)
11975  return SCIPvarCompare((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
11976 }
11977 
11978 /** comparison method for sorting variables by non-decreasing objective coefficient */
11979 SCIP_DECL_SORTPTRCOMP(SCIPvarCompObj)
11981  SCIP_Real obj1;
11982  SCIP_Real obj2;
11983 
11984  obj1 = SCIPvarGetObj((SCIP_VAR*)elem1);
11985  obj2 = SCIPvarGetObj((SCIP_VAR*)elem2);
11986 
11987  if( obj1 < obj2 )
11988  return -1;
11989  else if( obj1 > obj2 )
11990  return +1;
11991  else
11992  return 0;
11993 }
11994 
11995 /** hash key retrieval function for variables */
11996 SCIP_DECL_HASHGETKEY(SCIPvarGetHashkey)
11997 { /*lint --e{715}*/
11998  return elem;
11999 }
12000 
12001 /** returns TRUE iff the indices of both variables are equal */
12002 SCIP_DECL_HASHKEYEQ(SCIPvarIsHashkeyEq)
12003 { /*lint --e{715}*/
12004  if( key1 == key2 )
12005  return TRUE;
12006  return FALSE;
12007 }
12008 
12009 /** returns the hash value of the key */
12010 SCIP_DECL_HASHKEYVAL(SCIPvarGetHashkeyVal)
12011 { /*lint --e{715}*/
12012  assert( SCIPvarGetIndex((SCIP_VAR*) key) >= 0 );
12013  return (unsigned int) SCIPvarGetIndex((SCIP_VAR*) key);
12014 }
12015 
12016 /** return for given variables all their active counterparts; all active variables will be pairwise different */
12018  SCIP_SET* set, /**< global SCIP settings */
12019  SCIP_VAR** vars, /**< variable array with given variables and as output all active
12020  * variables, if enough slots exist
12021  */
12022  int* nvars, /**< number of given variables, and as output number of active variables,
12023  * if enough slots exist
12024  */
12025  int varssize, /**< available slots in vars array */
12026  int* requiredsize /**< pointer to store the required array size for the active variables */
12027  )
12028 {
12029  SCIP_VAR** activevars;
12030  int nactivevars;
12031  int activevarssize;
12032 
12033  SCIP_VAR* var;
12034  int v;
12035 
12036  SCIP_VAR** tmpvars;
12037  SCIP_VAR** multvars;
12038  int tmpvarssize;
12039  int ntmpvars;
12040  int noldtmpvars;
12041  int nmultvars;
12042 
12043  assert(set != NULL);
12044  assert(nvars != NULL);
12045  assert(vars != NULL || *nvars == 0);
12046  assert(varssize >= *nvars);
12047  assert(requiredsize != NULL);
12048 
12049  *requiredsize = 0;
12050 
12051  if( *nvars == 0 )
12052  return SCIP_OKAY;
12053 
12054  nactivevars = 0;
12055  activevarssize = *nvars;
12056  ntmpvars = *nvars;
12057  tmpvarssize = *nvars;
12058 
12059  /* temporary memory */
12060  SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
12061  /* coverity[copy_paste_error] */
12062  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
12063 
12064  noldtmpvars = ntmpvars;
12065 
12066  /* sort all variables to combine equal variables easily */
12067  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
12068  for( v = ntmpvars - 1; v > 0; --v )
12069  {
12070  /* combine same variables */
12071  if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
12072  {
12073  --ntmpvars;
12074  tmpvars[v] = tmpvars[ntmpvars];
12075  }
12076  }
12077  /* sort all variables again to combine equal variables later on */
12078  if( noldtmpvars > ntmpvars )
12079  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
12080 
12081  /* collect for each variable the representation in active variables */
12082  while( ntmpvars >= 1 )
12083  {
12084  --ntmpvars;
12085  var = tmpvars[ntmpvars];
12086  assert( var != NULL );
12087 
12088  switch( SCIPvarGetStatus(var) )
12089  {
12091  if( var->data.original.transvar == NULL )
12092  {
12093  SCIPerrorMessage("original variable has no transformed variable attached\n");
12094  SCIPABORT();
12095  return SCIP_INVALIDDATA; /*lint !e527*/
12096  }
12097  tmpvars[ntmpvars] = var->data.original.transvar;
12098  ++ntmpvars;
12099  break;
12100 
12102  tmpvars[ntmpvars] = var->data.aggregate.var;
12103  ++ntmpvars;
12104  break;
12105 
12107  tmpvars[ntmpvars] = var->negatedvar;
12108  ++ntmpvars;
12109  break;
12110 
12111  case SCIP_VARSTATUS_LOOSE:
12112  case SCIP_VARSTATUS_COLUMN:
12113  /* check for space in temporary memory */
12114  if( nactivevars >= activevarssize )
12115  {
12116  activevarssize *= 2;
12117  SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
12118  assert(nactivevars < activevarssize);
12119  }
12120  activevars[nactivevars] = var;
12121  nactivevars++;
12122  break;
12123 
12125  /* x = a_1*y_1 + ... + a_n*y_n + c */
12126  nmultvars = var->data.multaggr.nvars;
12127  multvars = var->data.multaggr.vars;
12128 
12129  /* check for space in temporary memory */
12130  if( nmultvars + ntmpvars > tmpvarssize )
12131  {
12132  while( nmultvars + ntmpvars > tmpvarssize )
12133  tmpvarssize *= 2;
12134  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
12135  assert(nmultvars + ntmpvars <= tmpvarssize);
12136  }
12137 
12138  /* copy all multi-aggregation variables into our working array */
12139  BMScopyMemoryArray(&tmpvars[ntmpvars], multvars, nmultvars); /*lint !e866*/
12140 
12141  /* get active, fixed or multi-aggregated corresponding variables for all new ones */
12142  SCIPvarsGetProbvar(&tmpvars[ntmpvars], nmultvars);
12143 
12144  ntmpvars += nmultvars;
12145  noldtmpvars = ntmpvars;
12146 
12147  /* sort all variables to combine equal variables easily */
12148  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
12149  for( v = ntmpvars - 1; v > 0; --v )
12150  {
12151  /* combine same variables */
12152  if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
12153  {
12154  --ntmpvars;
12155  tmpvars[v] = tmpvars[ntmpvars];
12156  }
12157  }
12158  /* sort all variables again to combine equal variables later on */
12159  if( noldtmpvars > ntmpvars )
12160  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
12161 
12162  break;
12163 
12164  case SCIP_VARSTATUS_FIXED:
12165  /* no need for memorizing fixed variables */
12166  break;
12167 
12168  default:
12169  SCIPerrorMessage("unknown variable status\n");
12170  SCIPABORT();
12171  return SCIP_INVALIDDATA; /*lint !e527*/
12172  }
12173  }
12174 
12175  /* sort variable array by variable index */
12176  SCIPsortPtr((void**)activevars, SCIPvarComp, nactivevars);
12177 
12178  /* eliminate duplicates and count required size */
12179  v = nactivevars - 1;
12180  while( v > 0 )
12181  {
12182  /* combine both variable since they are the same */
12183  if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
12184  {
12185  --nactivevars;
12186  activevars[v] = activevars[nactivevars];
12187  }
12188  --v;
12189  }
12190  *requiredsize = nactivevars;
12191 
12192  if( varssize >= *requiredsize )
12193  {
12194  assert(vars != NULL);
12195 
12196  *nvars = *requiredsize;
12197  BMScopyMemoryArray(vars, activevars, nactivevars);
12198  }
12199 
12200  SCIPsetFreeBufferArray(set, &tmpvars);
12201  SCIPsetFreeBufferArray(set, &activevars);
12202 
12203  return SCIP_OKAY;
12204 }
12205 
12206 /** gets corresponding active, fixed, or multi-aggregated problem variables of given variables,
12207  * @note the content of the given array will/might change
12208  */
12209 void SCIPvarsGetProbvar(
12210  SCIP_VAR** vars, /**< array of problem variables */
12211  int nvars /**< number of variables */
12212  )
12213 {
12214  int v;
12215 
12216  assert(vars != NULL || nvars == 0);
12217 
12218  for( v = nvars - 1; v >= 0; --v )
12219  {
12220  assert(vars != NULL);
12221  assert(vars[v] != NULL);
12222 
12223  vars[v] = SCIPvarGetProbvar(vars[v]);
12224  assert(vars[v] != NULL);
12225  }
12226 }
12227 
12228 /** gets corresponding active, fixed, or multi-aggregated problem variable of a variable */
12230  SCIP_VAR* var /**< problem variable */
12231  )
12232 {
12233  SCIP_VAR* retvar;
12234 
12235  assert(var != NULL);
12236 
12237  retvar = var;
12238 
12239  SCIPdebugMessage("get problem variable of <%s>\n", var->name);
12240 
12241  while( TRUE ) /*lint !e716 */
12242  {
12243  assert(retvar != NULL);
12244 
12245  switch( SCIPvarGetStatus(retvar) )
12246  {
12248  if( retvar->data.original.transvar == NULL )
12249  {
12250  SCIPerrorMessage("original variable has no transformed variable attached\n");
12251  SCIPABORT();
12252  return NULL; /*lint !e527 */
12253  }
12254  retvar = retvar->data.original.transvar;
12255  break;
12256 
12257  case SCIP_VARSTATUS_LOOSE:
12258  case SCIP_VARSTATUS_COLUMN:
12259  case SCIP_VARSTATUS_FIXED:
12260  return retvar;
12261 
12263  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12264  if ( retvar->data.multaggr.nvars == 1 )
12265  retvar = retvar->data.multaggr.vars[0];
12266  else
12267  return retvar;
12268  break;
12269 
12271  retvar = retvar->data.aggregate.var;
12272  break;
12273 
12275  retvar = retvar->negatedvar;
12276  break;
12277 
12278  default:
12279  SCIPerrorMessage("unknown variable status\n");
12280  SCIPABORT();
12281  return NULL; /*lint !e527*/
12282  }
12283  }
12284 }
12285 
12286 /** gets corresponding active, fixed, or multi-aggregated problem variables of binary variables and updates the given
12287  * negation status of each variable
12288  */
12290  SCIP_VAR*** vars, /**< pointer to binary problem variables */
12291  SCIP_Bool** negatedarr, /**< pointer to corresponding array to update the negation status */
12292  int nvars /**< number of variables and values in vars and negated array */
12293  )
12294 {
12295  SCIP_VAR** var;
12296  SCIP_Bool* negated;
12297  int v;
12298 
12299  assert(vars != NULL);
12300  assert(*vars != NULL || nvars == 0);
12301  assert(negatedarr != NULL);
12302  assert(*negatedarr != NULL || nvars == 0);
12303 
12304  for( v = nvars - 1; v >= 0; --v )
12305  {
12306  var = &((*vars)[v]);
12307  negated = &((*negatedarr)[v]);
12308 
12309  /* get problem variable */
12310  SCIP_CALL( SCIPvarGetProbvarBinary(var, negated) );
12311  }
12312 
12313  return SCIP_OKAY;
12314 }
12315 
12316 
12317 /** gets corresponding active, fixed, or multi-aggregated problem variable of a binary variable and updates the given
12318  * negation status (this means you have to assign a value to SCIP_Bool negated before calling this method, usually
12319  * FALSE is used)
12320  */
12322  SCIP_VAR** var, /**< pointer to binary problem variable */
12323  SCIP_Bool* negated /**< pointer to update the negation status */
12324  )
12325 {
12327 #ifndef NDEBUG
12328  SCIP_Real constant = 0.0;
12329  SCIP_Bool orignegated;
12330 #endif
12331 
12332  assert(var != NULL);
12333  assert(*var != NULL);
12334  assert(negated != NULL);
12335  assert(SCIPvarIsBinary(*var));
12336 
12337 #ifndef NDEBUG
12338  orignegated = *negated;
12339 #endif
12340 
12341  while( !active && *var != NULL )
12342  {
12343  switch( SCIPvarGetStatus(*var) )
12344  {
12346  if( (*var)->data.original.transvar == NULL )
12347  return SCIP_OKAY;
12348  *var = (*var)->data.original.transvar;
12349  break;
12350 
12351  case SCIP_VARSTATUS_LOOSE:
12352  case SCIP_VARSTATUS_COLUMN:
12353  case SCIP_VARSTATUS_FIXED:
12354  active = TRUE;
12355  break;
12356 
12358  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12359  if ( (*var)->data.multaggr.nvars == 1 )
12360  {
12361  assert( (*var)->data.multaggr.vars != NULL );
12362  assert( (*var)->data.multaggr.scalars != NULL );
12363  assert( SCIPvarIsBinary((*var)->data.multaggr.vars[0]) );
12364  assert(!EPSZ((*var)->data.multaggr.scalars[0], 1e-06));
12365 
12366  /* if not all variables were fully propagated, it might happen that a variable is multi-aggregated to
12367  * another variable which needs to be fixed
12368  *
12369  * e.g. x = y - 1 => (x = 0 && y = 1)
12370  * e.g. x = y + 1 => (x = 1 && y = 0)
12371  *
12372  * is this special case we need to return the muti-aggregation
12373  */
12374  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)) )
12375  {
12376  assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06));
12377  }
12378  else
12379  {
12380  /* @note due to fixations, a multi-aggregation can have a constant of zero and a negative scalar or even
12381  * a scalar in absolute value unequal to one, in this case this aggregation variable needs to be
12382  * fixed to zero, but this should be done by another enforcement; so not depending on the scalar,
12383  * we will return the aggregated variable;
12384  */
12385  if( !EPSEQ(REALABS((*var)->data.multaggr.scalars[0]), 1.0, 1e-06) )
12386  {
12387  active = TRUE;
12388  break;
12389  }
12390 
12391  /* @note it may also happen that the constant is larger than 1 or smaller than 0, in that case the
12392  * aggregation variable needs to be fixed to one, but this should be done by another enforcement;
12393  * so if this is the case, we will return the aggregated variable
12394  */
12395  assert(EPSZ((*var)->data.multaggr.constant, 1e-06) || EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06)
12396  || EPSZ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1e-06)
12397  || EPSEQ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1.0, 1e-06));
12398 
12399  if( !EPSZ((*var)->data.multaggr.constant, 1e-06) && !EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06) )
12400  {
12401  active = TRUE;
12402  break;
12403  }
12404 
12405  assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06) || EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
12406 
12407  if( EPSZ((*var)->data.multaggr.constant, 1e-06) )
12408  {
12409  /* if the scalar is negative, either the aggregation variable is already fixed to zero or has at
12410  * least one uplock (that hopefully will enforce this fixation to zero); can it happen that this
12411  * variable itself is multi-aggregated again?
12412  */
12413  assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06) ?
12414  ((SCIPvarGetUbGlobal((*var)->data.multaggr.vars[0]) < 0.5) ||
12415  SCIPvarGetNLocksUpType((*var)->data.multaggr.vars[0], SCIP_LOCKTYPE_MODEL) > 0) : TRUE);
12416  }
12417  else
12418  {
12419  assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
12420 #ifndef NDEBUG
12421  constant += (*negated) != orignegated ? -1.0 : 1.0;
12422 #endif
12423 
12424  *negated = !(*negated);
12425  }
12426  *var = (*var)->data.multaggr.vars[0];
12427  break;
12428  }
12429  }
12430  active = TRUE; /*lint !e838*/
12431  break;
12432 
12433  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
12434  assert((*var)->data.aggregate.var != NULL);
12435  assert(EPSEQ((*var)->data.aggregate.scalar, 1.0, 1e-06) || EPSEQ((*var)->data.aggregate.scalar, -1.0, 1e-06));
12436  assert(EPSLE((*var)->data.aggregate.var->glbdom.ub - (*var)->data.aggregate.var->glbdom.lb, 1.0, 1e-06));
12437 #ifndef NDEBUG
12438  constant += (*negated) != orignegated ? -(*var)->data.aggregate.constant : (*var)->data.aggregate.constant;
12439 #endif
12440 
12441  *negated = ((*var)->data.aggregate.scalar > 0.0) ? *negated : !(*negated);
12442  *var = (*var)->data.aggregate.var;
12443  break;
12444 
12445  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
12446  assert((*var)->negatedvar != NULL);
12447 #ifndef NDEBUG
12448  constant += (*negated) != orignegated ? -1.0 : 1.0;
12449 #endif
12450 
12451  *negated = !(*negated);
12452  *var = (*var)->negatedvar;
12453  break;
12454 
12455  default:
12456  SCIPerrorMessage("unknown variable status\n");
12457  return SCIP_INVALIDDATA;
12458  }
12459  }
12460  assert(active == (*var != NULL));
12461 
12462  if( active )
12463  {
12464  assert(SCIPvarIsBinary(*var));
12465  assert(EPSZ(constant, 1e-06) || EPSEQ(constant, 1.0, 1e-06));
12466  assert(EPSZ(constant, 1e-06) == ((*negated) == orignegated));
12467 
12468  return SCIP_OKAY;
12469  }
12470  else
12471  {
12472  SCIPerrorMessage("active variable path leads to NULL pointer\n");
12473  return SCIP_INVALIDDATA;
12474  }
12475 }
12476 
12477 /** transforms given variable, boundtype and bound to the corresponding active, fixed, or multi-aggregated variable
12478  * values
12479  */
12481  SCIP_VAR** var, /**< pointer to problem variable */
12482  SCIP_Real* bound, /**< pointer to bound value to transform */
12483  SCIP_BOUNDTYPE* boundtype /**< pointer to type of bound: lower or upper bound */
12484  )
12485 {
12486  assert(var != NULL);
12487  assert(*var != NULL);
12488  assert(bound != NULL);
12489  assert(boundtype != NULL);
12490 
12491  SCIPdebugMessage("get probvar bound %g of type %d of variable <%s>\n", *bound, *boundtype, (*var)->name);
12492 
12493  switch( SCIPvarGetStatus(*var) )
12494  {
12496  if( (*var)->data.original.transvar == NULL )
12497  {
12498  SCIPerrorMessage("original variable has no transformed variable attached\n");
12499  return SCIP_INVALIDDATA;
12500  }
12501  *var = (*var)->data.original.transvar;
12502  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12503  break;
12504 
12505  case SCIP_VARSTATUS_LOOSE:
12506  case SCIP_VARSTATUS_COLUMN:
12507  case SCIP_VARSTATUS_FIXED:
12508  break;
12509 
12511  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12512  if ( (*var)->data.multaggr.nvars == 1 )
12513  {
12514  assert( (*var)->data.multaggr.vars != NULL );
12515  assert( (*var)->data.multaggr.scalars != NULL );
12516  assert( (*var)->data.multaggr.scalars[0] != 0.0 );
12517 
12518  (*bound) /= (*var)->data.multaggr.scalars[0];
12519  (*bound) -= (*var)->data.multaggr.constant/(*var)->data.multaggr.scalars[0];
12520  if ( (*var)->data.multaggr.scalars[0] < 0.0 )
12521  {
12522  if ( *boundtype == SCIP_BOUNDTYPE_LOWER )
12523  *boundtype = SCIP_BOUNDTYPE_UPPER;
12524  else
12525  *boundtype = SCIP_BOUNDTYPE_LOWER;
12526  }
12527  *var = (*var)->data.multaggr.vars[0];
12528  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12529  }
12530  break;
12531 
12532  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
12533  assert((*var)->data.aggregate.var != NULL);
12534  assert((*var)->data.aggregate.scalar != 0.0);
12535 
12536  (*bound) /= (*var)->data.aggregate.scalar;
12537  (*bound) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12538  if( (*var)->data.aggregate.scalar < 0.0 )
12539  {
12540  if( *boundtype == SCIP_BOUNDTYPE_LOWER )
12541  *boundtype = SCIP_BOUNDTYPE_UPPER;
12542  else
12543  *boundtype = SCIP_BOUNDTYPE_LOWER;
12544  }
12545  *var = (*var)->data.aggregate.var;
12546  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12547  break;
12548 
12549  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12550  assert((*var)->negatedvar != NULL);
12551  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12552  assert((*var)->negatedvar->negatedvar == *var);
12553  (*bound) = (*var)->data.negate.constant - *bound;
12554  if( *boundtype == SCIP_BOUNDTYPE_LOWER )
12555  *boundtype = SCIP_BOUNDTYPE_UPPER;
12556  else
12557  *boundtype = SCIP_BOUNDTYPE_LOWER;
12558  *var = (*var)->negatedvar;
12559  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12560  break;
12561 
12562  default:
12563  SCIPerrorMessage("unknown variable status\n");
12564  return SCIP_INVALIDDATA;
12565  }
12566 
12567  return SCIP_OKAY;
12568 }
12569 
12570 /** transforms given variable and domain hole to the corresponding active, fixed, or multi-aggregated variable
12571  * values
12572  */
12574  SCIP_VAR** var, /**< pointer to problem variable */
12575  SCIP_Real* left, /**< pointer to left bound of open interval in hole to transform */
12576  SCIP_Real* right /**< pointer to right bound of open interval in hole to transform */
12577  )
12578 {
12579  assert(var != NULL);
12580  assert(*var != NULL);
12581  assert(left != NULL);
12582  assert(right != NULL);
12583 
12584  SCIPdebugMessage("get probvar hole (%g,%g) of variable <%s>\n", *left, *right, (*var)->name);
12585 
12586  switch( SCIPvarGetStatus(*var) )
12587  {
12589  if( (*var)->data.original.transvar == NULL )
12590  {
12591  SCIPerrorMessage("original variable has no transformed variable attached\n");
12592  return SCIP_INVALIDDATA;
12593  }
12594  *var = (*var)->data.original.transvar;
12595  SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
12596  break;
12597 
12598  case SCIP_VARSTATUS_LOOSE:
12599  case SCIP_VARSTATUS_COLUMN:
12600  case SCIP_VARSTATUS_FIXED:
12602  break;
12603 
12604  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
12605  assert((*var)->data.aggregate.var != NULL);
12606  assert((*var)->data.aggregate.scalar != 0.0);
12607 
12608  /* scale back */
12609  (*left) /= (*var)->data.aggregate.scalar;
12610  (*right) /= (*var)->data.aggregate.scalar;
12611 
12612  /* shift back */
12613  (*left) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12614  (*right) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12615 
12616  *var = (*var)->data.aggregate.var;
12617 
12618  /* check if the interval bounds have to swapped */
12619  if( (*var)->data.aggregate.scalar < 0.0 )
12620  {
12621  SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
12622  }
12623  else
12624  {
12625  SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
12626  }
12627  break;
12628 
12629  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12630  assert((*var)->negatedvar != NULL);
12631  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12632  assert((*var)->negatedvar->negatedvar == *var);
12633 
12634  /* shift and scale back */
12635  (*left) = (*var)->data.negate.constant - (*left);
12636  (*right) = (*var)->data.negate.constant - (*right);
12637 
12638  *var = (*var)->negatedvar;
12639 
12640  /* through the negated variable the left and right interval bound have to swapped */
12641  SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
12642  break;
12643 
12644  default:
12645  SCIPerrorMessage("unknown variable status\n");
12646  return SCIP_INVALIDDATA;
12647  }
12648 
12649  return SCIP_OKAY;
12650 }
12651 
12652 /** transforms given variable, scalar and constant to the corresponding active, fixed, or
12653  * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed variable,
12654  * "scalar" will be 0.0 and the value of the sum will be stored in "constant"; a multi-aggregation
12655  * with only one active variable (this can happen due to fixings after the multi-aggregation),
12656  * is treated like an aggregation; if the multi-aggregation constant is infinite, "scalar" will be 0.0
12657  */
12659  SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
12660  SCIP_SET* set, /**< global SCIP settings */
12661  SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
12662  SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
12663  )
12664 {
12665  assert(var != NULL);
12666  assert(scalar != NULL);
12667  assert(constant != NULL);
12668 
12669  while( *var != NULL )
12670  {
12671  switch( SCIPvarGetStatus(*var) )
12672  {
12674  if( (*var)->data.original.transvar == NULL )
12675  {
12676  SCIPerrorMessage("original variable has no transformed variable attached\n");
12677  return SCIP_INVALIDDATA;
12678  }
12679  *var = (*var)->data.original.transvar;
12680  break;
12681 
12682  case SCIP_VARSTATUS_LOOSE:
12683  case SCIP_VARSTATUS_COLUMN:
12684  return SCIP_OKAY;
12685 
12686  case SCIP_VARSTATUS_FIXED: /* x = c' => a*x + c == (a*c' + c) */
12687  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12688  {
12689  if( SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)) )
12690  {
12691  assert(*scalar != 0.0);
12692  if( (*scalar) * (*var)->glbdom.lb > 0.0 )
12693  (*constant) = SCIPsetInfinity(set);
12694  else
12695  (*constant) = -SCIPsetInfinity(set);
12696  }
12697  else
12698  (*constant) += *scalar * (*var)->glbdom.lb;
12699  }
12700 #ifndef NDEBUG
12701  else
12702  {
12703  assert(!SCIPsetIsInfinity(set, (*constant)) || !((*scalar) * (*var)->glbdom.lb < 0.0 &&
12704  (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
12705  assert(!SCIPsetIsInfinity(set, -(*constant)) || !((*scalar) * (*var)->glbdom.lb > 0.0 &&
12706  (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
12707  }
12708 #endif
12709  *scalar = 0.0;
12710  return SCIP_OKAY;
12711 
12713  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12714  if ( (*var)->data.multaggr.nvars == 1 )
12715  {
12716  assert((*var)->data.multaggr.vars != NULL);
12717  assert((*var)->data.multaggr.scalars != NULL);
12718  assert((*var)->data.multaggr.vars[0] != NULL);
12719  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12720  {
12721  /* the multi-aggregation constant can be infinite, if one of the multi-aggregation variables
12722  * was fixed to +/-infinity; ensure that the constant is set to +/-infinity, too, and the scalar
12723  * is set to 0.0, because the multi-aggregated variable can be seen as fixed, too
12724  */
12725  if( SCIPsetIsInfinity(set, (*var)->data.multaggr.constant)
12726  || SCIPsetIsInfinity(set, -((*var)->data.multaggr.constant)) )
12727  {
12728  if( (*scalar) * (*var)->data.multaggr.constant > 0 )
12729  {
12730  assert(!SCIPsetIsInfinity(set, -(*constant)));
12731  (*constant) = SCIPsetInfinity(set);
12732  }
12733  else
12734  {
12735  assert(!SCIPsetIsInfinity(set, *constant));
12736  (*constant) = -SCIPsetInfinity(set);
12737  }
12738  (*scalar) = 0.0;
12739  }
12740  else
12741  (*constant) += *scalar * (*var)->data.multaggr.constant;
12742  }
12743  (*scalar) *= (*var)->data.multaggr.scalars[0];
12744  *var = (*var)->data.multaggr.vars[0];
12745  break;
12746  }
12747  return SCIP_OKAY;
12748 
12749  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
12750  assert((*var)->data.aggregate.var != NULL);
12751  assert(!SCIPsetIsInfinity(set, (*var)->data.aggregate.constant)
12752  && !SCIPsetIsInfinity(set, (*var)->data.aggregate.constant));
12753  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12754  (*constant) += *scalar * (*var)->data.aggregate.constant;
12755  (*scalar) *= (*var)->data.aggregate.scalar;
12756  *var = (*var)->data.aggregate.var;
12757  break;
12758 
12759  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
12760  assert((*var)->negatedvar != NULL);
12761  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12762  assert((*var)->negatedvar->negatedvar == *var);
12763  assert(!SCIPsetIsInfinity(set, (*var)->data.negate.constant)
12764  && !SCIPsetIsInfinity(set, (*var)->data.negate.constant));
12765  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12766  (*constant) += *scalar * (*var)->data.negate.constant;
12767  (*scalar) *= -1.0;
12768  *var = (*var)->negatedvar;
12769  break;
12770 
12771  default:
12772  SCIPerrorMessage("unknown variable status\n");
12773  SCIPABORT();
12774  return SCIP_INVALIDDATA; /*lint !e527*/
12775  }
12776  }
12777  *scalar = 0.0;
12778 
12779  return SCIP_OKAY;
12780 }
12781 
12782 /** retransforms given variable, scalar and constant to the corresponding original variable, scalar
12783  * and constant, if possible; if the retransformation is impossible, NULL is returned as variable
12784  */
12786  SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
12787  SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
12788  SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
12789  )
12790 {
12791  SCIP_VAR* parentvar;
12792 
12793  assert(var != NULL);
12794  assert(*var != NULL);
12795  assert(scalar != NULL);
12796  assert(constant != NULL);
12797 
12798  while( !SCIPvarIsOriginal(*var) )
12799  {
12800  /* if the variable has no parent variables, it was generated during solving and has no corresponding original
12801  * var
12802  */
12803  if( (*var)->nparentvars == 0 )
12804  {
12805  /* negated variables do not need to have a parent variables, and negated variables can exist in original
12806  * space
12807  */
12809  ((*var)->negatedvar->nparentvars == 0 || (*var)->negatedvar->parentvars[0] != *var) )
12810  {
12811  *scalar *= -1.0;
12812  *constant -= (*var)->data.negate.constant * (*scalar);
12813  *var = (*var)->negatedvar;
12814 
12815  continue;
12816  }
12817  /* if the variables does not have any parent the variables was created during solving and has no original
12818  * counterpart
12819  */
12820  else
12821  {
12822  *var = NULL;
12823 
12824  return SCIP_OKAY;
12825  }
12826  }
12827 
12828  /* follow the link to the first parent variable */
12829  parentvar = (*var)->parentvars[0];
12830  assert(parentvar != NULL);
12831 
12832  switch( SCIPvarGetStatus(parentvar) )
12833  {
12835  break;
12836 
12837  case SCIP_VARSTATUS_COLUMN:
12838  case SCIP_VARSTATUS_LOOSE:
12839  case SCIP_VARSTATUS_FIXED:
12841  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
12842  return SCIP_INVALIDDATA;
12843 
12844  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + b -> y = (x-b)/a, s*y + c = (s/a)*x + c-b*s/a */
12845  assert(parentvar->data.aggregate.var == *var);
12846  assert(parentvar->data.aggregate.scalar != 0.0);
12847  *scalar /= parentvar->data.aggregate.scalar;
12848  *constant -= parentvar->data.aggregate.constant * (*scalar);
12849  break;
12850 
12851  case SCIP_VARSTATUS_NEGATED: /* x = b - y -> y = b - x, s*y + c = -s*x + c+b*s */
12852  assert(parentvar->negatedvar != NULL);
12853  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
12854  assert(parentvar->negatedvar->negatedvar == parentvar);
12855  *scalar *= -1.0;
12856  *constant -= parentvar->data.negate.constant * (*scalar);
12857  break;
12858 
12859  default:
12860  SCIPerrorMessage("unknown variable status\n");
12861  return SCIP_INVALIDDATA;
12862  }
12863 
12864  assert( parentvar != NULL );
12865  *var = parentvar;
12866  }
12867 
12868  return SCIP_OKAY;
12869 }
12870 
12871 /** returns whether the given variable is the direct counterpart of an original problem variable */
12873  SCIP_VAR* var /**< problem variable */
12874  )
12875 {
12876  SCIP_VAR* parentvar;
12877  assert(var != NULL);
12878 
12879  if( !SCIPvarIsTransformed(var) || var->nparentvars < 1 )
12880  return FALSE;
12881 
12882  assert(var->parentvars != NULL);
12883  parentvar = var->parentvars[0];
12884  assert(parentvar != NULL);
12885 
12886  /* we follow the aggregation tree to the root unless an original variable has been found - the first entries in the parentlist are candidates */
12887  while( parentvar->nparentvars >= 1 && SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL )
12888  parentvar = parentvar->parentvars[0];
12889  assert( parentvar != NULL );
12890 
12891  return ( SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_ORIGINAL );
12892 }
12893 
12894 /** gets objective value of variable in current SCIP_LP; the value can be different from the objective value stored in
12895  * the variable's own data due to diving, that operate only on the LP without updating the variables
12896  */
12898  SCIP_VAR* var /**< problem variable */
12899  )
12900 {
12901  assert(var != NULL);
12902 
12903  /* get bounds of attached variables */
12904  switch( SCIPvarGetStatus(var) )
12905  {
12907  assert(var->data.original.transvar != NULL);
12908  return SCIPvarGetObjLP(var->data.original.transvar);
12909 
12910  case SCIP_VARSTATUS_COLUMN:
12911  assert(var->data.col != NULL);
12912  return SCIPcolGetObj(var->data.col);
12913 
12914  case SCIP_VARSTATUS_LOOSE:
12915  case SCIP_VARSTATUS_FIXED:
12916  return var->obj;
12917 
12918  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12919  assert(var->data.aggregate.var != NULL);
12920  return var->data.aggregate.scalar * SCIPvarGetObjLP(var->data.aggregate.var);
12921 
12923  SCIPerrorMessage("cannot get the objective value of a multiple aggregated variable\n");
12924  SCIPABORT();
12925  return 0.0; /*lint !e527*/
12926 
12927  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12928  assert(var->negatedvar != NULL);
12930  assert(var->negatedvar->negatedvar == var);
12931  return -SCIPvarGetObjLP(var->negatedvar);
12932 
12933  default:
12934  SCIPerrorMessage("unknown variable status\n");
12935  SCIPABORT();
12936  return 0.0; /*lint !e527*/
12937  }
12938 }
12939 
12940 /** gets lower bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
12941  * data due to diving or conflict analysis, that operate only on the LP without updating the variables
12942  */
12944  SCIP_VAR* var, /**< problem variable */
12945  SCIP_SET* set /**< global SCIP settings */
12946  )
12947 {
12948  assert(var != NULL);
12949  assert(set != NULL);
12950  assert(var->scip == set->scip);
12951 
12952  /* get bounds of attached variables */
12953  switch( SCIPvarGetStatus(var) )
12954  {
12956  assert(var->data.original.transvar != NULL);
12957  return SCIPvarGetLbLP(var->data.original.transvar, set);
12958 
12959  case SCIP_VARSTATUS_COLUMN:
12960  assert(var->data.col != NULL);
12961  return SCIPcolGetLb(var->data.col);
12962 
12963  case SCIP_VARSTATUS_LOOSE:
12964  case SCIP_VARSTATUS_FIXED:
12965  return var->locdom.lb;
12966 
12967  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12968  assert(var->data.aggregate.var != NULL);
12969  if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set)))
12970  || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set))) )
12971  {
12972  return -SCIPsetInfinity(set);
12973  }
12974  else if( var->data.aggregate.scalar > 0.0 )
12975  {
12976  /* a > 0 -> get lower bound of y */
12977  return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12978  }
12979  else if( var->data.aggregate.scalar < 0.0 )
12980  {
12981  /* a < 0 -> get upper bound of y */
12982  return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12983  }
12984  else
12985  {
12986  SCIPerrorMessage("scalar is zero in aggregation\n");
12987  SCIPABORT();
12988  return SCIP_INVALID; /*lint !e527*/
12989  }
12990 
12992  /**@todo get the sides of the corresponding linear constraint */
12993  SCIPerrorMessage("getting the bounds of a multiple aggregated variable is not implemented yet\n");
12994  SCIPABORT();
12995  return SCIP_INVALID; /*lint !e527*/
12996 
12997  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12998  assert(var->negatedvar != NULL);
13000  assert(var->negatedvar->negatedvar == var);
13001  return var->data.negate.constant - SCIPvarGetUbLP(var->negatedvar, set);
13002 
13003  default:
13004  SCIPerrorMessage("unknown variable status\n");
13005  SCIPABORT();
13006  return SCIP_INVALID; /*lint !e527*/
13007  }
13008 }
13009 
13010 /** gets upper bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
13011  * data due to diving or conflict analysis, that operate only on the LP without updating the variables
13012  */
13014  SCIP_VAR* var, /**< problem variable */
13015  SCIP_SET* set /**< global SCIP settings */
13016  )
13017 {
13018  assert(var != NULL);
13019  assert(set != NULL);
13020  assert(var->scip == set->scip);
13021 
13022  /* get bounds of attached variables */
13023  switch( SCIPvarGetStatus(var) )
13024  {
13026  assert(var->data.original.transvar != NULL);
13027  return SCIPvarGetUbLP(var->data.original.transvar, set);
13028 
13029  case SCIP_VARSTATUS_COLUMN:
13030  assert(var->data.col != NULL);
13031  return SCIPcolGetUb(var->data.col);
13032 
13033  case SCIP_VARSTATUS_LOOSE:
13034  case SCIP_VARSTATUS_FIXED:
13035  return var->locdom.ub;
13036 
13037  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
13038  assert(var->data.aggregate.var != NULL);
13039  if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set)))
13040  || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set))) )
13041  {
13042  return SCIPsetInfinity(set);
13043  }
13044  if( var->data.aggregate.scalar > 0.0 )
13045  {
13046  /* a > 0 -> get upper bound of y */
13047  return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
13048  }
13049  else if( var->data.aggregate.scalar < 0.0 )
13050  {
13051  /* a < 0 -> get lower bound of y */
13052  return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
13053  }
13054  else
13055  {
13056  SCIPerrorMessage("scalar is zero in aggregation\n");
13057  SCIPABORT();
13058  return SCIP_INVALID; /*lint !e527*/
13059  }
13060 
13062  SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
13063  SCIPABORT();
13064  return SCIP_INVALID; /*lint !e527*/
13065 
13066  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13067  assert(var->negatedvar != NULL);
13069  assert(var->negatedvar->negatedvar == var);
13070  return var->data.negate.constant - SCIPvarGetLbLP(var->negatedvar, set);
13071 
13072  default:
13073  SCIPerrorMessage("unknown variable status\n");
13074  SCIPABORT();
13075  return SCIP_INVALID; /*lint !e527*/
13076  }
13077 }
13078 
13079 /** gets primal LP solution value of variable */
13081  SCIP_VAR* var /**< problem variable */
13082  )
13083 {
13084  assert(var != NULL);
13085 
13086  switch( SCIPvarGetStatus(var) )
13087  {
13089  if( var->data.original.transvar == NULL )
13090  return SCIP_INVALID;
13091  return SCIPvarGetLPSol(var->data.original.transvar);
13092 
13093  case SCIP_VARSTATUS_LOOSE:
13094  return SCIPvarGetBestBoundLocal(var);
13095 
13096  case SCIP_VARSTATUS_COLUMN:
13097  assert(var->data.col != NULL);
13098  return SCIPcolGetPrimsol(var->data.col);
13099 
13100  case SCIP_VARSTATUS_FIXED:
13101  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13102  return var->locdom.lb;
13103 
13105  {
13106  SCIP_Real lpsolval;
13107 
13108  assert(!var->donotaggr);
13109  assert(var->data.aggregate.var != NULL);
13110  lpsolval = SCIPvarGetLPSol(var->data.aggregate.var);
13111 
13112  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13113  * corresponding infinity value instead of performing an arithmetical transformation (compare method
13114  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13115  * (or is called by) a public interface method; instead, we only assert that values are finite
13116  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13117  * positives and negatives if the parameter <numerics/infinity> is modified by the user
13118  */
13119  assert(lpsolval > -SCIP_DEFAULT_INFINITY);
13120  assert(lpsolval < +SCIP_DEFAULT_INFINITY);
13121  return var->data.aggregate.scalar * lpsolval + var->data.aggregate.constant;
13122  }
13124  {
13125  SCIP_Real primsol;
13126  int i;
13127 
13128  assert(!var->donotmultaggr);
13129  assert(var->data.multaggr.vars != NULL);
13130  assert(var->data.multaggr.scalars != NULL);
13131  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13132  * assert(var->data.multaggr.nvars >= 2);
13133  */
13134  primsol = var->data.multaggr.constant;
13135  for( i = 0; i < var->data.multaggr.nvars; ++i )
13136  primsol += var->data.multaggr.scalars[i] * SCIPvarGetLPSol(var->data.multaggr.vars[i]);
13137  return primsol;
13138  }
13139  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13140  assert(var->negatedvar != NULL);
13142  assert(var->negatedvar->negatedvar == var);
13143  return var->data.negate.constant - SCIPvarGetLPSol(var->negatedvar);
13144 
13145  default:
13146  SCIPerrorMessage("unknown variable status\n");
13147  SCIPABORT();
13148  return SCIP_INVALID; /*lint !e527*/
13149  }
13150 }
13151 
13152 /** gets primal NLP solution value of variable */
13154  SCIP_VAR* var /**< problem variable */
13155  )
13156 {
13157  SCIP_Real solval;
13158  int i;
13159 
13160  assert(var != NULL);
13161 
13162  /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
13163  switch( SCIPvarGetStatus(var) )
13164  {
13166  return SCIPvarGetNLPSol(var->data.original.transvar);
13167 
13168  case SCIP_VARSTATUS_LOOSE:
13169  case SCIP_VARSTATUS_COLUMN:
13170  return var->nlpsol;
13171 
13172  case SCIP_VARSTATUS_FIXED:
13173  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
13174  assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
13175  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
13176  return SCIPvarGetLbGlobal(var);
13177 
13178  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13179  solval = SCIPvarGetNLPSol(var->data.aggregate.var);
13180  return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
13181 
13183  solval = var->data.multaggr.constant;
13184  for( i = 0; i < var->data.multaggr.nvars; ++i )
13185  solval += var->data.multaggr.scalars[i] * SCIPvarGetNLPSol(var->data.multaggr.vars[i]);
13186  return solval;
13187 
13189  solval = SCIPvarGetNLPSol(var->negatedvar);
13190  return var->data.negate.constant - solval;
13191 
13192  default:
13193  SCIPerrorMessage("unknown variable status\n");
13194  SCIPABORT();
13195  return SCIP_INVALID; /*lint !e527*/
13196  }
13197 }
13198 
13199 /** gets pseudo solution value of variable at current node */
13200 static
13202  SCIP_VAR* var /**< problem variable */
13203  )
13204 {
13205  SCIP_Real pseudosol;
13206  int i;
13207 
13208  assert(var != NULL);
13209 
13210  switch( SCIPvarGetStatus(var) )
13211  {
13213  if( var->data.original.transvar == NULL )
13214  return SCIP_INVALID;
13216 
13217  case SCIP_VARSTATUS_LOOSE:
13218  case SCIP_VARSTATUS_COLUMN:
13219  return SCIPvarGetBestBoundLocal(var);
13220 
13221  case SCIP_VARSTATUS_FIXED:
13222  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13223  return var->locdom.lb;
13224 
13226  {
13227  SCIP_Real pseudosolval;
13228  assert(!var->donotaggr);
13229  assert(var->data.aggregate.var != NULL);
13230  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13231  * corresponding infinity value instead of performing an arithmetical transformation (compare method
13232  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13233  * (or is called by) a public interface method; instead, we only assert that values are finite
13234  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13235  * positives and negatives if the parameter <numerics/infinity> is modified by the user
13236  */
13237  pseudosolval = SCIPvarGetPseudoSol(var->data.aggregate.var);
13238  assert(pseudosolval > -SCIP_DEFAULT_INFINITY);
13239  assert(pseudosolval < +SCIP_DEFAULT_INFINITY);
13240  return var->data.aggregate.scalar * pseudosolval + var->data.aggregate.constant;
13241  }
13243  assert(!var->donotmultaggr);
13244  assert(var->data.multaggr.vars != NULL);
13245  assert(var->data.multaggr.scalars != NULL);
13246  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13247  * assert(var->data.multaggr.nvars >= 2);
13248  */
13249  pseudosol = var->data.multaggr.constant;
13250  for( i = 0; i < var->data.multaggr.nvars; ++i )
13251  pseudosol += var->data.multaggr.scalars[i] * SCIPvarGetPseudoSol(var->data.multaggr.vars[i]);
13252  return pseudosol;
13253 
13254  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13255  assert(var->negatedvar != NULL);
13257  assert(var->negatedvar->negatedvar == var);
13258  return var->data.negate.constant - SCIPvarGetPseudoSol(var->negatedvar);
13259 
13260  default:
13261  SCIPerrorMessage("unknown variable status\n");
13262  SCIPABORT();
13263  return SCIP_INVALID; /*lint !e527*/
13264  }
13265 }
13266 
13267 /** gets current LP or pseudo solution value of variable */
13269  SCIP_VAR* var, /**< problem variable */
13270  SCIP_Bool getlpval /**< should the LP solution value be returned? */
13271  )
13272 {
13273  if( getlpval )
13274  return SCIPvarGetLPSol(var);
13275  else
13276  return SCIPvarGetPseudoSol(var);
13277 }
13278 
13279 /** remembers the current solution as root solution in the problem variables */
13280 void SCIPvarStoreRootSol(
13281  SCIP_VAR* var, /**< problem variable */
13282  SCIP_Bool roothaslp /**< is the root solution from LP? */
13283  )
13284 {
13285  assert(var != NULL);
13286 
13287  var->rootsol = SCIPvarGetSol(var, roothaslp);
13288 }
13289 
13290 /** updates the current solution as best root solution of the given variable if it is better */
13292  SCIP_VAR* var, /**< problem variable */
13293  SCIP_SET* set, /**< global SCIP settings */
13294  SCIP_Real rootsol, /**< root solution value */
13295  SCIP_Real rootredcost, /**< root reduced cost */
13296  SCIP_Real rootlpobjval /**< objective value of the root LP */
13297  )
13298 {
13299  assert(var != NULL);
13300  assert(set != NULL);
13301  assert(var->scip == set->scip);
13302 
13303  /* if reduced cost are zero nothing to update */
13304  if( SCIPsetIsDualfeasZero(set, rootredcost) )
13305  return;
13306 
13307  /* check if we have already a best combination stored */
13308  if( !SCIPsetIsDualfeasZero(set, var->bestrootredcost) )
13309  {
13310  SCIP_Real currcutoffbound;
13311  SCIP_Real cutoffbound;
13312  SCIP_Real bound;
13313 
13314  /* compute the cutoff bound which would improve the corresponding bound with the current stored root solution,
13315  * root reduced cost, and root LP objective value combination
13316  */
13317  if( var->bestrootredcost > 0.0 )
13318  bound = SCIPvarGetUbGlobal(var);
13319  else
13320  bound = SCIPvarGetLbGlobal(var);
13321 
13322  currcutoffbound = (bound - var->bestrootsol) * var->bestrootredcost + var->bestrootlpobjval;
13323 
13324  /* compute the cutoff bound which would improve the corresponding bound with new root solution, root reduced
13325  * cost, and root LP objective value combination
13326  */
13327  if( rootredcost > 0.0 )
13328  bound = SCIPvarGetUbGlobal(var);
13329  else
13330  bound = SCIPvarGetLbGlobal(var);
13331 
13332  cutoffbound = (bound - rootsol) * rootredcost + rootlpobjval;
13333 
13334  /* check if an improving root solution, root reduced cost, and root LP objective value is at hand */
13335  if( cutoffbound > currcutoffbound )
13336  {
13337  SCIPsetDebugMsg(set, "-> <%s> update potential cutoff bound <%g> -> <%g>\n",
13338  SCIPvarGetName(var), currcutoffbound, cutoffbound);
13339 
13340  var->bestrootsol = rootsol;
13341  var->bestrootredcost = rootredcost;
13342  var->bestrootlpobjval = rootlpobjval;
13343  }
13344  }
13345  else
13346  {
13347  SCIPsetDebugMsg(set, "-> <%s> initialize best root reduced cost information\n", SCIPvarGetName(var));
13348  SCIPsetDebugMsg(set, " -> rootsol <%g>\n", rootsol);
13349  SCIPsetDebugMsg(set, " -> rootredcost <%g>\n", rootredcost);
13350  SCIPsetDebugMsg(set, " -> rootlpobjval <%g>\n", rootlpobjval);
13351 
13352  var->bestrootsol = rootsol;
13353  var->bestrootredcost = rootredcost;
13354  var->bestrootlpobjval = rootlpobjval;
13355  }
13356 }
13357 
13358 /** returns the solution of the variable in the last root node's relaxation, if the root relaxation is not yet
13359  * completely solved, zero is returned
13360  */
13362  SCIP_VAR* var /**< problem variable */
13363  )
13364 {
13365  SCIP_Real rootsol;
13366  int i;
13367 
13368  assert(var != NULL);
13369 
13370  switch( SCIPvarGetStatus(var) )
13371  {
13373  if( var->data.original.transvar == NULL )
13374  return 0.0;
13375  return SCIPvarGetRootSol(var->data.original.transvar);
13376 
13377  case SCIP_VARSTATUS_LOOSE:
13378  case SCIP_VARSTATUS_COLUMN:
13379  return var->rootsol;
13380 
13381  case SCIP_VARSTATUS_FIXED:
13382  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13383  return var->locdom.lb;
13384 
13386  assert(!var->donotaggr);
13387  assert(var->data.aggregate.var != NULL);
13388  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13389  * corresponding infinity value instead of performing an arithmetical transformation (compare method
13390  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13391  * (or is called by) a public interface method; instead, we only assert that values are finite
13392  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13393  * positives and negatives if the parameter <numerics/infinity> is modified by the user
13394  */
13398 
13400  assert(!var->donotmultaggr);
13401  assert(var->data.multaggr.vars != NULL);
13402  assert(var->data.multaggr.scalars != NULL);
13403  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13404  * assert(var->data.multaggr.nvars >= 2);
13405  */
13406  rootsol = var->data.multaggr.constant;
13407  for( i = 0; i < var->data.multaggr.nvars; ++i )
13408  rootsol += var->data.multaggr.scalars[i] * SCIPvarGetRootSol(var->data.multaggr.vars[i]);
13409  return rootsol;
13410 
13411  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13412  assert(var->negatedvar != NULL);
13414  assert(var->negatedvar->negatedvar == var);
13415  return var->data.negate.constant - SCIPvarGetRootSol(var->negatedvar);
13416 
13417  default:
13418  SCIPerrorMessage("unknown variable status\n");
13419  SCIPABORT();
13420  return SCIP_INVALID; /*lint !e527*/
13421  }
13422 }
13423 
13424 /** returns for given variable the reduced cost */
13425 static
13427  SCIP_VAR* var, /**< problem variable */
13428  SCIP_SET* set, /**< global SCIP settings */
13429  SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
13430  SCIP_STAT* stat, /**< problem statistics */
13431  SCIP_LP* lp /**< current LP data */
13432  )
13433 {
13435  {
13436  SCIP_COL* col;
13437  SCIP_Real primsol;
13438  SCIP_BASESTAT basestat;
13439  SCIP_Bool lpissolbasic;
13440 
13441  col = SCIPvarGetCol(var);
13442  assert(col != NULL);
13443 
13444  basestat = SCIPcolGetBasisStatus(col);
13445  lpissolbasic = SCIPlpIsSolBasic(lp);
13446  primsol = SCIPcolGetPrimsol(col);
13447 
13448  if( (lpissolbasic && (basestat == SCIP_BASESTAT_LOWER || basestat == SCIP_BASESTAT_UPPER)) ||
13449  (!lpissolbasic && (SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol) || SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol))) )
13450  {
13451  SCIP_Real redcost = SCIPcolGetRedcost(col, stat, lp);
13452 
13453  assert(((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)) ||
13454  (lpissolbasic && basestat == SCIP_BASESTAT_LOWER)) ? (!SCIPsetIsDualfeasNegative(set, redcost) ||
13456  assert(((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)) ||
13457  (lpissolbasic && basestat == SCIP_BASESTAT_UPPER)) ? (!SCIPsetIsDualfeasPositive(set, redcost) ||
13458  SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var))) : TRUE);
13459 
13460  if( (varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_LOWER) ||
13461  (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)))) ||
13462  (!varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_UPPER) ||
13463  (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)))) )
13464  return redcost;
13465  else
13466  return 0.0;
13467  }
13468 
13469  return 0.0;
13470  }
13471 
13472  return 0.0;
13473 }
13474 
13475 #define MAX_CLIQUELENGTH 50
13476 /** returns for the given binary variable the reduced cost which are given by the variable itself and its implication if
13477  * the binary variable is fixed to the given value
13478  */
13480  SCIP_VAR* var, /**< problem variable */
13481  SCIP_SET* set, /**< global SCIP settings */
13482  SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
13483  SCIP_STAT* stat, /**< problem statistics */
13484  SCIP_PROB* prob, /**< transformed problem, or NULL */
13485  SCIP_LP* lp /**< current LP data */
13486  )
13487 {
13488  SCIP_Real implredcost;
13489  int ncliques;
13490  int nvars;
13491 
13492  assert(SCIPvarIsBinary(var));
13493  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
13494 
13495  /* get reduced cost of given variable */
13496  implredcost = getImplVarRedcost(var, set, varfixing, stat, lp);
13497 
13498 #ifdef SCIP_MORE_DEBUG
13499  SCIPsetDebugMsg(set, "variable <%s> itself has reduced cost of %g\n", SCIPvarGetName(var), implredcost);
13500 #endif
13501 
13502  /* the following algorithm is expensive */
13503  ncliques = SCIPvarGetNCliques(var, varfixing);
13504 
13505  if( ncliques > 0 )
13506  {
13507  SCIP_CLIQUE** cliques;
13508  SCIP_CLIQUE* clique;
13509  SCIP_VAR** clqvars;
13510  SCIP_VAR** probvars;
13511  SCIP_VAR* clqvar;
13512  SCIP_Bool* clqvalues;
13513  int* entries;
13514  int* ids;
13515  SCIP_Real redcost;
13516  SCIP_Bool cleanedup;
13517  int nclqvars;
13518  int nentries;
13519  int nids;
13520  int id;
13521  int c;
13522  int v;
13523 
13524  assert(prob != NULL);
13525  assert(SCIPprobIsTransformed(prob));
13526 
13527  nentries = SCIPprobGetNVars(prob) - SCIPprobGetNContVars(prob) + 1;
13528 
13529  SCIP_CALL_ABORT( SCIPsetAllocBufferArray(set, &ids, nentries) );
13530  nids = 0;
13531  SCIP_CALL_ABORT( SCIPsetAllocCleanBufferArray(set, &entries, nentries) );
13532 
13533  cliques = SCIPvarGetCliques(var, varfixing);
13534  assert(cliques != NULL);
13535 
13536  for( c = ncliques - 1; c >= 0; --c )
13537  {
13538  clique = cliques[c];
13539  assert(clique != NULL);
13540  nclqvars = SCIPcliqueGetNVars(clique);
13541  assert(nclqvars > 0);
13542 
13543  if( nclqvars > MAX_CLIQUELENGTH )
13544  continue;
13545 
13546  clqvars = SCIPcliqueGetVars(clique);
13547  clqvalues = SCIPcliqueGetValues(clique);
13548  assert(clqvars != NULL);
13549  assert(clqvalues != NULL);
13550 
13551  cleanedup = SCIPcliqueIsCleanedUp(clique);
13552 
13553  for( v = nclqvars - 1; v >= 0; --v )
13554  {
13555  clqvar = clqvars[v];
13556  assert(clqvar != NULL);
13557 
13558  /* ignore binary variable which are fixed */
13559  if( clqvar != var && (cleanedup || SCIPvarIsActive(clqvar)) &&
13560  (SCIPvarGetLbLocal(clqvar) < 0.5 && SCIPvarGetUbLocal(clqvar) > 0.5) )
13561  {
13562  int probindex = SCIPvarGetProbindex(clqvar) + 1;
13563  assert(0 < probindex && probindex < nentries);
13564 
13565 #if 0
13566  /* check that the variable was not yet visited or does not appear with two contradicting implications, ->
13567  * can appear since there is no guarantee that all these infeasible bounds were found
13568  */
13569  assert(!entries[probindex] || entries[probindex] == (clqvalues[v] ? probindex : -probindex));
13570 #endif
13571  if( entries[probindex] == 0 )
13572  {
13573  ids[nids] = probindex;
13574  ++nids;
13575 
13576  /* mark variable as visited */
13577  entries[probindex] = (clqvalues[v] ? probindex : -probindex);
13578  }
13579  }
13580  }
13581  }
13582 
13583  probvars = SCIPprobGetVars(prob);
13584  assert(probvars != NULL);
13585 
13586  /* add all implied reduced cost */
13587  for( v = nids - 1; v >= 0; --v )
13588  {
13589  id = ids[v];
13590  assert(0 < id && id < nentries);
13591  assert(entries[id] != 0);
13592  assert(probvars[id - 1] != NULL);
13593  assert(SCIPvarIsActive(probvars[id - 1]));
13594  assert(SCIPvarIsBinary(probvars[id - 1]));
13595  assert(SCIPvarGetLbLocal(probvars[id - 1]) < 0.5 && SCIPvarGetUbLocal(probvars[id - 1]) > 0.5);
13596 
13597  if( (entries[id] > 0) != varfixing )
13598  redcost = getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
13599  else
13600  redcost = -getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
13601 
13602  if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
13603  implredcost += redcost;
13604 
13605  /* reset entries clear buffer array */
13606  entries[id] = 0;
13607  }
13608 
13609  SCIPsetFreeCleanBufferArray(set, &entries);
13610  SCIPsetFreeBufferArray(set, &ids);
13611  }
13612 
13613 #ifdef SCIP_MORE_DEBUG
13614  SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) has implied reduced cost of %g\n", SCIPvarGetName(var), ncliques,
13615  implredcost);
13616 #endif
13617 
13618  /* collect non-binary implication information */
13619  nvars = SCIPimplicsGetNImpls(var->implics, varfixing);
13620 
13621  if( nvars > 0 )
13622  {
13623  SCIP_VAR** vars;
13624  SCIP_VAR* implvar;
13625  SCIP_COL* col;
13626  SCIP_Real* bounds;
13627  SCIP_BOUNDTYPE* boundtypes;
13628  SCIP_Real redcost;
13629  SCIP_Real lb;
13630  SCIP_Real ub;
13631  SCIP_Bool lpissolbasic;
13632  int v;
13633 
13634  vars = SCIPimplicsGetVars(var->implics, varfixing);
13635  boundtypes = SCIPimplicsGetTypes(var->implics, varfixing);
13636  bounds = SCIPimplicsGetBounds(var->implics, varfixing);
13637  lpissolbasic = SCIPlpIsSolBasic(lp);
13638 
13639  for( v = nvars - 1; v >= 0; --v )
13640  {
13641  implvar = vars[v];
13642  assert(implvar != NULL);
13643 
13644  lb = SCIPvarGetLbLocal(implvar);
13645  ub = SCIPvarGetUbLocal(implvar);
13646 
13647  /* ignore binary variable which are fixed or not of column status */
13648  if( SCIPvarGetStatus(implvar) != SCIP_VARSTATUS_COLUMN || SCIPsetIsFeasEQ(set, lb, ub) )
13649  continue;
13650 
13651  col = SCIPvarGetCol(implvar);
13652  assert(col != NULL);
13653  redcost = 0.0;
13654 
13655  /* solved lp with basis information or not? */
13656  if( lpissolbasic )
13657  {
13658  SCIP_BASESTAT basestat = SCIPcolGetBasisStatus(col);
13659 
13660  /* check if the implication is not not yet applied */
13661  if( basestat == SCIP_BASESTAT_LOWER && boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGT(set, bounds[v], lb) )
13662  {
13663  redcost = SCIPcolGetRedcost(col, stat, lp);
13664  assert(!SCIPsetIsDualfeasNegative(set, redcost));
13665 
13666  if( !varfixing )
13667  redcost *= (lb - bounds[v]);
13668  else
13669  redcost *= (bounds[v] - lb);
13670  }
13671  else if( basestat == SCIP_BASESTAT_UPPER && boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLT(set, bounds[v], ub) )
13672  {
13673  redcost = SCIPcolGetRedcost(col, stat, lp);
13674  assert(!SCIPsetIsDualfeasPositive(set, redcost));
13675 
13676  if( varfixing )
13677  redcost *= (bounds[v] - ub);
13678  else
13679  redcost *= (ub - bounds[v]);
13680  }
13681  }
13682  else
13683  {
13684  SCIP_Real primsol = SCIPcolGetPrimsol(col);
13685 
13686  /* check if the implication is not not yet applied */
13687  if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasEQ(set, lb, primsol) && SCIPsetIsFeasGT(set, bounds[v], lb) )
13688  {
13689  redcost = SCIPcolGetRedcost(col, stat, lp);
13690  assert(!SCIPsetIsDualfeasNegative(set, redcost));
13691 
13692  if( varfixing )
13693  redcost *= (lb - bounds[v]);
13694  else
13695  redcost *= (bounds[v] - lb);
13696  }
13697  else if( boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasEQ(set, ub, primsol) && SCIPsetIsFeasLT(set, bounds[v], ub) )
13698  {
13699  redcost = SCIPcolGetRedcost(col, stat, lp);
13700  assert(!SCIPsetIsDualfeasPositive(set, redcost));
13701 
13702  if( varfixing )
13703  redcost *= (bounds[v] - ub);
13704  else
13705  redcost *= (ub - bounds[v]);
13706  }
13707  }
13708 
13709  /* improve implied reduced cost */
13710  if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
13711  implredcost += redcost;
13712  }
13713  }
13714 
13715 #ifdef SCIP_MORE_DEBUG
13716  SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) and implications (%d) has implied reduced cost of %g\n",
13717  SCIPvarGetName(var), ncliques, nvars, implredcost);
13718 #endif
13719 
13720  return implredcost;
13721 }
13722 
13723 /** returns the best solution (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation, if
13724  * the root relaxation is not yet completely solved, zero is returned
13725  */
13727  SCIP_VAR* var /**< problem variable */
13728  )
13729 {
13730  SCIP_Real rootsol;
13731  int i;
13732 
13733  assert(var != NULL);
13734 
13735  switch( SCIPvarGetStatus(var) )
13736  {
13738  if( var->data.original.transvar == NULL )
13739  return 0.0;
13741 
13742  case SCIP_VARSTATUS_LOOSE:
13743  case SCIP_VARSTATUS_COLUMN:
13744  return var->bestrootsol;
13745 
13746  case SCIP_VARSTATUS_FIXED:
13747  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13748  return var->locdom.lb;
13749 
13751  assert(!var->donotaggr);
13752  assert(var->data.aggregate.var != NULL);
13753  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13754  * corresponding infinity value instead of performing an arithmetical transformation (compare method
13755  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13756  * (or is called by) a public interface method; instead, we only assert that values are finite
13757  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13758  * positives and negatives if the parameter <numerics/infinity> is modified by the user
13759  */
13763 
13765  assert(!var->donotmultaggr);
13766  assert(var->data.multaggr.vars != NULL);
13767  assert(var->data.multaggr.scalars != NULL);
13768  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13769  * assert(var->data.multaggr.nvars >= 2);
13770  */
13771  rootsol = var->data.multaggr.constant;
13772  for( i = 0; i < var->data.multaggr.nvars; ++i )
13773  rootsol += var->data.multaggr.scalars[i] * SCIPvarGetBestRootSol(var->data.multaggr.vars[i]);
13774  return rootsol;
13775 
13776  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13777  assert(var->negatedvar != NULL);
13779  assert(var->negatedvar->negatedvar == var);
13780  return var->data.negate.constant - SCIPvarGetBestRootSol(var->negatedvar);
13781 
13782  default:
13783  SCIPerrorMessage("unknown variable status\n");
13784  SCIPABORT();
13785  return 0.0; /*lint !e527*/
13786  }
13787 }
13788 
13789 /** returns the best reduced costs (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation,
13790  * if the root relaxation is not yet completely solved, or the variable was no column of the root LP, SCIP_INVALID is
13791  * returned
13792  */
13794  SCIP_VAR* var /**< problem variable */
13795  )
13796 {
13797  assert(var != NULL);
13798 
13799  switch( SCIPvarGetStatus(var) )
13800  {
13802  if( var->data.original.transvar == NULL )
13803  return SCIP_INVALID;
13805 
13806  case SCIP_VARSTATUS_LOOSE:
13807  case SCIP_VARSTATUS_COLUMN:
13808  return var->bestrootredcost;
13809 
13810  case SCIP_VARSTATUS_FIXED:
13814  return 0.0;
13815 
13816  default:
13817  SCIPerrorMessage("unknown variable status\n");
13818  SCIPABORT();
13819  return 0.0; /*lint !e527*/
13820  }
13821 }
13822 
13823 /** returns the best objective value (w.r.t. root reduced cost propagation) of the root LP which belongs the root
13824  * reduced cost which is accessible via SCIPvarGetRootRedcost() or the variable was no column of the root LP,
13825  * SCIP_INVALID is returned
13826  */
13828  SCIP_VAR* var /**< problem variable */
13829  )
13830 {
13831  assert(var != NULL);
13832 
13833  switch( SCIPvarGetStatus(var) )
13834  {
13836  if( var->data.original.transvar == NULL )
13837  return SCIP_INVALID;
13839 
13840  case SCIP_VARSTATUS_LOOSE:
13841  case SCIP_VARSTATUS_COLUMN:
13842  return var->bestrootlpobjval;
13843 
13844  case SCIP_VARSTATUS_FIXED:
13848  return SCIP_INVALID;
13849 
13850  default:
13851  SCIPerrorMessage("unknown variable status\n");
13852  SCIPABORT();
13853  return SCIP_INVALID; /*lint !e527*/
13854  }
13855 }
13856 
13857 /** set the given solution as the best root solution w.r.t. root reduced cost propagation in the variables */
13859  SCIP_VAR* var, /**< problem variable */
13860  SCIP_Real rootsol, /**< root solution value */
13861  SCIP_Real rootredcost, /**< root reduced cost */
13862  SCIP_Real rootlpobjval /**< objective value of the root LP */
13863  )
13864 {
13865  assert(var != NULL);
13866 
13867  var->bestrootsol = rootsol;
13868  var->bestrootredcost = rootredcost;
13869  var->bestrootlpobjval = rootlpobjval;
13870 }
13871 
13872 /** stores the solution value as relaxation solution in the problem variable */
13874  SCIP_VAR* var, /**< problem variable */
13875  SCIP_SET* set, /**< global SCIP settings */
13876  SCIP_RELAXATION* relaxation, /**< global relaxation data */
13877  SCIP_Real solval, /**< solution value in the current relaxation solution */
13878  SCIP_Bool updateobj /**< should the objective value be updated? */
13879  )
13880 {
13881  assert(var != NULL);
13882  assert(relaxation != NULL);
13883  assert(set != NULL);
13884  assert(var->scip == set->scip);
13885 
13886  /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
13887  switch( SCIPvarGetStatus(var) )
13888  {
13890  SCIP_CALL( SCIPvarSetRelaxSol(var->data.original.transvar, set, relaxation, solval, updateobj) );
13891  break;
13892 
13893  case SCIP_VARSTATUS_LOOSE:
13894  case SCIP_VARSTATUS_COLUMN:
13895  if( updateobj )
13896  SCIPrelaxationSolObjAdd(relaxation, var->obj * (solval - var->relaxsol));
13897  var->relaxsol = solval;
13898  break;
13899 
13900  case SCIP_VARSTATUS_FIXED:
13901  if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
13902  {
13903  SCIPerrorMessage("cannot set relaxation solution value for variable <%s> fixed to %.15g to different value %.15g\n",
13904  SCIPvarGetName(var), var->glbdom.lb, solval);
13905  return SCIP_INVALIDDATA;
13906  }
13907  break;
13908 
13909  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13910  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
13911  SCIP_CALL( SCIPvarSetRelaxSol(var->data.aggregate.var, set, relaxation,
13912  (solval - var->data.aggregate.constant)/var->data.aggregate.scalar, updateobj) );
13913  break;
13915  SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
13916  return SCIP_INVALIDDATA;
13917 
13919  SCIP_CALL( SCIPvarSetRelaxSol(var->negatedvar, set, relaxation, var->data.negate.constant - solval, updateobj) );
13920  break;
13921 
13922  default:
13923  SCIPerrorMessage("unknown variable status\n");
13924  return SCIP_INVALIDDATA;
13925  }
13926 
13927  return SCIP_OKAY;
13928 }
13929 
13930 /** returns the solution value of the problem variable in the relaxation solution
13931  *
13932  * @todo Inline this function - similar to SCIPvarGetLPSol_rec.
13933  */
13935  SCIP_VAR* var, /**< problem variable */
13936  SCIP_SET* set /**< global SCIP settings */
13937  )
13938 {
13939  SCIP_Real solvalsum;
13940  SCIP_Real solval;
13941  int i;
13942 
13943  assert(var != NULL);
13944  assert(set != NULL);
13945  assert(var->scip == set->scip);
13946 
13947  /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
13948  switch( SCIPvarGetStatus(var) )
13949  {
13951  return SCIPvarGetRelaxSol(var->data.original.transvar, set);
13952 
13953  case SCIP_VARSTATUS_LOOSE:
13954  case SCIP_VARSTATUS_COLUMN:
13955  return var->relaxsol;
13956 
13957  case SCIP_VARSTATUS_FIXED:
13958  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
13959  assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
13960  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
13961  return SCIPvarGetLbGlobal(var);
13962 
13963  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13964  solval = SCIPvarGetRelaxSol(var->data.aggregate.var, set);
13965  if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
13966  {
13967  if( var->data.aggregate.scalar * solval > 0.0 )
13968  return SCIPsetInfinity(set);
13969  if( var->data.aggregate.scalar * solval < 0.0 )
13970  return -SCIPsetInfinity(set);
13971  }
13972  return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
13973 
13975  solvalsum = var->data.multaggr.constant;
13976  for( i = 0; i < var->data.multaggr.nvars; ++i )
13977  {
13978  solval = SCIPvarGetRelaxSol(var->data.multaggr.vars[i], set);
13979  if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
13980  {
13981  if( var->data.multaggr.scalars[i] * solval > 0.0 )
13982  return SCIPsetInfinity(set);
13983  if( var->data.multaggr.scalars[i] * solval < 0.0 )
13984  return -SCIPsetInfinity(set);
13985  }
13986  solvalsum += var->data.multaggr.scalars[i] * solval;
13987  }
13988  return solvalsum;
13989 
13991  solval = SCIPvarGetRelaxSol(var->negatedvar, set);
13992  if( SCIPsetIsInfinity(set, solval) )
13993  return -SCIPsetInfinity(set);
13994  if( SCIPsetIsInfinity(set, -solval) )
13995  return SCIPsetInfinity(set);
13996  return var->data.negate.constant - solval;
13997 
13998  default:
13999  SCIPerrorMessage("unknown variable status\n");
14000  SCIPABORT();
14001  return SCIP_INVALID; /*lint !e527*/
14002  }
14003 }
14004 
14005 /** returns the solution value of the transformed problem variable in the relaxation solution */
14007  SCIP_VAR* var /**< problem variable */
14008  )
14009 {
14010  assert(var != NULL);
14012 
14013  return var->relaxsol;
14014 }
14015 
14016 /** stores the solution value as NLP solution in the problem variable */
14018  SCIP_VAR* var, /**< problem variable */
14019  SCIP_SET* set, /**< global SCIP settings */
14020  SCIP_Real solval /**< solution value in the current NLP solution */
14021  )
14022 {
14023  assert(var != NULL);
14024  assert(set != NULL);
14025  assert(var->scip == set->scip);
14026 
14027  /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
14028  switch( SCIPvarGetStatus(var) )
14029  {
14031  SCIP_CALL( SCIPvarSetNLPSol(var->data.original.transvar, set, solval) );
14032  break;
14033 
14034  case SCIP_VARSTATUS_LOOSE:
14035  case SCIP_VARSTATUS_COLUMN:
14036  var->nlpsol = solval;
14037  break;
14038 
14039  case SCIP_VARSTATUS_FIXED:
14040  if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
14041  {
14042  SCIPerrorMessage("cannot set NLP solution value for variable <%s> fixed to %.15g to different value %.15g\n",
14043  SCIPvarGetName(var), var->glbdom.lb, solval);
14044  SCIPABORT();
14045  return SCIP_INVALIDCALL; /*lint !e527*/
14046  }
14047  break;
14048 
14049  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
14050  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
14051  SCIP_CALL( SCIPvarSetNLPSol(var->data.aggregate.var, set, (solval - var->data.aggregate.constant)/var->data.aggregate.scalar) );
14052  break;
14053 
14055  SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
14056  SCIPABORT();
14057  return SCIP_INVALIDCALL; /*lint !e527*/
14058 
14060  SCIP_CALL( SCIPvarSetNLPSol(var->negatedvar, set, var->data.negate.constant - solval) );
14061  break;
14062 
14063  default:
14064  SCIPerrorMessage("unknown variable status\n");
14065  SCIPABORT();
14066  return SCIP_ERROR; /*lint !e527*/
14067  }
14068 
14069  return SCIP_OKAY;
14070 }
14071 
14072 /** returns a weighted average solution value of the variable in all feasible primal solutions found so far */
14074  SCIP_VAR* var /**< problem variable */
14075  )
14076 {
14077  SCIP_Real avgsol;
14078  int i;
14079 
14080  assert(var != NULL);
14081 
14082  switch( SCIPvarGetStatus(var) )
14083  {
14085  if( var->data.original.transvar == NULL )
14086  return 0.0;
14087  return SCIPvarGetAvgSol(var->data.original.transvar);
14088 
14089  case SCIP_VARSTATUS_LOOSE:
14090  case SCIP_VARSTATUS_COLUMN:
14091  avgsol = var->primsolavg;
14092  avgsol = MAX(avgsol, var->glbdom.lb);
14093  avgsol = MIN(avgsol, var->glbdom.ub);
14094  return avgsol;
14095 
14096  case SCIP_VARSTATUS_FIXED:
14097  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
14098  return var->locdom.lb;
14099 
14101  assert(!var->donotaggr);
14102  assert(var->data.aggregate.var != NULL);
14103  return var->data.aggregate.scalar * SCIPvarGetAvgSol(var->data.aggregate.var)
14104  + var->data.aggregate.constant;
14105 
14107  assert(!var->donotmultaggr);
14108  assert(var->data.multaggr.vars != NULL);
14109  assert(var->data.multaggr.scalars != NULL);
14110  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
14111  * assert(var->data.multaggr.nvars >= 2);
14112  */
14113  avgsol = var->data.multaggr.constant;
14114  for( i = 0; i < var->data.multaggr.nvars; ++i )
14115  avgsol += var->data.multaggr.scalars[i] * SCIPvarGetAvgSol(var->data.multaggr.vars[i]);
14116  return avgsol;
14117 
14118  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
14119  assert(var->negatedvar != NULL);
14121  assert(var->negatedvar->negatedvar == var);
14122  return var->data.negate.constant - SCIPvarGetAvgSol(var->negatedvar);
14123 
14124  default:
14125  SCIPerrorMessage("unknown variable status\n");
14126  SCIPABORT();
14127  return 0.0; /*lint !e527*/
14128  }
14129 }
14130 
14131 /** returns solution value and index of variable lower bound that is closest to the variable's value in the given primal solution
14132  * or current LP solution if no primal solution is given; returns an index of -1 if no variable lower bound is available
14133  */
14135  SCIP_VAR* var, /**< active problem variable */
14136  SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
14137  SCIP_SET* set, /**< global SCIP settings */
14138  SCIP_STAT* stat, /**< problem statistics */
14139  SCIP_Real* closestvlb, /**< pointer to store the value of the closest variable lower bound */
14140  int* closestvlbidx /**< pointer to store the index of the closest variable lower bound */
14141  )
14142 {
14143  int nvlbs;
14144 
14145  assert(var != NULL);
14146  assert(stat != NULL);
14147  assert(set != NULL);
14148  assert(var->scip == set->scip);
14149  assert(closestvlb != NULL);
14150  assert(closestvlbidx != NULL);
14151 
14152  *closestvlbidx = -1;
14153  *closestvlb = SCIP_REAL_MIN;
14154 
14155  nvlbs = SCIPvarGetNVlbs(var);
14156  if( nvlbs > 0 )
14157  {
14158  SCIP_VAR** vlbvars;
14159  SCIP_Real* vlbcoefs;
14160  SCIP_Real* vlbconsts;
14161  int i;
14162 
14163  vlbvars = SCIPvarGetVlbVars(var);
14164  vlbcoefs = SCIPvarGetVlbCoefs(var);
14165  vlbconsts = SCIPvarGetVlbConstants(var);
14166 
14167  /* check for cached values */
14168  if( var->closestvblpcount == stat->lpcount && var->closestvlbidx != -1 && sol == NULL)
14169  {
14170  i = var->closestvlbidx;
14171  assert(0 <= i && i < nvlbs);
14172  assert(SCIPvarIsActive(vlbvars[i]));
14173  *closestvlbidx = i;
14174  *closestvlb = vlbcoefs[i] * SCIPvarGetLPSol(vlbvars[i]) + vlbconsts[i];
14175  }
14176  else
14177  {
14178  /* search best VUB */
14179  for( i = 0; i < nvlbs; i++ )
14180  {
14181  if( SCIPvarIsActive(vlbvars[i]) )
14182  {
14183  SCIP_Real vlbsol;
14184 
14185  vlbsol = vlbcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vlbvars[i]) : SCIPsolGetVal(sol, set, stat, vlbvars[i])) + vlbconsts[i];
14186  if( vlbsol > *closestvlb )
14187  {
14188  *closestvlb = vlbsol;
14189  *closestvlbidx = i;
14190  }
14191  }
14192  }
14193 
14194  if( sol == NULL )
14195  {
14196  /* update cached value */
14197  if( var->closestvblpcount != stat->lpcount )
14198  var->closestvubidx = -1;
14199  var->closestvlbidx = *closestvlbidx;
14200  var->closestvblpcount = stat->lpcount;
14201  }
14202  }
14203  }
14204 }
14205 
14206 /** returns solution value and index of variable upper bound that is closest to the variable's value in the given primal solution;
14207  * or current LP solution if no primal solution is given; returns an index of -1 if no variable upper bound is available
14208  */
14210  SCIP_VAR* var, /**< active problem variable */
14211  SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
14212  SCIP_SET* set, /**< global SCIP settings */
14213  SCIP_STAT* stat, /**< problem statistics */
14214  SCIP_Real* closestvub, /**< pointer to store the value of the closest variable upper bound */
14215  int* closestvubidx /**< pointer to store the index of the closest variable upper bound */
14216  )
14217 {
14218  int nvubs;
14219 
14220  assert(var != NULL);
14221  assert(set != NULL);
14222  assert(var->scip == set->scip);
14223  assert(closestvub != NULL);
14224  assert(closestvubidx != NULL);
14225 
14226  *closestvubidx = -1;
14227  *closestvub = SCIP_REAL_MAX;
14228 
14229  nvubs = SCIPvarGetNVubs(var);
14230  if( nvubs > 0 )
14231  {
14232  SCIP_VAR** vubvars;
14233  SCIP_Real* vubcoefs;
14234  SCIP_Real* vubconsts;
14235  int i;
14236 
14237  vubvars = SCIPvarGetVubVars(var);
14238  vubcoefs = SCIPvarGetVubCoefs(var);
14239  vubconsts = SCIPvarGetVubConstants(var);
14240 
14241  /* check for cached values */
14242  if( var->closestvblpcount == stat->lpcount && var->closestvubidx != -1 && sol == NULL)
14243  {
14244  i = var->closestvubidx;
14245  assert(0 <= i && i < nvubs);
14246  assert(SCIPvarIsActive(vubvars[i]));
14247  *closestvubidx = i;
14248  *closestvub = vubcoefs[i] * SCIPvarGetLPSol(vubvars[i]) + vubconsts[i];
14249  }
14250  else
14251  {
14252  /* search best VUB */
14253  for( i = 0; i < nvubs; i++ )
14254  {
14255  if( SCIPvarIsActive(vubvars[i]) )
14256  {
14257  SCIP_Real vubsol;
14258 
14259  vubsol = vubcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vubvars[i]) : SCIPsolGetVal(sol, set, stat, vubvars[i])) + vubconsts[i];
14260  if( vubsol < *closestvub )
14261  {
14262  *closestvub = vubsol;
14263  *closestvubidx = i;
14264  }
14265  }
14266  }
14267 
14268  if( sol == NULL )
14269  {
14270  /* update cached value */
14271  if( var->closestvblpcount != stat->lpcount )
14272  var->closestvlbidx = -1;
14273  var->closestvubidx = *closestvubidx;
14274  var->closestvblpcount = stat->lpcount;
14275  }
14276  }
14277  }
14278 }
14279 
14280 /** resolves variable to columns and adds them with the coefficient to the row */
14282  SCIP_VAR* var, /**< problem variable */
14283  BMS_BLKMEM* blkmem, /**< block memory */
14284  SCIP_SET* set, /**< global SCIP settings */
14285  SCIP_STAT* stat, /**< problem statistics */
14286  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
14287  SCIP_PROB* prob, /**< problem data */
14288  SCIP_LP* lp, /**< current LP data */
14289  SCIP_ROW* row, /**< LP row */
14290  SCIP_Real val /**< value of coefficient */
14291  )
14292 {
14293  int i;
14294 
14295  assert(var != NULL);
14296  assert(set != NULL);
14297  assert(var->scip == set->scip);
14298  assert(row != NULL);
14299  assert(!SCIPsetIsInfinity(set, REALABS(val)));
14300 
14301  SCIPsetDebugMsg(set, "adding coefficient %g<%s> to row <%s>\n", val, var->name, row->name);
14302 
14303  if ( SCIPsetIsZero(set, val) )
14304  return SCIP_OKAY;
14305 
14306  switch( SCIPvarGetStatus(var) )
14307  {
14309  if( var->data.original.transvar == NULL )
14310  {
14311  SCIPerrorMessage("cannot add untransformed original variable <%s> to LP row <%s>\n", var->name, row->name);
14312  return SCIP_INVALIDDATA;
14313  }
14314  SCIP_CALL( SCIPvarAddToRow(var->data.original.transvar, blkmem, set, stat, eventqueue, prob, lp, row, val) );
14315  return SCIP_OKAY;
14316 
14317  case SCIP_VARSTATUS_LOOSE:
14318  /* add globally fixed variables as constant */
14319  if( SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub) )
14320  {
14321  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->glbdom.lb) );
14322  return SCIP_OKAY;
14323  }
14324  /* convert loose variable into column */
14325  SCIP_CALL( SCIPvarColumn(var, blkmem, set, stat, prob, lp) );
14326  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
14327  /*lint -fallthrough*/
14328 
14329  case SCIP_VARSTATUS_COLUMN:
14330  assert(var->data.col != NULL);
14331  assert(var->data.col->var == var);
14332  SCIP_CALL( SCIProwIncCoef(row, blkmem, set, eventqueue, lp, var->data.col, val) );
14333  return SCIP_OKAY;
14334 
14335  case SCIP_VARSTATUS_FIXED:
14336  assert(var->glbdom.lb == var->glbdom.ub); /*lint !e777*/
14337  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
14338  assert(var->locdom.lb == var->glbdom.lb); /*lint !e777*/
14339  assert(!SCIPsetIsInfinity(set, REALABS(var->locdom.lb)));
14340  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->locdom.lb) );
14341  return SCIP_OKAY;
14342 
14344  assert(!var->donotaggr);
14345  assert(var->data.aggregate.var != NULL);
14346  SCIP_CALL( SCIPvarAddToRow(var->data.aggregate.var, blkmem, set, stat, eventqueue, prob, lp,
14347  row, var->data.aggregate.scalar * val) );
14348  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.aggregate.constant * val) );
14349  return SCIP_OKAY;
14350 
14352  assert(!var->donotmultaggr);
14353  assert(var->data.multaggr.vars != NULL);
14354  assert(var->data.multaggr.scalars != NULL);
14355  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
14356  * assert(var->data.multaggr.nvars >= 2);
14357  */
14358  for( i = 0; i < var->data.multaggr.nvars; ++i )
14359  {
14360  SCIP_CALL( SCIPvarAddToRow(var->data.multaggr.vars[i], blkmem, set, stat, eventqueue, prob, lp,
14361  row, var->data.multaggr.scalars[i] * val) );
14362  }
14363  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.multaggr.constant * val) );
14364  return SCIP_OKAY;
14365 
14366  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
14367  assert(var->negatedvar != NULL);
14369  assert(var->negatedvar->negatedvar == var);
14370  SCIP_CALL( SCIPvarAddToRow(var->negatedvar, blkmem, set, stat, eventqueue, prob, lp, row, -val) );
14371  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.negate.constant * val) );
14372  return SCIP_OKAY;
14373 
14374  default:
14375  SCIPerrorMessage("unknown variable status\n");
14376  return SCIP_INVALIDDATA;
14377  }
14378 }
14379 
14380 /* optionally, define this compiler flag to write complete variable histories to a file */
14381 #ifdef SCIP_HISTORYTOFILE
14382 SCIP_Longint counter = 0l;
14383 const char* historypath="."; /* allows for user-defined path; use '.' for calling directory of SCIP */
14384 #include "scip/scip.h"
14385 #endif
14386 
14387 /** updates the pseudo costs of the given variable and the global pseudo costs after a change of
14388  * "solvaldelta" in the variable's solution value and resulting change of "objdelta" in the in the LP's objective value
14389  */
14391  SCIP_VAR* var, /**< problem variable */
14392  SCIP_SET* set, /**< global SCIP settings */
14393  SCIP_STAT* stat, /**< problem statistics */
14394  SCIP_Real solvaldelta, /**< difference of variable's new LP value - old LP value */
14395  SCIP_Real objdelta, /**< difference of new LP's objective value - old LP's objective value */
14396  SCIP_Real weight /**< weight in (0,1] of this update in pseudo cost sum */
14397  )
14398 {
14399  SCIP_Real oldrootpseudocosts;
14400  assert(var != NULL);
14401  assert(set != NULL);
14402  assert(var->scip == set->scip);
14403  assert(stat != NULL);
14404 
14405  /* check if history statistics should be collected for a variable */
14406  if( !stat->collectvarhistory )
14407  return SCIP_OKAY;
14408 
14409  switch( SCIPvarGetStatus(var) )
14410  {
14412  if( var->data.original.transvar == NULL )
14413  {
14414  SCIPerrorMessage("cannot update pseudo costs of original untransformed variable\n");
14415  return SCIP_INVALIDDATA;
14416  }
14417  SCIP_CALL( SCIPvarUpdatePseudocost(var->data.original.transvar, set, stat, solvaldelta, objdelta, weight) );
14418  return SCIP_OKAY;
14419 
14420  case SCIP_VARSTATUS_LOOSE:
14421  case SCIP_VARSTATUS_COLUMN:
14422  /* store old pseudo-costs for root LP best-estimate update */
14423  oldrootpseudocosts = SCIPvarGetMinPseudocostScore(var, stat, set, SCIPvarGetRootSol(var));
14424 
14425  /* update history */
14426  SCIPhistoryUpdatePseudocost(var->history, set, solvaldelta, objdelta, weight);
14427  SCIPhistoryUpdatePseudocost(var->historycrun, set, solvaldelta, objdelta, weight);
14428  SCIPhistoryUpdatePseudocost(stat->glbhistory, set, solvaldelta, objdelta, weight);
14429  SCIPhistoryUpdatePseudocost(stat->glbhistorycrun, set, solvaldelta, objdelta, weight);
14430 
14431  /* update root LP best-estimate */
14432  SCIP_CALL( SCIPstatUpdateVarRootLPBestEstimate(stat, set, var, oldrootpseudocosts) );
14433 
14434  /* append history to file */
14435 #ifdef SCIP_HISTORYTOFILE
14436  {
14437  FILE* f;
14438  char filename[256];
14439  SCIP_NODE* currentnode;
14440  SCIP_NODE* parentnode;
14441  currentnode = SCIPgetFocusNode(set->scip);
14442  parentnode = SCIPnodeGetParent(currentnode);
14443 
14444  sprintf(filename, "%s/%s.pse", historypath, SCIPgetProbName(set->scip));
14445  f = fopen(filename, "a");
14446  if( NULL != f )
14447  {
14448  fprintf(f, "%lld %s \t %lld \t %lld \t %lld \t %d \t %15.9f \t %.3f\n",
14449  ++counter,
14450  SCIPvarGetName(var),
14451  SCIPnodeGetNumber(currentnode),
14452  parentnode != NULL ? SCIPnodeGetNumber(parentnode) : -1,
14453  SCIPgetNLPIterations(set->scip),
14454  SCIPgetDepth(set->scip),
14455  objdelta,
14456  solvaldelta);
14457  fclose(f);
14458  }
14459  }
14460 #endif
14461  return SCIP_OKAY;
14462 
14463  case SCIP_VARSTATUS_FIXED:
14464  SCIPerrorMessage("cannot update pseudo cost values of a fixed variable\n");
14465  return SCIP_INVALIDDATA;
14466 
14468  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
14470  solvaldelta/var->data.aggregate.scalar, objdelta, weight) );
14471  return SCIP_OKAY;
14472 
14474  SCIPerrorMessage("cannot update pseudo cost values of a multi-aggregated variable\n");
14475  return SCIP_INVALIDDATA;
14476 
14478  SCIP_CALL( SCIPvarUpdatePseudocost(var->negatedvar, set, stat, -solvaldelta, objdelta, weight) );
14479  return SCIP_OKAY;
14480 
14481  default:
14482  SCIPerrorMessage("unknown variable status\n");
14483  return SCIP_INVALIDDATA;
14484  }
14485 }
14486 
14487 /** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value */
14489  SCIP_VAR* var, /**< problem variable */
14490  SCIP_STAT* stat, /**< problem statistics */
14491  SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
14492  )
14493 {
14494  SCIP_BRANCHDIR dir;
14495 
14496  assert(var != NULL);
14497  assert(stat != NULL);
14498 
14499  switch( SCIPvarGetStatus(var) )
14500  {
14502  if( var->data.original.transvar == NULL )
14503  return SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
14504  else
14505  return SCIPvarGetPseudocost(var->data.original.transvar, stat, solvaldelta);
14506 
14507  case SCIP_VARSTATUS_LOOSE:
14508  case SCIP_VARSTATUS_COLUMN:
14509  dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
14510 
14511  return SCIPhistoryGetPseudocostCount(var->history, dir) > 0.0
14512  ? SCIPhistoryGetPseudocost(var->history, solvaldelta)
14513  : SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
14514 
14515  case SCIP_VARSTATUS_FIXED:
14516  return 0.0;
14517 
14519  return SCIPvarGetPseudocost(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
14520 
14522  return 0.0;
14523 
14525  return SCIPvarGetPseudocost(var->negatedvar, stat, -solvaldelta);
14526 
14527  default:
14528  SCIPerrorMessage("unknown variable status\n");
14529  SCIPABORT();
14530  return 0.0; /*lint !e527*/
14531  }
14532 }
14533 
14534 /** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value,
14535  * only using the pseudo cost information of the current run
14536  */
14538  SCIP_VAR* var, /**< problem variable */
14539  SCIP_STAT* stat, /**< problem statistics */
14540  SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
14541  )
14542 {
14543  SCIP_BRANCHDIR dir;
14544 
14545  assert(var != NULL);
14546  assert(stat != NULL);
14547 
14548  switch( SCIPvarGetStatus(var) )
14549  {
14551  if( var->data.original.transvar == NULL )
14552  return SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
14553  else
14554  return SCIPvarGetPseudocostCurrentRun(var->data.original.transvar, stat, solvaldelta);
14555 
14556  case SCIP_VARSTATUS_LOOSE:
14557  case SCIP_VARSTATUS_COLUMN:
14558  dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
14559 
14560  return SCIPhistoryGetPseudocostCount(var->historycrun, dir) > 0.0
14561  ? SCIPhistoryGetPseudocost(var->historycrun, solvaldelta)
14562  : SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
14563 
14564  case SCIP_VARSTATUS_FIXED:
14565  return 0.0;
14566 
14568  return SCIPvarGetPseudocostCurrentRun(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
14569 
14571  return 0.0;
14572 
14574  return SCIPvarGetPseudocostCurrentRun(var->negatedvar, stat, -solvaldelta);
14575 
14576  default:
14577  SCIPerrorMessage("unknown variable status\n");
14578  SCIPABORT();
14579  return 0.0; /*lint !e527*/
14580  }
14581 }
14582 
14583 /** gets the variable's (possible fractional) number of pseudo cost updates for the given direction */
14585  SCIP_VAR* var, /**< problem variable */
14586  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14587  )
14588 {
14589  assert(var != NULL);
14590  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14591 
14592  switch( SCIPvarGetStatus(var) )
14593  {
14595  if( var->data.original.transvar == NULL )
14596  return 0.0;
14597  else
14598  return SCIPvarGetPseudocostCount(var->data.original.transvar, dir);
14599 
14600  case SCIP_VARSTATUS_LOOSE:
14601  case SCIP_VARSTATUS_COLUMN:
14602  return SCIPhistoryGetPseudocostCount(var->history, dir);
14603 
14604  case SCIP_VARSTATUS_FIXED:
14605  return 0.0;
14606 
14608  if( var->data.aggregate.scalar > 0.0 )
14609  return SCIPvarGetPseudocostCount(var->data.aggregate.var, dir);
14610  else
14612 
14614  return 0.0;
14615 
14618 
14619  default:
14620  SCIPerrorMessage("unknown variable status\n");
14621  SCIPABORT();
14622  return 0.0; /*lint !e527*/
14623  }
14624 }
14625 
14626 /** gets the variable's (possible fractional) number of pseudo cost updates for the given direction,
14627  * only using the pseudo cost information of the current run
14628  */
14630  SCIP_VAR* var, /**< problem variable */
14631  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14632  )
14633 {
14634  assert(var != NULL);
14635  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14636 
14637  switch( SCIPvarGetStatus(var) )
14638  {
14640  if( var->data.original.transvar == NULL )
14641  return 0.0;
14642  else
14644 
14645  case SCIP_VARSTATUS_LOOSE:
14646  case SCIP_VARSTATUS_COLUMN:
14647  return SCIPhistoryGetPseudocostCount(var->historycrun, dir);
14648 
14649  case SCIP_VARSTATUS_FIXED:
14650  return 0.0;
14651 
14653  if( var->data.aggregate.scalar > 0.0 )
14655  else
14657 
14659  return 0.0;
14660 
14663 
14664  default:
14665  SCIPerrorMessage("unknown variable status\n");
14666  SCIPABORT();
14667  return 0.0; /*lint !e527*/
14668  }
14669 }
14670 
14671 /** compares both possible directions for rounding the given solution value and returns the minimum pseudo-costs of the variable */
14673  SCIP_VAR* var, /**< problem variable */
14674  SCIP_STAT* stat, /**< problem statistics */
14675  SCIP_SET* set, /**< global SCIP settings */
14676  SCIP_Real solval /**< solution value, e.g., LP solution value */
14677  )
14678 {
14679  SCIP_Real upscore;
14680  SCIP_Real downscore;
14681  SCIP_Real solvaldeltaup;
14682  SCIP_Real solvaldeltadown;
14683 
14684  /* LP root estimate only works for variables with fractional LP root solution */
14685  if( SCIPsetIsFeasIntegral(set, solval) )
14686  return 0.0;
14687 
14688  /* no min pseudo-cost score is calculated as long as the variable was not initialized in a direction */
14690  return 0.0;
14691 
14692  /* compute delta's to ceil and floor of root LP solution value */
14693  solvaldeltaup = SCIPsetCeil(set, solval) - solval;
14694  solvaldeltadown = SCIPsetFloor(set, solval) - solval;
14695 
14696  upscore = SCIPvarGetPseudocost(var, stat, solvaldeltaup);
14697  downscore = SCIPvarGetPseudocost(var, stat, solvaldeltadown);
14698 
14699  return MIN(upscore, downscore);
14700 }
14701 
14702 /** gets the an estimate of the variable's pseudo cost variance in direction \p dir */
14704  SCIP_VAR* var, /**< problem variable */
14705  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
14706  SCIP_Bool onlycurrentrun /**< return pseudo cost variance only for current branch and bound run */
14707  )
14708 {
14709  assert(var != NULL);
14710  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14711 
14712  switch( SCIPvarGetStatus(var) )
14713  {
14715  if( var->data.original.transvar == NULL )
14716  return 0.0;
14717  else
14718  return SCIPvarGetPseudocostVariance(var->data.original.transvar, dir, onlycurrentrun);
14719 
14720  case SCIP_VARSTATUS_LOOSE:
14721  case SCIP_VARSTATUS_COLUMN:
14722  if( onlycurrentrun )
14724  else
14725  return SCIPhistoryGetPseudocostVariance(var->history, dir);
14726 
14727  case SCIP_VARSTATUS_FIXED:
14728  return 0.0;
14729 
14731  if( var->data.aggregate.scalar > 0.0 )
14732  return SCIPvarGetPseudocostVariance(var->data.aggregate.var, dir, onlycurrentrun);
14733  else
14734  return SCIPvarGetPseudocostVariance(var->data.aggregate.var, SCIPbranchdirOpposite(dir), onlycurrentrun);
14735 
14737  return 0.0;
14738 
14740  return SCIPvarGetPseudocostVariance(var->negatedvar, SCIPbranchdirOpposite(dir), onlycurrentrun);
14741 
14742  default:
14743  SCIPerrorMessage("unknown variable status\n");
14744  SCIPABORT();
14745  return 0.0; /*lint !e527*/
14746  }
14747 }
14748 
14749 /** calculates a confidence bound for this variable under the assumption of normally distributed pseudo costs
14750  *
14751  * The confidence bound \f$ \theta \geq 0\f$ denotes the interval borders \f$ [X - \theta, \ X + \theta]\f$, which contains
14752  * the true pseudo costs of the variable, i.e., the expected value of the normal distribution, with a probability
14753  * of 2 * clevel - 1.
14754  *
14755  * @return value of confidence bound for this variable
14756  */
14758  SCIP_VAR* var, /**< variable in question */
14759  SCIP_SET* set, /**< global SCIP settings */
14760  SCIP_BRANCHDIR dir, /**< the branching direction for the confidence bound */
14761  SCIP_Bool onlycurrentrun, /**< should only the current run be taken into account */
14762  SCIP_CONFIDENCELEVEL clevel /**< confidence level for the interval */
14763  )
14764 {
14765  SCIP_Real confidencebound;
14766 
14767  confidencebound = SCIPvarGetPseudocostVariance(var, dir, onlycurrentrun);
14768  if( SCIPsetIsFeasPositive(set, confidencebound) )
14769  {
14770  SCIP_Real count;
14771 
14772  if( onlycurrentrun )
14773  count = SCIPvarGetPseudocostCountCurrentRun(var, dir);
14774  else
14775  count = SCIPvarGetPseudocostCount(var, dir);
14776  /* assertion is valid because variance is positive */
14777  assert(count >= 1.9);
14778 
14779  confidencebound /= count; /*lint !e414 division by zero can obviously not occur */
14780  confidencebound = sqrt(confidencebound);
14781 
14782  /* the actual, underlying distribution of the mean is a student-t-distribution with degrees of freedom equal to
14783  * the number of pseudo cost evaluations of this variable in the respective direction. */
14784  confidencebound *= SCIPstudentTGetCriticalValue(clevel, (int)SCIPsetFloor(set, count) - 1);
14785  }
14786  else
14787  confidencebound = 0.0;
14788 
14789  return confidencebound;
14790 }
14791 
14792 /** check if the current pseudo cost relative error in a direction violates the given threshold. The Relative
14793  * Error is calculated at a specific confidence level
14794  */
14796  SCIP_VAR* var, /**< variable in question */
14797  SCIP_SET* set, /**< global SCIP settings */
14798  SCIP_STAT* stat, /**< problem statistics */
14799  SCIP_Real threshold, /**< threshold for relative errors to be considered reliable (enough) */
14800  SCIP_CONFIDENCELEVEL clevel /**< a given confidence level */
14801  )
14802 {
14803  SCIP_Real downsize;
14804  SCIP_Real upsize;
14805  SCIP_Real size;
14806  SCIP_Real relerrorup;
14807  SCIP_Real relerrordown;
14808  SCIP_Real relerror;
14809 
14810  /* check, if the pseudo cost score of the variable is reliable */
14813  size = MIN(downsize, upsize);
14814 
14815  /* Pseudo costs relative error can only be reliable if both directions have been tried at least twice */
14816  if( size <= 1.9 )
14817  return FALSE;
14818 
14819  /* use the relative error between the current mean pseudo cost value of the candidate and its upper
14820  * confidence interval bound at confidence level of 95% for individual variable reliability.
14821  * this is only possible if we have at least 2 measurements and therefore a valid variance estimate.
14822  */
14823  if( downsize >= 1.9 )
14824  {
14825  SCIP_Real normval;
14826 
14827  relerrordown = SCIPvarCalcPscostConfidenceBound(var, set, SCIP_BRANCHDIR_DOWNWARDS, TRUE, clevel);
14828  normval = SCIPvarGetPseudocostCurrentRun(var, stat, -1.0);
14829  normval = MAX(1.0, normval);
14830 
14831  relerrordown /= normval;
14832  }
14833  else
14834  relerrordown = 0.0;
14835 
14836  if( upsize >= 1.9 )
14837  {
14838  SCIP_Real normval;
14839 
14840  relerrorup = SCIPvarCalcPscostConfidenceBound(var, set, SCIP_BRANCHDIR_UPWARDS, TRUE, clevel);
14841  normval = SCIPvarGetPseudocostCurrentRun(var, stat, +1.0);
14842  normval = MAX(1.0, normval);
14843  relerrorup /= normval;
14844  }
14845  else
14846  relerrorup = 0.0;
14847 
14848  /* consider the relative error threshold violated, if it is violated in at least one branching direction */
14849  relerror = MAX(relerrorup, relerrordown);
14850 
14851  return (relerror <= threshold);
14852 }
14853 
14854 /** check if variable pseudo-costs have a significant difference in location. The significance depends on
14855  * the choice of \p clevel and on the kind of tested hypothesis. The one-sided hypothesis, which
14856  * should be rejected, is that fracy * mu_y >= fracx * mu_x, where mu_y and mu_x denote the
14857  * unknown location means of the underlying pseudo-cost distributions of x and y.
14858  *
14859  * This method is applied best if variable x has a better pseudo-cost score than y. The method hypothesizes that y were actually
14860  * better than x (despite the current information), meaning that y can be expected to yield branching
14861  * decisions as least as good as x in the long run. If the method returns TRUE, the current history information is
14862  * sufficient to safely rely on the alternative hypothesis that x yields indeed a better branching score (on average)
14863  * than y.
14864  *
14865  * @note The order of x and y matters for the one-sided hypothesis
14866  *
14867  * @note set \p onesided to FALSE if you are not sure which variable is better. The hypothesis tested then reads
14868  * fracy * mu_y == fracx * mu_x vs the alternative hypothesis fracy * mu_y != fracx * mu_x.
14869  *
14870  * @return TRUE if the hypothesis can be safely rejected at the given confidence level
14871  */
14873  SCIP_SET* set, /**< global SCIP settings */
14874  SCIP_STAT* stat, /**< problem statistics */
14875  SCIP_VAR* varx, /**< variable x */
14876  SCIP_Real fracx, /**< the fractionality of variable x */
14877  SCIP_VAR* vary, /**< variable y */
14878  SCIP_Real fracy, /**< the fractionality of variable y */
14879  SCIP_BRANCHDIR dir, /**< branching direction */
14880  SCIP_CONFIDENCELEVEL clevel, /**< confidence level for rejecting hypothesis */
14881  SCIP_Bool onesided /**< should a one-sided hypothesis y >= x be tested? */
14882  )
14883 {
14884  SCIP_Real meanx;
14885  SCIP_Real meany;
14886  SCIP_Real variancex;
14887  SCIP_Real variancey;
14888  SCIP_Real countx;
14889  SCIP_Real county;
14890  SCIP_Real tresult;
14891  SCIP_Real realdirection;
14892 
14893  if( varx == vary )
14894  return FALSE;
14895 
14896  countx = SCIPvarGetPseudocostCount(varx, dir);
14897  county = SCIPvarGetPseudocostCount(vary, dir);
14898 
14899  /* if not at least 2 measurements were taken, return FALSE */
14900  if( countx <= 1.9 || county <= 1.9 )
14901  return FALSE;
14902 
14903  realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
14904 
14905  meanx = fracx * SCIPvarGetPseudocost(varx, stat, realdirection);
14906  meany = fracy * SCIPvarGetPseudocost(vary, stat, realdirection);
14907 
14908  variancex = SQR(fracx) * SCIPvarGetPseudocostVariance(varx, dir, FALSE);
14909  variancey = SQR(fracy) * SCIPvarGetPseudocostVariance(vary, dir, FALSE);
14910 
14911  /* if there is no variance, the means are taken from a constant distribution */
14912  if( SCIPsetIsFeasEQ(set, variancex + variancey, 0.0) )
14913  return (onesided ? SCIPsetIsFeasGT(set, meanx, meany) : !SCIPsetIsFeasEQ(set, meanx, meany));
14914 
14915  tresult = SCIPcomputeTwoSampleTTestValue(meanx, meany, variancex, variancey, countx, county);
14916 
14917  /* for the two-sided hypothesis, just take the absolute of t */
14918  if( !onesided )
14919  tresult = REALABS(tresult);
14920 
14921  return (tresult >= SCIPstudentTGetCriticalValue(clevel, (int)(countx + county - 2)));
14922 }
14923 
14924 /** tests at a given confidence level whether the variable pseudo-costs only have a small probability to
14925  * exceed a \p threshold. This is useful to determine if past observations provide enough evidence
14926  * to skip an expensive strong-branching step if there is already a candidate that has been proven to yield an improvement
14927  * of at least \p threshold.
14928  *
14929  * @note use \p clevel to adjust the level of confidence. For SCIP_CONFIDENCELEVEL_MIN, the method returns TRUE if
14930  * the estimated probability to exceed \p threshold is less than 25 %.
14931  *
14932  * @see SCIP_Confidencelevel for a list of available levels. The used probability limits refer to the one-sided levels
14933  * of confidence.
14934  *
14935  * @return TRUE if the variable pseudo-cost probabilistic model is likely to be smaller than \p threshold
14936  * at the given confidence level \p clevel.
14937  */
14939  SCIP_SET* set, /**< global SCIP settings */
14940  SCIP_STAT* stat, /**< problem statistics */
14941  SCIP_VAR* var, /**< variable x */
14942  SCIP_Real frac, /**< the fractionality of variable x */
14943  SCIP_Real threshold, /**< the threshold to test against */
14944  SCIP_BRANCHDIR dir, /**< branching direction */
14945  SCIP_CONFIDENCELEVEL clevel /**< confidence level for rejecting hypothesis */
14946  )
14947 {
14948  SCIP_Real mean;
14949  SCIP_Real variance;
14950  SCIP_Real count;
14951  SCIP_Real realdirection;
14952  SCIP_Real probability;
14953  SCIP_Real problimit;
14954 
14955  count = SCIPvarGetPseudocostCount(var, dir);
14956 
14957  /* if not at least 2 measurements were taken, return FALSE */
14958  if( count <= 1.9 )
14959  return FALSE;
14960 
14961  realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
14962 
14963  mean = frac * SCIPvarGetPseudocost(var, stat, realdirection);
14964  variance = SQR(frac) * SCIPvarGetPseudocostVariance(var, dir, FALSE);
14965 
14966  /* if mean is at least threshold, it has at least a 50% probability to exceed threshold, we therefore return FALSE */
14967  if( SCIPsetIsFeasGE(set, mean, threshold) )
14968  return FALSE;
14969 
14970  /* if there is no variance, the means are taken from a constant distribution */
14971  if( SCIPsetIsFeasEQ(set, variance, 0.0) )
14972  return SCIPsetIsFeasLT(set, mean, threshold);
14973 
14974  /* obtain probability of a normally distributed random variable at given mean and variance to yield at most threshold */
14975  probability = SCIPnormalCDF(mean, variance, threshold);
14976 
14977  /* determine a probability limit corresponding to the given confidence level */
14978  switch( clevel )
14979  {
14981  problimit = 0.75;
14982  break;
14984  problimit = 0.875;
14985  break;
14987  problimit = 0.9;
14988  break;
14990  problimit = 0.95;
14991  break;
14993  problimit = 0.975;
14994  break;
14995  default:
14996  problimit = -1;
14997  SCIPerrorMessage("Confidence level set to unknown value <%d>", (int)clevel);
14998  SCIPABORT();
14999  break;
15000  }
15001 
15002  return (probability >= problimit);
15003 }
15004 
15005 /** find the corresponding history entry if already existing, otherwise create new entry */
15006 static
15008  SCIP_VAR* var, /**< problem variable */
15009  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15010  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15011  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15012  SCIP_HISTORY** history /**< pointer to store the value based history, or NULL */
15013  )
15014 {
15015  assert(var != NULL);
15016  assert(blkmem != NULL);
15017  assert(set != NULL);
15018  assert(history != NULL);
15019 
15020  (*history) = NULL;
15021 
15022  if( var->valuehistory == NULL )
15023  {
15024  SCIP_CALL( SCIPvaluehistoryCreate(&var->valuehistory, blkmem) );
15025  }
15026 
15027  SCIP_CALL( SCIPvaluehistoryFind(var->valuehistory, blkmem, set, value, history) );
15028 
15029  return SCIP_OKAY;
15030 }
15031 
15032 /** check if value based history should be used */
15033 static
15035  SCIP_VAR* var, /**< problem variable */
15036  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15037  SCIP_SET* set /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15038  )
15039 {
15040  /* check if the domain value is unknown (not specific) */
15041  if( value == SCIP_UNKNOWN ) /*lint !e777*/
15042  return FALSE;
15043 
15044  assert(set != NULL);
15045 
15046  /* check if value based history should be collected */
15047  if( !set->history_valuebased )
15048  return FALSE;
15049 
15050  /* value based history is not collected for binary variable since the standard history already contains all information */
15051  if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
15052  return FALSE;
15053 
15054  /* value based history is not collected for continuous variables */
15056  return FALSE;
15057 
15058  return TRUE;
15059 }
15060 
15061 /** increases VSIDS of the variable by the given weight */
15063  SCIP_VAR* var, /**< problem variable */
15064  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15065  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15066  SCIP_STAT* stat, /**< problem statistics */
15067  SCIP_BRANCHDIR dir, /**< branching direction */
15068  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15069  SCIP_Real weight /**< weight of this update in VSIDS */
15070  )
15071 {
15072  assert(var != NULL);
15073  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15074 
15075  /* check if history statistics should be collected for a variable */
15076  if( !stat->collectvarhistory )
15077  return SCIP_OKAY;
15078 
15079  if( SCIPsetIsZero(set, weight) )
15080  return SCIP_OKAY;
15081 
15082  switch( SCIPvarGetStatus(var) )
15083  {
15085  if( var->data.original.transvar == NULL )
15086  {
15087  SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
15088  return SCIP_INVALIDDATA;
15089  }
15090  SCIP_CALL( SCIPvarIncVSIDS(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
15091  return SCIP_OKAY;
15092 
15093  case SCIP_VARSTATUS_LOOSE:
15094  case SCIP_VARSTATUS_COLUMN:
15095  {
15096  SCIPhistoryIncVSIDS(var->history, dir, weight);
15097  SCIPhistoryIncVSIDS(var->historycrun, dir, weight);
15098 
15099  if( useValuehistory(var, value, set) )
15100  {
15101  SCIP_HISTORY* history;
15102 
15103  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15104  assert(history != NULL);
15105 
15106  SCIPhistoryIncVSIDS(history, dir, weight);
15107  SCIPsetDebugMsg(set, "variable (<%s> %s %g) + <%g> = <%g>\n", SCIPvarGetName(var), dir == SCIP_BRANCHDIR_UPWARDS ? ">=" : "<=",
15108  value, weight, SCIPhistoryGetVSIDS(history, dir));
15109  }
15110 
15111  return SCIP_OKAY;
15112  }
15113  case SCIP_VARSTATUS_FIXED:
15114  SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
15115  return SCIP_INVALIDDATA;
15116 
15118  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15119 
15120  if( var->data.aggregate.scalar > 0.0 )
15121  {
15122  SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
15123  }
15124  else
15125  {
15126  assert(var->data.aggregate.scalar < 0.0);
15127  SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15128  }
15129  return SCIP_OKAY;
15130 
15132  SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
15133  return SCIP_INVALIDDATA;
15134 
15136  value = 1.0 - value;
15137 
15138  SCIP_CALL( SCIPvarIncVSIDS(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15139  return SCIP_OKAY;
15140 
15141  default:
15142  SCIPerrorMessage("unknown variable status\n");
15143  return SCIP_INVALIDDATA;
15144  }
15145 }
15146 
15147 /** scales the VSIDS of the variable by the given scalar */
15149  SCIP_VAR* var, /**< problem variable */
15150  SCIP_Real scalar /**< scalar to multiply the VSIDSs with */
15151  )
15152 {
15153  assert(var != NULL);
15154 
15155  switch( SCIPvarGetStatus(var) )
15156  {
15158  if( var->data.original.transvar == NULL )
15159  {
15160  SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
15161  return SCIP_INVALIDDATA;
15162  }
15164  return SCIP_OKAY;
15165 
15166  case SCIP_VARSTATUS_LOOSE:
15167  case SCIP_VARSTATUS_COLUMN:
15168  {
15169  SCIPhistoryScaleVSIDS(var->history, scalar);
15170  SCIPhistoryScaleVSIDS(var->historycrun, scalar);
15172 
15173  return SCIP_OKAY;
15174  }
15175  case SCIP_VARSTATUS_FIXED:
15176  SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
15177  return SCIP_INVALIDDATA;
15178 
15180  SCIP_CALL( SCIPvarScaleVSIDS(var->data.aggregate.var, scalar) );
15181  return SCIP_OKAY;
15182 
15184  SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
15185  return SCIP_INVALIDDATA;
15186 
15188  SCIP_CALL( SCIPvarScaleVSIDS(var->negatedvar, scalar) );
15189  return SCIP_OKAY;
15190 
15191  default:
15192  SCIPerrorMessage("unknown variable status\n");
15193  return SCIP_INVALIDDATA;
15194  }
15195 }
15196 
15197 /** increases the number of active conflicts by one and the overall length of the variable by the given length */
15199  SCIP_VAR* var, /**< problem variable */
15200  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15201  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15202  SCIP_STAT* stat, /**< problem statistics */
15203  SCIP_BRANCHDIR dir, /**< branching direction */
15204  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15205  SCIP_Real length /**< length of the conflict */
15206  )
15207 {
15208  assert(var != NULL);
15209  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15210 
15211  /* check if history statistics should be collected for a variable */
15212  if( !stat->collectvarhistory )
15213  return SCIP_OKAY;
15214 
15215  switch( SCIPvarGetStatus(var) )
15216  {
15218  if( var->data.original.transvar == NULL )
15219  {
15220  SCIPerrorMessage("cannot update conflict score of original untransformed variable\n");
15221  return SCIP_INVALIDDATA;
15222  }
15223  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.original.transvar, blkmem, set, stat, dir, value, length) );
15224  return SCIP_OKAY;
15225 
15226  case SCIP_VARSTATUS_LOOSE:
15227  case SCIP_VARSTATUS_COLUMN:
15228  {
15229  SCIPhistoryIncNActiveConflicts(var->history, dir, length);
15230  SCIPhistoryIncNActiveConflicts(var->historycrun, dir, length);
15231 
15232  if( useValuehistory(var, value, set) )
15233  {
15234  SCIP_HISTORY* history;
15235 
15236  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15237  assert(history != NULL);
15238 
15239  SCIPhistoryIncNActiveConflicts(history, dir, length);
15240  }
15241 
15242  return SCIP_OKAY;
15243  }
15244  case SCIP_VARSTATUS_FIXED:
15245  SCIPerrorMessage("cannot update conflict score of a fixed variable\n");
15246  return SCIP_INVALIDDATA;
15247 
15249  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15250 
15251  if( var->data.aggregate.scalar > 0.0 )
15252  {
15253  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, dir, value, length) );
15254  }
15255  else
15256  {
15257  assert(var->data.aggregate.scalar < 0.0);
15258  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
15259  }
15260  return SCIP_OKAY;
15261 
15263  SCIPerrorMessage("cannot update conflict score of a multi-aggregated variable\n");
15264  return SCIP_INVALIDDATA;
15265 
15267  value = 1.0 - value;
15268 
15269  SCIP_CALL( SCIPvarIncNActiveConflicts(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
15270  return SCIP_OKAY;
15271 
15272  default:
15273  SCIPerrorMessage("unknown variable status\n");
15274  return SCIP_INVALIDDATA;
15275  }
15276 }
15277 
15278 /** gets the number of active conflicts containing this variable in given direction */
15280  SCIP_VAR* var, /**< problem variable */
15281  SCIP_STAT* stat, /**< problem statistics */
15282  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15283  )
15284 {
15285  assert(var != NULL);
15286  assert(stat != NULL);
15287  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15288 
15289  switch( SCIPvarGetStatus(var) )
15290  {
15292  if( var->data.original.transvar == NULL )
15293  return 0;
15294  else
15295  return SCIPvarGetNActiveConflicts(var->data.original.transvar, stat, dir);
15296 
15297  case SCIP_VARSTATUS_LOOSE:
15298  case SCIP_VARSTATUS_COLUMN:
15299  return SCIPhistoryGetNActiveConflicts(var->history, dir);
15300 
15301  case SCIP_VARSTATUS_FIXED:
15302  return 0;
15303 
15305  if( var->data.aggregate.scalar > 0.0 )
15306  return SCIPvarGetNActiveConflicts(var->data.aggregate.var, stat, dir);
15307  else
15309 
15311  return 0;
15312 
15315 
15316  default:
15317  SCIPerrorMessage("unknown variable status\n");
15318  SCIPABORT();
15319  return 0; /*lint !e527*/
15320  }
15321 }
15322 
15323 /** gets the number of active conflicts containing this variable in given direction
15324  * in the current run
15325  */
15327  SCIP_VAR* var, /**< problem variable */
15328  SCIP_STAT* stat, /**< problem statistics */
15329  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15330  )
15331 {
15332  assert(var != NULL);
15333  assert(stat != NULL);
15334  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15335 
15336  switch( SCIPvarGetStatus(var) )
15337  {
15339  if( var->data.original.transvar == NULL )
15340  return 0;
15341  else
15343 
15344  case SCIP_VARSTATUS_LOOSE:
15345  case SCIP_VARSTATUS_COLUMN:
15346  return SCIPhistoryGetNActiveConflicts(var->historycrun, dir);
15347 
15348  case SCIP_VARSTATUS_FIXED:
15349  return 0;
15350 
15352  if( var->data.aggregate.scalar > 0.0 )
15353  return SCIPvarGetNActiveConflictsCurrentRun(var->data.aggregate.var, stat, dir);
15354  else
15356 
15358  return 0;
15359 
15362 
15363  default:
15364  SCIPerrorMessage("unknown variable status\n");
15365  SCIPABORT();
15366  return 0; /*lint !e527*/
15367  }
15368 }
15369 
15370 /** gets the average conflict length in given direction due to branching on the variable */
15372  SCIP_VAR* var, /**< problem variable */
15373  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15374  )
15375 {
15376  assert(var != NULL);
15377  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15378 
15379  switch( SCIPvarGetStatus(var) )
15380  {
15382  if( var->data.original.transvar == NULL )
15383  return 0.0;
15384  else
15386 
15387  case SCIP_VARSTATUS_LOOSE:
15388  case SCIP_VARSTATUS_COLUMN:
15389  return SCIPhistoryGetAvgConflictlength(var->history, dir);
15390  case SCIP_VARSTATUS_FIXED:
15391  return 0.0;
15392 
15394  if( var->data.aggregate.scalar > 0.0 )
15395  return SCIPvarGetAvgConflictlength(var->data.aggregate.var, dir);
15396  else
15398 
15400  return 0.0;
15401 
15404 
15405  default:
15406  SCIPerrorMessage("unknown variable status\n");
15407  SCIPABORT();
15408  return 0.0; /*lint !e527*/
15409  }
15410 }
15411 
15412 /** gets the average conflict length in given direction due to branching on the variable
15413  * in the current run
15414  */
15416  SCIP_VAR* var, /**< problem variable */
15417  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15418  )
15419 {
15420  assert(var != NULL);
15421  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15422 
15423  switch( SCIPvarGetStatus(var) )
15424  {
15426  if( var->data.original.transvar == NULL )
15427  return 0.0;
15428  else
15430 
15431  case SCIP_VARSTATUS_LOOSE:
15432  case SCIP_VARSTATUS_COLUMN:
15433  return SCIPhistoryGetAvgConflictlength(var->historycrun, dir);
15434 
15435  case SCIP_VARSTATUS_FIXED:
15436  return 0.0;
15437 
15439  if( var->data.aggregate.scalar > 0.0 )
15441  else
15443 
15445  return 0.0;
15446 
15449 
15450  default:
15451  SCIPerrorMessage("unknown variable status\n");
15452  SCIPABORT();
15453  return 0.0; /*lint !e527*/
15454  }
15455 }
15456 
15457 /** increases the number of branchings counter of the variable */
15459  SCIP_VAR* var, /**< problem variable */
15460  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15461  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15462  SCIP_STAT* stat, /**< problem statistics */
15463  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
15464  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15465  int depth /**< depth at which the bound change took place */
15466  )
15467 {
15468  assert(var != NULL);
15469  assert(stat != NULL);
15470  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15471 
15472  /* check if history statistics should be collected for a variable */
15473  if( !stat->collectvarhistory )
15474  return SCIP_OKAY;
15475 
15476  switch( SCIPvarGetStatus(var) )
15477  {
15479  if( var->data.original.transvar == NULL )
15480  {
15481  SCIPerrorMessage("cannot update branching counter of original untransformed variable\n");
15482  return SCIP_INVALIDDATA;
15483  }
15484  SCIP_CALL( SCIPvarIncNBranchings(var->data.original.transvar, blkmem, set, stat, dir, value, depth) );
15485  return SCIP_OKAY;
15486 
15487  case SCIP_VARSTATUS_LOOSE:
15488  case SCIP_VARSTATUS_COLUMN:
15489  {
15490  SCIPhistoryIncNBranchings(var->history, dir, depth);
15491  SCIPhistoryIncNBranchings(var->historycrun, dir, depth);
15492  SCIPhistoryIncNBranchings(stat->glbhistory, dir, depth);
15493  SCIPhistoryIncNBranchings(stat->glbhistorycrun, dir, depth);
15494 
15495  if( useValuehistory(var, value, set) )
15496  {
15497  SCIP_HISTORY* history;
15498 
15499  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15500  assert(history != NULL);
15501 
15502  SCIPhistoryIncNBranchings(history, dir, depth);
15503  }
15504 
15505  return SCIP_OKAY;
15506  }
15507  case SCIP_VARSTATUS_FIXED:
15508  SCIPerrorMessage("cannot update branching counter of a fixed variable\n");
15509  return SCIP_INVALIDDATA;
15510 
15512  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15513 
15514  if( var->data.aggregate.scalar > 0.0 )
15515  {
15516  SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, dir, value, depth) );
15517  }
15518  else
15519  {
15520  assert(var->data.aggregate.scalar < 0.0);
15521  SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
15522  }
15523  return SCIP_OKAY;
15524 
15526  SCIPerrorMessage("cannot update branching counter of a multi-aggregated variable\n");
15527  return SCIP_INVALIDDATA;
15528 
15530  value = 1.0 - value;
15531 
15532  SCIP_CALL( SCIPvarIncNBranchings(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
15533  return SCIP_OKAY;
15534 
15535  default:
15536  SCIPerrorMessage("unknown variable status\n");
15537  return SCIP_INVALIDDATA;
15538  }
15539 }
15540 
15541 /** increases the inference sum of the variable by the given weight */
15543  SCIP_VAR* var, /**< problem variable */
15544  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15545  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15546  SCIP_STAT* stat, /**< problem statistics */
15547  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
15548  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15549  SCIP_Real weight /**< weight of this update in inference score */
15550  )
15551 {
15552  assert(var != NULL);
15553  assert(stat != NULL);
15554  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15555 
15556  /* check if history statistics should be collected for a variable */
15557  if( !stat->collectvarhistory )
15558  return SCIP_OKAY;
15559 
15560  switch( SCIPvarGetStatus(var) )
15561  {
15563  if( var->data.original.transvar == NULL )
15564  {
15565  SCIPerrorMessage("cannot update inference counter of original untransformed variable\n");
15566  return SCIP_INVALIDDATA;
15567  }
15568  SCIP_CALL( SCIPvarIncInferenceSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
15569  return SCIP_OKAY;
15570 
15571  case SCIP_VARSTATUS_LOOSE:
15572  case SCIP_VARSTATUS_COLUMN:
15573  {
15574  SCIPhistoryIncInferenceSum(var->history, dir, weight);
15575  SCIPhistoryIncInferenceSum(var->historycrun, dir, weight);
15576  SCIPhistoryIncInferenceSum(stat->glbhistory, dir, weight);
15577  SCIPhistoryIncInferenceSum(stat->glbhistorycrun, dir, weight);
15578 
15579  if( useValuehistory(var, value, set) )
15580  {
15581  SCIP_HISTORY* history;
15582 
15583  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15584  assert(history != NULL);
15585 
15586  SCIPhistoryIncInferenceSum(history, dir, weight);
15587  }
15588 
15589  return SCIP_OKAY;
15590  }
15591  case SCIP_VARSTATUS_FIXED:
15592  SCIPerrorMessage("cannot update inference counter of a fixed variable\n");
15593  return SCIP_INVALIDDATA;
15594 
15596  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15597 
15598  if( var->data.aggregate.scalar > 0.0 )
15599  {
15600  SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
15601  }
15602  else
15603  {
15604  assert(var->data.aggregate.scalar < 0.0);
15605  SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15606  }
15607  return SCIP_OKAY;
15608 
15610  SCIPerrorMessage("cannot update inference counter of a multi-aggregated variable\n");
15611  return SCIP_INVALIDDATA;
15612 
15614  value = 1.0 - value;
15615 
15616  SCIP_CALL( SCIPvarIncInferenceSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15617  return SCIP_OKAY;
15618 
15619  default:
15620  SCIPerrorMessage("unknown variable status\n");
15621  return SCIP_INVALIDDATA;
15622  }
15623 }
15624 
15625 /** increases the cutoff sum of the variable by the given weight */
15627  SCIP_VAR* var, /**< problem variable */
15628  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15629  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15630  SCIP_STAT* stat, /**< problem statistics */
15631  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
15632  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15633  SCIP_Real weight /**< weight of this update in cutoff score */
15634  )
15635 {
15636  assert(var != NULL);
15637  assert(stat != NULL);
15638  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15639 
15640  /* check if history statistics should be collected for a variable */
15641  if( !stat->collectvarhistory )
15642  return SCIP_OKAY;
15643 
15644  switch( SCIPvarGetStatus(var) )
15645  {
15647  if( var->data.original.transvar == NULL )
15648  {
15649  SCIPerrorMessage("cannot update cutoff sum of original untransformed variable\n");
15650  return SCIP_INVALIDDATA;
15651  }
15652  SCIP_CALL( SCIPvarIncCutoffSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
15653  return SCIP_OKAY;
15654 
15655  case SCIP_VARSTATUS_LOOSE:
15656  case SCIP_VARSTATUS_COLUMN:
15657  {
15658  SCIPhistoryIncCutoffSum(var->history, dir, weight);
15659  SCIPhistoryIncCutoffSum(var->historycrun, dir, weight);
15660  SCIPhistoryIncCutoffSum(stat->glbhistory, dir, weight);
15661  SCIPhistoryIncCutoffSum(stat->glbhistorycrun, dir, weight);
15662 
15663  if( useValuehistory(var, value, set) )
15664  {
15665  SCIP_HISTORY* history;
15666 
15667  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15668  assert(history != NULL);
15669 
15670  SCIPhistoryIncCutoffSum(history, dir, weight);
15671  }
15672 
15673  return SCIP_OKAY;
15674  }
15675  case SCIP_VARSTATUS_FIXED:
15676  SCIPerrorMessage("cannot update cutoff sum of a fixed variable\n");
15677  return SCIP_INVALIDDATA;
15678 
15680  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15681 
15682  if( var->data.aggregate.scalar > 0.0 )
15683  {
15684  SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
15685  }
15686  else
15687  {
15688  assert(var->data.aggregate.scalar < 0.0);
15689  SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15690  }
15691  return SCIP_OKAY;
15692 
15694  SCIPerrorMessage("cannot update cutoff sum of a multi-aggregated variable\n");
15695  return SCIP_INVALIDDATA;
15696 
15698  value = 1.0 - value;
15699 
15700  SCIP_CALL( SCIPvarIncCutoffSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15701  return SCIP_OKAY;
15702 
15703  default:
15704  SCIPerrorMessage("unknown variable status\n");
15705  return SCIP_INVALIDDATA;
15706  }
15707 }
15708 
15709 /** returns the number of times, a bound of the variable was changed in given direction due to branching */
15711  SCIP_VAR* var, /**< problem variable */
15712  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15713  )
15714 {
15715  assert(var != NULL);
15716  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15717 
15718  switch( SCIPvarGetStatus(var) )
15719  {
15721  if( var->data.original.transvar == NULL )
15722  return 0;
15723  else
15724  return SCIPvarGetNBranchings(var->data.original.transvar, dir);
15725 
15726  case SCIP_VARSTATUS_LOOSE:
15727  case SCIP_VARSTATUS_COLUMN:
15728  return SCIPhistoryGetNBranchings(var->history, dir);
15729 
15730  case SCIP_VARSTATUS_FIXED:
15731  return 0;
15732 
15734  if( var->data.aggregate.scalar > 0.0 )
15735  return SCIPvarGetNBranchings(var->data.aggregate.var, dir);
15736  else
15738 
15740  return 0;
15741 
15744 
15745  default:
15746  SCIPerrorMessage("unknown variable status\n");
15747  SCIPABORT();
15748  return 0; /*lint !e527*/
15749  }
15750 }
15751 
15752 /** returns the number of times, a bound of the variable was changed in given direction due to branching
15753  * in the current run
15754  */
15756  SCIP_VAR* var, /**< problem variable */
15757  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15758  )
15759 {
15760  assert(var != NULL);
15761  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15762 
15763  switch( SCIPvarGetStatus(var) )
15764  {
15766  if( var->data.original.transvar == NULL )
15767  return 0;
15768  else
15770 
15771  case SCIP_VARSTATUS_LOOSE:
15772  case SCIP_VARSTATUS_COLUMN:
15773  return SCIPhistoryGetNBranchings(var->historycrun, dir);
15774 
15775  case SCIP_VARSTATUS_FIXED:
15776  return 0;
15777 
15779  if( var->data.aggregate.scalar > 0.0 )
15781  else
15783 
15785  return 0;
15786 
15789 
15790  default:
15791  SCIPerrorMessage("unknown variable status\n");
15792  SCIPABORT();
15793  return 0; /*lint !e527*/
15794  }
15795 }
15796 
15797 /** returns the average depth of bound changes in given direction due to branching on the variable */
15799  SCIP_VAR* var, /**< problem variable */
15800  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15801  )
15802 {
15803  assert(var != NULL);
15804  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15805 
15806  switch( SCIPvarGetStatus(var) )
15807  {
15809  if( var->data.original.transvar == NULL )
15810  return 0.0;
15811  else
15812  return SCIPvarGetAvgBranchdepth(var->data.original.transvar, dir);
15813 
15814  case SCIP_VARSTATUS_LOOSE:
15815  case SCIP_VARSTATUS_COLUMN:
15816  return SCIPhistoryGetAvgBranchdepth(var->history, dir);
15817 
15818  case SCIP_VARSTATUS_FIXED:
15819  return 0.0;
15820 
15822  if( var->data.aggregate.scalar > 0.0 )
15823  return SCIPvarGetAvgBranchdepth(var->data.aggregate.var, dir);
15824  else
15826 
15828  return 0.0;
15829 
15832 
15833  default:
15834  SCIPerrorMessage("unknown variable status\n");
15835  SCIPABORT();
15836  return 0.0; /*lint !e527*/
15837  }
15838 }
15839 
15840 /** returns the average depth of bound changes in given direction due to branching on the variable
15841  * in the current run
15842  */
15844  SCIP_VAR* var, /**< problem variable */
15845  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15846  )
15847 {
15848  assert(var != NULL);
15849  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15850 
15851  switch( SCIPvarGetStatus(var) )
15852  {
15854  if( var->data.original.transvar == NULL )
15855  return 0.0;
15856  else
15858 
15859  case SCIP_VARSTATUS_LOOSE:
15860  case SCIP_VARSTATUS_COLUMN:
15861  return SCIPhistoryGetAvgBranchdepth(var->historycrun, dir);
15862 
15863  case SCIP_VARSTATUS_FIXED:
15864  return 0.0;
15865 
15867  if( var->data.aggregate.scalar > 0.0 )
15869  else
15872 
15874  return 0.0;
15875 
15878  dir == SCIP_BRANCHDIR_DOWNWARDS ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
15879 
15880  default:
15881  SCIPerrorMessage("unknown variable status\n");
15882  SCIPABORT();
15883  return 0.0; /*lint !e527*/
15884  }
15885 }
15886 
15887 /** returns the variable's VSIDS score */
15889  SCIP_VAR* var, /**< problem variable */
15890  SCIP_STAT* stat, /**< problem statistics */
15891  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15892  )
15893 {
15894  assert(var != NULL);
15895  assert(stat != NULL);
15896  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15897 
15899  return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
15900 
15901  switch( SCIPvarGetStatus(var) )
15902  {
15904  if( var->data.original.transvar == NULL )
15905  return 0.0;
15906  else
15907  return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
15908 
15909  case SCIP_VARSTATUS_LOOSE:
15910  case SCIP_VARSTATUS_COLUMN:
15911  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE); /* column case already handled in if condition above */
15912  return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
15913 
15914  case SCIP_VARSTATUS_FIXED:
15915  return 0.0;
15916 
15918  if( var->data.aggregate.scalar > 0.0 )
15919  return SCIPvarGetVSIDS(var->data.aggregate.var, stat, dir);
15920  else
15921  /* coverity[overrun-local] */
15922  return SCIPvarGetVSIDS(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
15923 
15925  return 0.0;
15926 
15928  /* coverity[overrun-local] */
15929  return SCIPvarGetVSIDS(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15930 
15931  default:
15932  SCIPerrorMessage("unknown variable status\n");
15933  SCIPABORT();
15934  return 0.0; /*lint !e527*/
15935  }
15936 }
15937 
15938 /** returns the variable's VSIDS score only using conflicts of the current run */
15940  SCIP_VAR* var, /**< problem variable */
15941  SCIP_STAT* stat, /**< problem statistics */
15942  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15943  )
15944 {
15945  assert(var != NULL);
15946  assert(stat != NULL);
15947  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15948 
15949  if( dir != SCIP_BRANCHDIR_DOWNWARDS && dir != SCIP_BRANCHDIR_UPWARDS )
15950  {
15951  SCIPerrorMessage("invalid branching direction %d when asking for VSIDS value\n", dir);
15952  return SCIP_INVALID;
15953  }
15954 
15955  switch( SCIPvarGetStatus(var) )
15956  {
15958  if( var->data.original.transvar == NULL )
15959  return 0.0;
15960  else
15961  return SCIPvarGetVSIDSCurrentRun(var->data.original.transvar, stat, dir);
15962 
15963  case SCIP_VARSTATUS_LOOSE:
15964  case SCIP_VARSTATUS_COLUMN:
15965  return SCIPhistoryGetVSIDS(var->historycrun, dir)/stat->vsidsweight;
15966 
15967  case SCIP_VARSTATUS_FIXED:
15968  return 0.0;
15969 
15971  if( var->data.aggregate.scalar > 0.0 )
15972  return SCIPvarGetVSIDSCurrentRun(var->data.aggregate.var, stat, dir);
15973  else
15975 
15977  return 0.0;
15978 
15981 
15982  default:
15983  SCIPerrorMessage("unknown variable status\n");
15984  SCIPABORT();
15985  return 0.0; /*lint !e527*/
15986  }
15987 }
15988 
15989 /** returns the number of inferences branching on this variable in given direction triggered */
15991  SCIP_VAR* var, /**< problem variable */
15992  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15993  )
15994 {
15995  assert(var != NULL);
15996  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15997 
15998  switch( SCIPvarGetStatus(var) )
15999  {
16001  if( var->data.original.transvar == NULL )
16002  return 0.0;
16003  else
16004  return SCIPvarGetInferenceSum(var->data.original.transvar, dir);
16005 
16006  case SCIP_VARSTATUS_LOOSE:
16007  case SCIP_VARSTATUS_COLUMN:
16008  return SCIPhistoryGetInferenceSum(var->history, dir);
16009 
16010  case SCIP_VARSTATUS_FIXED:
16011  return 0.0;
16012 
16014  if( var->data.aggregate.scalar > 0.0 )
16015  return SCIPvarGetInferenceSum(var->data.aggregate.var, dir);
16016  else
16018 
16020  return 0.0;
16021 
16024 
16025  default:
16026  SCIPerrorMessage("unknown variable status\n");
16027  SCIPABORT();
16028  return 0.0; /*lint !e527*/
16029  }
16030 }
16031 
16032 /** returns the number of inferences branching on this variable in given direction triggered
16033  * in the current run
16034  */
16036  SCIP_VAR* var, /**< problem variable */
16037  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16038  )
16039 {
16040  assert(var != NULL);
16041  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16042 
16043  switch( SCIPvarGetStatus(var) )
16044  {
16046  if( var->data.original.transvar == NULL )
16047  return 0.0;
16048  else
16050 
16051  case SCIP_VARSTATUS_LOOSE:
16052  case SCIP_VARSTATUS_COLUMN:
16053  return SCIPhistoryGetInferenceSum(var->historycrun, dir);
16054 
16055  case SCIP_VARSTATUS_FIXED:
16056  return 0.0;
16057 
16059  if( var->data.aggregate.scalar > 0.0 )
16061  else
16063 
16065  return 0.0;
16066 
16069 
16070  default:
16071  SCIPerrorMessage("unknown variable status\n");
16072  SCIPABORT();
16073  return 0.0; /*lint !e527*/
16074  }
16075 }
16076 
16077 /** returns the average number of inferences found after branching on the variable in given direction */
16079  SCIP_VAR* var, /**< problem variable */
16080  SCIP_STAT* stat, /**< problem statistics */
16081  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16082  )
16083 {
16084  assert(var != NULL);
16085  assert(stat != NULL);
16086  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16087 
16088  switch( SCIPvarGetStatus(var) )
16089  {
16091  if( var->data.original.transvar == NULL )
16092  return SCIPhistoryGetAvgInferences(stat->glbhistory, dir);
16093  else
16094  return SCIPvarGetAvgInferences(var->data.original.transvar, stat, dir);
16095 
16096  case SCIP_VARSTATUS_LOOSE:
16097  case SCIP_VARSTATUS_COLUMN:
16098  if( SCIPhistoryGetNBranchings(var->history, dir) > 0 )
16099  return SCIPhistoryGetAvgInferences(var->history, dir);
16100  else
16101  {
16102  int nimpls;
16103  int ncliques;
16104 
16105  nimpls = SCIPvarGetNImpls(var, dir == SCIP_BRANCHDIR_UPWARDS);
16106  ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
16107  return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistory, dir); /*lint !e790*/
16108  }
16109 
16110  case SCIP_VARSTATUS_FIXED:
16111  return 0.0;
16112 
16114  if( var->data.aggregate.scalar > 0.0 )
16115  return SCIPvarGetAvgInferences(var->data.aggregate.var, stat, dir);
16116  else
16118 
16120  return 0.0;
16121 
16123  return SCIPvarGetAvgInferences(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
16124 
16125  default:
16126  SCIPerrorMessage("unknown variable status\n");
16127  SCIPABORT();
16128  return 0.0; /*lint !e527*/
16129  }
16130 }
16131 
16132 /** returns the average number of inferences found after branching on the variable in given direction
16133  * in the current run
16134  */
16136  SCIP_VAR* var, /**< problem variable */
16137  SCIP_STAT* stat, /**< problem statistics */
16138  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16139  )
16140 {
16141  assert(var != NULL);
16142  assert(stat != NULL);
16143  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16144 
16145  switch( SCIPvarGetStatus(var) )
16146  {
16148  if( var->data.original.transvar == NULL )
16149  return SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir);
16150  else
16151  return SCIPvarGetAvgInferencesCurrentRun(var->data.original.transvar, stat, dir);
16152 
16153  case SCIP_VARSTATUS_LOOSE:
16154  case SCIP_VARSTATUS_COLUMN:
16155  if( SCIPhistoryGetNBranchings(var->historycrun, dir) > 0 )
16156  return SCIPhistoryGetAvgInferences(var->historycrun, dir);
16157  else
16158  {
16159  int nimpls;
16160  int ncliques;
16161 
16162  nimpls = SCIPvarGetNImpls(var, dir == SCIP_BRANCHDIR_UPWARDS);
16163  ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
16164  return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir); /*lint !e790*/
16165  }
16166 
16167  case SCIP_VARSTATUS_FIXED:
16168  return 0.0;
16169 
16171  if( var->data.aggregate.scalar > 0.0 )
16172  return SCIPvarGetAvgInferencesCurrentRun(var->data.aggregate.var, stat, dir);
16173  else
16175 
16177  return 0.0;
16178 
16181 
16182  default:
16183  SCIPerrorMessage("unknown variable status\n");
16184  SCIPABORT();
16185  return 0.0; /*lint !e527*/
16186  }
16187 }
16188 
16189 /** returns the number of cutoffs branching on this variable in given direction produced */
16191  SCIP_VAR* var, /**< problem variable */
16192  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16193  )
16194 {
16195  assert(var != NULL);
16196  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16197 
16198  switch( SCIPvarGetStatus(var) )
16199  {
16201  if( var->data.original.transvar == NULL )
16202  return 0;
16203  else
16204  return SCIPvarGetCutoffSum(var->data.original.transvar, dir);
16205 
16206  case SCIP_VARSTATUS_LOOSE:
16207  case SCIP_VARSTATUS_COLUMN:
16208  return SCIPhistoryGetCutoffSum(var->history, dir);
16209 
16210  case SCIP_VARSTATUS_FIXED:
16211  return 0;
16212 
16214  if( var->data.aggregate.scalar > 0.0 )
16215  return SCIPvarGetCutoffSum(var->data.aggregate.var, dir);
16216  else
16218 
16220  return 0;
16221 
16224 
16225  default:
16226  SCIPerrorMessage("unknown variable status\n");
16227  SCIPABORT();
16228  return 0; /*lint !e527*/
16229  }
16230 }
16231 
16232 /** returns the number of cutoffs branching on this variable in given direction produced in the current run */
16234  SCIP_VAR* var, /**< problem variable */
16235  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16236  )
16237 {
16238  assert(var != NULL);
16239  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16240 
16241  switch( SCIPvarGetStatus(var) )
16242  {
16244  if( var->data.original.transvar == NULL )
16245  return 0;
16246  else
16248 
16249  case SCIP_VARSTATUS_LOOSE:
16250  case SCIP_VARSTATUS_COLUMN:
16251  return SCIPhistoryGetCutoffSum(var->historycrun, dir);
16252 
16253  case SCIP_VARSTATUS_FIXED:
16254  return 0;
16255 
16257  if( var->data.aggregate.scalar > 0.0 )
16258  return SCIPvarGetCutoffSumCurrentRun(var->data.aggregate.var, dir);
16259  else
16261 
16263  return 0;
16264 
16267 
16268  default:
16269  SCIPerrorMessage("unknown variable status\n");
16270  SCIPABORT();
16271  return 0; /*lint !e527*/
16272  }
16273 }
16274 
16275 /** returns the average number of cutoffs found after branching on the variable in given direction */
16277  SCIP_VAR* var, /**< problem variable */
16278  SCIP_STAT* stat, /**< problem statistics */
16279  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16280  )
16281 {
16282  assert(var != NULL);
16283  assert(stat != NULL);
16284  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16285 
16286  switch( SCIPvarGetStatus(var) )
16287  {
16289  if( var->data.original.transvar == NULL )
16290  return SCIPhistoryGetAvgCutoffs(stat->glbhistory, dir);
16291  else
16292  return SCIPvarGetAvgCutoffs(var->data.original.transvar, stat, dir);
16293 
16294  case SCIP_VARSTATUS_LOOSE:
16295  case SCIP_VARSTATUS_COLUMN:
16296  return SCIPhistoryGetNBranchings(var->history, dir) > 0
16297  ? SCIPhistoryGetAvgCutoffs(var->history, dir)
16298  : SCIPhistoryGetAvgCutoffs(stat->glbhistory, dir);
16299 
16300  case SCIP_VARSTATUS_FIXED:
16301  return 0.0;
16302 
16304  if( var->data.aggregate.scalar > 0.0 )
16305  return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, dir);
16306  else
16307  return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
16308 
16310  return 0.0;
16311 
16313  return SCIPvarGetAvgCutoffs(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
16314 
16315  default:
16316  SCIPerrorMessage("unknown variable status\n");
16317  SCIPABORT();
16318  return 0.0; /*lint !e527*/
16319  }
16320 }
16321 
16322 /** returns the average number of cutoffs found after branching on the variable in given direction in the current run */
16324  SCIP_VAR* var, /**< problem variable */
16325  SCIP_STAT* stat, /**< problem statistics */
16326  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16327  )
16328 {
16329  assert(var != NULL);
16330  assert(stat != NULL);
16331  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16332 
16333  switch( SCIPvarGetStatus(var) )
16334  {
16336  if( var->data.original.transvar == NULL )
16337  return SCIPhistoryGetAvgCutoffs(stat->glbhistorycrun, dir);
16338  else
16339  return SCIPvarGetAvgCutoffsCurrentRun(var->data.original.transvar, stat, dir);
16340 
16341  case SCIP_VARSTATUS_LOOSE:
16342  case SCIP_VARSTATUS_COLUMN:
16343  return SCIPhistoryGetNBranchings(var->historycrun, dir) > 0
16346 
16347  case SCIP_VARSTATUS_FIXED:
16348  return 0.0;
16349 
16351  if( var->data.aggregate.scalar > 0.0 )
16352  return SCIPvarGetAvgCutoffsCurrentRun(var->data.aggregate.var, stat, dir);
16353  else
16355 
16357  return 0.0;
16358 
16361 
16362  default:
16363  SCIPerrorMessage("unknown variable status\n");
16364  SCIPABORT();
16365  return 0.0; /*lint !e527*/
16366  }
16367 }
16368 
16369 
16370 
16371 
16372 /*
16373  * information methods for bound changes
16374  */
16375 
16376 /** creates an artificial bound change information object with depth = INT_MAX and pos = -1 */
16378  SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
16379  BMS_BLKMEM* blkmem, /**< block memory */
16380  SCIP_VAR* var, /**< active variable that changed the bounds */
16381  SCIP_BOUNDTYPE boundtype, /**< type of bound for var: lower or upper bound */
16382  SCIP_Real oldbound, /**< old value for bound */
16383  SCIP_Real newbound /**< new value for bound */
16384  )
16385 {
16386  assert(bdchginfo != NULL);
16387 
16388  SCIP_ALLOC( BMSallocBlockMemory(blkmem, bdchginfo) );
16389  (*bdchginfo)->oldbound = oldbound;
16390  (*bdchginfo)->newbound = newbound;
16391  (*bdchginfo)->var = var;
16392  (*bdchginfo)->inferencedata.var = var;
16393  (*bdchginfo)->inferencedata.reason.prop = NULL;
16394  (*bdchginfo)->inferencedata.info = 0;
16395  (*bdchginfo)->bdchgidx.depth = INT_MAX;
16396  (*bdchginfo)->bdchgidx.pos = -1;
16397  (*bdchginfo)->pos = 0;
16398  (*bdchginfo)->boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
16399  (*bdchginfo)->boundtype = boundtype; /*lint !e641*/
16400  (*bdchginfo)->inferboundtype = boundtype; /*lint !e641*/
16401  (*bdchginfo)->redundant = FALSE;
16402 
16403  return SCIP_OKAY;
16404 }
16405 
16406 /** frees a bound change information object */
16407 void SCIPbdchginfoFree(
16408  SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
16409  BMS_BLKMEM* blkmem /**< block memory */
16410  )
16411 {
16412  assert(bdchginfo != NULL);
16413 
16414  BMSfreeBlockMemory(blkmem, bdchginfo);
16415 }
16416 
16417 /** returns the bound change information for the last lower bound change on given active problem variable before or
16418  * after the bound change with the given index was applied;
16419  * returns NULL, if no change to the lower bound was applied up to this point of time
16420  */
16422  SCIP_VAR* var, /**< active problem variable */
16423  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16424  SCIP_Bool after /**< should the bound change with given index be included? */
16425  )
16426 {
16427  int i;
16428 
16429  assert(var != NULL);
16430  assert(SCIPvarIsActive(var));
16431 
16432  /* search the correct bound change information for the given bound change index */
16433  if( after )
16434  {
16435  for( i = var->nlbchginfos-1; i >= 0; --i )
16436  {
16437  assert(var->lbchginfos[i].var == var);
16439  assert(var->lbchginfos[i].pos == i);
16440 
16441  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16442  if( var->lbchginfos[i].redundant )
16443  return NULL;
16444  assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
16445 
16446  /* if we reached the bound change index, return the current bound change info */
16447  if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->lbchginfos[i].bdchgidx) )
16448  return &var->lbchginfos[i];
16449  }
16450  }
16451  else
16452  {
16453  for( i = var->nlbchginfos-1; i >= 0; --i )
16454  {
16455  assert(var->lbchginfos[i].var == var);
16457  assert(var->lbchginfos[i].pos == i);
16458 
16459  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16460  if( var->lbchginfos[i].redundant )
16461  return NULL;
16462  assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
16463 
16464  /* if we reached the bound change index, return the current bound change info */
16465  if( SCIPbdchgidxIsEarlier(&var->lbchginfos[i].bdchgidx, bdchgidx) )
16466  return &var->lbchginfos[i];
16467  }
16468  }
16469 
16470  return NULL;
16471 }
16472 
16473 /** returns the bound change information for the last upper bound change on given active problem variable before or
16474  * after the bound change with the given index was applied;
16475  * returns NULL, if no change to the upper bound was applied up to this point of time
16476  */
16478  SCIP_VAR* var, /**< active problem variable */
16479  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16480  SCIP_Bool after /**< should the bound change with given index be included? */
16481  )
16482 {
16483  int i;
16484 
16485  assert(var != NULL);
16486  assert(SCIPvarIsActive(var));
16487 
16488  /* search the correct bound change information for the given bound change index */
16489  if( after )
16490  {
16491  for( i = var->nubchginfos-1; i >= 0; --i )
16492  {
16493  assert(var->ubchginfos[i].var == var);
16495  assert(var->ubchginfos[i].pos == i);
16496 
16497  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16498  if( var->ubchginfos[i].redundant )
16499  return NULL;
16500  assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
16501 
16502  /* if we reached the bound change index, return the current bound change info */
16503  if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->ubchginfos[i].bdchgidx) )
16504  return &var->ubchginfos[i];
16505  }
16506  }
16507  else
16508  {
16509  for( i = var->nubchginfos-1; i >= 0; --i )
16510  {
16511  assert(var->ubchginfos[i].var == var);
16513  assert(var->ubchginfos[i].pos == i);
16514 
16515  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16516  if( var->ubchginfos[i].redundant )
16517  return NULL;
16518  assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
16519 
16520  /* if we reached the bound change index, return the current bound change info */
16521  if( SCIPbdchgidxIsEarlier(&var->ubchginfos[i].bdchgidx, bdchgidx) )
16522  return &var->ubchginfos[i];
16523  }
16524  }
16525 
16526  return NULL;
16527 }
16528 
16529 /** returns the bound change information for the last lower or upper bound change on given active problem variable
16530  * before or after the bound change with the given index was applied;
16531  * returns NULL, if no change to the lower/upper bound was applied up to this point of time
16532  */
16534  SCIP_VAR* var, /**< active problem variable */
16535  SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
16536  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16537  SCIP_Bool after /**< should the bound change with given index be included? */
16538  )
16539 {
16540  if( boundtype == SCIP_BOUNDTYPE_LOWER )
16541  return SCIPvarGetLbchgInfo(var, bdchgidx, after);
16542  else
16543  {
16544  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16545  return SCIPvarGetUbchgInfo(var, bdchgidx, after);
16546  }
16547 }
16548 
16549 /** returns lower bound of variable directly before or after the bound change given by the bound change index
16550  * was applied
16551  *
16552  * @deprecated Please use SCIPgetVarLbAtIndex()
16553  */
16555  SCIP_VAR* var, /**< problem variable */
16556  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16557  SCIP_Bool after /**< should the bound change with given index be included? */
16558  )
16559 {
16560  SCIP_VARSTATUS varstatus;
16561  assert(var != NULL);
16562 
16563  varstatus = SCIPvarGetStatus(var);
16564 
16565  /* get bounds of attached variables */
16566  switch( varstatus )
16567  {
16569  assert(var->data.original.transvar != NULL);
16570  return SCIPvarGetLbAtIndex(var->data.original.transvar, bdchgidx, after);
16571 
16572  case SCIP_VARSTATUS_LOOSE:
16573  case SCIP_VARSTATUS_COLUMN:
16574  if( bdchgidx == NULL )
16575  return SCIPvarGetLbLocal(var);
16576  else
16577  {
16578  SCIP_BDCHGINFO* bdchginfo;
16579 
16580  bdchginfo = SCIPvarGetLbchgInfo(var, bdchgidx, after);
16581  if( bdchginfo != NULL )
16582  return SCIPbdchginfoGetNewbound(bdchginfo);
16583  else
16584  return var->glbdom.lb;
16585  }
16586  case SCIP_VARSTATUS_FIXED:
16587  return var->glbdom.lb;
16588 
16589  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
16590  assert(var->data.aggregate.var != NULL);
16591  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
16592  * corresponding infinity value instead of performing an arithmetical transformation (compare method
16593  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
16594  * (or is called by) a public interface method; instead, we only assert that values are finite
16595  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
16596  * positives and negatives if the parameter <numerics/infinity> is modified by the user
16597  */
16598  if( var->data.aggregate.scalar > 0.0 )
16599  {
16600  /* a > 0 -> get lower bound of y */
16601  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16602  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16603  return var->data.aggregate.scalar * SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after)
16604  + var->data.aggregate.constant;
16605  }
16606  else if( var->data.aggregate.scalar < 0.0 )
16607  {
16608  /* a < 0 -> get upper bound of y */
16609  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16610  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16611  return var->data.aggregate.scalar * SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after)
16612  + var->data.aggregate.constant;
16613  }
16614  else
16615  {
16616  SCIPerrorMessage("scalar is zero in aggregation\n");
16617  SCIPABORT();
16618  return SCIP_INVALID; /*lint !e527*/
16619  }
16620 
16622  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
16623  if ( var->data.multaggr.nvars == 1 )
16624  {
16625  assert(var->data.multaggr.vars != NULL);
16626  assert(var->data.multaggr.scalars != NULL);
16627  assert(var->data.multaggr.vars[0] != NULL);
16628 
16629  if( var->data.multaggr.scalars[0] > 0.0 )
16630  {
16631  /* a > 0 -> get lower bound of y */
16632  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16633  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16634  return var->data.multaggr.scalars[0] * SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16635  + var->data.multaggr.constant;
16636  }
16637  else if( var->data.multaggr.scalars[0] < 0.0 )
16638  {
16639  /* a < 0 -> get upper bound of y */
16640  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16641  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16642  return var->data.multaggr.scalars[0] * SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16643  + var->data.multaggr.constant;
16644  }
16645  else
16646  {
16647  SCIPerrorMessage("scalar is zero in multi-aggregation\n");
16648  SCIPABORT();
16649  return SCIP_INVALID; /*lint !e527*/
16650  }
16651  }
16652  SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
16653  SCIPABORT();
16654  return SCIP_INVALID; /*lint !e527*/
16655 
16656  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
16657  assert(var->negatedvar != NULL);
16659  assert(var->negatedvar->negatedvar == var);
16660  return var->data.negate.constant - SCIPvarGetUbAtIndex(var->negatedvar, bdchgidx, after);
16661  default:
16662  SCIPerrorMessage("unknown variable status\n");
16663  SCIPABORT();
16664  return SCIP_INVALID; /*lint !e527*/
16665  }
16666 }
16667 
16668 /** returns upper bound of variable directly before or after the bound change given by the bound change index
16669  * was applied
16670  *
16671  * @deprecated Please use SCIPgetVarUbAtIndex()
16672  */
16674  SCIP_VAR* var, /**< problem variable */
16675  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16676  SCIP_Bool after /**< should the bound change with given index be included? */
16677  )
16678 {
16679  SCIP_VARSTATUS varstatus;
16680  assert(var != NULL);
16681 
16682  varstatus = SCIPvarGetStatus(var);
16683 
16684  /* get bounds of attached variables */
16685  switch( varstatus )
16686  {
16688  assert(var->data.original.transvar != NULL);
16689  return SCIPvarGetUbAtIndex(var->data.original.transvar, bdchgidx, after);
16690 
16691  case SCIP_VARSTATUS_COLUMN:
16692  case SCIP_VARSTATUS_LOOSE:
16693  if( bdchgidx == NULL )
16694  return SCIPvarGetUbLocal(var);
16695  else
16696  {
16697  SCIP_BDCHGINFO* bdchginfo;
16698 
16699  bdchginfo = SCIPvarGetUbchgInfo(var, bdchgidx, after);
16700  if( bdchginfo != NULL )
16701  return SCIPbdchginfoGetNewbound(bdchginfo);
16702  else
16703  return var->glbdom.ub;
16704  }
16705 
16706  case SCIP_VARSTATUS_FIXED:
16707  return var->glbdom.ub;
16708 
16709  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
16710  assert(var->data.aggregate.var != NULL);
16711  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
16712  * corresponding infinity value instead of performing an arithmetical transformation (compare method
16713  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
16714  * (or is called by) a public interface method; instead, we only assert that values are finite
16715  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
16716  * positives and negatives if the parameter <numerics/infinity> is modified by the user
16717  */
16718  if( var->data.aggregate.scalar > 0.0 )
16719  {
16720  /* a > 0 -> get lower bound of y */
16721  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16722  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16723  return var->data.aggregate.scalar * SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after)
16724  + var->data.aggregate.constant;
16725  }
16726  else if( var->data.aggregate.scalar < 0.0 )
16727  {
16728  /* a < 0 -> get upper bound of y */
16729  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16730  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16731  return var->data.aggregate.scalar * SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after)
16732  + var->data.aggregate.constant;
16733  }
16734  else
16735  {
16736  SCIPerrorMessage("scalar is zero in aggregation\n");
16737  SCIPABORT();
16738  return SCIP_INVALID; /*lint !e527*/
16739  }
16740 
16742  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
16743  if ( var->data.multaggr.nvars == 1 )
16744  {
16745  assert(var->data.multaggr.vars != NULL);
16746  assert(var->data.multaggr.scalars != NULL);
16747  assert(var->data.multaggr.vars[0] != NULL);
16748 
16749  if( var->data.multaggr.scalars[0] > 0.0 )
16750  {
16751  /* a > 0 -> get lower bound of y */
16752  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16753  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16754  return var->data.multaggr.scalars[0] * SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16755  + var->data.multaggr.constant;
16756  }
16757  else if( var->data.multaggr.scalars[0] < 0.0 )
16758  {
16759  /* a < 0 -> get upper bound of y */
16760  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16761  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16762  return var->data.multaggr.scalars[0] * SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16763  + var->data.multaggr.constant;
16764  }
16765  else
16766  {
16767  SCIPerrorMessage("scalar is zero in multi-aggregation\n");
16768  SCIPABORT();
16769  return SCIP_INVALID; /*lint !e527*/
16770  }
16771  }
16772  SCIPerrorMessage("cannot get the bounds of a multiple aggregated variable.\n");
16773  SCIPABORT();
16774  return SCIP_INVALID; /*lint !e527*/
16775 
16776  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
16777  assert(var->negatedvar != NULL);
16779  assert(var->negatedvar->negatedvar == var);
16780  return var->data.negate.constant - SCIPvarGetLbAtIndex(var->negatedvar, bdchgidx, after);
16781 
16782  default:
16783  SCIPerrorMessage("unknown variable status\n");
16784  SCIPABORT();
16785  return SCIP_INVALID; /*lint !e527*/
16786  }
16787 }
16788 
16789 /** returns lower or upper bound of variable directly before or after the bound change given by the bound change index
16790  * was applied
16791  *
16792  * @deprecated Please use SCIPgetVarBdAtIndex()
16793  */
16795  SCIP_VAR* var, /**< problem variable */
16796  SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
16797  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16798  SCIP_Bool after /**< should the bound change with given index be included? */
16799  )
16800 {
16801  if( boundtype == SCIP_BOUNDTYPE_LOWER )
16802  return SCIPvarGetLbAtIndex(var, bdchgidx, after);
16803  else
16804  {
16805  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16806  return SCIPvarGetUbAtIndex(var, bdchgidx, after);
16807  }
16808 }
16809 
16810 /** returns whether the binary variable was fixed at the time given by the bound change index
16811  *
16812  * @deprecated Please use SCIPgetVarWasFixedAtIndex()
16813  */
16815  SCIP_VAR* var, /**< problem variable */
16816  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16817  SCIP_Bool after /**< should the bound change with given index be included? */
16818  )
16819 {
16820  assert(var != NULL);
16821  assert(SCIPvarIsBinary(var));
16822 
16823  /* check the current bounds first in order to decide at which bound change information we have to look
16824  * (which is expensive because we have to follow the aggregation tree to the active variable)
16825  */
16826  return ((SCIPvarGetLbLocal(var) > 0.5 && SCIPvarGetLbAtIndex(var, bdchgidx, after) > 0.5)
16827  || (SCIPvarGetUbLocal(var) < 0.5 && SCIPvarGetUbAtIndex(var, bdchgidx, after) < 0.5));
16828 }
16829 
16830 /** bound change index representing the initial time before any bound changes took place */
16831 static SCIP_BDCHGIDX initbdchgidx = {-2, 0};
16833 /** bound change index representing the presolving stage */
16834 static SCIP_BDCHGIDX presolvebdchgidx = {-1, 0};
16836 /** returns the last bound change index, at which the bounds of the given variable were tightened */
16838  SCIP_VAR* var /**< problem variable */
16839  )
16840 {
16841  SCIP_BDCHGIDX* lbchgidx;
16842  SCIP_BDCHGIDX* ubchgidx;
16843 
16844  assert(var != NULL);
16845 
16846  var = SCIPvarGetProbvar(var);
16847 
16848  /* check, if variable is original without transformed variable */
16849  if( var == NULL )
16850  return &initbdchgidx;
16851 
16852  /* check, if variable was fixed in presolving */
16853  if( !SCIPvarIsActive(var) )
16854  return &presolvebdchgidx;
16855 
16857 
16858  /* get depths of last bound change information for the lower and upper bound */
16859  lbchgidx = (var->nlbchginfos > 0 && !var->lbchginfos[var->nlbchginfos-1].redundant
16860  ? &var->lbchginfos[var->nlbchginfos-1].bdchgidx : &initbdchgidx);
16861  ubchgidx = (var->nubchginfos > 0 && !var->ubchginfos[var->nubchginfos-1].redundant
16862  ? &var->ubchginfos[var->nubchginfos-1].bdchgidx : &initbdchgidx);
16863 
16864  if( SCIPbdchgidxIsEarlierNonNull(lbchgidx, ubchgidx) )
16865  return ubchgidx;
16866  else
16867  return lbchgidx;
16868 }
16869 
16870 /** returns the last depth level, at which the bounds of the given variable were tightened;
16871  * returns -2, if the variable's bounds are still the global bounds
16872  * returns -1, if the variable was fixed in presolving
16873  */
16875  SCIP_VAR* var /**< problem variable */
16876  )
16877 {
16878  SCIP_BDCHGIDX* bdchgidx;
16879 
16880  bdchgidx = SCIPvarGetLastBdchgIndex(var);
16881  assert(bdchgidx != NULL);
16882 
16883  return bdchgidx->depth;
16884 }
16885 
16886 /** returns at which depth in the tree a bound change was applied to the variable that conflicts with the
16887  * given bound; returns -1 if the bound does not conflict with the current local bounds of the variable
16888  */
16890  SCIP_VAR* var, /**< problem variable */
16891  SCIP_SET* set, /**< global SCIP settings */
16892  SCIP_BOUNDTYPE boundtype, /**< bound type of the conflicting bound */
16893  SCIP_Real bound /**< conflicting bound */
16894  )
16895 {
16896  int i;
16897 
16898  assert(var != NULL);
16899  assert(set != NULL);
16900  assert(var->scip == set->scip);
16901 
16902  if( boundtype == SCIP_BOUNDTYPE_LOWER )
16903  {
16904  /* check if the bound is in conflict with the current local bounds */
16905  if( SCIPsetIsLE(set, bound, var->locdom.ub) )
16906  return -1;
16907 
16908  /* check if the bound is in conflict with the global bound */
16909  if( SCIPsetIsGT(set, bound, var->glbdom.ub) )
16910  return 0;
16911 
16912  /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
16913  assert(var->nubchginfos > 0);
16914  assert(SCIPsetIsGT(set, bound, var->ubchginfos[var->nubchginfos-1].newbound));
16915 
16916  /* search for the first conflicting bound change */
16917  for( i = var->nubchginfos-1; i > 0 && SCIPsetIsGT(set, bound, var->ubchginfos[i-1].newbound); --i )
16918  {
16919  assert(var->ubchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
16921  }
16922  assert(SCIPsetIsGT(set, bound, var->ubchginfos[i].newbound)); /* bound change i is conflicting */
16923  assert(i == 0 || SCIPsetIsLE(set, bound, var->ubchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
16924 
16925  /* return the depth at which the first conflicting bound change took place */
16926  return var->ubchginfos[i].bdchgidx.depth;
16927  }
16928  else
16929  {
16930  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16931 
16932  /* check if the bound is in conflict with the current local bounds */
16933  if( SCIPsetIsGE(set, bound, var->locdom.lb) )
16934  return -1;
16935 
16936  /* check if the bound is in conflict with the global bound */
16937  if( SCIPsetIsLT(set, bound, var->glbdom.lb) )
16938  return 0;
16939 
16940  /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
16941  assert(var->nlbchginfos > 0);
16942  assert(SCIPsetIsLT(set, bound, var->lbchginfos[var->nlbchginfos-1].newbound));
16943 
16944  /* search for the first conflicting bound change */
16945  for( i = var->nlbchginfos-1; i > 0 && SCIPsetIsLT(set, bound, var->lbchginfos[i-1].newbound); --i )
16946  {
16947  assert(var->lbchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
16949  }
16950  assert(SCIPsetIsLT(set, bound, var->lbchginfos[i].newbound)); /* bound change i is conflicting */
16951  assert(i == 0 || SCIPsetIsGE(set, bound, var->lbchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
16952 
16953  /* return the depth at which the first conflicting bound change took place */
16954  return var->lbchginfos[i].bdchgidx.depth;
16955  }
16956 }
16957 
16958 /** returns whether the first binary variable was fixed earlier than the second one;
16959  * returns FALSE, if the first variable is not fixed, and returns TRUE, if the first variable is fixed, but the
16960  * second one is not fixed
16961  */
16963  SCIP_VAR* var1, /**< first binary variable */
16964  SCIP_VAR* var2 /**< second binary variable */
16965  )
16966 {
16967  SCIP_BDCHGIDX* bdchgidx1;
16968  SCIP_BDCHGIDX* bdchgidx2;
16969 
16970  assert(var1 != NULL);
16971  assert(var2 != NULL);
16972  assert(SCIPvarIsBinary(var1));
16973  assert(SCIPvarIsBinary(var2));
16974 
16975  var1 = SCIPvarGetProbvar(var1);
16976  var2 = SCIPvarGetProbvar(var2);
16977  assert(var1 != NULL);
16978  assert(var2 != NULL);
16979 
16980  /* check, if variables are globally fixed */
16981  if( !SCIPvarIsActive(var2) || var2->glbdom.lb > 0.5 || var2->glbdom.ub < 0.5 )
16982  return FALSE;
16983  if( !SCIPvarIsActive(var1) || var1->glbdom.lb > 0.5 || var1->glbdom.ub < 0.5 )
16984  return TRUE;
16985 
16988  assert(SCIPvarIsBinary(var1));
16989  assert(SCIPvarIsBinary(var2));
16990  assert(var1->nlbchginfos + var1->nubchginfos <= 1);
16991  assert(var2->nlbchginfos + var2->nubchginfos <= 1);
16992  assert(var1->nlbchginfos == 0 || !var1->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
16993  assert(var1->nubchginfos == 0 || !var1->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
16994  assert(var2->nlbchginfos == 0 || !var2->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
16995  assert(var2->nubchginfos == 0 || !var2->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
16996 
16997  if( var1->nlbchginfos == 1 )
16998  bdchgidx1 = &var1->lbchginfos[0].bdchgidx;
16999  else if( var1->nubchginfos == 1 )
17000  bdchgidx1 = &var1->ubchginfos[0].bdchgidx;
17001  else
17002  bdchgidx1 = NULL;
17003 
17004  if( var2->nlbchginfos == 1 )
17005  bdchgidx2 = &var2->lbchginfos[0].bdchgidx;
17006  else if( var2->nubchginfos == 1 )
17007  bdchgidx2 = &var2->ubchginfos[0].bdchgidx;
17008  else
17009  bdchgidx2 = NULL;
17010 
17011  return SCIPbdchgidxIsEarlier(bdchgidx1, bdchgidx2);
17012 }
17013 
17014 
17015 
17016 /*
17017  * Hash functions
17018  */
17019 
17020 /** gets the key (i.e. the name) of the given variable */
17021 SCIP_DECL_HASHGETKEY(SCIPhashGetKeyVar)
17022 { /*lint --e{715}*/
17023  SCIP_VAR* var = (SCIP_VAR*)elem;
17024 
17025  assert(var != NULL);
17026  return var->name;
17027 }
17028 
17029 
17030 
17031 
17032 /*
17033  * simple functions implemented as defines
17034  */
17035 
17036 /* In debug mode, the following methods are implemented as function calls to ensure
17037  * type validity.
17038  * In optimized mode, the methods are implemented as defines to improve performance.
17039  * However, we want to have them in the library anyways, so we have to undef the defines.
17040  */
17041 
17042 #undef SCIPboundchgGetNewbound
17043 #undef SCIPboundchgGetVar
17044 #undef SCIPboundchgGetBoundchgtype
17045 #undef SCIPboundchgGetBoundtype
17046 #undef SCIPboundchgIsRedundant
17047 #undef SCIPdomchgGetNBoundchgs
17048 #undef SCIPdomchgGetBoundchg
17049 #undef SCIPholelistGetLeft
17050 #undef SCIPholelistGetRight
17051 #undef SCIPholelistGetNext
17052 #undef SCIPvarGetName
17053 #undef SCIPvarGetNUses
17054 #undef SCIPvarGetData
17055 #undef SCIPvarSetData
17056 #undef SCIPvarSetDelorigData
17057 #undef SCIPvarSetTransData
17058 #undef SCIPvarSetDeltransData
17059 #undef SCIPvarGetStatus
17060 #undef SCIPvarIsOriginal
17061 #undef SCIPvarIsTransformed
17062 #undef SCIPvarIsNegated
17063 #undef SCIPvarGetType
17064 #undef SCIPvarIsBinary
17065 #undef SCIPvarIsIntegral
17066 #undef SCIPvarIsInitial
17067 #undef SCIPvarIsRemovable
17068 #undef SCIPvarIsDeleted
17069 #undef SCIPvarIsDeletable
17070 #undef SCIPvarMarkDeletable
17071 #undef SCIPvarMarkNotDeletable
17072 #undef SCIPvarIsActive
17073 #undef SCIPvarGetIndex
17074 #undef SCIPvarGetProbindex
17075 #undef SCIPvarGetTransVar
17076 #undef SCIPvarGetCol
17077 #undef SCIPvarIsInLP
17078 #undef SCIPvarGetAggrVar
17079 #undef SCIPvarGetAggrScalar
17080 #undef SCIPvarGetAggrConstant
17081 #undef SCIPvarGetMultaggrNVars
17082 #undef SCIPvarGetMultaggrVars
17083 #undef SCIPvarGetMultaggrScalars
17084 #undef SCIPvarGetMultaggrConstant
17085 #undef SCIPvarGetNegatedVar
17086 #undef SCIPvarGetNegationVar
17087 #undef SCIPvarGetNegationConstant
17088 #undef SCIPvarGetObj
17089 #undef SCIPvarGetLbOriginal
17090 #undef SCIPvarGetUbOriginal
17091 #undef SCIPvarGetHolelistOriginal
17092 #undef SCIPvarGetLbGlobal
17093 #undef SCIPvarGetUbGlobal
17094 #undef SCIPvarGetHolelistGlobal
17095 #undef SCIPvarGetBestBoundGlobal
17096 #undef SCIPvarGetWorstBoundGlobal
17097 #undef SCIPvarGetLbLocal
17098 #undef SCIPvarGetUbLocal
17099 #undef SCIPvarGetHolelistLocal
17100 #undef SCIPvarGetBestBoundLocal
17101 #undef SCIPvarGetWorstBoundLocal
17102 #undef SCIPvarGetBestBoundType
17103 #undef SCIPvarGetWorstBoundType
17104 #undef SCIPvarGetLbLazy
17105 #undef SCIPvarGetUbLazy
17106 #undef SCIPvarGetBranchFactor
17107 #undef SCIPvarGetBranchPriority
17108 #undef SCIPvarGetBranchDirection
17109 #undef SCIPvarGetNVlbs
17110 #undef SCIPvarGetVlbVars
17111 #undef SCIPvarGetVlbCoefs
17112 #undef SCIPvarGetVlbConstants
17113 #undef SCIPvarGetNVubs
17114 #undef SCIPvarGetVubVars
17115 #undef SCIPvarGetVubCoefs
17116 #undef SCIPvarGetVubConstants
17117 #undef SCIPvarGetNImpls
17118 #undef SCIPvarGetImplVars
17119 #undef SCIPvarGetImplTypes
17120 #undef SCIPvarGetImplBounds
17121 #undef SCIPvarGetImplIds
17122 #undef SCIPvarGetNCliques
17123 #undef SCIPvarGetCliques
17124 #undef SCIPvarGetLPSol
17125 #undef SCIPvarGetNLPSol
17126 #undef SCIPvarGetBdchgInfoLb
17127 #undef SCIPvarGetNBdchgInfosLb
17128 #undef SCIPvarGetBdchgInfoUb
17129 #undef SCIPvarGetNBdchgInfosUb
17130 #undef SCIPvarGetValuehistory
17131 #undef SCIPvarGetPseudoSol
17132 #undef SCIPvarCatchEvent
17133 #undef SCIPvarDropEvent
17134 #undef SCIPvarGetVSIDS
17135 #undef SCIPvarGetCliqueComponentIdx
17136 #undef SCIPvarIsRelaxationOnly
17137 #undef SCIPvarMarkRelaxationOnly
17138 #undef SCIPbdchgidxGetPos
17139 #undef SCIPbdchgidxIsEarlierNonNull
17140 #undef SCIPbdchgidxIsEarlier
17141 #undef SCIPbdchginfoGetOldbound
17142 #undef SCIPbdchginfoGetNewbound
17143 #undef SCIPbdchginfoGetVar
17144 #undef SCIPbdchginfoGetChgtype
17145 #undef SCIPbdchginfoGetBoundtype
17146 #undef SCIPbdchginfoGetDepth
17147 #undef SCIPbdchginfoGetPos
17148 #undef SCIPbdchginfoGetIdx
17149 #undef SCIPbdchginfoGetInferVar
17150 #undef SCIPbdchginfoGetInferCons
17151 #undef SCIPbdchginfoGetInferProp
17152 #undef SCIPbdchginfoGetInferInfo
17153 #undef SCIPbdchginfoGetInferBoundtype
17154 #undef SCIPbdchginfoIsRedundant
17155 #undef SCIPbdchginfoHasInferenceReason
17156 #undef SCIPbdchginfoIsTighter
17157 
17158 
17159 /** returns the new value of the bound in the bound change data */
17161  SCIP_BOUNDCHG* boundchg /**< bound change data */
17162  )
17163 {
17164  assert(boundchg != NULL);
17165 
17166  return boundchg->newbound;
17167 }
17168 
17169 /** returns the variable of the bound change in the bound change data */
17171  SCIP_BOUNDCHG* boundchg /**< bound change data */
17172  )
17173 {
17174  assert(boundchg != NULL);
17175 
17176  return boundchg->var;
17177 }
17178 
17179 /** returns the bound change type of the bound change in the bound change data */
17181  SCIP_BOUNDCHG* boundchg /**< bound change data */
17182  )
17183 {
17184  assert(boundchg != NULL);
17185 
17186  return (SCIP_BOUNDCHGTYPE)(boundchg->boundchgtype);
17187 }
17188 
17189 /** returns the bound type of the bound change in the bound change data */
17191  SCIP_BOUNDCHG* boundchg /**< bound change data */
17192  )
17193 {
17194  assert(boundchg != NULL);
17195 
17196  return (SCIP_BOUNDTYPE)(boundchg->boundtype);
17197 }
17198 
17199 /** returns whether the bound change is redundant due to a more global bound that is at least as strong */
17201  SCIP_BOUNDCHG* boundchg /**< bound change data */
17202  )
17203 {
17204  assert(boundchg != NULL);
17205 
17206  return boundchg->redundant;
17207 }
17208 
17209 /** returns the number of bound changes in the domain change data */
17211  SCIP_DOMCHG* domchg /**< domain change data */
17212  )
17213 {
17214  return domchg != NULL ? domchg->domchgbound.nboundchgs : 0;
17215 }
17216 
17217 /** returns a particular bound change in the domain change data */
17219  SCIP_DOMCHG* domchg, /**< domain change data */
17220  int pos /**< position of the bound change in the domain change data */
17221  )
17222 {
17223  assert(domchg != NULL);
17224  assert(0 <= pos && pos < (int)domchg->domchgbound.nboundchgs);
17225 
17226  return &domchg->domchgbound.boundchgs[pos];
17227 }
17228 
17229 /** returns left bound of open interval in hole */
17231  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
17232  )
17233 {
17234  assert(holelist != NULL);
17235 
17236  return holelist->hole.left;
17237 }
17238 
17239 /** returns right bound of open interval in hole */
17241  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
17242  )
17243 {
17244  assert(holelist != NULL);
17245 
17246  return holelist->hole.right;
17247 }
17248 
17249 /** returns next hole in list */
17251  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
17252  )
17253 {
17254  assert(holelist != NULL);
17255 
17256  return holelist->next;
17257 }
17258 
17259 /** returns the name of the variable
17260  *
17261  * @note to change the name of a variable, use SCIPchgVarName() from scip.h
17262  */
17263 const char* SCIPvarGetName(
17264  SCIP_VAR* var /**< problem variable */
17265  )
17266 {
17267  assert(var != NULL);
17268 
17269  return var->name;
17270 }
17271 
17272 /** gets number of times, the variable is currently captured */
17273 int SCIPvarGetNUses(
17274  SCIP_VAR* var /**< problem variable */
17275  )
17276 {
17277  assert(var != NULL);
17278 
17279  return var->nuses;
17280 }
17281 
17282 /** returns the user data of the variable */
17284  SCIP_VAR* var /**< problem variable */
17285  )
17286 {
17287  assert(var != NULL);
17288 
17289  return var->vardata;
17290 }
17291 
17292 /** sets the user data for the variable */
17293 void SCIPvarSetData(
17294  SCIP_VAR* var, /**< problem variable */
17295  SCIP_VARDATA* vardata /**< user variable data */
17296  )
17297 {
17298  assert(var != NULL);
17299 
17300  var->vardata = vardata;
17301 }
17302 
17303 /** sets method to free user data for the original variable */
17305  SCIP_VAR* var, /**< problem variable */
17306  SCIP_DECL_VARDELORIG ((*vardelorig)) /**< frees user data of original variable */
17307  )
17308 {
17309  assert(var != NULL);
17310  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
17311 
17312  var->vardelorig = vardelorig;
17313 }
17314 
17315 /** sets method to transform user data of the variable */
17316 void SCIPvarSetTransData(
17317  SCIP_VAR* var, /**< problem variable */
17318  SCIP_DECL_VARTRANS ((*vartrans)) /**< creates transformed user data by transforming original user data */
17319  )
17320 {
17321  assert(var != NULL);
17322  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
17323 
17324  var->vartrans = vartrans;
17325 }
17326 
17327 /** sets method to free transformed user data for the variable */
17329  SCIP_VAR* var, /**< problem variable */
17330  SCIP_DECL_VARDELTRANS ((*vardeltrans)) /**< frees user data of transformed variable */
17331  )
17332 {
17333  assert(var != NULL);
17334 
17335  var->vardeltrans = vardeltrans;
17336 }
17337 
17338 /** sets method to copy this variable into sub-SCIPs */
17339 void SCIPvarSetCopyData(
17340  SCIP_VAR* var, /**< problem variable */
17341  SCIP_DECL_VARCOPY ((*varcopy)) /**< copy method of the variable */
17342  )
17343 {
17344  assert(var != NULL);
17345 
17346  var->varcopy = varcopy;
17347 }
17348 
17349 /** sets the initial flag of a variable; only possible for original or loose variables */
17351  SCIP_VAR* var, /**< problem variable */
17352  SCIP_Bool initial /**< initial flag */
17353  )
17354 {
17355  assert(var != NULL);
17356 
17358  return SCIP_INVALIDCALL;
17359 
17360  var->initial = initial;
17361 
17362  return SCIP_OKAY;
17363 }
17364 
17365 /** sets the removable flag of a variable; only possible for original or loose variables */
17367  SCIP_VAR* var, /**< problem variable */
17368  SCIP_Bool removable /**< removable flag */
17369  )
17370 {
17371  assert(var != NULL);
17372 
17374  return SCIP_INVALIDCALL;
17375 
17376  var->removable = removable;
17377 
17378  return SCIP_OKAY;
17379 }
17380 
17381 /** gets status of variable */
17383  SCIP_VAR* var /**< problem variable */
17384  )
17385 {
17386  assert(var != NULL);
17387 
17388  return (SCIP_VARSTATUS)(var->varstatus);
17389 }
17390 
17391 /** returns whether the variable belongs to the original problem */
17393  SCIP_VAR* var /**< problem variable */
17394  )
17395 {
17396  assert(var != NULL);
17397  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED || var->negatedvar != NULL);
17398 
17402 }
17403 
17404 /** returns whether the variable belongs to the transformed problem */
17406  SCIP_VAR* var /**< problem variable */
17407  )
17408 {
17409  assert(var != NULL);
17410  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED || var->negatedvar != NULL);
17411 
17415 }
17416 
17417 /** returns whether the variable was created by negation of a different variable */
17419  SCIP_VAR* var /**< problem variable */
17420  )
17421 {
17422  assert(var != NULL);
17423 
17424  return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17425 }
17426 
17427 /** gets type of variable */
17429  SCIP_VAR* var /**< problem variable */
17430  )
17431 {
17432  assert(var != NULL);
17433 
17434  return (SCIP_VARTYPE)(var->vartype);
17435 }
17436 
17437 /** returns TRUE if the variable is of binary type; this is the case if:
17438  * (1) variable type is binary
17439  * (2) variable type is integer or implicit integer and
17440  * (i) the global lower bound is greater than or equal to zero
17441  * (ii) the global upper bound is less than or equal to one
17442  */
17444  SCIP_VAR* var /**< problem variable */
17445  )
17446 {
17447  assert(var != NULL);
17448 
17449  return (SCIPvarGetType(var) == SCIP_VARTYPE_BINARY ||
17450  (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && var->glbdom.lb >= 0.0 && var->glbdom.ub <= 1.0));
17451 }
17452 
17453 /** returns whether variable is of integral type (binary, integer, or implicit integer) */
17455  SCIP_VAR* var /**< problem variable */
17456  )
17457 {
17458  assert(var != NULL);
17459 
17460  return (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
17461 }
17462 
17463 /** returns whether variable's column should be present in the initial root LP */
17465  SCIP_VAR* var /**< problem variable */
17466  )
17467 {
17468  assert(var != NULL);
17469 
17470  return var->initial;
17471 }
17472 
17473 /** returns whether variable's column is removable from the LP (due to aging or cleanup) */
17475  SCIP_VAR* var /**< problem variable */
17476  )
17477 {
17478  assert(var != NULL);
17479 
17480  return var->removable;
17481 }
17482 
17483 /** returns whether the variable was deleted from the problem */
17485  SCIP_VAR* var /**< problem variable */
17486  )
17487 {
17488  assert(var != NULL);
17489 
17490  return var->deleted;
17491 }
17492 
17493 /** marks the variable to be deletable, i.e., it may be deleted completely from the problem;
17494  * method can only be called before the variable is added to the problem by SCIPaddVar() or SCIPaddPricedVar()
17495  */
17497  SCIP_VAR* var /**< problem variable */
17498  )
17499 {
17500  assert(var != NULL);
17501  assert(var->probindex == -1);
17502 
17503  var->deletable = TRUE;
17504 }
17505 
17506 /** marks the variable to be not deletable from the problem */
17509  )
17510 {
17511  assert(var != NULL);
17512 
17513  var->deletable = FALSE;
17514 }
17515 
17516 /** marks variable to be deleted from global structures (cliques etc.) when cleaning up
17517  *
17518  * @note: this is not equivalent to marking the variable itself for deletion, this is done by using SCIPvarMarkDeletable()
17519  */
17521  SCIP_VAR* var /**< problem variable */
17522  )
17523 {
17524  assert(var != NULL);
17525 
17526  var->delglobalstructs = TRUE;
17527 }
17528 
17529 /** returns whether the variable was flagged for deletion from global structures (cliques etc.) */
17531  SCIP_VAR* var /**< problem variable */
17532  )
17533 {
17534  assert(var != NULL);
17535 
17536  return var->delglobalstructs;
17537 }
17538 
17539 /** returns whether a variable has been introduced to define a relaxation
17540  *
17541  * These variables are only valid for the current SCIP solve round,
17542  * they are not contained in any (checked) constraints, but may be used
17543  * in cutting planes, for example.
17544  * Relaxation-only variables are not copied by SCIPcopyVars and cuts
17545  * that contain these variables are not added as linear constraints when
17546  * restarting or transferring information from a copied SCIP to a SCIP.
17547  * Also conflicts with relaxation-only variables are not generated at
17548  * the moment.
17549  */
17551  SCIP_VAR* var /**< problem variable */
17552  )
17553 {
17554  assert(var != NULL);
17555 
17556  return var->relaxationonly;
17557 }
17558 
17559 /** marks that this variable has only been introduced to define a relaxation
17560  *
17561  * The variable must not have a coefficient in the objective and must be deletable.
17562  * If it is not marked deletable, it will be marked as deletable, which is only possible
17563  * before the variable is added to a problem.
17564  *
17565  * @see SCIPvarIsRelaxationOnly
17566  * @see SCIPvarMarkDeletable
17567  */
17569  SCIP_VAR* var /**< problem variable */
17570  )
17571 {
17572  assert(var != NULL);
17573  assert(SCIPvarGetObj(var) == 0.0);
17574 
17575  if( !SCIPvarIsDeletable(var) )
17576  SCIPvarMarkDeletable(var);
17577 
17578  var->relaxationonly = TRUE;
17579 }
17580 
17581 /** returns whether variable is allowed to be deleted completely from the problem */
17584  )
17585 {
17586  assert(var != NULL);
17587 
17588  return var->deletable;
17589 }
17590 
17591 /** returns whether variable is an active (neither fixed nor aggregated) variable */
17593  SCIP_VAR* var /**< problem variable */
17594  )
17595 {
17596  assert(var != NULL);
17597 
17598  return (var->probindex >= 0);
17599 }
17600 
17601 /** gets unique index of variable */
17602 int SCIPvarGetIndex(
17603  SCIP_VAR* var /**< problem variable */
17604  )
17605 {
17606  assert(var != NULL);
17607 
17608  return var->index;
17609 }
17610 
17611 /** gets position of variable in problem, or -1 if variable is not active */
17613  SCIP_VAR* var /**< problem variable */
17614  )
17615 {
17616  assert(var != NULL);
17617 
17618  return var->probindex;
17619 }
17620 
17621 /** gets transformed variable of ORIGINAL variable */
17623  SCIP_VAR* var /**< problem variable */
17624  )
17625 {
17626  assert(var != NULL);
17627  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
17628 
17629  return var->data.original.transvar;
17630 }
17631 
17632 /** gets column of COLUMN variable */
17634  SCIP_VAR* var /**< problem variable */
17635  )
17636 {
17637  assert(var != NULL);
17638  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
17639 
17640  return var->data.col;
17641 }
17642 
17643 /** returns whether the variable is a COLUMN variable that is member of the current LP */
17645  SCIP_VAR* var /**< problem variable */
17646  )
17647 {
17648  assert(var != NULL);
17649 
17650  return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN && SCIPcolIsInLP(var->data.col));
17651 }
17652 
17653 /** gets aggregation variable y of an aggregated variable x = a*y + c */
17655  SCIP_VAR* var /**< problem variable */
17656  )
17657 {
17658  assert(var != NULL);
17660  assert(!var->donotaggr);
17661 
17662  return var->data.aggregate.var;
17663 }
17664 
17665 /** gets aggregation scalar a of an aggregated variable x = a*y + c */
17667  SCIP_VAR* var /**< problem variable */
17668  )
17669 {
17670  assert(var != NULL);
17672  assert(!var->donotaggr);
17673 
17674  return var->data.aggregate.scalar;
17675 }
17676 
17677 /** gets aggregation constant c of an aggregated variable x = a*y + c */
17679  SCIP_VAR* var /**< problem variable */
17680  )
17681 {
17682  assert(var != NULL);
17684  assert(!var->donotaggr);
17685 
17686  return var->data.aggregate.constant;
17687 }
17688 
17689 /** gets number n of aggregation variables of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17691  SCIP_VAR* var /**< problem variable */
17692  )
17693 {
17694  assert(var != NULL);
17695  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17696  assert(!var->donotmultaggr);
17697 
17698  return var->data.multaggr.nvars;
17699 }
17700 
17701 /** gets vector of aggregation variables y of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17703  SCIP_VAR* var /**< problem variable */
17704  )
17705 {
17706  assert(var != NULL);
17707  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17708  assert(!var->donotmultaggr);
17709 
17710  return var->data.multaggr.vars;
17711 }
17712 
17713 /** gets vector of aggregation scalars a of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17715  SCIP_VAR* var /**< problem variable */
17716  )
17717 {
17718  assert(var != NULL);
17719  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17720  assert(!var->donotmultaggr);
17721 
17722  return var->data.multaggr.scalars;
17723 }
17724 
17725 /** gets aggregation constant c of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17727  SCIP_VAR* var /**< problem variable */
17728  )
17729 {
17730  assert(var != NULL);
17731  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17732  assert(!var->donotmultaggr);
17733 
17734  return var->data.multaggr.constant;
17735 }
17736 
17737 /** gets the negation of the given variable; may return NULL, if no negation is existing yet */
17739  SCIP_VAR* var /**< negated problem variable */
17740  )
17741 {
17742  assert(var != NULL);
17743 
17744  return var->negatedvar;
17745 }
17746 
17747 /** gets the negation variable x of a negated variable x' = offset - x */
17749  SCIP_VAR* var /**< negated problem variable */
17750  )
17751 {
17752  assert(var != NULL);
17753  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17754 
17755  return var->negatedvar;
17756 }
17757 
17758 /** gets the negation offset of a negated variable x' = offset - x */
17760  SCIP_VAR* var /**< negated problem variable */
17761  )
17762 {
17763  assert(var != NULL);
17764  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17765 
17766  return var->data.negate.constant;
17767 }
17768 
17769 /** gets objective function value of variable */
17771  SCIP_VAR* var /**< problem variable */
17772  )
17773 {
17774  assert(var != NULL);
17775 
17776  return var->obj;
17777 }
17778 
17779 /** gets the unchanged objective function value of a variable (ignoring temproray changes performed in probing mode) */
17781  SCIP_VAR* var /**< problem variable */
17782  )
17783 {
17784  assert(var != NULL);
17785 
17786  return var->unchangedobj;
17787 }
17788 
17789 /** gets corresponding objective value of active, fixed, or multi-aggregated problem variable of given variable
17790  * e.g. obj(x) = 1 this method returns for ~x the value -1
17791  */
17793  SCIP_VAR* var, /**< problem variable */
17794  SCIP_Real* aggrobj /**< pointer to store the aggregated objective value */
17795  )
17796 {
17797  SCIP_VAR* probvar = var;
17798  SCIP_Real mult = 1.0;
17799 
17800  assert(probvar != NULL);
17801  assert(aggrobj != NULL);
17802 
17803  while( probvar != NULL )
17804  {
17805  switch( SCIPvarGetStatus(probvar) )
17806  {
17808  case SCIP_VARSTATUS_LOOSE:
17809  case SCIP_VARSTATUS_COLUMN:
17810  (*aggrobj) = mult * SCIPvarGetObj(probvar);
17811  return SCIP_OKAY;
17812 
17813  case SCIP_VARSTATUS_FIXED:
17814  assert(SCIPvarGetObj(probvar) == 0.0);
17815  (*aggrobj) = 0.0;
17816  return SCIP_OKAY;
17817 
17819  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
17820  if ( probvar->data.multaggr.nvars == 1 )
17821  {
17822  assert( probvar->data.multaggr.vars != NULL );
17823  assert( probvar->data.multaggr.scalars != NULL );
17824  assert( probvar->data.multaggr.vars[0] != NULL );
17825  mult *= probvar->data.multaggr.scalars[0];
17826  probvar = probvar->data.multaggr.vars[0];
17827  break;
17828  }
17829  else
17830  {
17831  SCIP_Real tmpobj;
17832  int v;
17833 
17834  (*aggrobj) = 0.0;
17835 
17836  for( v = probvar->data.multaggr.nvars - 1; v >= 0; --v )
17837  {
17838  SCIP_CALL( SCIPvarGetAggregatedObj(probvar->data.multaggr.vars[v], &tmpobj) );
17839  (*aggrobj) += probvar->data.multaggr.scalars[v] * tmpobj;
17840  }
17841  return SCIP_OKAY;
17842  }
17843 
17844  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
17845  assert(probvar->data.aggregate.var != NULL);
17846  mult *= probvar->data.aggregate.scalar;
17847  probvar = probvar->data.aggregate.var;
17848  break;
17849 
17850  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
17851  assert(probvar->negatedvar != NULL);
17852  assert(SCIPvarGetStatus(probvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
17853  assert(probvar->negatedvar->negatedvar == probvar);
17854  mult *= -1.0;
17855  probvar = probvar->negatedvar;
17856  break;
17857 
17858  default:
17859  SCIPABORT();
17860  return SCIP_INVALIDDATA; /*lint !e527*/
17861  }
17862  }
17863 
17864  return SCIP_INVALIDDATA;
17865 }
17866 
17867 /** gets original lower bound of original problem variable (i.e. the bound set in problem creation) */
17869  SCIP_VAR* var /**< original problem variable */
17870  )
17871 {
17872  assert(var != NULL);
17873  assert(SCIPvarIsOriginal(var));
17874 
17876  return var->data.original.origdom.lb;
17877  else
17878  {
17879  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17880  assert(var->negatedvar != NULL);
17882 
17883  return var->data.negate.constant - var->negatedvar->data.original.origdom.ub;
17884  }
17885 }
17886 
17887 /** gets original upper bound of original problem variable (i.e. the bound set in problem creation) */
17889  SCIP_VAR* var /**< original problem variable */
17890  )
17891 {
17892  assert(var != NULL);
17893  assert(SCIPvarIsOriginal(var));
17894 
17896  return var->data.original.origdom.ub;
17897  else
17898  {
17899  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17900  assert(var->negatedvar != NULL);
17902 
17903  return var->data.negate.constant - var->negatedvar->data.original.origdom.lb;
17904  }
17905 }
17906 
17907 /** gets the original hole list of an original variable */
17909  SCIP_VAR* var /**< problem variable */
17910  )
17911 {
17912  assert(var != NULL);
17913  assert(SCIPvarIsOriginal(var));
17914 
17916  return var->data.original.origdom.holelist;
17917 
17918  return NULL;
17919 }
17920 
17921 /** gets global lower bound of variable */
17923  SCIP_VAR* var /**< problem variable */
17924  )
17925 {
17926  assert(var != NULL);
17927 
17928  return var->glbdom.lb;
17929 }
17930 
17931 /** gets global upper bound of variable */
17933  SCIP_VAR* var /**< problem variable */
17934  )
17935 {
17936  assert(var != NULL);
17937 
17938  return var->glbdom.ub;
17939 }
17940 
17941 /** gets the global hole list of an active variable */
17943  SCIP_VAR* var /**< problem variable */
17944  )
17945 {
17946  assert(var != NULL);
17947 
17948  return var->glbdom.holelist;
17949 }
17950 
17951 /** gets best global bound of variable with respect to the objective function */
17953  SCIP_VAR* var /**< problem variable */
17954  )
17955 {
17956  assert(var != NULL);
17957 
17958  if( var->obj >= 0.0 )
17959  return var->glbdom.lb;
17960  else
17961  return var->glbdom.ub;
17962 }
17963 
17964 /** gets worst global bound of variable with respect to the objective function */
17966  SCIP_VAR* var /**< problem variable */
17967  )
17968 {
17969  assert(var != NULL);
17970 
17971  if( var->obj >= 0.0 )
17972  return var->glbdom.ub;
17973  else
17974  return var->glbdom.lb;
17975 }
17976 
17977 /** gets current lower bound of variable */
17979  SCIP_VAR* var /**< problem variable */
17980  )
17981 {
17982  assert(var != NULL);
17983 
17984  return var->locdom.lb;
17985 }
17986 
17987 /** gets current upper bound of variable */
17989  SCIP_VAR* var /**< problem variable */
17990  )
17991 {
17992  assert(var != NULL);
17993 
17994  return var->locdom.ub;
17995 }
17996 
17997 /** gets the current hole list of an active variable */
17999  SCIP_VAR* var /**< problem variable */
18000  )
18001 {
18002  assert(var != NULL);
18003 
18004  return var->locdom.holelist;
18005 }
18006 
18007 /** gets best local bound of variable with respect to the objective function */
18009  SCIP_VAR* var /**< problem variable */
18010  )
18011 {
18012  assert(var != NULL);
18013 
18014  if( var->obj >= 0.0 )
18015  return var->locdom.lb;
18016  else
18017  return var->locdom.ub;
18018 }
18019 
18020 /** gets worst local bound of variable with respect to the objective function */
18022  SCIP_VAR* var /**< problem variable */
18023  )
18024 {
18025  assert(var != NULL);
18026 
18027  if( var->obj >= 0.0 )
18028  return var->locdom.ub;
18029  else
18030  return var->locdom.lb;
18031 }
18032 
18033 /** gets type (lower or upper) of best bound of variable with respect to the objective function */
18035  SCIP_VAR* var /**< problem variable */
18036  )
18037 {
18038  assert(var != NULL);
18039 
18040  if( var->obj >= 0.0 )
18041  return SCIP_BOUNDTYPE_LOWER;
18042  else
18043  return SCIP_BOUNDTYPE_UPPER;
18044 }
18045 
18046 /** gets type (lower or upper) of worst bound of variable with respect to the objective function */
18048  SCIP_VAR* var /**< problem variable */
18049  )
18050 {
18051  assert(var != NULL);
18052 
18053  if( var->obj >= 0.0 )
18054  return SCIP_BOUNDTYPE_UPPER;
18055  else
18056  return SCIP_BOUNDTYPE_LOWER;
18057 }
18058 
18059 /** gets lazy lower bound of variable, returns -infinity if the variable has no lazy lower bound */
18061  SCIP_VAR* var /**< problem variable */
18062  )
18063 {
18064  assert(var != NULL);
18065 
18066  return var->lazylb;
18067 }
18068 
18069 /** gets lazy upper bound of variable, returns infinity if the variable has no lazy upper bound */
18071  SCIP_VAR* var /**< problem variable */
18072  )
18073 {
18074  assert(var != NULL);
18075 
18076  return var->lazyub;
18077 }
18078 
18079 /** gets the branch factor of the variable; this value can be used in the branching methods to scale the score
18080  * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
18081  */
18083  SCIP_VAR* var /**< problem variable */
18084  )
18085 {
18086  assert(var != NULL);
18087 
18088  return var->branchfactor;
18089 }
18090 
18091 /** gets the branch priority of the variable; variables with higher priority should always be preferred to variables
18092  * with lower priority
18093  */
18095  SCIP_VAR* var /**< problem variable */
18096  )
18097 {
18098  assert(var != NULL);
18099 
18100  return var->branchpriority;
18101 }
18102 
18103 /** gets the preferred branch direction of the variable (downwards, upwards, or auto) */
18105  SCIP_VAR* var /**< problem variable */
18106  )
18107 {
18108  assert(var != NULL);
18109 
18110  return (SCIP_BRANCHDIR)var->branchdirection;
18111 }
18112 
18113 /** gets number of variable lower bounds x >= b_i*z_i + d_i of given variable x */
18114 int SCIPvarGetNVlbs(
18115  SCIP_VAR* var /**< problem variable */
18116  )
18117 {
18118  assert(var != NULL);
18119 
18120  return SCIPvboundsGetNVbds(var->vlbs);
18121 }
18122 
18123 /** gets array with bounding variables z_i in variable lower bounds x >= b_i*z_i + d_i of given variable x;
18124  * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
18125  */
18127  SCIP_VAR* var /**< problem variable */
18128  )
18129 {
18130  assert(var != NULL);
18131 
18132  return SCIPvboundsGetVars(var->vlbs);
18133 }
18134 
18135 /** gets array with bounding coefficients b_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
18137  SCIP_VAR* var /**< problem variable */
18138  )
18139 {
18140  assert(var != NULL);
18141 
18142  return SCIPvboundsGetCoefs(var->vlbs);
18143 }
18144 
18145 /** gets array with bounding constants d_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
18147  SCIP_VAR* var /**< problem variable */
18148  )
18149 {
18150  assert(var != NULL);
18151 
18152  return SCIPvboundsGetConstants(var->vlbs);
18153 }
18154 
18155 /** gets number of variable upper bounds x <= b_i*z_i + d_i of given variable x */
18156 int SCIPvarGetNVubs(
18157  SCIP_VAR* var /**< problem variable */
18158  )
18159 {
18160  assert(var != NULL);
18161 
18162  return SCIPvboundsGetNVbds(var->vubs);
18163 }
18164 
18165 /** gets array with bounding variables z_i in variable upper bounds x <= b_i*z_i + d_i of given variable x;
18166  * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
18167  */
18169  SCIP_VAR* var /**< problem variable */
18170  )
18171 {
18172  assert(var != NULL);
18173 
18174  return SCIPvboundsGetVars(var->vubs);
18175 }
18176 
18177 /** gets array with bounding coefficients b_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
18179  SCIP_VAR* var /**< problem variable */
18180  )
18181 {
18182  assert(var != NULL);
18183 
18184  return SCIPvboundsGetCoefs(var->vubs);
18185 }
18186 
18187 /** gets array with bounding constants d_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
18189  SCIP_VAR* var /**< problem variable */
18190  )
18191 {
18192  assert(var != NULL);
18193 
18194  return SCIPvboundsGetConstants(var->vubs);
18195 }
18196 
18197 /** gets number of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
18198  * there are no implications for nonbinary variable x
18199  */
18200 int SCIPvarGetNImpls(
18201  SCIP_VAR* var, /**< active problem variable */
18202  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
18203  )
18204 {
18205  assert(var != NULL);
18206  assert(SCIPvarIsActive(var));
18207 
18208  return SCIPimplicsGetNImpls(var->implics, varfixing);
18209 }
18210 
18211 /** gets array with implication variables y of implications y <= b or y >= b for x == 0 or x == 1 of given active
18212  * problem variable x, there are no implications for nonbinary variable x;
18213  * the implications are sorted such that implications with binary implied variables precede the ones with non-binary
18214  * implied variables, and as a second criteria, the implied variables are sorted by increasing variable index
18215  * (see SCIPvarGetIndex())
18216  */
18218  SCIP_VAR* var, /**< active problem variable */
18219  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
18220  )
18221 {
18222  assert(var != NULL);
18223  assert(SCIPvarIsActive(var));
18224 
18225  return SCIPimplicsGetVars(var->implics, varfixing);
18226 }
18227 
18228 /** gets array with implication types of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
18229  * variable x (SCIP_BOUNDTYPE_UPPER if y <= b, SCIP_BOUNDTYPE_LOWER if y >= b),
18230  * there are no implications for nonbinary variable x
18231  */
18233  SCIP_VAR* var, /**< active problem variable */
18234  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
18235  )
18236 {
18237  assert(var != NULL);
18238  assert(SCIPvarIsActive(var));
18239 
18240  return SCIPimplicsGetTypes(var->implics, varfixing);
18241 }
18242 
18243 /** gets array with implication bounds b of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
18244  * variable x, there are no implications for nonbinary variable x
18245  */
18247  SCIP_VAR* var, /**< active problem variable */
18248  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
18249  )
18250 {
18251  assert(var != NULL);
18252  assert(SCIPvarIsActive(var));
18253 
18254  return SCIPimplicsGetBounds(var->implics, varfixing);
18255 }
18256 
18257 /** Gets array with unique ids of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
18258  * there are no implications for nonbinary variable x.
18259  * If an implication is a shortcut, i.e., it was added as part of the transitive closure of another implication,
18260  * its id is negative, otherwise it is nonnegative.
18261  */
18262 int* SCIPvarGetImplIds(
18263  SCIP_VAR* var, /**< active problem variable */
18264  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
18265  )
18266 {
18267  assert(var != NULL);
18268  assert(SCIPvarIsActive(var));
18269 
18270  return SCIPimplicsGetIds(var->implics, varfixing);
18271 }
18272 
18273 /** gets number of cliques, the active variable is contained in */
18274 int SCIPvarGetNCliques(
18275  SCIP_VAR* var, /**< active problem variable */
18276  SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
18277  )
18278 {
18279  assert(var != NULL);
18280 
18281  return SCIPcliquelistGetNCliques(var->cliquelist, varfixing);
18282 }
18283 
18284 /** gets array of cliques, the active variable is contained in */
18286  SCIP_VAR* var, /**< active problem variable */
18287  SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
18288  )
18289 {
18290  assert(var != NULL);
18291 
18292  return SCIPcliquelistGetCliques(var->cliquelist, varfixing);
18293 }
18294 
18295 /** gets primal LP solution value of variable */
18297  SCIP_VAR* var /**< problem variable */
18298  )
18299 {
18300  assert(var != NULL);
18301 
18303  return SCIPcolGetPrimsol(var->data.col);
18304  else
18305  return SCIPvarGetLPSol_rec(var);
18306 }
18307 
18308 /** gets primal NLP solution value of variable */
18310  SCIP_VAR* var /**< problem variable */
18311  )
18312 {
18313  assert(var != NULL);
18314 
18316  return var->nlpsol;
18317  else
18318  return SCIPvarGetNLPSol_rec(var);
18319 }
18320 
18321 /** return lower bound change info at requested position */
18323  SCIP_VAR* var, /**< problem variable */
18324  int pos /**< requested position */
18325  )
18326 {
18327  assert(pos >= 0);
18328  assert(pos < var->nlbchginfos);
18329 
18330  return &var->lbchginfos[pos];
18331 }
18332 
18333 /** gets the number of lower bound change info array */
18335  SCIP_VAR* var /**< problem variable */
18336  )
18337 {
18338  return var->nlbchginfos;
18339 }
18340 
18341 /** return upper bound change info at requested position */
18343  SCIP_VAR* var, /**< problem variable */
18344  int pos /**< requested position */
18345  )
18346 {
18347  assert(pos >= 0);
18348  assert(pos < var->nubchginfos);
18349 
18350  return &var->ubchginfos[pos];
18351 }
18352 
18353 /** gets the number upper bound change info array */
18355  SCIP_VAR* var /**< problem variable */
18356  )
18357 {
18358  assert(var != NULL);
18359 
18360  return var->nubchginfos;
18361 }
18362 
18363 /** returns the value based history for the variable */
18365  SCIP_VAR* var /**< problem variable */
18366  )
18367 {
18368  assert(var != NULL);
18369 
18370  return var->valuehistory;
18371 }
18372 
18373 /** gets pseudo solution value of variable */
18375  SCIP_VAR* var /**< problem variable */
18376  )
18377 {
18378  assert(var != NULL);
18379 
18381  return SCIPvarGetBestBoundLocal(var);
18382  else
18383  return SCIPvarGetPseudoSol_rec(var);
18384 }
18385 
18386 /** returns the variable's VSIDS score */
18388  SCIP_VAR* var, /**< problem variable */
18389  SCIP_STAT* stat, /**< problem statistics */
18390  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
18391  )
18392 {
18393  assert(var != NULL);
18394 
18396  return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
18397  else
18398  return SCIPvarGetVSIDS_rec(var, stat, dir);
18399 }
18400 
18401 /** includes event handler with given data in variable's event filter */
18403  SCIP_VAR* var, /**< problem variable */
18404  BMS_BLKMEM* blkmem, /**< block memory */
18405  SCIP_SET* set, /**< global SCIP settings */
18406  SCIP_EVENTTYPE eventtype, /**< event type to catch */
18407  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
18408  SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
18409  int* filterpos /**< pointer to store position of event filter entry, or NULL */
18410  )
18411 {
18412  assert(var != NULL);
18413  assert(set != NULL);
18414  assert(var->scip == set->scip);
18415  assert(var->eventfilter != NULL);
18416  assert((eventtype & ~SCIP_EVENTTYPE_VARCHANGED) == 0);
18417  assert((eventtype & SCIP_EVENTTYPE_VARCHANGED) != 0);
18418  assert(SCIPvarIsTransformed(var));
18419 
18420  SCIPsetDebugMsg(set, "catch event of type 0x%" SCIP_EVENTTYPE_FORMAT " of variable <%s> with handler %p and data %p\n",
18421  eventtype, var->name, (void*)eventhdlr, (void*)eventdata);
18422 
18423  SCIP_CALL( SCIPeventfilterAdd(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
18424 
18425  return SCIP_OKAY;
18426 }
18427 
18428 /** deletes event handler with given data from variable's event filter */
18430  SCIP_VAR* var, /**< problem variable */
18431  BMS_BLKMEM* blkmem, /**< block memory */
18432  SCIP_SET* set, /**< global SCIP settings */
18433  SCIP_EVENTTYPE eventtype, /**< event type mask of dropped event */
18434  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
18435  SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
18436  int filterpos /**< position of event filter entry returned by SCIPvarCatchEvent(), or -1 */
18437  )
18438 {
18439  assert(var != NULL);
18440  assert(set != NULL);
18441  assert(var->scip == set->scip);
18442  assert(var->eventfilter != NULL);
18443  assert(SCIPvarIsTransformed(var));
18444 
18445  SCIPsetDebugMsg(set, "drop event of variable <%s> with handler %p and data %p\n", var->name, (void*)eventhdlr,
18446  (void*)eventdata);
18447 
18448  SCIP_CALL( SCIPeventfilterDel(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
18449 
18450  return SCIP_OKAY;
18451 }
18452 
18453 /** returns the position of the bound change index */
18454 int SCIPbdchgidxGetPos(
18455  SCIP_BDCHGIDX* bdchgidx /**< bound change index */
18456  )
18457 {
18458  assert(bdchgidx != NULL);
18459 
18460  return bdchgidx->pos;
18461 }
18462 
18463 /** returns whether first bound change index belongs to an earlier applied bound change than second one */
18465  SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index */
18466  SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index */
18467  )
18468 {
18469  assert(bdchgidx1 != NULL);
18470  assert(bdchgidx1->depth >= -2);
18471  assert(bdchgidx1->pos >= 0);
18472  assert(bdchgidx2 != NULL);
18473  assert(bdchgidx2->depth >= -2);
18474  assert(bdchgidx2->pos >= 0);
18475 
18476  return (bdchgidx1->depth < bdchgidx2->depth)
18477  || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
18478 }
18479 
18480 /** returns whether first bound change index belongs to an earlier applied bound change than second one;
18481  * if a bound change index is NULL, the bound change index represents the current time, i.e. the time after the
18482  * last bound change was applied to the current node
18483  */
18485  SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index, or NULL */
18486  SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index, or NULL */
18487  )
18488 {
18489  assert(bdchgidx1 == NULL || bdchgidx1->depth >= -2);
18490  assert(bdchgidx1 == NULL || bdchgidx1->pos >= 0);
18491  assert(bdchgidx2 == NULL || bdchgidx2->depth >= -2);
18492  assert(bdchgidx2 == NULL || bdchgidx2->pos >= 0);
18493 
18494  if( bdchgidx1 == NULL )
18495  return FALSE;
18496  else if( bdchgidx2 == NULL )
18497  return TRUE;
18498  else
18499  return (bdchgidx1->depth < bdchgidx2->depth)
18500  || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
18501 }
18502 
18503 /** returns old bound that was overwritten for given bound change information */
18505  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18506  )
18507 {
18508  assert(bdchginfo != NULL);
18509 
18510  return bdchginfo->oldbound;
18511 }
18512 
18513 /** returns new bound installed for given bound change information */
18515  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18516  )
18517 {
18518  assert(bdchginfo != NULL);
18519 
18520  return bdchginfo->newbound;
18521 }
18522 
18523 /** returns variable that belongs to the given bound change information */
18525  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18526  )
18527 {
18528  assert(bdchginfo != NULL);
18529 
18530  return bdchginfo->var;
18531 }
18532 
18533 /** returns whether the bound change information belongs to a branching decision or a deduction */
18535  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18536  )
18537 {
18538  assert(bdchginfo != NULL);
18539 
18540  return (SCIP_BOUNDCHGTYPE)(bdchginfo->boundchgtype);
18541 }
18542 
18543 /** returns whether the bound change information belongs to a lower or upper bound change */
18545  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18546  )
18547 {
18548  assert(bdchginfo != NULL);
18549 
18550  return (SCIP_BOUNDTYPE)(bdchginfo->boundtype);
18551 }
18552 
18553 /** returns depth level of given bound change information */
18555  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18556  )
18557 {
18558  assert(bdchginfo != NULL);
18559 
18560  return bdchginfo->bdchgidx.depth;
18561 }
18562 
18563 /** returns bound change position in its depth level of given bound change information */
18565  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18566  )
18567 {
18568  assert(bdchginfo != NULL);
18569 
18570  return bdchginfo->bdchgidx.pos;
18571 }
18572 
18573 /** returns bound change index of given bound change information */
18575  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18576  )
18577 {
18578  assert(bdchginfo != NULL);
18579 
18580  return &bdchginfo->bdchgidx;
18581 }
18582 
18583 /** returns inference variable of given bound change information */
18585  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18586  )
18587 {
18588  assert(bdchginfo != NULL);
18591 
18592  return bdchginfo->inferencedata.var;
18593 }
18594 
18595 /** returns inference constraint of given bound change information */
18597  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18598  )
18599 {
18600  assert(bdchginfo != NULL);
18602  assert(bdchginfo->inferencedata.reason.cons != NULL);
18603 
18604  return bdchginfo->inferencedata.reason.cons;
18605 }
18606 
18607 /** returns inference propagator of given bound change information, or NULL if no propagator was responsible */
18609  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18610  )
18611 {
18612  assert(bdchginfo != NULL);
18614 
18615  return bdchginfo->inferencedata.reason.prop;
18616 }
18617 
18618 /** returns inference user information of given bound change information */
18620  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18621  )
18622 {
18623  assert(bdchginfo != NULL);
18626 
18627  return bdchginfo->inferencedata.info;
18628 }
18629 
18630 /** returns inference bound of inference variable of given bound change information */
18632  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18633  )
18634 {
18635  assert(bdchginfo != NULL);
18638 
18639  return (SCIP_BOUNDTYPE)(bdchginfo->inferboundtype);
18640 }
18641 
18642 /** returns the relaxed bound change type */
18644  SCIP_BDCHGINFO* bdchginfo /**< bound change to add to the conflict set */
18645  )
18646 {
18647  return ((SCIP_BOUNDTYPE)(bdchginfo->boundtype) == SCIP_BOUNDTYPE_LOWER ? bdchginfo->var->conflictrelaxedlb : bdchginfo->var->conflictrelaxedub);
18648 }
18649 
18650 
18651 /** returns whether the bound change information belongs to a redundant bound change */
18653  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18654  )
18655 {
18656  assert(bdchginfo != NULL);
18657  assert(bdchginfo->redundant == (bdchginfo->oldbound == bdchginfo->newbound)); /*lint !e777*/
18658 
18659  return bdchginfo->redundant;
18660 }
18661 
18662 /** returns whether the bound change has an inference reason (constraint or propagator), that can be resolved */
18664  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18665  )
18666 {
18667  assert(bdchginfo != NULL);
18668 
18671  && bdchginfo->inferencedata.reason.prop != NULL);
18672 }
18673 
18674 /** for two bound change informations belonging to the same variable and bound, returns whether the first bound change
18675  * has a tighter new bound as the second bound change
18676  */
18678  SCIP_BDCHGINFO* bdchginfo1, /**< first bound change information */
18679  SCIP_BDCHGINFO* bdchginfo2 /**< second bound change information */
18680  )
18681 {
18682  assert(bdchginfo1 != NULL);
18683  assert(bdchginfo2 != NULL);
18684  assert(bdchginfo1->var == bdchginfo2->var);
18685  assert(bdchginfo1->boundtype == bdchginfo2->boundtype);
18686 
18687  return (SCIPbdchginfoGetBoundtype(bdchginfo1) == SCIP_BOUNDTYPE_LOWER
18688  ? bdchginfo1->newbound > bdchginfo2->newbound
18689  : bdchginfo1->newbound < bdchginfo2->newbound);
18690 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:61
SCIP_Real SCIPhistoryGetAvgConflictlength(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:571
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:18644
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:15416
SCIP_Real SCIPvarGetWorstBoundLocal(SCIP_VAR *var)
Definition: var.c:18022
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6215
SCIP_Real * SCIPvarGetVlbCoefs(SCIP_VAR *var)
Definition: var.c:18137
#define BMSfreeBlockMemoryArrayNull(mem, ptr, num)
Definition: memory.h:470
void SCIPvarGetClosestVlb(SCIP_VAR *var, SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *closestvlb, int *closestvlbidx)
Definition: var.c:14135
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:18048
static void checkImplic(SCIP_SET *set, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool *redundant, SCIP_Bool *infeasible)
Definition: var.c:9391
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:15543
SCIP_Bool SCIPvarsHaveCommonClique(SCIP_VAR *var1, SCIP_Bool value1, SCIP_VAR *var2, SCIP_Bool value2, SCIP_Bool regardimplics)
Definition: var.c:11487
SCIP_BRANCHINGDATA branchingdata
Definition: struct_var.h:96
void SCIPhistoryIncNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, int depth)
Definition: history.c:584
SCIP_VAR ** SCIPcliqueGetVars(SCIP_CLIQUE *clique)
Definition: implics.c:3377
SCIP_Bool SCIPsetIsLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6273
SCIP_Bool SCIPsetIsFeasZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6723
internal methods for storing primal CIP solutions
void SCIPhistoryIncVSIDS(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition: history.c:503
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:15063
static SCIP_RETCODE varEventImplAdded(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:9273
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:10474
SCIP_Real SCIPvarGetBdAtIndex(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16795
SCIP_PROP * SCIPbdchginfoGetInferProp(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18609
void SCIPvarMarkNotDeletable(SCIP_VAR *var)
Definition: var.c:17508
void SCIPvarUpdateBestRootSol(SCIP_VAR *var, SCIP_SET *set, SCIP_Real rootsol, SCIP_Real rootredcost, SCIP_Real rootlpobjval)
Definition: var.c:13292
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:14018
int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:3299
public methods for branching and inference history structure
SCIP_Bool SCIPlpDiving(SCIP_LP *lp)
Definition: lp.c:17850
int nubchginfos
Definition: struct_var.h:269
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoLb(SCIP_VAR *var, int pos)
Definition: var.c:18323
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition: var.c:17715
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:616
SCIP_Real SCIPvarGetAvgCutoffsCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:16324
SCIP_RETCODE SCIPvaluehistoryCreate(SCIP_VALUEHISTORY **valuehistory, BMS_BLKMEM *blkmem)
Definition: history.c:240
SCIP_Real SCIPsetFeastol(SCIP_SET *set)
Definition: set.c:6122
SCIP_Real SCIPvarGetBranchFactor(SCIP_VAR *var)
Definition: var.c:18083
unsigned int inferboundtype
Definition: struct_var.h:102
SCIP_Real SCIPbdchginfoGetOldbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18505
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:18105
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:18071
SCIP_Real SCIPsetFloor(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6402
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:6844
SCIP_Bool SCIPsetIsFeasEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6613
int SCIPvarGetNVlbs(SCIP_VAR *var)
Definition: var.c:18115
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18525
#define SCIPsetDuplicateBufferArray(set, ptr, source, num)
Definition: set.h:1736
SCIP_Real SCIPvarGetWorstBoundGlobal(SCIP_VAR *var)
Definition: var.c:17966
#define SCIP_DECL_VARTRANS(x)
Definition: type_var.h:147
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:7194
enum SCIP_BaseStat SCIP_BASESTAT
Definition: type_lpi.h:96
SCIP_Bool SCIPvarDoNotMultaggr(SCIP_VAR *var)
Definition: var.c:5889
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:2121
public methods for implications, variable bounds, and cliques
SCIP_Real SCIPvarGetPseudocostCountCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14630
methods for implications, variable bounds, and cliques
int SCIPvarGetLastBdchgDepth(SCIP_VAR *var)
Definition: var.c:16875
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:17923
SCIP_Real SCIPvarGetAvgBranchdepth(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15799
SCIP_RETCODE SCIPvarGetProbvarBinary(SCIP_VAR **var, SCIP_Bool *negated)
Definition: var.c:12322
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:14796
#define SCIP_MAXSTRLEN
Definition: def.h:302
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:3357
SCIP_DOM origdom
Definition: struct_var.h:178
SCIP_BASESTAT SCIPcolGetBasisStatus(SCIP_COL *col)
Definition: lp.c:17034
SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition: var.c:17465
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:3328
SCIP_RETCODE SCIPvarChgLbOriginal(SCIP_VAR *var, SCIP_SET *set, SCIP_Real newbound)
Definition: var.c:6576
SCIP_BOUNDCHG * boundchgs
Definition: struct_var.h:134
void SCIPhistoryIncInferenceSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition: history.c:600
SCIP_Bool SCIPsetIsPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6338
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:17703
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:2976
#define MAXABSVBCOEF
Definition: var.c:80
#define SCIPsetAllocCleanBufferArray(set, ptr, num)
Definition: set.h:1745
static SCIP_Real getImplVarRedcost(SCIP_VAR *var, SCIP_SET *set, SCIP_Bool varfixing, SCIP_STAT *stat, SCIP_LP *lp)
Definition: var.c:13427
SCIP_RETCODE SCIPbdchginfoCreate(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_Real oldbound, SCIP_Real newbound)
Definition: var.c:16378
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:17979
SCIP_RETCODE SCIPvarChgLbLazy(SCIP_VAR *var, SCIP_SET *set, SCIP_Real lazylb)
Definition: var.c:7478
SCIP_Real constant
Definition: struct_var.h:193
SCIP_CLIQUE ** SCIPvarGetCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18286
SCIP_RETCODE SCIPprobVarChangedStatus(SCIP_PROB *prob, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_BRANCHCAND *branchcand, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var)
Definition: prob.c:1191
SCIP_Real bestrootredcost
Definition: struct_var.h:214
SCIP_Real SCIPvarGetMultaggrLbGlobal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8575
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:18365
int SCIPcliquelistGetNCliques(SCIP_CLIQUELIST *cliquelist, SCIP_Bool value)
Definition: implics.c:3443
SCIP_NODE * SCIPnodeGetParent(SCIP_NODE *node)
Definition: tree.c:7716
void SCIPprobAddObjoffset(SCIP_PROB *prob, SCIP_Real addval)
Definition: prob.c:1440
void SCIPvarSetTransData(SCIP_VAR *var, SCIP_DECL_VARTRANS((*vartrans)))
Definition: var.c:17317
SCIP_RETCODE SCIPvarChgUbOriginal(SCIP_VAR *var, SCIP_SET *set, SCIP_Real newbound)
Definition: var.c:6635
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:8883
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:2500
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:17444
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:6771
SCIP_VAR ** SCIPvboundsGetVars(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3295
SCIP_Real SCIPsetInfinity(SCIP_SET *set)
Definition: set.c:6080
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:3702
SCIP_Real SCIPvarGetSol(SCIP_VAR *var, SCIP_Bool getlpval)
Definition: var.c:13269
int SCIPprobGetNVars(SCIP_PROB *prob)
Definition: prob.c:2352
SCIP_BDCHGINFO * ubchginfos
Definition: struct_var.h:249
SCIP_Bool SCIPbdchgidxIsEarlier(SCIP_BDCHGIDX *bdchgidx1, SCIP_BDCHGIDX *bdchgidx2)
Definition: var.c:18485
SCIP_Bool SCIPvarWasFixedAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16815
SCIP_Real SCIPvarGetBestBoundLocal(SCIP_VAR *var)
Definition: var.c:18009
SCIP_Real SCIPvarGetRootSol(SCIP_VAR *var)
Definition: var.c:13362
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:6150
SCIP_RETCODE SCIPvarScaleVSIDS(SCIP_VAR *var, SCIP_Real scalar)
Definition: var.c:15149
SCIP_Real SCIPvarGetLbLP(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:12944
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:17191
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:18403
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:3283
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:326
void SCIPvarSetProbindex(SCIP_VAR *var, int probindex)
Definition: var.c:6034
#define NLOCKTYPES
Definition: type_var.h:90
SCIP_RETCODE SCIPhistoryCreate(SCIP_HISTORY **history, BMS_BLKMEM *blkmem)
Definition: history.c:51
SCIP_HOLELIST * SCIPholelistGetNext(SCIP_HOLELIST *holelist)
Definition: var.c:17251
#define FALSE
Definition: def.h:96
int lppos
Definition: struct_lp.h:172
#define EPSEQ(x, y, eps)
Definition: def.h:211
#define EPSISINT(x, eps)
Definition: def.h:223
SCIP_Bool SCIPlpIsSolBasic(SCIP_LP *lp)
Definition: lp.c:17840
datastructures for managing events
SCIP_Bool SCIPsetIsFeasIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6756
int SCIPvarGetNBdchgInfosLb(SCIP_VAR *var)
Definition: var.c:18335
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:116
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:16976
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:3465
void SCIPhistoryReset(SCIP_HISTORY *history)
Definition: history.c:78
SCIP_Real SCIPcolGetObj(SCIP_COL *col)
Definition: lp.c:16956
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:3150
SCIP_Real constant
Definition: struct_var.h:203
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10788
SCIP_Bool SCIPsetIsZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6327
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:15035
#define TRUE
Definition: def.h:95
SCIP_Bool SCIPvarHasImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition: var.c:11120
static void varSetProbindex(SCIP_VAR *var, int probindex)
Definition: var.c:6015
SCIP_Real SCIPvarGetAvgConflictlength(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15372
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:17760
#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:18157
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:18620
int nlbchginfos
Definition: struct_var.h:267
static SCIP_BDCHGIDX presolvebdchgidx
Definition: var.c:16835
enum SCIP_Varstatus SCIP_VARSTATUS
Definition: type_var.h:57
#define SCIPsetAllocBufferArray(set, ptr, num)
Definition: set.h:1734
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:2078
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:17613
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:10921
#define SCIP_DECL_VARCOPY(x)
Definition: type_var.h:190
SCIP_RETCODE SCIPvarChgLbDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newbound)
Definition: var.c:8258
void SCIPvarSetNamePointer(SCIP_VAR *var, const char *name)
Definition: var.c:6049
int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
Definition: set.c:5794
#define SCIP_EVENTTYPE_GLBCHANGED
Definition: type_event.h:75
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:8232
SCIP_Real SCIPvarGetAggrScalar(SCIP_VAR *var)
Definition: var.c:17667
void SCIPvarInitSolve(SCIP_VAR *var)
Definition: var.c:2935
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:7337
public methods for problem variables
static GRAPHNODE ** active
SCIP_Real SCIPvarGetInferenceSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15991
void SCIPvarMarkDeletable(SCIP_VAR *var)
Definition: var.c:17497
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:1933
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:16079
SCIP_Real SCIPhistoryGetVSIDS(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:529
#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:11282
SCIP_VAR ** SCIPvarGetVlbVars(SCIP_VAR *var)
Definition: var.c:18127
void SCIPprobUpdateNObjVars(SCIP_PROB *prob, SCIP_SET *set, SCIP_Real oldobj, SCIP_Real newobj)
Definition: prob.c:1551
SCIP_RETCODE SCIPvarsGetActiveVars(SCIP_SET *set, SCIP_VAR **vars, int *nvars, int varssize, int *requiredsize)
Definition: var.c:12018
int SCIPbdchgidxGetPos(SCIP_BDCHGIDX *bdchgidx)
Definition: var.c:18455
SCIP_CLIQUE ** SCIPcliquelistGetCliques(SCIP_CLIQUELIST *cliquelist, SCIP_Bool value)
Definition: implics.c:3452
SCIP_PROB * transprob
Definition: struct_scip.h:98
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:6349
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:6186
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:17583
int SCIPvarGetConflictingBdchgDepth(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real bound)
Definition: var.c:16890
SCIP_RETCODE SCIPvarUpdatePseudocost(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition: var.c:14391
#define SCIPsetFreeBufferArray(set, ptr)
Definition: set.h:1741
SCIP_Longint SCIPvarGetNBranchingsCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15756
SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
Definition: var.c:17475
void SCIPvarAdjustLb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *lb)
Definition: var.c:6526
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:11830
SCIP_Real SCIPhistoryGetAvgCutoffs(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:684
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:17749
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:5532
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:6413
int conflictlbcount
Definition: struct_var.h:270
SCIP_Real SCIPvarGetRelaxSolTransVar(SCIP_VAR *var)
Definition: var.c:14007
#define SCIPstatIncrement(stat, set, field)
Definition: stat.h:260
SCIP_Real SCIPsetGetHugeValue(SCIP_SET *set)
Definition: set.c:6092
internal methods for LP management
SCIP_BDCHGIDX * SCIPvarGetLastBdchgIndex(SCIP_VAR *var)
Definition: var.c:16838
int SCIPvarGetNCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18275
Definition: heur_padm.c:132
SCIP_PROB * origprob
Definition: struct_scip.h:80
SCIP_Real SCIPvarGetLPSol_rec(SCIP_VAR *var)
Definition: var.c:13081
SCIP_Real SCIPhistoryGetPseudocost(SCIP_HISTORY *history, SCIP_Real solvaldelta)
Definition: history.c:439
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:16234
int * SCIPvarGetImplIds(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18263
SCIP_HOLELIST * SCIPvarGetHolelistOriginal(SCIP_VAR *var)
Definition: var.c:17909
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:1347
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:2353
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:12011
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:13014
int nrootboundchgs
Definition: struct_stat.h:222
#define SCIP_DECL_VARDELTRANS(x)
Definition: type_var.h:160
SCIP_Bool SCIPsetIsGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6309
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:7555
SCIP_HISTORY * glbhistorycrun
Definition: struct_stat.h:182
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:17739
const char * SCIPgetProbName(SCIP *scip)
Definition: scip_prob.c:1075
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3373
SCIP_Real SCIPvarGetVSIDSCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15940
void SCIPhistoryScaleVSIDS(SCIP_HISTORY *history, SCIP_Real scalar)
Definition: history.c:517
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:9305
SCIP_Real SCIPvarGetNLPSol_rec(SCIP_VAR *var)
Definition: var.c:13154
int SCIPvarGetNBdchgInfosUb(SCIP_VAR *var)
Definition: var.c:18355
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:7436
SCIP_Bool SCIPbdchginfoIsTighter(SCIP_BDCHGINFO *bdchginfo1, SCIP_BDCHGINFO *bdchginfo2)
Definition: var.c:18678
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:7979
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17933
SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6255
SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
Definition: var.c:12230
SCIP_Real SCIPvarGetObjLP(SCIP_VAR *var)
Definition: var.c:12898
SCIP_RETCODE SCIPvaluehistoryFind(SCIP_VALUEHISTORY *valuehistory, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real value, SCIP_HISTORY **history)
Definition: history.c:281
SCIP_Real SCIPvarGetBestRootLPObjval(SCIP_VAR *var)
Definition: var.c:13828
void SCIPvarSetHistory(SCIP_VAR *var, SCIP_HISTORY *history, SCIP_STAT *stat)
Definition: var.c:4529
public methods for managing constraints
static SCIP_RETCODE varProcessChgBranchFactor(SCIP_VAR *var, SCIP_SET *set, SCIP_Real branchfactor)
Definition: var.c:11508
SCIP_Real SCIPhistoryGetPseudocostVariance(SCIP_HISTORY *history, SCIP_BRANCHDIR direction)
Definition: history.c:453
SCIP_Real SCIPvarGetImplRedcost(SCIP_VAR *var, SCIP_SET *set, SCIP_Bool varfixing, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_LP *lp)
Definition: var.c:13480
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:259
SCIP_Real conflictrelaxedlb
Definition: struct_var.h:221
void SCIPvarSetDelorigData(SCIP_VAR *var, SCIP_DECL_VARDELORIG((*vardelorig)))
Definition: var.c:17305
enum SCIP_Confidencelevel SCIP_CONFIDENCELEVEL
Definition: type_misc.h:53
SCIP_RETCODE SCIPvarChgBranchPriority(SCIP_VAR *var, int branchpriority)
Definition: var.c:11699
SCIP_Real SCIPvarGetPseudocost(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition: var.c:14489
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:464
SCIP_Real SCIPcolGetPrimsol(SCIP_COL *col)
Definition: lp.c:16999
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:7593
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:4544
void SCIPvarSetDeltransData(SCIP_VAR *var, SCIP_DECL_VARDELTRANS((*vardeltrans)))
Definition: var.c:17329
SCIP_RETCODE SCIPvarChgUbLazy(SCIP_VAR *var, SCIP_SET *set, SCIP_Real lazyub)
Definition: var.c:7501
SCIP_Real SCIPvarGetBestBoundGlobal(SCIP_VAR *var)
Definition: var.c:17953
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:7813
void SCIPvarMergeHistories(SCIP_VAR *targetvar, SCIP_VAR *othervar, SCIP_STAT *stat)
Definition: var.c:4513
enum SCIP_LockType SCIP_LOCKTYPE
Definition: type_var.h:96
void SCIPhistoryIncNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real length)
Definition: history.c:542
SCIP_BOUNDTYPE * SCIPimplicsGetTypes(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3337
SCIP_Bool SCIPvarDoNotAggr(SCIP_VAR *var)
Definition: var.c:5856
internal methods for storing and manipulating the main problem
#define MAX_CLIQUELENGTH
Definition: var.c:13476
#define SCIPerrorMessage
Definition: pub_message.h:64
SCIP_Bool SCIPboundchgIsRedundant(SCIP_BOUNDCHG *boundchg)
Definition: var.c:17201
void SCIPlpDecNLoosevars(SCIP_LP *lp)
Definition: lp.c:14333
SCIP_Real SCIPvarGetLbOriginal(SCIP_VAR *var)
Definition: var.c:17869
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:16832
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:14939
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:18465
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:6273
int SCIPvarCompareActiveAndNegated(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11916
int lbchginfossize
Definition: struct_var.h:266
SCIP_Real SCIPvarGetAvgBranchdepthCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15844
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:2876
SCIP_Real SCIPvarGetUbOriginal(SCIP_VAR *var)
Definition: var.c:17889
SCIP_Bool SCIPvarIsTransformedOrigvar(SCIP_VAR *var)
Definition: var.c:12873
SCIP_Real SCIPhistoryGetAvgBranchdepth(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:697
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:6463
SCIP_EVENTTYPE eventmask
Definition: struct_event.h:198
SCIP_DECL_SORTPTRCOMP(SCIPvarCompActiveAndNegated)
Definition: var.c:11946
SCIP_Real SCIPvarGetPseudocostCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition: var.c:14538
SCIP_Real SCIPvarGetUbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16674
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:10919
SCIP_Bool SCIPvarHasBinaryImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_Bool implvarfixing)
Definition: var.c:11140
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:3171
SCIP_RETCODE SCIPvarGetTransformed(SCIP_VAR *origvar, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **transvar)
Definition: var.c:3552
#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:8090
union SCIP_BoundChg::@20 data
SCIP_Real * SCIPvarGetVubConstants(SCIP_VAR *var)
Definition: var.c:18189
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:7020
SCIP_OBJSENSE objsense
Definition: struct_prob.h:86
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:1901
SCIP_Real SCIPvarGetAggrConstant(SCIP_VAR *var)
Definition: var.c:17679
SCIP_Real SCIPcolGetLb(SCIP_COL *col)
Definition: lp.c:16966
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:173
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17264
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:5049
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:6791
void SCIPhistoryUnite(SCIP_HISTORY *history, SCIP_HISTORY *addhistory, SCIP_Bool switcheddirs)
Definition: history.c:110
void SCIPmessagePrintWarning(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
Definition: message.c:427
#define SCIPsetReallocBufferArray(set, ptr, num)
Definition: set.h:1738
SCIP_Longint SCIPhistoryGetNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:558
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:11997
unsigned int initial
Definition: struct_var.h:274
#define NULL
Definition: lpi_spx1.cpp:164
void SCIPvarGetClosestVub(SCIP_VAR *var, SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *closestvub, int *closestvubidx)
Definition: var.c:14210
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:7646
SCIP_RETCODE SCIPvarSetRelaxSol(SCIP_VAR *var, SCIP_SET *set, SCIP_RELAXATION *relaxation, SCIP_Real solval, SCIP_Bool updateobj)
Definition: var.c:13874
SCIP_HISTORY * glbhistory
Definition: struct_stat.h:181
SCIP_Real SCIPboundchgGetNewbound(SCIP_BOUNDCHG *boundchg)
Definition: var.c:17161
SCIP_Real * SCIPvboundsGetCoefs(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3303
#define REALABS(x)
Definition: def.h:210
int nparentvars
Definition: struct_var.h:261
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition: var.c:18297
SCIP_Real unchangedobj
Definition: struct_var.h:210
SCIP_HOLELIST * SCIPvarGetHolelistGlobal(SCIP_VAR *var)
Definition: var.c:17943
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:10010
SCIP_Longint SCIPvarGetNActiveConflicts(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15280
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:17793
SCIP_Real SCIPvarCalcPscostConfidenceBound(SCIP_VAR *var, SCIP_SET *set, SCIP_BRANCHDIR dir, SCIP_Bool onlycurrentrun, SCIP_CONFIDENCELEVEL clevel)
Definition: var.c:14758
#define SCIP_CALL(x)
Definition: def.h:394
SCIP main data structure.
SCIP_Bool SCIPbdchginfoHasInferenceReason(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18664
SCIP_VBOUNDS * vubs
Definition: struct_var.h:244
SCIP_Real SCIPvarGetLbLazy(SCIP_VAR *var)
Definition: var.c:18061
SCIP_Bool SCIPsetIsFeasGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6701
SCIP_Real * SCIPvarGetVlbConstants(SCIP_VAR *var)
Definition: var.c:18147
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:15459
SCIP_Real SCIPvarGetMultaggrConstant(SCIP_VAR *var)
Definition: var.c:17727
SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
Definition: var.c:17551
int SCIPprobGetNContVars(SCIP_PROB *prob)
Definition: prob.c:2388
SCIP_Real SCIPvarGetPseudocostCount(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14585
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:9729
static SCIP_VAR * varGetActiveVar(SCIP_VAR *var)
Definition: var.c:5807
SCIP_Real * SCIPvboundsGetConstants(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3311
SCIP_Real SCIPvarGetCutoffSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:16191
SCIP_Real * SCIPvarGetVubCoefs(SCIP_VAR *var)
Definition: var.c:18179
SCIP_Bool SCIPbdchginfoIsRedundant(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18653
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:14673
SCIP_Real SCIPhistoryGetPseudocostCount(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:477
SCIP_Bool SCIPsetIsEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6237
static SCIP_RETCODE varProcessChgBranchPriority(SCIP_VAR *var, int branchpriority)
Definition: var.c:11643
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:8106
#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:18575
SCIP_Longint SCIPvarGetNActiveConflictsCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15327
SCIP_RETCODE SCIPvarPrint(SCIP_VAR *var, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: var.c:3010
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:6657
#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:13859
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:6560
#define BMSfreeBlockMemory(mem, ptr)
Definition: memory.h:467
internal methods for problem variables
SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
Definition: var.c:17393
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:6238
SCIP_RETCODE SCIPvarChgBranchFactor(SCIP_VAR *var, SCIP_SET *set, SCIP_Real branchfactor)
Definition: var.c:11572
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:5287
#define SCIP_UNKNOWN
Definition: def.h:207
SCIP_Bool SCIPsetIsIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6360
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:18233
unsigned int boundchgtype
Definition: struct_var.h:100
#define BMSfreeBlockMemorySize(mem, ptr, size)
Definition: memory.h:471
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:15627
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:6695
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:17241
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:9002
#define SCIP_Bool
Definition: def.h:93
void SCIPvarCapture(SCIP_VAR *var)
Definition: var.c:2851
#define BMSreallocBlockMemorySize(mem, ptr, oldsize, newsize)
Definition: memory.h:458
SCIP_BOUNDCHGTYPE SCIPboundchgGetBoundchgtype(SCIP_BOUNDCHG *boundchg)
Definition: var.c:17181
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:4735
int SCIPbdchginfoGetPos(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18565
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:16963
SCIP_Real SCIPvarGetInferenceSumCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:16036
SCIP_Bool SCIPvarIsInLP(SCIP_VAR *var)
Definition: var.c:17645
SCIP_RETCODE SCIPvarRemove(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_CLIQUETABLE *cliquetable, SCIP_SET *set, SCIP_Bool final)
Definition: var.c:6067
SCIP_RETCODE SCIPconsRelease(SCIP_CONS **cons, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: cons.c:6208
void SCIPvarMarkRelaxationOnly(SCIP_VAR *var)
Definition: var.c:17569
void SCIPvarStoreRootSol(SCIP_VAR *var, SCIP_Bool roothaslp)
Definition: var.c:13281
SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
Definition: var.c:18310
int SCIPvarGetBranchPriority(SCIP_VAR *var)
Definition: var.c:18095
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:3753
SCIP_Real SCIPvarGetLbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16555
SCIP_Bool divingobjchg
Definition: struct_lp.h:381
int SCIPvarGetNImpls(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18201
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:8348
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition: memory.h:469
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
union SCIP_Var::@21 data
int * SCIPimplicsGetIds(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3358
SCIP_VARDATA * SCIPvarGetData(SCIP_VAR *var)
Definition: var.c:17284
SCIP_RETCODE SCIPcolChgLb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newlb)
Definition: lp.c:3761
int SCIPvarGetNLocksUp(SCIP_VAR *var)
Definition: var.c:3433
#define MAX(x, y)
Definition: tclique_def.h:92
SCIP_Bool SCIPstrToRealValue(const char *str, SCIP_Real *value, char **endptr)
Definition: misc.c:10889
int SCIPimplicsGetNImpls(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3319
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:17171
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11954
SCIP_Bool * SCIPcliqueGetValues(SCIP_CLIQUE *clique)
Definition: implics.c:3389
SCIP_BOUNDCHG * SCIPdomchgGetBoundchg(SCIP_DOMCHG *domchg, int pos)
Definition: var.c:17219
SCIP_Real SCIPvarGetUnchangedObj(SCIP_VAR *var)
Definition: var.c:17781
public methods for LP management
unsigned int removable
Definition: struct_var.h:275
#define SCIPsetDebugMsg
Definition: set.h:1770
static SCIP_RETCODE varAddParent(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_VAR *parentvar)
Definition: var.c:2647
SCIP_Real SCIPvarGetMultaggrUbGlobal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8641
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:17771
SCIP_RETCODE SCIPvarAddCliqueToList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:11405
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18515
SCIP_Real SCIPvarGetBestRootRedcost(SCIP_VAR *var)
Definition: var.c:13794
SCIP_VAR * SCIPvarGetAggrVar(SCIP_VAR *var)
Definition: var.c:17655
int closestvlbidx
Definition: struct_var.h:272
#define EPSLE(x, y, eps)
Definition: def.h:213
SCIP_RETCODE SCIPvarFlattenAggregationGraph(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:4418
int nuses
Definition: struct_var.h:262
SCIP_Real SCIPvarGetAvgInferencesCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:16136
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:11191
SCIP_Real SCIPcomputeTwoSampleTTestValue(SCIP_Real meanx, SCIP_Real meany, SCIP_Real variancex, SCIP_Real variancey, SCIP_Real countx, SCIP_Real county)
Definition: misc.c:122
SCIP_RETCODE SCIPvarDelClique(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:11444
#define SCIP_EVENTTYPE_GHOLEADDED
Definition: type_event.h:81
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:136
void SCIPhistoryUpdatePseudocost(SCIP_HISTORY *history, SCIP_SET *set, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition: history.c:171
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition: var.c:17634
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:8754
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:2163
SCIP_Real SCIPvarGetRelaxSol(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:13935
datastructures for problem statistics
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:17691
SCIP_Longint SCIPhistoryGetNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:632
SCIP_Real * SCIPvarGetImplBounds(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18247
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12786
SCIP_Bool SCIPsetIsFeasLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6635
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:6348
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:15199
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:9521
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:3806
SCIP_RETCODE SCIPcolFree(SCIP_COL **col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: lp.c:3381
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:13202
SCIP_BDCHGINFO * SCIPvarGetLbchgInfo(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16422
SCIP_Bool SCIPprobIsTransformed(SCIP_PROB *prob)
Definition: prob.c:2287
SCIP_BOUNDTYPE SCIPbdchginfoGetInferBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18632
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:16478
int conflictubcount
Definition: struct_var.h:271
int SCIPvboundsGetNVbds(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3287
SCIP_RETCODE SCIPvarGetProbvarBound(SCIP_VAR **var, SCIP_Real *bound, SCIP_BOUNDTYPE *boundtype)
Definition: var.c:12481
static SCIP_RETCODE parseValue(SCIP_SET *set, const char *str, SCIP_Real *value, char **endptr)
Definition: var.c:2276
SCIP_DOM locdom
Definition: struct_var.h:226
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoUb(SCIP_VAR *var, int pos)
Definition: var.c:18343
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:9802
SCIP_BDCHGINFO * SCIPvarGetBdchgInfo(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16534
#define SCIP_REAL_MAX
Definition: def.h:187
SCIP_Bool SCIPsetIsDualfeasPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6945
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:2948
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:127
SCIP_Real SCIPhistoryGetCutoffSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:671
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:14282
SCIP_RETCODE SCIPvarLoose(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *prob, SCIP_LP *lp)
Definition: var.c:3617
SCIP_Real newbound
Definition: struct_var.h:93
#define SCIP_REAL_MIN
Definition: def.h:188
static SCIP_RETCODE varEventVarFixed(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, int fixeventtype)
Definition: var.c:3658
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:430
SCIP_VAR ** SCIPvarGetImplVars(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18218
static SCIP_RETCODE varFreeParents(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:2675
SCIP_Real SCIPsetFeasFloor(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6780
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:7527
#define SCIP_DEFAULT_INFINITY
Definition: def.h:191
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:3420
SCIP_Real SCIPstudentTGetCriticalValue(SCIP_CONFIDENCELEVEL clevel, int df)
Definition: misc.c:105
SCIP_HOLELIST * next
Definition: struct_var.h:61
void SCIPconsCapture(SCIP_CONS *cons)
Definition: cons.c:6196
SCIP_Real SCIPhistoryGetInferenceSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:645
#define BMSallocBlockMemorySize(mem, ptr, size)
Definition: memory.h:455
unsigned int boundtype
Definition: struct_var.h:124
#define SCIPsetFreeCleanBufferArray(set, ptr)
Definition: set.h:1748
void SCIPrelaxationSolObjAdd(SCIP_RELAXATION *relaxation, SCIP_Real val)
Definition: relax.c:849
static const SCIP_Real scalars[]
Definition: lp.c:5747
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:5453
int lpipos
Definition: struct_lp.h:173
SCIP_NODE * SCIPtreeGetRootNode(SCIP_TREE *tree)
Definition: tree.c:8446
int SCIPdomchgGetNBoundchgs(SCIP_DOMCHG *domchg)
Definition: var.c:17211
SCIP_RETCODE SCIPvarColumn(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_LP *lp)
Definition: var.c:3583
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:18555
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:3923
SCIP_Real SCIPnormalCDF(SCIP_Real mean, SCIP_Real variance, SCIP_Real value)
Definition: misc.c:195
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:14873
SCIP_RETCODE SCIPvarMarkDoNotAggr(SCIP_VAR *var)
Definition: var.c:6114
SCIP_DECL_HASHKEYEQ(SCIPvarIsHashkeyEq)
Definition: var.c:12003
SCIP_Real SCIPvarGetBestRootSol(SCIP_VAR *var)
Definition: var.c:13727
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:3461
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:17340
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:9293
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:17231
SCIP_Bool SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6291
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:17383
SCIP_RETCODE SCIPvarResetBounds(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat)
Definition: var.c:9240
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:9422
#define SCIP_Real
Definition: def.h:186
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:2748
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:15711
SCIP_RETCODE SCIPvarsGetProbvarBinary(SCIP_VAR ***vars, SCIP_Bool **negatedarr, int nvars)
Definition: var.c:12290
SCIP_VAR * SCIPbdchginfoGetInferVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18585
SCIP_Bool SCIPsetIsFeasPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6734
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:17351
SCIP_VAR ** SCIPprobGetVars(SCIP_PROB *prob)
Definition: prob.c:2397
SCIP_RETCODE SCIPvarGetProbvarHole(SCIP_VAR **var, SCIP_Real *left, SCIP_Real *right)
Definition: var.c:12574
SCIP_RETCODE SCIPlpUpdateVarLoose(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:14312
SCIP_Real SCIPvarGetVSIDS(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:18388
#define SCIP_INVALID
Definition: def.h:206
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:17274
void SCIPvarsGetProbvar(SCIP_VAR **vars, int nvars)
Definition: var.c:12210
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:2564
static SCIP_RETCODE parseBounds(SCIP_SET *set, const char *str, char *type, SCIP_Real *lb, SCIP_Real *ub, char **endptr)
Definition: var.c:2308
SCIP_VAR ** SCIPvarGetVubVars(SCIP_VAR *var)
Definition: var.c:18169
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:171
SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
Definition: var.c:18035
SCIP_CONS * SCIPbdchginfoGetInferCons(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18597
SCIP_Bool SCIPsetIsDualfeasZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6934
SCIP_Real SCIPvarGetAvgSol(SCIP_VAR *var)
Definition: var.c:14074
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:17603
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:2623
SCIP_Real SCIPvarGetAvgCutoffs(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:16277
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:6679
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:9131
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:17429
SCIP_Real SCIPvarGetMultaggrUbLocal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8509
SCIP_RETCODE SCIPvarChgName(SCIP_VAR *var, BMS_BLKMEM *blkmem, const char *name)
Definition: var.c:2917
SCIP_DOM glbdom
Definition: struct_var.h:225
SCIP_Real SCIPsetEpsilon(SCIP_SET *set)
Definition: set.c:6102
SCIP_Real SCIPhistoryGetAvgInferences(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:658
SCIP_STAGE SCIPsetGetStage(SCIP_SET *set)
Definition: set.c:2997
enum SCIP_Vartype SCIP_VARTYPE
Definition: type_var.h:69
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:6733
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:17531
SCIP_Bool SCIPcliqueIsCleanedUp(SCIP_CLIQUE *clique)
Definition: implics.c:3423
SCIP_Real newbound
Definition: struct_var.h:118
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17989
int SCIPcliqueGetNVars(SCIP_CLIQUE *clique)
Definition: implics.c:3367
SCIP_RETCODE SCIPvarAddHoleOriginal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real left, SCIP_Real right)
Definition: var.c:8702
void SCIPbdchginfoFree(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem)
Definition: var.c:16408
void SCIPvarAdjustUb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *ub)
Definition: var.c:6543
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:17406
static void varIncRootboundchgs(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat)
Definition: var.c:6803
#define BMSallocBlockMemory(mem, ptr)
Definition: memory.h:453
SCIP_HOLELIST * SCIPvarGetHolelistLocal(SCIP_VAR *var)
Definition: var.c:17999
unsigned int delglobalstructs
Definition: struct_var.h:285
SCIP_Bool SCIPsetIsDualfeasNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6956
SCIP_BOUNDTYPE SCIPbdchginfoGetBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18545
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:18430
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:3106
SCIP_RETCODE SCIPlpUpdateVarColumn(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:14188
SCIP_HISTORY * history
Definition: struct_var.h:250
SCIP_RETCODE SCIPvarSetRemovable(SCIP_VAR *var, SCIP_Bool removable)
Definition: var.c:17367
SCIP_Real SCIPvarGetVSIDS_rec(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15889
int nrootintfixingsrun
Definition: struct_stat.h:225
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:439
SCIP_RETCODE SCIPvarGetProbvarSum(SCIP_VAR **var, SCIP_SET *set, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12659
#define SCIP_EVENTTYPE_GUBCHANGED
Definition: type_event.h:76
#define SCIP_CALL_ABORT(x)
Definition: def.h:373
SCIP_Real SCIPvarGetPseudoSol(SCIP_VAR *var)
Definition: var.c:18375
enum SCIP_BoundchgType SCIP_BOUNDCHGTYPE
Definition: type_var.h:87
SCIP_Real * SCIPimplicsGetBounds(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3346
SCIP_ORIGINAL original
Definition: struct_var.h:229
SCIP_Real SCIPcolGetRedcost(SCIP_COL *col, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:3956
SCIP_VAR * SCIPvarGetTransVar(SCIP_VAR *var)
Definition: var.c:17623
#define SCIP_ALLOC(x)
Definition: def.h:405
#define SCIPABORT()
Definition: def.h:366
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:17455
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:8443
const char * SCIPprobGetName(SCIP_PROB *prob)
Definition: prob.c:2343
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9032
unsigned int applied
Definition: struct_var.h:103
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition: var.c:17485
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:11367
void SCIPvarGetImplicVarBounds(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_Real *lb, SCIP_Real *ub)
Definition: var.c:11155
datastructures for global SCIP settings
SCIP_HOLELIST ** ptr
Definition: struct_var.h:67
#define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
Definition: memory.h:460
SCIP_BOUNDCHG * boundchgs
Definition: struct_var.h:152
void SCIPvarMarkDeleted(SCIP_VAR *var)
Definition: var.c:6103
void SCIPvarSetData(SCIP_VAR *var, SCIP_VARDATA *vardata)
Definition: var.c:17294
SCIP_Bool SCIPcolIsInLP(SCIP_COL *col)
Definition: lp.c:17118
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:5925
SCIP_Real left
Definition: struct_var.h:53
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9284
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:3455
#define EPSZ(x, eps)
Definition: def.h:216
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:11763
SCIP_Bool SCIPvarMayRoundDown(SCIP_VAR *var)
Definition: var.c:3444
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:937
SCIP callable library.
SCIP_Bool SCIPsetIsFeasNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6745
SCIP_Real SCIPvarGetPseudocostVariance(SCIP_VAR *var, SCIP_BRANCHDIR dir, SCIP_Bool onlycurrentrun)
Definition: var.c:14704
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:17593
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:15008
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:17419
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:5644
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:17521
SCIP_BOUNDCHGTYPE SCIPbdchginfoGetChgtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18535
SCIP_RETCODE SCIPvarDelCliqueFromList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:11427