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  SCIPcliquelistRemoveFromCliques(var->cliquelist, cliquetable, var, irrelevantvar);
1887 
1888  /**@todo variable bounds like x <= b*z + d with z general integer are not removed from x's vbd arrays, because
1889  * z has no link (like in the binary case) to x
1890  */
1891 
1892  return SCIP_OKAY;
1893 }
1894 
1895 /** sets the variable name */
1896 static
1898  SCIP_VAR* var, /**< problem variable */
1899  BMS_BLKMEM* blkmem, /**< block memory */
1900  SCIP_STAT* stat, /**< problem statistics, or NULL */
1901  const char* name /**< name of variable, or NULL for automatic name creation */
1902  )
1903 {
1904  assert(blkmem != NULL);
1905  assert(var != NULL);
1906 
1907  if( name == NULL )
1908  {
1909  char s[SCIP_MAXSTRLEN];
1910 
1911  assert(stat != NULL);
1912 
1913  (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "_var%d_", stat->nvaridx);
1914  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->name, s, strlen(s)+1) );
1915  }
1916  else
1917  {
1918  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->name, name, strlen(name)+1) );
1919  }
1920 
1921  return SCIP_OKAY;
1922 }
1923 
1924 
1925 /** creates variable; if variable is of integral type, fractional bounds are automatically rounded; an integer variable
1926  * with bounds zero and one is automatically converted into a binary variable
1927  */
1928 static
1930  SCIP_VAR** var, /**< pointer to variable data */
1931  BMS_BLKMEM* blkmem, /**< block memory */
1932  SCIP_SET* set, /**< global SCIP settings */
1933  SCIP_STAT* stat, /**< problem statistics */
1934  const char* name, /**< name of variable, or NULL for automatic name creation */
1935  SCIP_Real lb, /**< lower bound of variable */
1936  SCIP_Real ub, /**< upper bound of variable */
1937  SCIP_Real obj, /**< objective function value */
1938  SCIP_VARTYPE vartype, /**< type of variable */
1939  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
1940  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
1941  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
1942  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
1943  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
1944  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
1945  SCIP_VARDATA* vardata /**< user data for this specific variable */
1946  )
1947 {
1948  int i;
1949 
1950  assert(var != NULL);
1951  assert(blkmem != NULL);
1952  assert(stat != NULL);
1953 
1954  /* adjust bounds of variable */
1955  lb = adjustedLb(set, vartype, lb);
1956  ub = adjustedUb(set, vartype, ub);
1957 
1958  /* convert [0,1]-integers into binary variables and check that binary variables have correct bounds */
1959  if( (SCIPsetIsEQ(set, lb, 0.0) || SCIPsetIsEQ(set, lb, 1.0))
1960  && (SCIPsetIsEQ(set, ub, 0.0) || SCIPsetIsEQ(set, ub, 1.0)) )
1961  {
1962  if( vartype == SCIP_VARTYPE_INTEGER )
1963  vartype = SCIP_VARTYPE_BINARY;
1964  }
1965  else
1966  {
1967  if( vartype == SCIP_VARTYPE_BINARY )
1968  {
1969  SCIPerrorMessage("invalid bounds [%.2g,%.2g] for binary variable <%s>\n", lb, ub, name);
1970  return SCIP_INVALIDDATA;
1971  }
1972  }
1973 
1974  assert(vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, lb, 0.0) || SCIPsetIsEQ(set, lb, 1.0));
1975  assert(vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, ub, 0.0) || SCIPsetIsEQ(set, ub, 1.0));
1976 
1977  SCIP_ALLOC( BMSallocBlockMemory(blkmem, var) );
1978 
1979  /* set variable's name */
1980  SCIP_CALL( varSetName(*var, blkmem, stat, name) );
1981 
1982 #ifndef NDEBUG
1983  (*var)->scip = set->scip;
1984 #endif
1985  (*var)->obj = obj;
1986  (*var)->unchangedobj = obj;
1987  (*var)->branchfactor = 1.0;
1988  (*var)->rootsol = 0.0;
1989  (*var)->bestrootsol = 0.0;
1990  (*var)->bestrootredcost = 0.0;
1991  (*var)->bestrootlpobjval = SCIP_INVALID;
1992  (*var)->relaxsol = 0.0;
1993  (*var)->nlpsol = 0.0;
1994  (*var)->primsolavg = 0.5 * (lb + ub);
1995  (*var)->conflictlb = SCIP_REAL_MIN;
1996  (*var)->conflictub = SCIP_REAL_MAX;
1997  (*var)->conflictrelaxedlb = (*var)->conflictlb;
1998  (*var)->conflictrelaxedub = (*var)->conflictub;
1999  (*var)->lazylb = -SCIPsetInfinity(set);
2000  (*var)->lazyub = SCIPsetInfinity(set);
2001  (*var)->glbdom.holelist = NULL;
2002  (*var)->glbdom.lb = lb;
2003  (*var)->glbdom.ub = ub;
2004  (*var)->locdom.holelist = NULL;
2005  (*var)->locdom.lb = lb;
2006  (*var)->locdom.ub = ub;
2007  (*var)->varcopy = varcopy;
2008  (*var)->vardelorig = vardelorig;
2009  (*var)->vartrans = vartrans;
2010  (*var)->vardeltrans = vardeltrans;
2011  (*var)->vardata = vardata;
2012  (*var)->parentvars = NULL;
2013  (*var)->negatedvar = NULL;
2014  (*var)->vlbs = NULL;
2015  (*var)->vubs = NULL;
2016  (*var)->implics = NULL;
2017  (*var)->cliquelist = NULL;
2018  (*var)->eventfilter = NULL;
2019  (*var)->lbchginfos = NULL;
2020  (*var)->ubchginfos = NULL;
2021  (*var)->index = stat->nvaridx;
2022  (*var)->probindex = -1;
2023  (*var)->pseudocandindex = -1;
2024  (*var)->eventqueueindexobj = -1;
2025  (*var)->eventqueueindexlb = -1;
2026  (*var)->eventqueueindexub = -1;
2027  (*var)->parentvarssize = 0;
2028  (*var)->nparentvars = 0;
2029  (*var)->nuses = 0;
2030  (*var)->branchpriority = 0;
2031  (*var)->branchdirection = SCIP_BRANCHDIR_AUTO; /*lint !e641*/
2032  (*var)->lbchginfossize = 0;
2033  (*var)->nlbchginfos = 0;
2034  (*var)->ubchginfossize = 0;
2035  (*var)->nubchginfos = 0;
2036  (*var)->conflictlbcount = 0;
2037  (*var)->conflictubcount = 0;
2038  (*var)->closestvlbidx = -1;
2039  (*var)->closestvubidx = -1;
2040  (*var)->closestvblpcount = -1;
2041  (*var)->initial = initial;
2042  (*var)->removable = removable;
2043  (*var)->deleted = FALSE;
2044  (*var)->donotaggr = FALSE;
2045  (*var)->donotmultaggr = FALSE;
2046  (*var)->vartype = vartype; /*lint !e641*/
2047  (*var)->pseudocostflag = FALSE;
2048  (*var)->eventqueueimpl = FALSE;
2049  (*var)->deletable = FALSE;
2050  (*var)->delglobalstructs = FALSE;
2051  (*var)->relaxationonly = FALSE;
2052 
2053  for( i = 0; i < NLOCKTYPES; i++ )
2054  {
2055  (*var)->nlocksdown[i] = 0;
2056  (*var)->nlocksup[i] = 0;
2057  }
2058 
2059  stat->nvaridx++;
2060 
2061  /* create branching and inference history entries */
2062  SCIP_CALL( SCIPhistoryCreate(&(*var)->history, blkmem) );
2063  SCIP_CALL( SCIPhistoryCreate(&(*var)->historycrun, blkmem) );
2064 
2065  /* the value based history is only created on demand */
2066  (*var)->valuehistory = NULL;
2067 
2068  return SCIP_OKAY;
2069 }
2070 
2071 /** creates and captures an original problem variable; an integer variable with bounds
2072  * zero and one is automatically converted into a binary variable
2073  */
2075  SCIP_VAR** var, /**< pointer to variable data */
2076  BMS_BLKMEM* blkmem, /**< block memory */
2077  SCIP_SET* set, /**< global SCIP settings */
2078  SCIP_STAT* stat, /**< problem statistics */
2079  const char* name, /**< name of variable, or NULL for automatic name creation */
2080  SCIP_Real lb, /**< lower bound of variable */
2081  SCIP_Real ub, /**< upper bound of variable */
2082  SCIP_Real obj, /**< objective function value */
2083  SCIP_VARTYPE vartype, /**< type of variable */
2084  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2085  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2086  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2087  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2088  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2089  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2090  SCIP_VARDATA* vardata /**< user data for this specific variable */
2091  )
2092 {
2093  assert(var != NULL);
2094  assert(blkmem != NULL);
2095  assert(stat != NULL);
2096 
2097  /* create variable */
2098  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2099  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2100 
2101  /* set variable status and data */
2102  (*var)->varstatus = SCIP_VARSTATUS_ORIGINAL; /*lint !e641*/
2103  (*var)->data.original.origdom.holelist = NULL;
2104  (*var)->data.original.origdom.lb = lb;
2105  (*var)->data.original.origdom.ub = ub;
2106  (*var)->data.original.transvar = NULL;
2107 
2108  /* capture variable */
2109  SCIPvarCapture(*var);
2110 
2111  return SCIP_OKAY;
2112 }
2113 
2114 /** creates and captures a loose variable belonging to the transformed problem; an integer variable with bounds
2115  * zero and one is automatically converted into a binary variable
2116  */
2118  SCIP_VAR** var, /**< pointer to variable data */
2119  BMS_BLKMEM* blkmem, /**< block memory */
2120  SCIP_SET* set, /**< global SCIP settings */
2121  SCIP_STAT* stat, /**< problem statistics */
2122  const char* name, /**< name of variable, or NULL for automatic name creation */
2123  SCIP_Real lb, /**< lower bound of variable */
2124  SCIP_Real ub, /**< upper bound of variable */
2125  SCIP_Real obj, /**< objective function value */
2126  SCIP_VARTYPE vartype, /**< type of variable */
2127  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2128  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2129  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2130  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2131  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2132  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2133  SCIP_VARDATA* vardata /**< user data for this specific variable */
2134  )
2135 {
2136  assert(var != NULL);
2137  assert(blkmem != NULL);
2138 
2139  /* create variable */
2140  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2141  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2142 
2143  /* create event filter for transformed variable */
2144  SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
2145 
2146  /* set variable status and data */
2147  (*var)->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
2148 
2149  /* capture variable */
2150  SCIPvarCapture(*var);
2151 
2152  return SCIP_OKAY;
2153 }
2154 
2155 /** copies and captures a variable from source to target SCIP; an integer variable with bounds zero and one is
2156  * automatically converted into a binary variable; in case the variable data cannot be copied the variable is not
2157  * copied at all
2158  */
2160  SCIP_VAR** var, /**< pointer to store the target variable */
2161  BMS_BLKMEM* blkmem, /**< block memory */
2162  SCIP_SET* set, /**< global SCIP settings */
2163  SCIP_STAT* stat, /**< problem statistics */
2164  SCIP* sourcescip, /**< source SCIP data structure */
2165  SCIP_VAR* sourcevar, /**< source variable */
2166  SCIP_HASHMAP* varmap, /**< a hashmap to store the mapping of source variables corresponding
2167  * target variables */
2168  SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
2169  * target constraints */
2170  SCIP_Bool global /**< should global or local bounds be used? */
2171  )
2172 {
2173  SCIP_VARDATA* targetdata;
2174  SCIP_RESULT result;
2175  SCIP_Real lb;
2176  SCIP_Real ub;
2177 
2178  assert(set != NULL);
2179  assert(blkmem != NULL);
2180  assert(stat != NULL);
2181  assert(sourcescip != NULL);
2182  assert(sourcevar != NULL);
2183  assert(var != NULL);
2184  assert(set->stage == SCIP_STAGE_PROBLEM);
2185  assert(varmap != NULL);
2186  assert(consmap != NULL);
2187 
2188  /** @todo copy hole lists */
2189  assert(global || SCIPvarGetHolelistLocal(sourcevar) == NULL);
2190  assert(!global || SCIPvarGetHolelistGlobal(sourcevar) == NULL);
2191 
2192  result = SCIP_DIDNOTRUN;
2193  targetdata = NULL;
2194 
2195  if( SCIPvarGetStatus(sourcevar) == SCIP_VARSTATUS_ORIGINAL )
2196  {
2197  lb = SCIPvarGetLbOriginal(sourcevar);
2198  ub = SCIPvarGetUbOriginal(sourcevar);
2199  }
2200  else
2201  {
2202  lb = global ? SCIPvarGetLbGlobal(sourcevar) : SCIPvarGetLbLocal(sourcevar);
2203  ub = global ? SCIPvarGetUbGlobal(sourcevar) : SCIPvarGetUbLocal(sourcevar);
2204  }
2205 
2206  /* creates and captures the variable in the target SCIP and initialize callback methods and variable data to NULL */
2207  SCIP_CALL( SCIPvarCreateOriginal(var, blkmem, set, stat, SCIPvarGetName(sourcevar),
2208  lb, ub, SCIPvarGetObj(sourcevar), SCIPvarGetType(sourcevar),
2209  SCIPvarIsInitial(sourcevar), SCIPvarIsRemovable(sourcevar),
2210  NULL, NULL, NULL, NULL, NULL) );
2211  assert(*var != NULL);
2212 
2213  /* directly copy donot(mult)aggr flag */
2214  (*var)->donotaggr = sourcevar->donotaggr;
2215  (*var)->donotmultaggr = sourcevar->donotmultaggr;
2216 
2217  /* insert variable into mapping between source SCIP and the target SCIP */
2218  assert(!SCIPhashmapExists(varmap, sourcevar));
2219  SCIP_CALL( SCIPhashmapInsert(varmap, sourcevar, *var) );
2220 
2221  /* in case there exists variable data and the variable data copy callback, try to copy variable data */
2222  if( sourcevar->vardata != NULL && sourcevar->varcopy != NULL )
2223  {
2224  SCIP_CALL( sourcevar->varcopy(set->scip, sourcescip, sourcevar, sourcevar->vardata,
2225  varmap, consmap, (*var), &targetdata, &result) );
2226 
2227  /* evaluate result */
2228  if( result != SCIP_DIDNOTRUN && result != SCIP_SUCCESS )
2229  {
2230  SCIPerrorMessage("variable data copying method returned invalid result <%d>\n", result);
2231  return SCIP_INVALIDRESULT;
2232  }
2233 
2234  assert(targetdata == NULL || result == SCIP_SUCCESS);
2235 
2236  /* if copying was successful, add the created variable data to the variable as well as all callback methods */
2237  if( result == SCIP_SUCCESS )
2238  {
2239  (*var)->varcopy = sourcevar->varcopy;
2240  (*var)->vardelorig = sourcevar->vardelorig;
2241  (*var)->vartrans = sourcevar->vartrans;
2242  (*var)->vardeltrans = sourcevar->vardeltrans;
2243  (*var)->vardata = targetdata;
2244  }
2245  }
2246 
2247  /* we initialize histories of the variables by copying the source variable-information */
2248  if( set->history_allowtransfer )
2249  {
2250  SCIPvarMergeHistories((*var), sourcevar, stat);
2251  }
2252 
2253  /* in case the copying was successfully, add the created variable data to the variable as well as all callback
2254  * methods
2255  */
2256  if( result == SCIP_SUCCESS )
2257  {
2258  (*var)->varcopy = sourcevar->varcopy;
2259  (*var)->vardelorig = sourcevar->vardelorig;
2260  (*var)->vartrans = sourcevar->vartrans;
2261  (*var)->vardeltrans = sourcevar->vardeltrans;
2262  (*var)->vardata = targetdata;
2263  }
2264 
2265  SCIPsetDebugMsg(set, "created copy <%s> of variable <%s>\n", SCIPvarGetName(*var), SCIPvarGetName(sourcevar));
2266 
2267  return SCIP_OKAY;
2268 }
2269 
2270 /** parse given string for a SCIP_Real bound */
2271 static
2273  SCIP_SET* set, /**< global SCIP settings */
2274  const char* str, /**< string to parse */
2275  SCIP_Real* value, /**< pointer to store the parsed value */
2276  char** endptr /**< pointer to store the final string position if successfully parsed */
2277  )
2278 {
2279  /* first check for infinity value */
2280  if( strncmp(str, "+inf", 4) == 0 )
2281  {
2282  *value = SCIPsetInfinity(set);
2283  (*endptr) = (char*)str + 4;
2284  }
2285  else if( strncmp(str, "-inf", 4) == 0 )
2286  {
2287  *value = -SCIPsetInfinity(set);
2288  (*endptr) = (char*)str + 4;
2289  }
2290  else
2291  {
2292  if( !SCIPstrToRealValue(str, value, endptr) )
2293  {
2294  SCIPerrorMessage("expected value: %s.\n", str);
2295  return SCIP_READERROR;
2296  }
2297  }
2298 
2299  return SCIP_OKAY;
2300 }
2301 
2302 /** parse the characters as bounds */
2303 static
2305  SCIP_SET* set, /**< global SCIP settings */
2306  const char* str, /**< string to parse */
2307  char* type, /**< bound type (global, local, or lazy) */
2308  SCIP_Real* lb, /**< pointer to store the lower bound */
2309  SCIP_Real* ub, /**< pointer to store the upper bound */
2310  char** endptr /**< pointer to store the final string position if successfully parsed (or NULL if an error occured) */
2311  )
2312 {
2313  char token[SCIP_MAXSTRLEN];
2314  char* tmpend;
2315 
2316  SCIPsetDebugMsg(set, "parsing bounds: '%s'\n", str);
2317 
2318  /* get bound type */
2319  SCIPstrCopySection(str, ' ', ' ', type, SCIP_MAXSTRLEN, endptr);
2320  if ( *endptr == str
2321  || ( strncmp(type, "original", 8) != 0 && strncmp(type, "global", 6) != 0 && strncmp(type, "local", 5) != 0 && strncmp(type, "lazy", 4) != 0 ) )
2322  {
2323  SCIPsetDebugMsg(set, "unkown bound type\n");
2324  *endptr = NULL;
2325  return SCIP_OKAY;
2326  }
2327 
2328  SCIPsetDebugMsg(set, "parsed bound type <%s>\n", type);
2329 
2330  /* get lower bound */
2331  SCIPstrCopySection(str, '[', ',', token, SCIP_MAXSTRLEN, endptr);
2332  str = *endptr;
2333  SCIP_CALL( parseValue(set, token, lb, &tmpend) );
2334 
2335  /* get upper bound */
2336  SCIP_CALL( parseValue(set, str, ub, endptr) );
2337 
2338  SCIPsetDebugMsg(set, "parsed bounds: [%g,%g]\n", *lb, *ub);
2339 
2340  /* skip end of bounds */
2341  while ( **endptr != '\0' && (**endptr == ']' || **endptr == ',') )
2342  ++(*endptr);
2343 
2344  return SCIP_OKAY;
2345 }
2346 
2347 /** parses a given string for a variable informations */
2348 static
2350  SCIP_SET* set, /**< global SCIP settings */
2351  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2352  const char* str, /**< string to parse */
2353  char* name, /**< pointer to store the variable name */
2354  SCIP_Real* lb, /**< pointer to store the lower bound */
2355  SCIP_Real* ub, /**< pointer to store the upper bound */
2356  SCIP_Real* obj, /**< pointer to store the objective coefficient */
2357  SCIP_VARTYPE* vartype, /**< pointer to store the variable type */
2358  SCIP_Real* lazylb, /**< pointer to store if the lower bound is lazy */
2359  SCIP_Real* lazyub, /**< pointer to store if the upper bound is lazy */
2360  SCIP_Bool local, /**< should the local bound be applied */
2361  char** endptr, /**< pointer to store the final string position if successfully */
2362  SCIP_Bool* success /**< pointer store if the paring process was successful */
2363  )
2364 {
2365  SCIP_Real parsedlb;
2366  SCIP_Real parsedub;
2367  char token[SCIP_MAXSTRLEN];
2368  char* strptr;
2369  int i;
2370 
2371  assert(lb != NULL);
2372  assert(ub != NULL);
2373  assert(obj != NULL);
2374  assert(vartype != NULL);
2375  assert(lazylb != NULL);
2376  assert(lazyub != NULL);
2377  assert(success != NULL);
2378 
2379  (*success) = TRUE;
2380 
2381  /* copy variable type */
2382  SCIPstrCopySection(str, '[', ']', token, SCIP_MAXSTRLEN, endptr);
2383  assert(*endptr != str);
2384  SCIPsetDebugMsg(set, "parsed variable type <%s>\n", token);
2385 
2386  /* get variable type */
2387  if( strncmp(token, "binary", 3) == 0 )
2388  (*vartype) = SCIP_VARTYPE_BINARY;
2389  else if( strncmp(token, "integer", 3) == 0 )
2390  (*vartype) = SCIP_VARTYPE_INTEGER;
2391  else if( strncmp(token, "implicit", 3) == 0 )
2392  (*vartype) = SCIP_VARTYPE_IMPLINT;
2393  else if( strncmp(token, "continuous", 3) == 0 )
2394  (*vartype) = SCIP_VARTYPE_CONTINUOUS;
2395  else
2396  {
2397  SCIPmessagePrintWarning(messagehdlr, "unknown variable type\n");
2398  (*success) = FALSE;
2399  return SCIP_OKAY;
2400  }
2401 
2402  /* move string pointer behind variable type */
2403  str = *endptr;
2404 
2405  /* get variable name */
2406  SCIPstrCopySection(str, '<', '>', name, SCIP_MAXSTRLEN, endptr);
2407  assert(*endptr != str);
2408  SCIPsetDebugMsg(set, "parsed variable name <%s>\n", name);
2409 
2410  /* move string pointer behind variable name */
2411  str = *endptr;
2412 
2413  /* cut out objective coefficient */
2414  SCIPstrCopySection(str, '=', ',', token, SCIP_MAXSTRLEN, endptr);
2415 
2416  /* move string pointer behind objective coefficient */
2417  str = *endptr;
2418 
2419  /* get objective coefficient */
2420  if( !SCIPstrToRealValue(token, obj, endptr) )
2421  {
2422  *endptr = NULL;
2423  return SCIP_READERROR;
2424  }
2425 
2426  SCIPsetDebugMsg(set, "parsed objective coefficient <%g>\n", *obj);
2427 
2428  /* parse global/original bounds */
2429  SCIP_CALL( parseBounds(set, str, token, lb, ub, endptr) );
2430  if ( *endptr == NULL )
2431  {
2432  SCIPerrorMessage("Expected bound type: %s.\n", token);
2433  return SCIP_READERROR;
2434  }
2435  assert(strncmp(token, "global", 6) == 0 || strncmp(token, "original", 8) == 0);
2436 
2437  /* initialize the lazy bound */
2438  *lazylb = -SCIPsetInfinity(set);
2439  *lazyub = SCIPsetInfinity(set);
2440 
2441  /* store pointer */
2442  strptr = *endptr;
2443 
2444  /* possibly parse optional local and lazy bounds */
2445  for( i = 0; i < 2 && *endptr != NULL && **endptr != '\0'; ++i )
2446  {
2447  /* start after previous bounds */
2448  strptr = *endptr;
2449 
2450  /* parse global bounds */
2451  SCIP_CALL( parseBounds(set, strptr, token, &parsedlb, &parsedub, endptr) );
2452 
2453  /* stop if parsing of bounds failed */
2454  if( *endptr == NULL )
2455  break;
2456 
2457  if( strncmp(token, "local", 5) == 0 && local )
2458  {
2459  *lb = parsedlb;
2460  *ub = parsedub;
2461  }
2462  else if( strncmp(token, "lazy", 4) == 0 )
2463  {
2464  *lazylb = parsedlb;
2465  *lazyub = parsedub;
2466  }
2467  }
2468 
2469  /* restore pointer */
2470  if ( *endptr == NULL )
2471  *endptr = strptr;
2472 
2473  /* check bounds for binary variables */
2474  if ( (*vartype) == SCIP_VARTYPE_BINARY )
2475  {
2476  if ( SCIPsetIsLT(set, *lb, 0.0) || SCIPsetIsGT(set, *ub, 1.0) )
2477  {
2478  SCIPerrorMessage("Parsed invalid bounds for binary variable <%s>: [%f, %f].\n", name, *lb, *ub);
2479  return SCIP_READERROR;
2480  }
2481  if ( !SCIPsetIsInfinity(set, -(*lazylb)) && !SCIPsetIsInfinity(set, *lazyub) &&
2482  ( SCIPsetIsLT(set, *lazylb, 0.0) || SCIPsetIsGT(set, *lazyub, 1.0) ) )
2483  {
2484  SCIPerrorMessage("Parsed invalid lazy bounds for binary variable <%s>: [%f, %f].\n", name, *lazylb, *lazyub);
2485  return SCIP_READERROR;
2486  }
2487  }
2488 
2489  return SCIP_OKAY;
2490 }
2491 
2492 /** parses variable information (in cip format) out of a string; if the parsing process was successful an original
2493  * variable is created and captured; if variable is of integral type, fractional bounds are automatically rounded; an
2494  * integer variable with bounds zero and one is automatically converted into a binary variable
2495  */
2497  SCIP_VAR** var, /**< pointer to variable data */
2498  BMS_BLKMEM* blkmem, /**< block memory */
2499  SCIP_SET* set, /**< global SCIP settings */
2500  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2501  SCIP_STAT* stat, /**< problem statistics */
2502  const char* str, /**< string to parse */
2503  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2504  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2505  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2506  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable */
2507  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data */
2508  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable */
2509  SCIP_VARDATA* vardata, /**< user data for this specific variable */
2510  char** endptr, /**< pointer to store the final string position if successfully */
2511  SCIP_Bool* success /**< pointer store if the paring process was successful */
2512  )
2513 {
2514  char name[SCIP_MAXSTRLEN];
2515  SCIP_Real lb;
2516  SCIP_Real ub;
2517  SCIP_Real obj;
2518  SCIP_VARTYPE vartype;
2519  SCIP_Real lazylb;
2520  SCIP_Real lazyub;
2521 
2522  assert(var != NULL);
2523  assert(blkmem != NULL);
2524  assert(stat != NULL);
2525  assert(endptr != NULL);
2526  assert(success != NULL);
2527 
2528  /* parse string in cip format for variable information */
2529  SCIP_CALL( varParse(set, messagehdlr, str, name, &lb, &ub, &obj, &vartype, &lazylb, &lazyub, FALSE, endptr, success) );
2530 
2531  if( *success ) /*lint !e774*/
2532  {
2533  /* create variable */
2534  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2535  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2536 
2537  /* set variable status and data */
2538  (*var)->varstatus = SCIP_VARSTATUS_ORIGINAL; /*lint !e641*/
2539  (*var)->data.original.origdom.holelist = NULL;
2540  (*var)->data.original.origdom.lb = lb;
2541  (*var)->data.original.origdom.ub = ub;
2542  (*var)->data.original.transvar = NULL;
2543 
2544  /* set lazy status of variable bounds */
2545  (*var)->lazylb = lazylb;
2546  (*var)->lazyub = lazyub;
2547 
2548  /* capture variable */
2549  SCIPvarCapture(*var);
2550  }
2551 
2552  return SCIP_OKAY;
2553 }
2554 
2555 /** parses variable information (in cip format) out of a string; if the parsing process was successful a loose variable
2556  * belonging to the transformed problem is created and captured; if variable is of integral type, fractional bounds are
2557  * automatically rounded; an integer variable with bounds zero and one is automatically converted into a binary
2558  * variable
2559  */
2561  SCIP_VAR** var, /**< pointer to variable data */
2562  BMS_BLKMEM* blkmem, /**< block memory */
2563  SCIP_SET* set, /**< global SCIP settings */
2564  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2565  SCIP_STAT* stat, /**< problem statistics */
2566  const char* str, /**< string to parse */
2567  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2568  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2569  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2570  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable */
2571  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data */
2572  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable */
2573  SCIP_VARDATA* vardata, /**< user data for this specific variable */
2574  char** endptr, /**< pointer to store the final string position if successfully */
2575  SCIP_Bool* success /**< pointer store if the paring process was successful */
2576  )
2577 {
2578  char name[SCIP_MAXSTRLEN];
2579  SCIP_Real lb;
2580  SCIP_Real ub;
2581  SCIP_Real obj;
2582  SCIP_VARTYPE vartype;
2583  SCIP_Real lazylb;
2584  SCIP_Real lazyub;
2585 
2586  assert(var != NULL);
2587  assert(blkmem != NULL);
2588  assert(endptr != NULL);
2589  assert(success != NULL);
2590 
2591  /* parse string in cip format for variable information */
2592  SCIP_CALL( varParse(set, messagehdlr, str, name, &lb, &ub, &obj, &vartype, &lazylb, &lazyub, TRUE, endptr, success) );
2593 
2594  if( *success ) /*lint !e774*/
2595  {
2596  /* create variable */
2597  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2598  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2599 
2600  /* create event filter for transformed variable */
2601  SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
2602 
2603  /* set variable status and data */
2604  (*var)->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
2605 
2606  /* set lazy status of variable bounds */
2607  (*var)->lazylb = lazylb;
2608  (*var)->lazyub = lazyub;
2609 
2610  /* capture variable */
2611  SCIPvarCapture(*var);
2612  }
2613 
2614  return SCIP_OKAY;
2615 }
2616 
2617 /** ensures, that parentvars array of var can store at least num entries */
2618 static
2620  SCIP_VAR* var, /**< problem variable */
2621  BMS_BLKMEM* blkmem, /**< block memory */
2622  SCIP_SET* set, /**< global SCIP settings */
2623  int num /**< minimum number of entries to store */
2624  )
2625 {
2626  assert(var->nparentvars <= var->parentvarssize);
2627 
2628  if( num > var->parentvarssize )
2629  {
2630  int newsize;
2631 
2632  newsize = SCIPsetCalcMemGrowSize(set, num);
2633  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->parentvars, var->parentvarssize, newsize) );
2634  var->parentvarssize = newsize;
2635  }
2636  assert(num <= var->parentvarssize);
2637 
2638  return SCIP_OKAY;
2639 }
2640 
2641 /** adds variable to parent list of a variable and captures parent variable */
2642 static
2644  SCIP_VAR* var, /**< variable to add parent to */
2645  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
2646  SCIP_SET* set, /**< global SCIP settings */
2647  SCIP_VAR* parentvar /**< parent variable to add */
2648  )
2649 {
2650  assert(var != NULL);
2651  assert(parentvar != NULL);
2652 
2653  /* the direct original counterpart must be stored as first parent */
2654  assert(var->nparentvars == 0 || SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL);
2655 
2656  SCIPsetDebugMsg(set, "adding parent <%s>[%p] to variable <%s>[%p] in slot %d\n",
2657  parentvar->name, (void*)parentvar, var->name, (void*)var, var->nparentvars);
2658 
2659  SCIP_CALL( varEnsureParentvarsSize(var, blkmem, set, var->nparentvars+1) );
2660 
2661  var->parentvars[var->nparentvars] = parentvar;
2662  var->nparentvars++;
2663 
2664  SCIPvarCapture(parentvar);
2665 
2666  return SCIP_OKAY;
2667 }
2668 
2669 /** deletes and releases all variables from the parent list of a variable, frees the memory of parents array */
2670 static
2672  SCIP_VAR** var, /**< pointer to variable */
2673  BMS_BLKMEM* blkmem, /**< block memory */
2674  SCIP_SET* set, /**< global SCIP settings */
2675  SCIP_EVENTQUEUE* eventqueue, /**< event queue (or NULL, if it's an original variable) */
2676  SCIP_LP* lp /**< current LP data (or NULL, if it's an original variable) */
2677  )
2678 {
2679  SCIP_VAR* parentvar;
2680  int i;
2681 
2682  SCIPsetDebugMsg(set, "free parents of <%s>\n", (*var)->name);
2683 
2684  /* release the parent variables and remove the link from the parent variable to the child */
2685  for( i = 0; i < (*var)->nparentvars; ++i )
2686  {
2687  assert((*var)->parentvars != NULL);
2688  parentvar = (*var)->parentvars[i];
2689  assert(parentvar != NULL);
2690 
2691  switch( SCIPvarGetStatus(parentvar) )
2692  {
2694  assert(parentvar->data.original.transvar == *var);
2695  assert(&parentvar->data.original.transvar != var);
2696  parentvar->data.original.transvar = NULL;
2697  break;
2698 
2700  assert(parentvar->data.aggregate.var == *var);
2701  assert(&parentvar->data.aggregate.var != var);
2702  parentvar->data.aggregate.var = NULL;
2703  break;
2704 
2705 #if 0
2706  /* The following code is unclear: should the current variable be removed from its parents? */
2708  assert(parentvar->data.multaggr.vars != NULL);
2709  for( v = 0; v < parentvar->data.multaggr.nvars && parentvar->data.multaggr.vars[v] != *var; ++v )
2710  {}
2711  assert(v < parentvar->data.multaggr.nvars && parentvar->data.multaggr.vars[v] == *var);
2712  if( v < parentvar->data.multaggr.nvars-1 )
2713  {
2714  parentvar->data.multaggr.vars[v] = parentvar->data.multaggr.vars[parentvar->data.multaggr.nvars-1];
2715  parentvar->data.multaggr.scalars[v] = parentvar->data.multaggr.scalars[parentvar->data.multaggr.nvars-1];
2716  }
2717  parentvar->data.multaggr.nvars--;
2718  break;
2719 #endif
2720 
2722  assert(parentvar->negatedvar == *var);
2723  assert((*var)->negatedvar == parentvar);
2724  parentvar->negatedvar = NULL;
2725  (*var)->negatedvar = NULL;
2726  break;
2727 
2728  default:
2729  SCIPerrorMessage("parent variable is neither ORIGINAL, AGGREGATED nor NEGATED\n");
2730  return SCIP_INVALIDDATA;
2731  } /*lint !e788*/
2732 
2733  SCIP_CALL( SCIPvarRelease(&(*var)->parentvars[i], blkmem, set, eventqueue, lp) );
2734  }
2735 
2736  /* free parentvars array */
2737  BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->parentvars, (*var)->parentvarssize);
2738 
2739  return SCIP_OKAY;
2740 }
2741 
2742 /** frees a variable */
2743 static
2745  SCIP_VAR** var, /**< pointer to variable */
2746  BMS_BLKMEM* blkmem, /**< block memory */
2747  SCIP_SET* set, /**< global SCIP settings */
2748  SCIP_EVENTQUEUE* eventqueue, /**< event queue (may be NULL, if it's not a column variable) */
2749  SCIP_LP* lp /**< current LP data (may be NULL, if it's not a column variable) */
2750  )
2751 {
2752  assert(var != NULL);
2753  assert(*var != NULL);
2754  assert(SCIPvarGetStatus(*var) != SCIP_VARSTATUS_COLUMN || &(*var)->data.col->var != var);
2755  assert((*var)->nuses == 0);
2756  assert((*var)->probindex == -1);
2757  assert((*var)->nlocksup[SCIP_LOCKTYPE_MODEL] == 0);
2758  assert((*var)->nlocksdown[SCIP_LOCKTYPE_MODEL] == 0);
2759 
2760  SCIPsetDebugMsg(set, "free variable <%s> with status=%d\n", (*var)->name, SCIPvarGetStatus(*var));
2761 
2762  switch( SCIPvarGetStatus(*var) )
2763  {
2765  assert((*var)->data.original.transvar == NULL); /* cannot free variable, if transformed variable is still existing */
2766  holelistFree(&(*var)->data.original.origdom.holelist, blkmem);
2767  assert((*var)->data.original.origdom.holelist == NULL);
2768  break;
2769  case SCIP_VARSTATUS_LOOSE:
2770  break;
2771  case SCIP_VARSTATUS_COLUMN:
2772  SCIP_CALL( SCIPcolFree(&(*var)->data.col, blkmem, set, eventqueue, lp) ); /* free corresponding LP column */
2773  break;
2774  case SCIP_VARSTATUS_FIXED:
2776  break;
2778  BMSfreeBlockMemoryArray(blkmem, &(*var)->data.multaggr.vars, (*var)->data.multaggr.varssize);
2779  BMSfreeBlockMemoryArray(blkmem, &(*var)->data.multaggr.scalars, (*var)->data.multaggr.varssize);
2780  break;
2782  break;
2783  default:
2784  SCIPerrorMessage("unknown variable status\n");
2785  return SCIP_INVALIDDATA;
2786  }
2787 
2788  /* release all parent variables and free the parentvars array */
2789  SCIP_CALL( varFreeParents(var, blkmem, set, eventqueue, lp) );
2790 
2791  /* free user data */
2793  {
2794  if( (*var)->vardelorig != NULL )
2795  {
2796  SCIP_CALL( (*var)->vardelorig(set->scip, *var, &(*var)->vardata) );
2797  }
2798  }
2799  else
2800  {
2801  if( (*var)->vardeltrans != NULL )
2802  {
2803  SCIP_CALL( (*var)->vardeltrans(set->scip, *var, &(*var)->vardata) );
2804  }
2805  }
2806 
2807  /* free event filter */
2808  if( (*var)->eventfilter != NULL )
2809  {
2810  SCIP_CALL( SCIPeventfilterFree(&(*var)->eventfilter, blkmem, set) );
2811  }
2812  assert((*var)->eventfilter == NULL);
2813 
2814  /* free hole lists */
2815  holelistFree(&(*var)->glbdom.holelist, blkmem);
2816  holelistFree(&(*var)->locdom.holelist, blkmem);
2817  assert((*var)->glbdom.holelist == NULL);
2818  assert((*var)->locdom.holelist == NULL);
2819 
2820  /* free variable bounds data structures */
2821  SCIPvboundsFree(&(*var)->vlbs, blkmem);
2822  SCIPvboundsFree(&(*var)->vubs, blkmem);
2823 
2824  /* free implications data structures */
2825  SCIPimplicsFree(&(*var)->implics, blkmem);
2826 
2827  /* free clique list data structures */
2828  SCIPcliquelistFree(&(*var)->cliquelist, blkmem);
2829 
2830  /* free bound change information arrays */
2831  BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->lbchginfos, (*var)->lbchginfossize);
2832  BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->ubchginfos, (*var)->ubchginfossize);
2833 
2834  /* free branching and inference history entries */
2835  SCIPhistoryFree(&(*var)->history, blkmem);
2836  SCIPhistoryFree(&(*var)->historycrun, blkmem);
2837  SCIPvaluehistoryFree(&(*var)->valuehistory, blkmem);
2838 
2839  /* free variable data structure */
2840  BMSfreeBlockMemoryArray(blkmem, &(*var)->name, strlen((*var)->name)+1);
2841  BMSfreeBlockMemory(blkmem, var);
2842 
2843  return SCIP_OKAY;
2844 }
2845 
2846 /** increases usage counter of variable */
2847 void SCIPvarCapture(
2848  SCIP_VAR* var /**< variable */
2849  )
2850 {
2851  assert(var != NULL);
2852  assert(var->nuses >= 0);
2853 
2854  SCIPdebugMessage("capture variable <%s> with nuses=%d\n", var->name, var->nuses);
2855  var->nuses++;
2856 
2857 #ifdef DEBUGUSES_VARNAME
2858  if( strcmp(var->name, DEBUGUSES_VARNAME) == 0
2859 #ifdef DEBUGUSES_PROBNAME
2860  && ((var->scip->transprob != NULL && strcmp(SCIPprobGetName(var->scip->transprob), DEBUGUSES_PROBNAME) == 0) ||
2861  strcmp(SCIPprobGetName(var->scip->origprob), DEBUGUSES_PROBNAME) == 0)
2862 #endif
2863  )
2864  {
2865  printf("Captured variable " DEBUGUSES_VARNAME " in SCIP %p, now %d uses; captured at\n", (void*)var->scip, var->nuses);
2866  print_backtrace();
2867  }
2868 #endif
2869 }
2870 
2871 /** decreases usage counter of variable, and frees memory if necessary */
2873  SCIP_VAR** var, /**< pointer to variable */
2874  BMS_BLKMEM* blkmem, /**< block memory */
2875  SCIP_SET* set, /**< global SCIP settings */
2876  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2877  SCIP_LP* lp /**< current LP data (or NULL, if it's an original variable) */
2878  )
2879 {
2880  assert(var != NULL);
2881  assert(*var != NULL);
2882  assert((*var)->nuses >= 1);
2883  assert(blkmem != NULL);
2884  assert((*var)->scip == set->scip);
2885 
2886  SCIPsetDebugMsg(set, "release variable <%s> with nuses=%d\n", (*var)->name, (*var)->nuses);
2887  (*var)->nuses--;
2888 
2889 #ifdef DEBUGUSES_VARNAME
2890  if( strcmp((*var)->name, DEBUGUSES_VARNAME) == 0
2891 #ifdef DEBUGUSES_PROBNAME
2892  && (((*var)->scip->transprob != NULL && strcmp(SCIPprobGetName((*var)->scip->transprob), DEBUGUSES_PROBNAME) == 0) ||
2893  strcmp(SCIPprobGetName((*var)->scip->origprob), DEBUGUSES_PROBNAME) == 0)
2894 #endif
2895  )
2896  {
2897  printf("Released variable " DEBUGUSES_VARNAME " in SCIP %p, now %d uses; released at\n", (void*)(*var)->scip, (*var)->nuses);
2898  print_backtrace();
2899  }
2900 #endif
2901 
2902  if( (*var)->nuses == 0 )
2903  {
2904  SCIP_CALL( varFree(var, blkmem, set, eventqueue, lp) );
2905  }
2906 
2907  *var = NULL;
2908 
2909  return SCIP_OKAY;
2910 }
2911 
2912 /** change variable name */
2914  SCIP_VAR* var, /**< problem variable */
2915  BMS_BLKMEM* blkmem, /**< block memory */
2916  const char* name /**< name of variable */
2917  )
2918 {
2919  assert(name != NULL);
2920 
2921  /* remove old variable name */
2922  BMSfreeBlockMemoryArray(blkmem, &var->name, strlen(var->name)+1);
2923 
2924  /* set new variable name */
2925  SCIP_CALL( varSetName(var, blkmem, NULL, name) );
2926 
2927  return SCIP_OKAY;
2928 }
2929 
2930 /** initializes variable data structure for solving */
2931 void SCIPvarInitSolve(
2932  SCIP_VAR* var /**< problem variable */
2933  )
2934 {
2935  assert(var != NULL);
2936 
2938  var->conflictlbcount = 0;
2939  var->conflictubcount = 0;
2940 }
2941 
2942 /** outputs the given bounds into the file stream */
2943 static
2944 void printBounds(
2945  SCIP_SET* set, /**< global SCIP settings */
2946  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2947  FILE* file, /**< output file (or NULL for standard output) */
2948  SCIP_Real lb, /**< lower bound */
2949  SCIP_Real ub, /**< upper bound */
2950  const char* name /**< bound type name */
2951  )
2952 {
2953  assert(set != NULL);
2954 
2955  SCIPmessageFPrintInfo(messagehdlr, file, ", %s=", name);
2956  if( SCIPsetIsInfinity(set, lb) )
2957  SCIPmessageFPrintInfo(messagehdlr, file, "[+inf,");
2958  else if( SCIPsetIsInfinity(set, -lb) )
2959  SCIPmessageFPrintInfo(messagehdlr, file, "[-inf,");
2960  else
2961  SCIPmessageFPrintInfo(messagehdlr, file, "[%.15g,", lb);
2962  if( SCIPsetIsInfinity(set, ub) )
2963  SCIPmessageFPrintInfo(messagehdlr, file, "+inf]");
2964  else if( SCIPsetIsInfinity(set, -ub) )
2965  SCIPmessageFPrintInfo(messagehdlr, file, "-inf]");
2966  else
2967  SCIPmessageFPrintInfo(messagehdlr, file, "%.15g]", ub);
2968 }
2969 
2970 /** prints hole list to file stream */
2971 static
2972 void printHolelist(
2973  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2974  FILE* file, /**< output file (or NULL for standard output) */
2975  SCIP_HOLELIST* holelist, /**< hole list pointer to hole of interest */
2976  const char* name /**< hole type name */
2977  )
2978 { /*lint --e{715}*/
2979  SCIP_Real left;
2980  SCIP_Real right;
2981 
2982  if( holelist == NULL )
2983  return;
2984 
2985  left = SCIPholelistGetLeft(holelist);
2986  right = SCIPholelistGetRight(holelist);
2987 
2988  /* display first hole */
2989  SCIPmessageFPrintInfo(messagehdlr, file, ", %s=(%g,%g)", name, left, right);
2990  holelist = SCIPholelistGetNext(holelist);
2991 
2992  while(holelist != NULL )
2993  {
2994  left = SCIPholelistGetLeft(holelist);
2995  right = SCIPholelistGetRight(holelist);
2996 
2997  /* display hole */
2998  SCIPmessageFPrintInfo(messagehdlr, file, "(%g,%g)", left, right);
2999 
3000  /* get next hole */
3001  holelist = SCIPholelistGetNext(holelist);
3002  }
3003 }
3004 
3005 /** outputs variable information into file stream */
3007  SCIP_VAR* var, /**< problem variable */
3008  SCIP_SET* set, /**< global SCIP settings */
3009  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3010  FILE* file /**< output file (or NULL for standard output) */
3011  )
3012 {
3013  SCIP_HOLELIST* holelist;
3014  SCIP_Real lb;
3015  SCIP_Real ub;
3016  int i;
3017 
3018  assert(var != NULL);
3019  assert(var->scip == set->scip);
3020 
3021  /* type of variable */
3022  switch( SCIPvarGetType(var) )
3023  {
3024  case SCIP_VARTYPE_BINARY:
3025  SCIPmessageFPrintInfo(messagehdlr, file, " [binary]");
3026  break;
3027  case SCIP_VARTYPE_INTEGER:
3028  SCIPmessageFPrintInfo(messagehdlr, file, " [integer]");
3029  break;
3030  case SCIP_VARTYPE_IMPLINT:
3031  SCIPmessageFPrintInfo(messagehdlr, file, " [implicit]");
3032  break;
3034  SCIPmessageFPrintInfo(messagehdlr, file, " [continuous]");
3035  break;
3036  default:
3037  SCIPerrorMessage("unknown variable type\n");
3038  SCIPABORT();
3039  return SCIP_ERROR; /*lint !e527*/
3040  }
3041 
3042  /* name */
3043  SCIPmessageFPrintInfo(messagehdlr, file, " <%s>:", var->name);
3044 
3045  /* objective value */
3046  SCIPmessageFPrintInfo(messagehdlr, file, " obj=%.15g", var->obj);
3047 
3048  /* bounds (global bounds for transformed variables, original bounds for original variables) */
3049  if( !SCIPvarIsTransformed(var) )
3050  {
3051  /* output original bound */
3052  lb = SCIPvarGetLbOriginal(var);
3053  ub = SCIPvarGetUbOriginal(var);
3054  printBounds(set, messagehdlr, file, lb, ub, "original bounds");
3055 
3056  /* output lazy bound */
3057  lb = SCIPvarGetLbLazy(var);
3058  ub = SCIPvarGetUbLazy(var);
3059 
3060  /* only display the lazy bounds if they are different from [-infinity,infinity] */
3061  if( !SCIPsetIsInfinity(set, -lb) || !SCIPsetIsInfinity(set, ub) )
3062  printBounds(set, messagehdlr, file, lb, ub, "lazy bounds");
3063 
3064  holelist = SCIPvarGetHolelistOriginal(var);
3065  printHolelist(messagehdlr, file, holelist, "original holes");
3066  }
3067  else
3068  {
3069  /* output global bound */
3070  lb = SCIPvarGetLbGlobal(var);
3071  ub = SCIPvarGetUbGlobal(var);
3072  printBounds(set, messagehdlr, file, lb, ub, "global bounds");
3073 
3074  /* output local bound */
3075  lb = SCIPvarGetLbLocal(var);
3076  ub = SCIPvarGetUbLocal(var);
3077  printBounds(set, messagehdlr, file, lb, ub, "local bounds");
3078 
3079  /* output lazy bound */
3080  lb = SCIPvarGetLbLazy(var);
3081  ub = SCIPvarGetUbLazy(var);
3082 
3083  /* only display the lazy bounds if they are different from [-infinity,infinity] */
3084  if( !SCIPsetIsInfinity(set, -lb) || !SCIPsetIsInfinity(set, ub) )
3085  printBounds(set, messagehdlr, file, lb, ub, "lazy bounds");
3086 
3087  /* global hole list */
3088  holelist = SCIPvarGetHolelistGlobal(var);
3089  printHolelist(messagehdlr, file, holelist, "global holes");
3090 
3091  /* local hole list */
3092  holelist = SCIPvarGetHolelistLocal(var);
3093  printHolelist(messagehdlr, file, holelist, "local holes");
3094  }
3095 
3096  /* fixings and aggregations */
3097  switch( SCIPvarGetStatus(var) )
3098  {
3100  case SCIP_VARSTATUS_LOOSE:
3101  case SCIP_VARSTATUS_COLUMN:
3102  break;
3103 
3104  case SCIP_VARSTATUS_FIXED:
3105  SCIPmessageFPrintInfo(messagehdlr, file, ", fixed:");
3106  if( SCIPsetIsInfinity(set, var->glbdom.lb) )
3107  SCIPmessageFPrintInfo(messagehdlr, file, "+inf");
3108  else if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
3109  SCIPmessageFPrintInfo(messagehdlr, file, "-inf");
3110  else
3111  SCIPmessageFPrintInfo(messagehdlr, file, "%.15g", var->glbdom.lb);
3112  break;
3113 
3115  SCIPmessageFPrintInfo(messagehdlr, file, ", aggregated:");
3116  if( !SCIPsetIsZero(set, var->data.aggregate.constant) )
3117  SCIPmessageFPrintInfo(messagehdlr, file, " %.15g", var->data.aggregate.constant);
3118  SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g<%s>", var->data.aggregate.scalar, SCIPvarGetName(var->data.aggregate.var));
3119  break;
3120 
3122  SCIPmessageFPrintInfo(messagehdlr, file, ", aggregated:");
3123  if( var->data.multaggr.nvars == 0 || !SCIPsetIsZero(set, var->data.multaggr.constant) )
3124  SCIPmessageFPrintInfo(messagehdlr, file, " %.15g", var->data.multaggr.constant);
3125  for( i = 0; i < var->data.multaggr.nvars; ++i )
3126  SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g<%s>", var->data.multaggr.scalars[i], SCIPvarGetName(var->data.multaggr.vars[i]));
3127  break;
3128 
3130  SCIPmessageFPrintInfo(messagehdlr, file, ", negated: %.15g - <%s>", var->data.negate.constant, SCIPvarGetName(var->negatedvar));
3131  break;
3132 
3133  default:
3134  SCIPerrorMessage("unknown variable status\n");
3135  SCIPABORT();
3136  return SCIP_ERROR; /*lint !e527*/
3137  }
3138 
3139  SCIPmessageFPrintInfo(messagehdlr, file, "\n");
3140 
3141  return SCIP_OKAY;
3142 }
3143 
3144 /** issues a VARUNLOCKED event on the given variable */
3145 static
3147  SCIP_VAR* var, /**< problem variable to change */
3148  BMS_BLKMEM* blkmem, /**< block memory */
3149  SCIP_SET* set, /**< global SCIP settings */
3150  SCIP_EVENTQUEUE* eventqueue /**< event queue */
3151  )
3152 {
3153  SCIP_EVENT* event;
3154 
3155  assert(var != NULL);
3156  assert(var->nlocksdown[SCIP_LOCKTYPE_MODEL] <= 1 && var->nlocksup[SCIP_LOCKTYPE_MODEL] <= 1);
3157  assert(var->scip == set->scip);
3158 
3159  /* issue VARUNLOCKED event on variable */
3160  SCIP_CALL( SCIPeventCreateVarUnlocked(&event, blkmem, var) );
3161  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
3162 
3163  return SCIP_OKAY;
3164 }
3165 
3166 /** modifies lock numbers for rounding */
3168  SCIP_VAR* var, /**< problem variable */
3169  BMS_BLKMEM* blkmem, /**< block memory */
3170  SCIP_SET* set, /**< global SCIP settings */
3171  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3172  SCIP_LOCKTYPE locktype, /**< type of the variable locks */
3173  int addnlocksdown, /**< increase in number of rounding down locks */
3174  int addnlocksup /**< increase in number of rounding up locks */
3175  )
3176 {
3177  SCIP_VAR* lockvar;
3178 
3179  assert(var != NULL);
3180  assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
3181  assert(var->nlocksup[locktype] >= 0);
3182  assert(var->nlocksdown[locktype] >= 0);
3183  assert(var->scip == set->scip);
3184 
3185  if( addnlocksdown == 0 && addnlocksup == 0 )
3186  return SCIP_OKAY;
3187 
3188 #ifdef SCIP_DEBUG
3189  SCIPsetDebugMsg(set, "add rounding locks %d/%d to variable <%s> (locks=%d/%d, type=%u)\n",
3190  addnlocksdown, addnlocksup, var->name, var->nlocksdown[locktype], var->nlocksup[locktype], locktype);
3191 #endif
3192 
3193  lockvar = var;
3194 
3195  while( TRUE ) /*lint !e716 */
3196  {
3197  assert(lockvar != NULL);
3198 
3199  switch( SCIPvarGetStatus(lockvar) )
3200  {
3202  if( lockvar->data.original.transvar != NULL )
3203  {
3204  lockvar = lockvar->data.original.transvar;
3205  break;
3206  }
3207  else
3208  {
3209  lockvar->nlocksdown[locktype] += addnlocksdown;
3210  lockvar->nlocksup[locktype] += addnlocksup;
3211 
3212  assert(lockvar->nlocksdown[locktype] >= 0);
3213  assert(lockvar->nlocksup[locktype] >= 0);
3214 
3215  return SCIP_OKAY;
3216  }
3217  case SCIP_VARSTATUS_LOOSE:
3218  case SCIP_VARSTATUS_COLUMN:
3219  case SCIP_VARSTATUS_FIXED:
3220  lockvar->nlocksdown[locktype] += addnlocksdown;
3221  lockvar->nlocksup[locktype] += addnlocksup;
3222 
3223  assert(lockvar->nlocksdown[locktype] >= 0);
3224  assert(lockvar->nlocksup[locktype] >= 0);
3225 
3226  if( locktype == SCIP_LOCKTYPE_MODEL && lockvar->nlocksdown[locktype] <= 1
3227  && lockvar->nlocksup[locktype] <= 1 )
3228  {
3229  SCIP_CALL( varEventVarUnlocked(lockvar, blkmem, set, eventqueue) );
3230  }
3231 
3232  return SCIP_OKAY;
3234  assert(!lockvar->donotaggr);
3235 
3236  if( lockvar->data.aggregate.scalar < 0.0 )
3237  {
3238  int tmp = addnlocksup;
3239 
3240  addnlocksup = addnlocksdown;
3241  addnlocksdown = tmp;
3242  }
3243 
3244  lockvar = lockvar->data.aggregate.var;
3245  break;
3247  {
3248  int v;
3249 
3250  assert(!lockvar->donotmultaggr);
3251 
3252  lockvar->nlocksdown[locktype] += addnlocksdown;
3253  lockvar->nlocksup[locktype] += addnlocksup;
3254 
3255  assert(lockvar->nlocksdown[locktype] >= 0);
3256  assert(lockvar->nlocksup[locktype] >= 0);
3257 
3258  for( v = lockvar->data.multaggr.nvars - 1; v >= 0; --v )
3259  {
3260  if( lockvar->data.multaggr.scalars[v] > 0.0 )
3261  {
3262  SCIP_CALL( SCIPvarAddLocks(lockvar->data.multaggr.vars[v], blkmem, set, eventqueue, locktype, addnlocksdown,
3263  addnlocksup) );
3264  }
3265  else
3266  {
3267  SCIP_CALL( SCIPvarAddLocks(lockvar->data.multaggr.vars[v], blkmem, set, eventqueue, locktype, addnlocksup,
3268  addnlocksdown) );
3269  }
3270  }
3271  return SCIP_OKAY;
3272  }
3274  {
3275  int tmp = addnlocksup;
3276 
3277  assert(lockvar->negatedvar != NULL);
3278  assert(SCIPvarGetStatus(lockvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
3279  assert(lockvar->negatedvar->negatedvar == lockvar);
3280 
3281  addnlocksup = addnlocksdown;
3282  addnlocksdown = tmp;
3283 
3284  lockvar = lockvar->negatedvar;
3285  break;
3286  }
3287  default:
3288  SCIPerrorMessage("unknown variable status\n");
3289  return SCIP_INVALIDDATA;
3290  }
3291  }
3292 }
3293 
3294 /** gets number of locks for rounding down of a special type */
3296  SCIP_VAR* var, /**< problem variable */
3297  SCIP_LOCKTYPE locktype /**< type of variable locks */
3298  )
3299 {
3300  int nlocks;
3301  int i;
3302 
3303  assert(var != NULL);
3304  assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
3305  assert(var->nlocksdown[locktype] >= 0);
3306 
3307  switch( SCIPvarGetStatus(var) )
3308  {
3310  if( var->data.original.transvar != NULL )
3311  return SCIPvarGetNLocksDownType(var->data.original.transvar, locktype);
3312  else
3313  return var->nlocksdown[locktype];
3314 
3315  case SCIP_VARSTATUS_LOOSE:
3316  case SCIP_VARSTATUS_COLUMN:
3317  case SCIP_VARSTATUS_FIXED:
3318  return var->nlocksdown[locktype];
3319 
3321  assert(!var->donotaggr);
3322  if( var->data.aggregate.scalar > 0.0 )
3323  return SCIPvarGetNLocksDownType(var->data.aggregate.var, locktype);
3324  else
3325  return SCIPvarGetNLocksUpType(var->data.aggregate.var, locktype);
3326 
3328  assert(!var->donotmultaggr);
3329  nlocks = 0;
3330  for( i = 0; i < var->data.multaggr.nvars; ++i )
3331  {
3332  if( var->data.multaggr.scalars[i] > 0.0 )
3333  nlocks += SCIPvarGetNLocksDownType(var->data.multaggr.vars[i], locktype);
3334  else
3335  nlocks += SCIPvarGetNLocksUpType(var->data.multaggr.vars[i], locktype);
3336  }
3337  return nlocks;
3338 
3340  assert(var->negatedvar != NULL);
3342  assert(var->negatedvar->negatedvar == var);
3343  return SCIPvarGetNLocksUpType(var->negatedvar, locktype);
3344 
3345  default:
3346  SCIPerrorMessage("unknown variable status\n");
3347  SCIPABORT();
3348  return INT_MAX; /*lint !e527*/
3349  }
3350 }
3351 
3352 /** gets number of locks for rounding up of a special type */
3354  SCIP_VAR* var, /**< problem variable */
3355  SCIP_LOCKTYPE locktype /**< type of variable locks */
3356  )
3357 {
3358  int nlocks;
3359  int i;
3360 
3361  assert(var != NULL);
3362  assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
3363  assert(var->nlocksup[locktype] >= 0);
3364 
3365  switch( SCIPvarGetStatus(var) )
3366  {
3368  if( var->data.original.transvar != NULL )
3369  return SCIPvarGetNLocksUpType(var->data.original.transvar, locktype);
3370  else
3371  return var->nlocksup[locktype];
3372 
3373  case SCIP_VARSTATUS_LOOSE:
3374  case SCIP_VARSTATUS_COLUMN:
3375  case SCIP_VARSTATUS_FIXED:
3376  return var->nlocksup[locktype];
3377 
3379  assert(!var->donotaggr);
3380  if( var->data.aggregate.scalar > 0.0 )
3381  return SCIPvarGetNLocksUpType(var->data.aggregate.var, locktype);
3382  else
3383  return SCIPvarGetNLocksDownType(var->data.aggregate.var, locktype);
3384 
3386  assert(!var->donotmultaggr);
3387  nlocks = 0;
3388  for( i = 0; i < var->data.multaggr.nvars; ++i )
3389  {
3390  if( var->data.multaggr.scalars[i] > 0.0 )
3391  nlocks += SCIPvarGetNLocksUpType(var->data.multaggr.vars[i], locktype);
3392  else
3393  nlocks += SCIPvarGetNLocksDownType(var->data.multaggr.vars[i], locktype);
3394  }
3395  return nlocks;
3396 
3398  assert(var->negatedvar != NULL);
3400  assert(var->negatedvar->negatedvar == var);
3401  return SCIPvarGetNLocksDownType(var->negatedvar, locktype);
3402 
3403  default:
3404  SCIPerrorMessage("unknown variable status\n");
3405  SCIPABORT();
3406  return INT_MAX; /*lint !e527*/
3407  }
3408 }
3409 
3410 /** gets number of locks for rounding down
3411  *
3412  * @note This method will always return variable locks of type model
3413  *
3414  * @note It is recommented to use SCIPvarGetNLocksDownType()
3415  */
3417  SCIP_VAR* var /**< problem variable */
3418  )
3419 {
3421 }
3422 
3423 /** gets number of locks for rounding up
3424  *
3425  * @note This method will always return variable locks of type model
3426  *
3427  * @note It is recommented to use SCIPvarGetNLocksUpType()
3428  */
3429 int SCIPvarGetNLocksUp(
3430  SCIP_VAR* var /**< problem variable */
3431  )
3432 {
3434 }
3435 
3436 /** is it possible, to round variable down and stay feasible?
3437  *
3438  * @note This method will always check w.r.t variable locks of type model
3439  */
3441  SCIP_VAR* var /**< problem variable */
3442  )
3443 {
3444  return (SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 0);
3445 }
3446 
3447 /** is it possible, to round variable up and stay feasible?
3448  *
3449  * @note This method will always check w.r.t. variable locks of type model
3450  */
3452  SCIP_VAR* var /**< problem variable */
3453  )
3454 {
3455  return (SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 0);
3456 }
3457 
3458 /** gets and captures transformed variable of a given variable; if the variable is not yet transformed,
3459  * a new transformed variable for this variable is created
3460  */
3462  SCIP_VAR* origvar, /**< original problem variable */
3463  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3464  SCIP_SET* set, /**< global SCIP settings */
3465  SCIP_STAT* stat, /**< problem statistics */
3466  SCIP_OBJSENSE objsense, /**< objective sense of original problem; transformed is always MINIMIZE */
3467  SCIP_VAR** transvar /**< pointer to store the transformed variable */
3468  )
3469 {
3470  char name[SCIP_MAXSTRLEN];
3471 
3472  assert(origvar != NULL);
3473  assert(origvar->scip == set->scip);
3474  assert(SCIPvarGetStatus(origvar) == SCIP_VARSTATUS_ORIGINAL);
3475  assert(SCIPsetIsEQ(set, origvar->glbdom.lb, origvar->locdom.lb));
3476  assert(SCIPsetIsEQ(set, origvar->glbdom.ub, origvar->locdom.ub));
3477  assert(origvar->vlbs == NULL);
3478  assert(origvar->vubs == NULL);
3479  assert(transvar != NULL);
3480 
3481  /* check if variable is already transformed */
3482  if( origvar->data.original.transvar != NULL )
3483  {
3484  *transvar = origvar->data.original.transvar;
3485  SCIPvarCapture(*transvar);
3486  }
3487  else
3488  {
3489  int i;
3490 
3491  /* create transformed variable */
3492  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "t_%s", origvar->name);
3493  SCIP_CALL( SCIPvarCreateTransformed(transvar, blkmem, set, stat, name,
3494  origvar->glbdom.lb, origvar->glbdom.ub, (SCIP_Real)objsense * origvar->obj,
3495  SCIPvarGetType(origvar), origvar->initial, origvar->removable,
3496  origvar->vardelorig, origvar->vartrans, origvar->vardeltrans, origvar->varcopy, NULL) );
3497 
3498  /* copy the branch factor and priority */
3499  (*transvar)->branchfactor = origvar->branchfactor;
3500  (*transvar)->branchpriority = origvar->branchpriority;
3501  (*transvar)->branchdirection = origvar->branchdirection; /*lint !e732*/
3502 
3503  /* duplicate hole lists */
3504  SCIP_CALL( holelistDuplicate(&(*transvar)->glbdom.holelist, blkmem, set, origvar->glbdom.holelist) );
3505  SCIP_CALL( holelistDuplicate(&(*transvar)->locdom.holelist, blkmem, set, origvar->locdom.holelist) );
3506 
3507  /* link original and transformed variable */
3508  origvar->data.original.transvar = *transvar;
3509  SCIP_CALL( varAddParent(*transvar, blkmem, set, origvar) );
3510 
3511  /* copy rounding locks */
3512  for( i = 0; i < NLOCKTYPES; i++ )
3513  {
3514  (*transvar)->nlocksdown[i] = origvar->nlocksdown[i];
3515  (*transvar)->nlocksup[i] = origvar->nlocksup[i];
3516  assert((*transvar)->nlocksdown[i] >= 0);
3517  assert((*transvar)->nlocksup[i] >= 0);
3518  }
3519 
3520  /* copy donot(mult)aggr status */
3521  (*transvar)->donotaggr = origvar->donotaggr;
3522  (*transvar)->donotmultaggr = origvar->donotmultaggr;
3523 
3524  /* copy lazy bounds */
3525  (*transvar)->lazylb = origvar->lazylb;
3526  (*transvar)->lazyub = origvar->lazyub;
3527 
3528  /* transfer eventual variable statistics; do not update global statistics, because this has been done
3529  * when original variable was created
3530  */
3531  SCIPhistoryUnite((*transvar)->history, origvar->history, FALSE);
3532 
3533  /* transform user data */
3534  if( origvar->vartrans != NULL )
3535  {
3536  SCIP_CALL( origvar->vartrans(set->scip, origvar, origvar->vardata, *transvar, &(*transvar)->vardata) );
3537  }
3538  else
3539  (*transvar)->vardata = origvar->vardata;
3540  }
3541 
3542  SCIPsetDebugMsg(set, "transformed variable: <%s>[%p] -> <%s>[%p]\n", origvar->name, (void*)origvar, (*transvar)->name, (void*)*transvar);
3543 
3544  return SCIP_OKAY;
3545 }
3546 
3547 /** gets corresponding transformed variable of an original or negated original variable */
3549  SCIP_VAR* origvar, /**< original problem variable */
3550  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3551  SCIP_SET* set, /**< global SCIP settings */
3552  SCIP_STAT* stat, /**< problem statistics */
3553  SCIP_VAR** transvar /**< pointer to store the transformed variable, or NULL if not existing yet */
3554  )
3555 {
3556  assert(origvar != NULL);
3558  assert(origvar->scip == set->scip);
3559 
3560  if( SCIPvarGetStatus(origvar) == SCIP_VARSTATUS_NEGATED )
3561  {
3562  assert(origvar->negatedvar != NULL);
3564 
3565  if( origvar->negatedvar->data.original.transvar == NULL )
3566  *transvar = NULL;
3567  else
3568  {
3569  SCIP_CALL( SCIPvarNegate(origvar->negatedvar->data.original.transvar, blkmem, set, stat, transvar) );
3570  }
3571  }
3572  else
3573  *transvar = origvar->data.original.transvar;
3574 
3575  return SCIP_OKAY;
3576 }
3577 
3578 /** converts loose transformed variable into column variable, creates LP column */
3580  SCIP_VAR* var, /**< problem variable */
3581  BMS_BLKMEM* blkmem, /**< block memory */
3582  SCIP_SET* set, /**< global SCIP settings */
3583  SCIP_STAT* stat, /**< problem statistics */
3584  SCIP_PROB* prob, /**< problem data */
3585  SCIP_LP* lp /**< current LP data */
3586  )
3587 {
3588  assert(var != NULL);
3589  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
3590  assert(var->scip == set->scip);
3591 
3592  SCIPsetDebugMsg(set, "creating column for variable <%s>\n", var->name);
3593 
3594  /* switch variable status */
3595  var->varstatus = SCIP_VARSTATUS_COLUMN; /*lint !e641*/
3596 
3597  /* create column of variable */
3598  SCIP_CALL( SCIPcolCreate(&var->data.col, blkmem, set, stat, var, 0, NULL, NULL, var->removable) );
3599 
3600  if( var->probindex != -1 )
3601  {
3602  /* inform problem about the variable's status change */
3603  SCIP_CALL( SCIPprobVarChangedStatus(prob, blkmem, set, NULL, NULL, var) );
3604 
3605  /* inform LP, that problem variable is now a column variable and no longer loose */
3606  SCIP_CALL( SCIPlpUpdateVarColumn(lp, set, var) );
3607  }
3608 
3609  return SCIP_OKAY;
3610 }
3611 
3612 /** converts column transformed variable back into loose variable, frees LP column */
3614  SCIP_VAR* var, /**< problem variable */
3615  BMS_BLKMEM* blkmem, /**< block memory */
3616  SCIP_SET* set, /**< global SCIP settings */
3617  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3618  SCIP_PROB* prob, /**< problem data */
3619  SCIP_LP* lp /**< current LP data */
3620  )
3621 {
3622  assert(var != NULL);
3623  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
3624  assert(var->scip == set->scip);
3625  assert(var->data.col != NULL);
3626  assert(var->data.col->lppos == -1);
3627  assert(var->data.col->lpipos == -1);
3628 
3629  SCIPsetDebugMsg(set, "deleting column for variable <%s>\n", var->name);
3630 
3631  /* free column of variable */
3632  SCIP_CALL( SCIPcolFree(&var->data.col, blkmem, set, eventqueue, lp) );
3633 
3634  /* switch variable status */
3635  var->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
3636 
3637  if( var->probindex != -1 )
3638  {
3639  /* inform problem about the variable's status change */
3640  SCIP_CALL( SCIPprobVarChangedStatus(prob, blkmem, set, NULL, NULL, var) );
3641 
3642  /* inform LP, that problem variable is now a loose variable and no longer a column */
3643  SCIP_CALL( SCIPlpUpdateVarLoose(lp, set, var) );
3644  }
3645 
3646  return SCIP_OKAY;
3647 }
3648 
3649 /** issues a VARFIXED event on the given variable and all its parents (except ORIGINAL parents);
3650  * the event issuing on the parents is necessary, because unlike with bound changes, the parent variables
3651  * are not informed about a fixing of an active variable they are pointing to
3652  */
3653 static
3655  SCIP_VAR* var, /**< problem variable to change */
3656  BMS_BLKMEM* blkmem, /**< block memory */
3657  SCIP_SET* set, /**< global SCIP settings */
3658  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3659  int fixeventtype /**< is this event a fixation(0), an aggregation(1), or a
3660  * multi-aggregation(2)
3661  */
3662  )
3663 {
3664  SCIP_EVENT* event;
3665  SCIP_VARSTATUS varstatus;
3666  int i;
3667 
3668  assert(var != NULL);
3669  assert(var->scip == set->scip);
3670  assert(0 <= fixeventtype && fixeventtype <= 2);
3671 
3672  /* issue VARFIXED event on variable */
3673  SCIP_CALL( SCIPeventCreateVarFixed(&event, blkmem, var) );
3674  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
3675 
3676 #ifndef NDEBUG
3677  for( i = var->nparentvars -1; i >= 0; --i )
3678  {
3680  }
3681 #endif
3682 
3683  switch( fixeventtype )
3684  {
3685  case 0:
3686  /* process all parents of a fixed variable */
3687  for( i = var->nparentvars - 1; i >= 0; --i )
3688  {
3689  varstatus = SCIPvarGetStatus(var->parentvars[i]);
3690 
3691  assert(varstatus != SCIP_VARSTATUS_FIXED);
3692 
3693  /* issue event on all not yet fixed parent variables, (that should already issued this event) except the original
3694  * one
3695  */
3696  if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3697  {
3698  SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3699  }
3700  }
3701  break;
3702  case 1:
3703  /* process all parents of a aggregated variable */
3704  for( i = var->nparentvars - 1; i >= 0; --i )
3705  {
3706  varstatus = SCIPvarGetStatus(var->parentvars[i]);
3707 
3708  assert(varstatus != SCIP_VARSTATUS_FIXED);
3709 
3710  /* issue event for not aggregated parent variable, because for these and its parents the var event was already
3711  * issued(, except the original one)
3712  *
3713  * @note that even before an aggregated parent variable, there might be variables, for which the vent was not
3714  * yet issued
3715  */
3716  if( varstatus == SCIP_VARSTATUS_AGGREGATED )
3717  continue;
3718 
3719  if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3720  {
3721  SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3722  }
3723  }
3724  break;
3725  case 2:
3726  /* process all parents of a aggregated variable */
3727  for( i = var->nparentvars - 1; i >= 0; --i )
3728  {
3729  varstatus = SCIPvarGetStatus(var->parentvars[i]);
3730 
3731  assert(varstatus != SCIP_VARSTATUS_FIXED);
3732 
3733  /* issue event on all parent variables except the original one */
3734  if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3735  {
3736  SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3737  }
3738  }
3739  break;
3740  default:
3741  SCIPerrorMessage("unknown variable fixation event origin\n");
3742  return SCIP_INVALIDDATA;
3743  }
3744 
3745  return SCIP_OKAY;
3746 }
3747 
3748 /** converts variable into fixed variable */
3750  SCIP_VAR* var, /**< problem variable */
3751  BMS_BLKMEM* blkmem, /**< block memory */
3752  SCIP_SET* set, /**< global SCIP settings */
3753  SCIP_STAT* stat, /**< problem statistics */
3754  SCIP_PROB* transprob, /**< tranformed problem data */
3755  SCIP_PROB* origprob, /**< original problem data */
3756  SCIP_PRIMAL* primal, /**< primal data */
3757  SCIP_TREE* tree, /**< branch and bound tree */
3758  SCIP_REOPT* reopt, /**< reoptimization data structure */
3759  SCIP_LP* lp, /**< current LP data */
3760  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3761  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
3762  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3763  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
3764  SCIP_Real fixedval, /**< value to fix variable at */
3765  SCIP_Bool* infeasible, /**< pointer to store whether the fixing is infeasible */
3766  SCIP_Bool* fixed /**< pointer to store whether the fixing was performed (variable was unfixed) */
3767  )
3768 {
3769  SCIP_Real obj;
3770  SCIP_Real childfixedval;
3771 
3772  assert(var != NULL);
3773  assert(var->scip == set->scip);
3774  assert(SCIPsetIsEQ(set, var->glbdom.lb, var->locdom.lb));
3775  assert(SCIPsetIsEQ(set, var->glbdom.ub, var->locdom.ub));
3776  assert(infeasible != NULL);
3777  assert(fixed != NULL);
3778 
3779  SCIPsetDebugMsg(set, "fix variable <%s>[%g,%g] to %g\n", var->name, var->glbdom.lb, var->glbdom.ub, fixedval);
3780 
3781  *infeasible = FALSE;
3782  *fixed = FALSE;
3783 
3785  {
3786  *infeasible = !SCIPsetIsFeasEQ(set, fixedval, var->locdom.lb);
3787  SCIPsetDebugMsg(set, " -> variable already fixed to %g (fixedval=%g): infeasible=%u\n", var->locdom.lb, fixedval, *infeasible);
3788  return SCIP_OKAY;
3789  }
3790  else if( (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPsetIsFeasIntegral(set, fixedval))
3791  || SCIPsetIsFeasLT(set, fixedval, var->locdom.lb)
3792  || SCIPsetIsFeasGT(set, fixedval, var->locdom.ub) )
3793  {
3794  SCIPsetDebugMsg(set, " -> fixing infeasible: locdom=[%g,%g], fixedval=%g\n", var->locdom.lb, var->locdom.ub, fixedval);
3795  *infeasible = TRUE;
3796  return SCIP_OKAY;
3797  }
3798 
3799  switch( SCIPvarGetStatus(var) )
3800  {
3802  if( var->data.original.transvar == NULL )
3803  {
3804  SCIPerrorMessage("cannot fix an untransformed original variable\n");
3805  return SCIP_INVALIDDATA;
3806  }
3807  SCIP_CALL( SCIPvarFix(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
3808  lp, branchcand, eventfilter, eventqueue, cliquetable, fixedval, infeasible, fixed) );
3809  break;
3810 
3811  case SCIP_VARSTATUS_LOOSE:
3812  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
3813 
3814  /* set the fixed variable's objective value to 0.0 */
3815  obj = var->obj;
3816  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
3817 
3818  /* since we change the variable type form loose to fixed, we have to adjust the number of loose
3819  * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
3820  * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
3821  * objective of this variable is set to zero
3822  */
3823  SCIPlpDecNLoosevars(lp);
3824 
3825  /* change variable's bounds to fixed value (thereby removing redundant implications and variable bounds) */
3826  holelistFree(&var->glbdom.holelist, blkmem);
3827  holelistFree(&var->locdom.holelist, blkmem);
3828  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, fixedval) );
3829  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, fixedval) );
3830 
3831  /* explicitly set variable's bounds, even if the fixed value is in epsilon range of the old bound */
3832  var->glbdom.lb = fixedval;
3833  var->glbdom.ub = fixedval;
3834  var->locdom.lb = fixedval;
3835  var->locdom.ub = fixedval;
3836 
3837  /* delete implications and variable bounds information */
3838  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
3839  assert(var->vlbs == NULL);
3840  assert(var->vubs == NULL);
3841  assert(var->implics == NULL);
3842 
3843  /* clear the history of the variable */
3844  SCIPhistoryReset(var->history);
3846 
3847  /* convert variable into fixed variable */
3848  var->varstatus = SCIP_VARSTATUS_FIXED; /*lint !e641*/
3849 
3850  /* inform problem about the variable's status change */
3851  if( var->probindex != -1 )
3852  {
3853  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
3854  }
3855 
3856  /* reset the objective value of the fixed variable, thus adjusting the problem's objective offset */
3857  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventfilter, eventqueue, obj) );
3858 
3859  /* issue VARFIXED event */
3860  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 0) );
3861 
3862  *fixed = TRUE;
3863  break;
3864 
3865  case SCIP_VARSTATUS_COLUMN:
3866  SCIPerrorMessage("cannot fix a column variable\n");
3867  return SCIP_INVALIDDATA;
3868 
3869  case SCIP_VARSTATUS_FIXED:
3870  SCIPerrorMessage("cannot fix a fixed variable again\n"); /*lint !e527*/
3871  SCIPABORT(); /* case is already handled in earlier if condition */
3872  return SCIP_INVALIDDATA; /*lint !e527*/
3873 
3875  /* fix aggregation variable y in x = a*y + c, instead of fixing x directly */
3876  assert(SCIPsetIsZero(set, var->obj));
3877  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
3878  if( SCIPsetIsInfinity(set, fixedval) || SCIPsetIsInfinity(set, -fixedval) )
3879  childfixedval = (var->data.aggregate.scalar < 0.0 ? -fixedval : fixedval);
3880  else
3881  childfixedval = (fixedval - var->data.aggregate.constant)/var->data.aggregate.scalar;
3882  SCIP_CALL( SCIPvarFix(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
3883  branchcand, eventfilter, eventqueue, cliquetable, childfixedval, infeasible, fixed) );
3884  break;
3885 
3887  SCIPerrorMessage("cannot fix a multiple aggregated variable\n");
3888  SCIPABORT();
3889  return SCIP_INVALIDDATA; /*lint !e527*/
3890 
3892  /* fix negation variable x in x' = offset - x, instead of fixing x' directly */
3893  assert(SCIPsetIsZero(set, var->obj));
3894  assert(var->negatedvar != NULL);
3896  assert(var->negatedvar->negatedvar == var);
3897  SCIP_CALL( SCIPvarFix(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
3898  branchcand, eventfilter, eventqueue, cliquetable, var->data.negate.constant - fixedval, infeasible, fixed) );
3899  break;
3900 
3901  default:
3902  SCIPerrorMessage("unknown variable status\n");
3903  return SCIP_INVALIDDATA;
3904  }
3905 
3906  return SCIP_OKAY;
3907 }
3908 
3909 /** transforms given variables, scalars and constant to the corresponding active variables, scalars and constant
3910  *
3911  * If the number of needed active variables is greater than the available slots in the variable array, nothing happens except
3912  * that the required size is stored in the corresponding variable; hence, if afterwards the required size is greater than the
3913  * available slots (varssize), nothing happens; otherwise, the active variable representation is stored in the arrays.
3914  *
3915  * The reason for this approach is that we cannot reallocate memory, since we do not know how the
3916  * memory has been allocated (e.g., by a C++ 'new' or SCIP functions).
3917  */
3919  SCIP_SET* set, /**< global SCIP settings */
3920  SCIP_VAR** vars, /**< variable array to get active variables */
3921  SCIP_Real* scalars, /**< scalars a_1, ..., a_n in linear sum a_1*x_1 + ... + a_n*x_n + c */
3922  int* nvars, /**< pointer to number of variables and values in vars and scalars array */
3923  int varssize, /**< available slots in vars and scalars array */
3924  SCIP_Real* constant, /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c */
3925  int* requiredsize, /**< pointer to store the required array size for the active variables */
3926  SCIP_Bool mergemultiples /**< should multiple occurrences of a var be replaced by a single coeff? */
3927  )
3928 {
3929  SCIP_VAR** activevars;
3930  SCIP_Real* activescalars;
3931  int nactivevars;
3932  SCIP_Real activeconstant;
3933  SCIP_Bool activeconstantinf;
3934  int activevarssize;
3935 
3936  SCIP_VAR* var;
3937  SCIP_Real scalar;
3938  int v;
3939  int k;
3940 
3941  SCIP_VAR** tmpvars;
3942  SCIP_VAR** multvars;
3943  SCIP_Real* tmpscalars;
3944  SCIP_Real* multscalars;
3945  int tmpvarssize;
3946  int ntmpvars;
3947  int nmultvars;
3948 
3949  SCIP_VAR* multvar;
3950  SCIP_Real multscalar;
3951  SCIP_Real multconstant;
3952  int pos;
3953 
3954  int noldtmpvars;
3955 
3956  SCIP_VAR** tmpvars2;
3957  SCIP_Real* tmpscalars2;
3958  int tmpvarssize2;
3959  int ntmpvars2;
3960 
3961  SCIP_Bool sortagain = FALSE;
3962 
3963  assert(set != NULL);
3964  assert(nvars != NULL);
3965  assert(scalars != NULL || *nvars == 0);
3966  assert(constant != NULL);
3967  assert(requiredsize != NULL);
3968  assert(*nvars <= varssize);
3969 
3970  *requiredsize = 0;
3971 
3972  if( *nvars == 0 )
3973  return SCIP_OKAY;
3974 
3975  assert(vars != NULL);
3976 
3977  /* handle the "easy" case of just one variable and avoid memory allocation if the variable is already active */
3978  if( *nvars == 1 && (vars[0]->varstatus == ((int) SCIP_VARSTATUS_COLUMN) || vars[0]->varstatus == ((int) SCIP_VARSTATUS_LOOSE)) )
3979  {
3980  *requiredsize = 1;
3981 
3982  return SCIP_OKAY;
3983  }
3984 
3985  nactivevars = 0;
3986  activeconstant = 0.0;
3987  activeconstantinf = FALSE;
3988  activevarssize = (*nvars) * 2;
3989  ntmpvars = *nvars;
3990  tmpvarssize = *nvars;
3991 
3992  tmpvarssize2 = 1;
3993 
3994  /* allocate temporary memory */
3995  SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpvars2, tmpvarssize2) );
3996  SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpscalars2, tmpvarssize2) );
3997  SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
3998  SCIP_CALL( SCIPsetAllocBufferArray(set, &activescalars, activevarssize) );
3999  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
4000  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpscalars, scalars, ntmpvars) );
4001 
4002  /* to avoid unnecessary expanding of variable arrays while disaggregating several variables multiple times combine same variables
4003  * first, first get all corresponding variables with status loose, column, multaggr or fixed
4004  */
4005  for( v = ntmpvars - 1; v >= 0; --v )
4006  {
4007  var = tmpvars[v];
4008  scalar = tmpscalars[v];
4009 
4010  assert(var != NULL);
4011  /* transforms given variable, scalar and constant to the corresponding active, fixed, or
4012  * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed
4013  * variable, "scalar" will be 0.0 and the value of the sum will be stored in "constant".
4014  */
4015  SCIP_CALL( SCIPvarGetProbvarSum(&var, set, &scalar, &activeconstant) );
4016  assert(var != NULL);
4017 
4018  assert(SCIPsetIsInfinity(set, activeconstant) == (activeconstant == SCIPsetInfinity(set))); /*lint !e777*/
4019  assert(SCIPsetIsInfinity(set, -activeconstant) == (activeconstant == -SCIPsetInfinity(set))); /*lint !e777*/
4020 
4021  activeconstantinf = SCIPsetIsInfinity(set, activeconstant) || SCIPsetIsInfinity(set, -activeconstant);
4022 
4023  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
4024  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
4027 
4028  tmpvars[v] = var;
4029  tmpscalars[v] = scalar;
4030  }
4031  noldtmpvars = ntmpvars;
4032 
4033  /* sort all variables to combine equal variables easily */
4034  SCIPsortPtrReal((void**)tmpvars, tmpscalars, SCIPvarComp, noldtmpvars);
4035  ntmpvars = 0;
4036  for( v = 1; v < noldtmpvars; ++v )
4037  {
4038  /* combine same variables */
4039  if( SCIPvarCompare(tmpvars[v], tmpvars[ntmpvars]) == 0 )
4040  {
4041  tmpscalars[ntmpvars] += tmpscalars[v];
4042  }
4043  else
4044  {
4045  ++ntmpvars;
4046  if( v > ntmpvars )
4047  {
4048  tmpscalars[ntmpvars] = tmpscalars[v];
4049  tmpvars[ntmpvars] = tmpvars[v];
4050  }
4051  }
4052  }
4053  ++ntmpvars;
4054 
4055 #ifdef SCIP_MORE_DEBUG
4056  for( v = 1; v < ntmpvars; ++v )
4057  assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
4058 #endif
4059 
4060  /* collect for each variable the representation in active variables */
4061  while( ntmpvars >= 1 )
4062  {
4063  --ntmpvars;
4064  ntmpvars2 = 0;
4065  var = tmpvars[ntmpvars];
4066  scalar = tmpscalars[ntmpvars];
4067 
4068  assert(var != NULL);
4069 
4070  /* TODO: maybe we should test here on SCIPsetIsZero() instead of 0.0 */
4071  if( scalar == 0.0 )
4072  continue;
4073 
4074  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
4075  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
4078 
4079  switch( SCIPvarGetStatus(var) )
4080  {
4081  case SCIP_VARSTATUS_LOOSE:
4082  case SCIP_VARSTATUS_COLUMN:
4083  /* x = a*y + c */
4084  if( nactivevars >= activevarssize )
4085  {
4086  activevarssize *= 2;
4087  SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
4088  SCIP_CALL( SCIPsetReallocBufferArray(set, &activescalars, activevarssize) );
4089  assert(nactivevars < activevarssize);
4090  }
4091  activevars[nactivevars] = var;
4092  activescalars[nactivevars] = scalar;
4093  nactivevars++;
4094  break;
4095 
4097  /* x = a_1*y_1 + ... + a_n*y_n + c */
4098  nmultvars = var->data.multaggr.nvars;
4099  multvars = var->data.multaggr.vars;
4100  multscalars = var->data.multaggr.scalars;
4101  sortagain = TRUE;
4102 
4103  if( nmultvars + ntmpvars > tmpvarssize )
4104  {
4105  while( nmultvars + ntmpvars > tmpvarssize )
4106  tmpvarssize *= 2;
4107  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
4108  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpscalars, tmpvarssize) );
4109  assert(nmultvars + ntmpvars <= tmpvarssize);
4110  }
4111 
4112  if( nmultvars > tmpvarssize2 )
4113  {
4114  while( nmultvars > tmpvarssize2 )
4115  tmpvarssize2 *= 2;
4116  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars2, tmpvarssize2) );
4117  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpscalars2, tmpvarssize2) );
4118  assert(nmultvars <= tmpvarssize2);
4119  }
4120 
4121  --nmultvars;
4122 
4123  for( ; nmultvars >= 0; --nmultvars )
4124  {
4125  multvar = multvars[nmultvars];
4126  multscalar = multscalars[nmultvars];
4127  multconstant = 0;
4128 
4129  assert(multvar != NULL);
4130  SCIP_CALL( SCIPvarGetProbvarSum(&multvar, set, &multscalar, &multconstant) );
4131  assert(multvar != NULL);
4132 
4133  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
4134  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
4137 
4138  if( !activeconstantinf )
4139  {
4140  assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
4141 
4142  if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) )
4143  {
4144  assert(scalar != 0.0);
4145  if( scalar * multconstant > 0.0 )
4146  {
4147  activeconstant = SCIPsetInfinity(set);
4148  activeconstantinf = TRUE;
4149  }
4150  else
4151  {
4152  activeconstant = -SCIPsetInfinity(set);
4153  activeconstantinf = TRUE;
4154  }
4155  }
4156  else
4157  activeconstant += scalar * multconstant;
4158  }
4159 #ifndef NDEBUG
4160  else
4161  {
4162  assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
4163  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4164  assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
4165  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4166  }
4167 #endif
4168 
4169  if( SCIPsortedvecFindPtr((void**)tmpvars, SCIPvarComp, multvar, ntmpvars, &pos) )
4170  {
4171  assert(SCIPvarCompare(tmpvars[pos], multvar) == 0);
4172  tmpscalars[pos] += scalar * multscalar;
4173  }
4174  else
4175  {
4176  tmpvars2[ntmpvars2] = multvar;
4177  tmpscalars2[ntmpvars2] = scalar * multscalar;
4178  ++(ntmpvars2);
4179  assert(ntmpvars2 <= tmpvarssize2);
4180  }
4181  }
4182 
4183  if( ntmpvars2 > 0 )
4184  {
4185  /* sort all variables to combine equal variables easily */
4186  SCIPsortPtrReal((void**)tmpvars2, tmpscalars2, SCIPvarComp, ntmpvars2);
4187  pos = 0;
4188  for( v = 1; v < ntmpvars2; ++v )
4189  {
4190  /* combine same variables */
4191  if( SCIPvarCompare(tmpvars2[v], tmpvars2[pos]) == 0 )
4192  {
4193  tmpscalars2[pos] += tmpscalars2[v];
4194  }
4195  else
4196  {
4197  ++pos;
4198  if( v > pos )
4199  {
4200  tmpscalars2[pos] = tmpscalars2[v];
4201  tmpvars2[pos] = tmpvars2[v];
4202  }
4203  }
4204  }
4205  ntmpvars2 = pos + 1;
4206 #ifdef SCIP_MORE_DEBUG
4207  for( v = 1; v < ntmpvars2; ++v )
4208  {
4209  assert(SCIPvarCompare(tmpvars2[v], tmpvars2[v-1]) > 0);
4210  }
4211  for( v = 1; v < ntmpvars; ++v )
4212  {
4213  assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
4214  }
4215 #endif
4216  v = ntmpvars - 1;
4217  k = ntmpvars2 - 1;
4218  pos = ntmpvars + ntmpvars2 - 1;
4219  ntmpvars += ntmpvars2;
4220 
4221  while( v >= 0 && k >= 0 )
4222  {
4223  assert(pos >= 0);
4224  assert(SCIPvarCompare(tmpvars[v], tmpvars2[k]) != 0);
4225  if( SCIPvarCompare(tmpvars[v], tmpvars2[k]) >= 0 )
4226  {
4227  tmpvars[pos] = tmpvars[v];
4228  tmpscalars[pos] = tmpscalars[v];
4229  --v;
4230  }
4231  else
4232  {
4233  tmpvars[pos] = tmpvars2[k];
4234  tmpscalars[pos] = tmpscalars2[k];
4235  --k;
4236  }
4237  --pos;
4238  assert(pos >= 0);
4239  }
4240  while( v >= 0 )
4241  {
4242  assert(pos >= 0);
4243  tmpvars[pos] = tmpvars[v];
4244  tmpscalars[pos] = tmpscalars[v];
4245  --v;
4246  --pos;
4247  }
4248  while( k >= 0 )
4249  {
4250  assert(pos >= 0);
4251  tmpvars[pos] = tmpvars2[k];
4252  tmpscalars[pos] = tmpscalars2[k];
4253  --k;
4254  --pos;
4255  }
4256  }
4257 #ifdef SCIP_MORE_DEBUG
4258  for( v = 1; v < ntmpvars; ++v )
4259  {
4260  assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
4261  }
4262 #endif
4263 
4264  if( !activeconstantinf )
4265  {
4266  assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
4267 
4268  multconstant = SCIPvarGetMultaggrConstant(var);
4269 
4270  if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) )
4271  {
4272  assert(scalar != 0.0);
4273  if( scalar * multconstant > 0.0 )
4274  {
4275  activeconstant = SCIPsetInfinity(set);
4276  activeconstantinf = TRUE;
4277  }
4278  else
4279  {
4280  activeconstant = -SCIPsetInfinity(set);
4281  activeconstantinf = TRUE;
4282  }
4283  }
4284  else
4285  activeconstant += scalar * multconstant;
4286  }
4287 #ifndef NDEBUG
4288  else
4289  {
4290  multconstant = SCIPvarGetMultaggrConstant(var);
4291  assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
4292  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4293  assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
4294  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4295  }
4296 #endif
4297  break;
4298 
4299  case SCIP_VARSTATUS_FIXED:
4303  default:
4304  /* case x = c, but actually we should not be here, since SCIPvarGetProbvarSum() returns a scalar of 0.0 for
4305  * fixed variables and is handled already
4306  */
4307  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED);
4308  assert(SCIPsetIsZero(set, var->glbdom.lb) && SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub));
4309  }
4310  }
4311 
4312  if( mergemultiples )
4313  {
4314  if( sortagain )
4315  {
4316  /* sort variable and scalar array by variable index */
4317  SCIPsortPtrReal((void**)activevars, activescalars, SCIPvarComp, nactivevars);
4318 
4319  /* eliminate duplicates and count required size */
4320  v = nactivevars - 1;
4321  while( v > 0 )
4322  {
4323  /* combine both variable since they are the same */
4324  if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
4325  {
4326  if( activescalars[v - 1] + activescalars[v] != 0.0 )
4327  {
4328  activescalars[v - 1] += activescalars[v];
4329  --nactivevars;
4330  activevars[v] = activevars[nactivevars];
4331  activescalars[v] = activescalars[nactivevars];
4332  }
4333  else
4334  {
4335  --nactivevars;
4336  activevars[v] = activevars[nactivevars];
4337  activescalars[v] = activescalars[nactivevars];
4338  --nactivevars;
4339  --v;
4340  activevars[v] = activevars[nactivevars];
4341  activescalars[v] = activescalars[nactivevars];
4342  }
4343  }
4344  --v;
4345  }
4346  }
4347  /* the variables were added in reverse order, we revert the order now;
4348  * this should not be necessary, but not doing this changes the behavior sometimes
4349  */
4350  else
4351  {
4352  SCIP_VAR* tmpvar;
4353  SCIP_Real tmpscalar;
4354 
4355  for( v = 0; v < nactivevars / 2; ++v )
4356  {
4357  tmpvar = activevars[v];
4358  tmpscalar = activescalars[v];
4359  activevars[v] = activevars[nactivevars - 1 - v];
4360  activescalars[v] = activescalars[nactivevars - 1 - v];
4361  activevars[nactivevars - 1 - v] = tmpvar;
4362  activescalars[nactivevars - 1 - v] = tmpscalar;
4363  }
4364  }
4365  }
4366  *requiredsize = nactivevars;
4367 
4368  if( varssize >= *requiredsize )
4369  {
4370  assert(vars != NULL);
4371 
4372  *nvars = *requiredsize;
4373 
4374  if( !SCIPsetIsInfinity(set, *constant) && !SCIPsetIsInfinity(set, -(*constant)) )
4375  {
4376  /* if the activeconstant is infinite, the constant pointer gets the same value, otherwise add the value */
4377  if( activeconstantinf )
4378  (*constant) = activeconstant;
4379  else
4380  (*constant) += activeconstant;
4381  }
4382 #ifndef NDEBUG
4383  else
4384  {
4385  assert(!SCIPsetIsInfinity(set, (*constant)) || !SCIPsetIsInfinity(set, -activeconstant));
4386  assert(!SCIPsetIsInfinity(set, -(*constant)) || !SCIPsetIsInfinity(set, activeconstant));
4387  }
4388 #endif
4389 
4390  /* copy active variable and scalar array to the given arrays */
4391  for( v = 0; v < *nvars; ++v )
4392  {
4393  vars[v] = activevars[v];
4394  scalars[v] = activescalars[v]; /*lint !e613*/
4395  }
4396  }
4397 
4398  assert(SCIPsetIsInfinity(set, *constant) == ((*constant) == SCIPsetInfinity(set))); /*lint !e777*/
4399  assert(SCIPsetIsInfinity(set, -(*constant)) == ((*constant) == -SCIPsetInfinity(set))); /*lint !e777*/
4400 
4401  SCIPsetFreeBufferArray(set, &tmpscalars);
4402  SCIPsetFreeBufferArray(set, &tmpvars);
4403  SCIPsetFreeBufferArray(set, &activescalars);
4404  SCIPsetFreeBufferArray(set, &activevars);
4405  SCIPsetFreeBufferArray(set, &tmpscalars2);
4406  SCIPsetFreeBufferArray(set, &tmpvars2);
4407 
4408  return SCIP_OKAY;
4409 }
4410 
4411 
4412 /** flattens aggregation graph of multi-aggregated variable in order to avoid exponential recursion later on */
4414  SCIP_VAR* var, /**< problem variable */
4415  BMS_BLKMEM* blkmem, /**< block memory */
4416  SCIP_SET* set, /**< global SCIP settings */
4417  SCIP_EVENTQUEUE* eventqueue /**< event queue */
4418  )
4419 {
4420  int nlocksup[NLOCKTYPES];
4421  int nlocksdown[NLOCKTYPES];
4422  SCIP_Real multconstant;
4423  int multvarssize;
4424  int nmultvars;
4425  int multrequiredsize;
4426  int i;
4427 
4428  assert( var != NULL );
4429  assert( SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR );
4430  assert(var->scip == set->scip);
4431 
4432  /* in order to update the locks on the active representation of the multi-aggregated variable, we remove all locks
4433  * on the current representation now and re-add the locks once the variable graph has been flattened, which
4434  * may lead to duplicate occurences of the same variable being merged
4435  *
4436  * Here is an example. Assume we have the multi-aggregation z = x + y.
4437  * z occures with positive coefficient in a <= constraint c1, so it has an uplock from there.
4438  * When the multi-aggregation is performed, all locks are added to the active representation,
4439  * so x and y both get an uplock from c1. However, z was not yet replaced by x + y in c1.
4440  * Next, a negation y = 1 - x is identified. Again, locks are moved, so that the uplock of y originating
4441  * from c1 is added to x as a downlock. Thus, x has both an up- and downlock from c1.
4442  * The multi-aggregation changes to z = x + 1 - x, which corresponds to the locks.
4443  * However, before z is replaced by that sum, SCIPvarFlattenAggregationGraph() is called
4444  * which changes z = x + y = x + 1 - x = 1, since it merges multiple occurences of the same variable.
4445  * The up- and downlock of x, however, is not removed when replacing z in c1 by its active representation,
4446  * because it is just 1 now. Therefore, we need to update locks when flattening the aggregation graph.
4447  * For this, the multi-aggregated variable knows its locks in addition to adding them to the active
4448  * representation, which corresponds to the locks from constraints where the variable was not replaced yet.
4449  * By removing the locks here, based on the old representation and adding them again after flattening,
4450  * we ensure that the locks are correct afterwards if coefficients were merged.
4451  */
4452  for( i = 0; i < NLOCKTYPES; ++i )
4453  {
4454  nlocksup[i] = var->nlocksup[i];
4455  nlocksdown[i] = var->nlocksdown[i];
4456 
4457  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, -nlocksdown[i], -nlocksup[i]) );
4458  }
4459 
4460  multconstant = var->data.multaggr.constant;
4461  nmultvars = var->data.multaggr.nvars;
4462  multvarssize = var->data.multaggr.varssize;
4463 
4464  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize, TRUE) );
4465 
4466  if( multrequiredsize > multvarssize )
4467  {
4468  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.vars), multvarssize, multrequiredsize) );
4469  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.scalars), multvarssize, multrequiredsize) );
4470  multvarssize = multrequiredsize;
4471  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize, TRUE) );
4472  assert( multrequiredsize <= multvarssize );
4473  }
4474  /**@note After the flattening the multi aggregation might resolve to be in fact an aggregation (or even a fixing?).
4475  * This issue is not resolved right now, since var->data.multaggr.nvars < 2 should not cause troubles. However, one
4476  * may loose performance hereby, since aggregated variables are easier to handle.
4477  *
4478  * Note, that there are two cases where SCIPvarFlattenAggregationGraph() is called: The easier one is that it is
4479  * called while installing the multi-aggregation. in principle, the described issue could be handled straightforward
4480  * in this case by aggregating or fixing the variable instead. The more complicated case is the one, when the
4481  * multi-aggregation is used, e.g., in linear presolving (and the variable is already declared to be multi-aggregated).
4482  *
4483  * By now, it is not allowed to fix or aggregate multi-aggregated variables which would be necessary in this case.
4484  *
4485  * The same issue appears in the SCIPvarGetProbvar...() methods.
4486  */
4487 
4488  var->data.multaggr.constant = multconstant;
4489  var->data.multaggr.nvars = nmultvars;
4490  var->data.multaggr.varssize = multvarssize;
4491 
4492  for( i = 0; i < NLOCKTYPES; ++i )
4493  {
4494  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
4495  }
4496 
4497  return SCIP_OKAY;
4498 }
4499 
4500 /** merge two variable histories together; a typical use case is that \p othervar is an image of the target variable
4501  * in a SCIP copy. Method should be applied with care, especially because no internal checks are performed whether
4502  * the history merge is reasonable
4503  *
4504  * @note Do not use this method if the two variables originate from two SCIP's with different objective functions, since
4505  * this corrupts the variable pseudo costs
4506  * @note Apply with care; no internal checks are performed if the two variables should be merged
4507  */
4509  SCIP_VAR* targetvar, /**< the variable that should contain both histories afterwards */
4510  SCIP_VAR* othervar, /**< the variable whose history is to be merged with that of the target variable */
4511  SCIP_STAT* stat /**< problem statistics */
4512  )
4513 {
4514  /* merge only the history of the current run into the target history */
4515  SCIPhistoryUnite(targetvar->history, othervar->historycrun, FALSE);
4516 
4517  /* apply the changes also to the global history */
4518  SCIPhistoryUnite(stat->glbhistory, othervar->historycrun, FALSE);
4519 }
4520 
4521 /** sets the history of a variable; this method is typically used within reoptimization to keep and update the variable
4522  * history over several iterations
4523  */
4524 void SCIPvarSetHistory(
4525  SCIP_VAR* var, /**< variable */
4526  SCIP_HISTORY* history, /**< the history which is to set */
4527  SCIP_STAT* stat /**< problem statistics */
4528  )
4529 {
4530  /* merge only the history of the current run into the target history */
4531  SCIPhistoryUnite(var->history, history, FALSE);
4532 
4533  /* apply the changes also to the global history */
4534  SCIPhistoryUnite(stat->glbhistory, history, FALSE);
4535 }
4536 
4537 /** tightens the bounds of both variables in aggregation x = a*y + c */
4538 static
4540  SCIP_VAR* var, /**< problem variable */
4541  BMS_BLKMEM* blkmem, /**< block memory */
4542  SCIP_SET* set, /**< global SCIP settings */
4543  SCIP_STAT* stat, /**< problem statistics */
4544  SCIP_PROB* transprob, /**< tranformed problem data */
4545  SCIP_PROB* origprob, /**< original problem data */
4546  SCIP_PRIMAL* primal, /**< primal data */
4547  SCIP_TREE* tree, /**< branch and bound tree */
4548  SCIP_REOPT* reopt, /**< reoptimization data structure */
4549  SCIP_LP* lp, /**< current LP data */
4550  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4551  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4552  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4553  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4554  SCIP_VAR* aggvar, /**< variable y in aggregation x = a*y + c */
4555  SCIP_Real scalar, /**< multiplier a in aggregation x = a*y + c */
4556  SCIP_Real constant, /**< constant shift c in aggregation x = a*y + c */
4557  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4558  SCIP_Bool* fixed /**< pointer to store whether the variables were fixed */
4559  )
4560 {
4561  SCIP_Real varlb;
4562  SCIP_Real varub;
4563  SCIP_Real aggvarlb;
4564  SCIP_Real aggvarub;
4565  SCIP_Bool aggvarbdschanged;
4566 
4567  assert(var != NULL);
4568  assert(var->scip == set->scip);
4569  assert(aggvar != NULL);
4570  assert(!SCIPsetIsZero(set, scalar));
4571  assert(infeasible != NULL);
4572  assert(fixed != NULL);
4573 
4574  *infeasible = FALSE;
4575  *fixed = FALSE;
4576 
4577  SCIPsetDebugMsg(set, "updating bounds of variables in aggregation <%s> == %g*<%s> %+g\n", var->name, scalar, aggvar->name, constant);
4578  SCIPsetDebugMsg(set, " old bounds: <%s> [%g,%g] <%s> [%g,%g]\n",
4579  var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
4580 
4581  /* loop as long additional changes may be found */
4582  do
4583  {
4584  aggvarbdschanged = FALSE;
4585 
4586  /* update the bounds of the aggregated variable x in x = a*y + c */
4587  if( scalar > 0.0 )
4588  {
4589  if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
4590  varlb = -SCIPsetInfinity(set);
4591  else
4592  varlb = aggvar->glbdom.lb * scalar + constant;
4593  if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
4594  varub = SCIPsetInfinity(set);
4595  else
4596  varub = aggvar->glbdom.ub * scalar + constant;
4597  }
4598  else
4599  {
4600  if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
4601  varub = SCIPsetInfinity(set);
4602  else
4603  varub = aggvar->glbdom.lb * scalar + constant;
4604  if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
4605  varlb = -SCIPsetInfinity(set);
4606  else
4607  varlb = aggvar->glbdom.ub * scalar + constant;
4608  }
4609  varlb = MAX(varlb, var->glbdom.lb);
4610  varub = MIN(varub, var->glbdom.ub);
4611  SCIPvarAdjustLb(var, set, &varlb);
4612  SCIPvarAdjustUb(var, set, &varub);
4613 
4614  /* check the new bounds */
4615  if( SCIPsetIsGT(set, varlb, varub) )
4616  {
4617  /* the aggregation is infeasible */
4618  *infeasible = TRUE;
4619  return SCIP_OKAY;
4620  }
4621  else if( SCIPsetIsEQ(set, varlb, varub) )
4622  {
4623  /* the aggregated variable is fixed -> fix both variables */
4624  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4625  eventfilter, eventqueue, cliquetable, varlb, infeasible, fixed) );
4626  if( !(*infeasible) )
4627  {
4628  SCIP_Bool aggfixed;
4629 
4630  SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4631  eventfilter, eventqueue, cliquetable, (varlb-constant)/scalar, infeasible, &aggfixed) );
4632  assert(*fixed == aggfixed);
4633  }
4634  return SCIP_OKAY;
4635  }
4636  else
4637  {
4638  if( SCIPsetIsGT(set, varlb, var->glbdom.lb) )
4639  {
4640  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, varlb) );
4641  }
4642  if( SCIPsetIsLT(set, varub, var->glbdom.ub) )
4643  {
4644  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, varub) );
4645  }
4646 
4647  /* update the hole list of the aggregation variable */
4648  /**@todo update hole list of aggregation variable */
4649  }
4650 
4651  /* update the bounds of the aggregation variable y in x = a*y + c -> y = (x-c)/a */
4652  if( scalar > 0.0 )
4653  {
4654  if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
4655  aggvarlb = -SCIPsetInfinity(set);
4656  else
4657  aggvarlb = (var->glbdom.lb - constant) / scalar;
4658  if( SCIPsetIsInfinity(set, var->glbdom.ub) )
4659  aggvarub = SCIPsetInfinity(set);
4660  else
4661  aggvarub = (var->glbdom.ub - constant) / scalar;
4662  }
4663  else
4664  {
4665  if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
4666  aggvarub = SCIPsetInfinity(set);
4667  else
4668  aggvarub = (var->glbdom.lb - constant) / scalar;
4669  if( SCIPsetIsInfinity(set, var->glbdom.ub) )
4670  aggvarlb = -SCIPsetInfinity(set);
4671  else
4672  aggvarlb = (var->glbdom.ub - constant) / scalar;
4673  }
4674  aggvarlb = MAX(aggvarlb, aggvar->glbdom.lb);
4675  aggvarub = MIN(aggvarub, aggvar->glbdom.ub);
4676  SCIPvarAdjustLb(aggvar, set, &aggvarlb);
4677  SCIPvarAdjustUb(aggvar, set, &aggvarub);
4678 
4679  /* check the new bounds */
4680  if( SCIPsetIsGT(set, aggvarlb, aggvarub) )
4681  {
4682  /* the aggregation is infeasible */
4683  *infeasible = TRUE;
4684  return SCIP_OKAY;
4685  }
4686  else if( SCIPsetIsEQ(set, aggvarlb, aggvarub) )
4687  {
4688  /* the aggregation variable is fixed -> fix both variables */
4689  SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4690  eventfilter, eventqueue, cliquetable, aggvarlb, infeasible, fixed) );
4691  if( !(*infeasible) )
4692  {
4693  SCIP_Bool varfixed;
4694 
4695  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4696  eventfilter, eventqueue, cliquetable, aggvarlb * scalar + constant, infeasible, &varfixed) );
4697  assert(*fixed == varfixed);
4698  }
4699  return SCIP_OKAY;
4700  }
4701  else
4702  {
4703  SCIP_Real oldbd;
4704  if( SCIPsetIsGT(set, aggvarlb, aggvar->glbdom.lb) )
4705  {
4706  oldbd = aggvar->glbdom.lb;
4707  SCIP_CALL( SCIPvarChgLbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, aggvarlb) );
4708  aggvarbdschanged = !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.lb);
4709  }
4710  if( SCIPsetIsLT(set, aggvarub, aggvar->glbdom.ub) )
4711  {
4712  oldbd = aggvar->glbdom.ub;
4713  SCIP_CALL( SCIPvarChgUbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, aggvarub) );
4714  aggvarbdschanged = aggvarbdschanged || !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.ub);
4715  }
4716 
4717  /* update the hole list of the aggregation variable */
4718  /**@todo update hole list of aggregation variable */
4719  }
4720  }
4721  while( aggvarbdschanged );
4722 
4723  SCIPsetDebugMsg(set, " new bounds: <%s> [%g,%g] <%s> [%g,%g]\n",
4724  var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
4725 
4726  return SCIP_OKAY;
4727 }
4728 
4729 /** converts loose variable into aggregated variable */
4731  SCIP_VAR* var, /**< loose problem variable */
4732  BMS_BLKMEM* blkmem, /**< block memory */
4733  SCIP_SET* set, /**< global SCIP settings */
4734  SCIP_STAT* stat, /**< problem statistics */
4735  SCIP_PROB* transprob, /**< tranformed problem data */
4736  SCIP_PROB* origprob, /**< original problem data */
4737  SCIP_PRIMAL* primal, /**< primal data */
4738  SCIP_TREE* tree, /**< branch and bound tree */
4739  SCIP_REOPT* reopt, /**< reoptimization data structure */
4740  SCIP_LP* lp, /**< current LP data */
4741  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4742  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4743  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4744  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4745  SCIP_VAR* aggvar, /**< loose variable y in aggregation x = a*y + c */
4746  SCIP_Real scalar, /**< multiplier a in aggregation x = a*y + c */
4747  SCIP_Real constant, /**< constant shift c in aggregation x = a*y + c */
4748  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4749  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
4750  )
4751 {
4752  SCIP_VAR** vars;
4753  SCIP_Real* coefs;
4754  SCIP_Real* constants;
4755  SCIP_Real obj;
4756  SCIP_Real branchfactor;
4757  SCIP_Bool fixed;
4758  int branchpriority;
4759  int nlocksdown[NLOCKTYPES];
4760  int nlocksup[NLOCKTYPES];
4761  int nvbds;
4762  int i;
4763  int j;
4764 
4765  assert(var != NULL);
4766  assert(aggvar != NULL);
4767  assert(var->scip == set->scip);
4768  assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
4769  assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
4770  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
4771  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
4772  assert(infeasible != NULL);
4773  assert(aggregated != NULL);
4774 
4775  *infeasible = FALSE;
4776  *aggregated = FALSE;
4777 
4778  /* get active problem variable of aggregation variable */
4779  SCIP_CALL( SCIPvarGetProbvarSum(&aggvar, set, &scalar, &constant) );
4780 
4781  /* aggregation is a fixing, if the scalar is zero */
4782  if( SCIPsetIsZero(set, scalar) )
4783  {
4784  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventfilter,
4785  eventqueue, cliquetable, constant, infeasible, aggregated) );
4786  goto TERMINATE;
4787  }
4788 
4789  /* don't perform the aggregation if the aggregation variable is multi-aggregated itself */
4790  if( SCIPvarGetStatus(aggvar) == SCIP_VARSTATUS_MULTAGGR )
4791  return SCIP_OKAY;
4792 
4793  /**@todo currently we don't perform the aggregation if the aggregation variable has a non-empty hole list; this
4794  * should be changed in the future
4795  */
4796  if( SCIPvarGetHolelistGlobal(var) != NULL )
4797  return SCIP_OKAY;
4798 
4799  /* if the variable is not allowed to be aggregated */
4800  if( SCIPvarDoNotAggr(var) )
4801  {
4802  SCIPsetDebugMsg(set, "variable is not allowed to be aggregated.\n");
4803  return SCIP_OKAY;
4804  }
4805 
4806  assert(aggvar->glbdom.lb == aggvar->locdom.lb); /*lint !e777*/
4807  assert(aggvar->glbdom.ub == aggvar->locdom.ub); /*lint !e777*/
4808  assert(SCIPvarGetStatus(aggvar) == SCIP_VARSTATUS_LOOSE);
4809 
4810  SCIPsetDebugMsg(set, "aggregate variable <%s>[%g,%g] == %g*<%s>[%g,%g] %+g\n", var->name, var->glbdom.lb, var->glbdom.ub,
4811  scalar, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub, constant);
4812 
4813  /* if variable and aggregation variable are equal, the variable can be fixed: x == a*x + c => x == c/(1-a) */
4814  if( var == aggvar )
4815  {
4816  if( SCIPsetIsEQ(set, scalar, 1.0) )
4817  *infeasible = !SCIPsetIsZero(set, constant);
4818  else
4819  {
4820  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4821  eventfilter, eventqueue, cliquetable, constant/(1.0-scalar), infeasible, aggregated) );
4822  }
4823  goto TERMINATE;
4824  }
4825 
4826  /* tighten the bounds of aggregated and aggregation variable */
4827  SCIP_CALL( varUpdateAggregationBounds(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
4828  branchcand, eventfilter, eventqueue, cliquetable, aggvar, scalar, constant, infeasible, &fixed) );
4829  if( *infeasible || fixed )
4830  {
4831  *aggregated = fixed;
4832  goto TERMINATE;
4833  }
4834 
4835  /* delete implications and variable bounds of the aggregated variable from other variables, but keep them in the
4836  * aggregated variable
4837  */
4838  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, FALSE) );
4839 
4840  /* set the aggregated variable's objective value to 0.0 */
4841  obj = var->obj;
4842  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
4843 
4844  /* unlock all locks */
4845  for( i = 0; i < NLOCKTYPES; i++ )
4846  {
4847  nlocksdown[i] = var->nlocksdown[i];
4848  nlocksup[i] = var->nlocksup[i];
4849 
4850  var->nlocksdown[i] = 0;
4851  var->nlocksup[i] = 0;
4852  }
4853 
4854  /* check, if variable should be used as NEGATED variable of the aggregation variable */
4855  if( SCIPvarIsBinary(var) && SCIPvarIsBinary(aggvar)
4856  && var->negatedvar == NULL && aggvar->negatedvar == NULL
4857  && SCIPsetIsEQ(set, scalar, -1.0) && SCIPsetIsEQ(set, constant, 1.0) )
4858  {
4859  /* link both variables as negation pair */
4860  var->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
4861  var->data.negate.constant = 1.0;
4862  var->negatedvar = aggvar;
4863  aggvar->negatedvar = var;
4864 
4865  /* copy donot(mult)aggr status */
4866  aggvar->donotaggr |= var->donotaggr;
4867  aggvar->donotmultaggr |= var->donotmultaggr;
4868 
4869  /* mark both variables to be non-deletable */
4871  SCIPvarMarkNotDeletable(aggvar);
4872  }
4873  else
4874  {
4875  /* convert variable into aggregated variable */
4876  var->varstatus = SCIP_VARSTATUS_AGGREGATED; /*lint !e641*/
4877  var->data.aggregate.var = aggvar;
4878  var->data.aggregate.scalar = scalar;
4879  var->data.aggregate.constant = constant;
4880 
4881  /* copy donot(mult)aggr status */
4882  aggvar->donotaggr |= var->donotaggr;
4883  aggvar->donotmultaggr |= var->donotmultaggr;
4884 
4885  /* mark both variables to be non-deletable */
4887  SCIPvarMarkNotDeletable(aggvar);
4888  }
4889 
4890  /* make aggregated variable a parent of the aggregation variable */
4891  SCIP_CALL( varAddParent(aggvar, blkmem, set, var) );
4892 
4893  /* relock the variable, thus increasing the locks of the aggregation variable */
4894  for( i = 0; i < NLOCKTYPES; i++ )
4895  {
4896  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
4897  }
4898 
4899  /* move the variable bounds to the aggregation variable:
4900  * - add all variable bounds again to the variable, thus adding it to the aggregation variable
4901  * - free the variable bounds data structures
4902  */
4903  if( var->vlbs != NULL )
4904  {
4905  nvbds = SCIPvboundsGetNVbds(var->vlbs);
4906  vars = SCIPvboundsGetVars(var->vlbs);
4907  coefs = SCIPvboundsGetCoefs(var->vlbs);
4908  constants = SCIPvboundsGetConstants(var->vlbs);
4909  for( i = 0; i < nvbds && !(*infeasible); ++i )
4910  {
4911  SCIP_CALL( SCIPvarAddVlb(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
4912  eventqueue, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
4913  }
4914  }
4915  if( var->vubs != NULL )
4916  {
4917  nvbds = SCIPvboundsGetNVbds(var->vubs);
4918  vars = SCIPvboundsGetVars(var->vubs);
4919  coefs = SCIPvboundsGetCoefs(var->vubs);
4920  constants = SCIPvboundsGetConstants(var->vubs);
4921  for( i = 0; i < nvbds && !(*infeasible); ++i )
4922  {
4923  SCIP_CALL( SCIPvarAddVub(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
4924  eventqueue, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
4925  }
4926  }
4927  SCIPvboundsFree(&var->vlbs, blkmem);
4928  SCIPvboundsFree(&var->vubs, blkmem);
4929 
4930  /* move the implications to the aggregation variable:
4931  * - add all implications again to the variable, thus adding it to the aggregation variable
4932  * - free the implications data structures
4933  */
4934  if( var->implics != NULL && SCIPvarGetType(aggvar) == SCIP_VARTYPE_BINARY )
4935  {
4936  assert(SCIPvarIsBinary(var));
4937  for( i = 0; i < 2; ++i )
4938  {
4939  SCIP_VAR** implvars;
4940  SCIP_BOUNDTYPE* impltypes;
4941  SCIP_Real* implbounds;
4942  int nimpls;
4943 
4944  nimpls = SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i);
4945  implvars = SCIPimplicsGetVars(var->implics, (SCIP_Bool)i);
4946  impltypes = SCIPimplicsGetTypes(var->implics, (SCIP_Bool)i);
4947  implbounds = SCIPimplicsGetBounds(var->implics, (SCIP_Bool)i);
4948 
4949  for( j = 0; j < nimpls && !(*infeasible); ++j )
4950  {
4951  /* @todo can't we omit transitive closure, because it should already have been done when adding the
4952  * implication to the aggregated variable?
4953  */
4954  SCIP_CALL( SCIPvarAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
4955  branchcand, eventqueue, (SCIP_Bool)i, implvars[j], impltypes[j], implbounds[j], FALSE, infeasible,
4956  NULL) );
4957  assert(nimpls == SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i));
4958  }
4959  }
4960  }
4961  SCIPimplicsFree(&var->implics, blkmem);
4962 
4963  /* add the history entries to the aggregation variable and clear the history of the aggregated variable */
4964  SCIPhistoryUnite(aggvar->history, var->history, scalar < 0.0);
4965  SCIPhistoryUnite(aggvar->historycrun, var->historycrun, scalar < 0.0);
4966  SCIPhistoryReset(var->history);
4968 
4969  /* update flags of aggregation variable */
4970  aggvar->removable &= var->removable;
4971 
4972  /* update branching factors and priorities of both variables to be the maximum of both variables */
4973  branchfactor = MAX(aggvar->branchfactor, var->branchfactor);
4974  branchpriority = MAX(aggvar->branchpriority, var->branchpriority);
4975  SCIP_CALL( SCIPvarChgBranchFactor(aggvar, set, branchfactor) );
4976  SCIP_CALL( SCIPvarChgBranchPriority(aggvar, branchpriority) );
4977  SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
4978  SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
4979 
4980  /* update branching direction of both variables to agree to a single direction */
4981  if( scalar >= 0.0 )
4982  {
4984  {
4986  }
4987  else if( (SCIP_BRANCHDIR)aggvar->branchdirection == SCIP_BRANCHDIR_AUTO )
4988  {
4990  }
4991  else if( var->branchdirection != aggvar->branchdirection )
4992  {
4994  }
4995  }
4996  else
4997  {
4999  {
5001  }
5002  else if( (SCIP_BRANCHDIR)aggvar->branchdirection == SCIP_BRANCHDIR_AUTO )
5003  {
5005  }
5006  else if( var->branchdirection != aggvar->branchdirection )
5007  {
5009  }
5010  }
5011 
5012  if( var->probindex != -1 )
5013  {
5014  /* inform problem about the variable's status change */
5015  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
5016  }
5017 
5018  /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
5019  * variable and the problem's objective offset
5020  */
5021  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventfilter, eventqueue, obj) );
5022 
5023  /* issue VARFIXED event */
5024  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 1) );
5025 
5026  *aggregated = TRUE;
5027 
5028 TERMINATE:
5029  /* check aggregation on debugging solution */
5030  if( *infeasible || *aggregated )
5031  SCIP_CALL( SCIPdebugCheckAggregation(set, var, &aggvar, &scalar, constant, 1) ); /*lint !e506 !e774*/
5032 
5033  return SCIP_OKAY;
5034 }
5035 
5036 /** Tries to aggregate an equality a*x + b*y == c consisting of two (implicit) integral active problem variables x and
5037  * y. An integer aggregation (i.e. integral coefficients a' and b', such that a'*x + b'*y == c') is searched.
5038  *
5039  * This can lead to the detection of infeasibility (e.g. if c' is fractional), or to a rejection of the aggregation
5040  * (denoted by aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
5041  */
5042 static
5044  SCIP_SET* set, /**< global SCIP settings */
5045  BMS_BLKMEM* blkmem, /**< block memory */
5046  SCIP_STAT* stat, /**< problem statistics */
5047  SCIP_PROB* transprob, /**< tranformed problem data */
5048  SCIP_PROB* origprob, /**< original problem data */
5049  SCIP_PRIMAL* primal, /**< primal data */
5050  SCIP_TREE* tree, /**< branch and bound tree */
5051  SCIP_REOPT* reopt, /**< reoptimization data structure */
5052  SCIP_LP* lp, /**< current LP data */
5053  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5054  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5055  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
5056  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5057  SCIP_VAR* varx, /**< integral variable x in equality a*x + b*y == c */
5058  SCIP_VAR* vary, /**< integral variable y in equality a*x + b*y == c */
5059  SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
5060  SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
5061  SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
5062  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
5063  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
5064  )
5065 {
5066  SCIP_VAR* aggvar;
5067  char aggvarname[SCIP_MAXSTRLEN];
5068  SCIP_Longint scalarxn = 0;
5069  SCIP_Longint scalarxd = 0;
5070  SCIP_Longint scalaryn = 0;
5071  SCIP_Longint scalaryd = 0;
5072  SCIP_Longint a;
5073  SCIP_Longint b;
5074  SCIP_Longint c;
5075  SCIP_Longint scm;
5076  SCIP_Longint gcd;
5077  SCIP_Longint currentclass;
5078  SCIP_Longint classstep;
5079  SCIP_Longint xsol;
5080  SCIP_Longint ysol;
5081  SCIP_Bool success;
5082  SCIP_VARTYPE vartype;
5083 
5084 #define MAXDNOM 1000000LL
5085 
5086  assert(set != NULL);
5087  assert(blkmem != NULL);
5088  assert(stat != NULL);
5089  assert(transprob != NULL);
5090  assert(origprob != NULL);
5091  assert(tree != NULL);
5092  assert(lp != NULL);
5093  assert(cliquetable != NULL);
5094  assert(branchcand != NULL);
5095  assert(eventqueue != NULL);
5096  assert(varx != NULL);
5097  assert(vary != NULL);
5098  assert(varx != vary);
5099  assert(infeasible != NULL);
5100  assert(aggregated != NULL);
5101  assert(SCIPsetGetStage(set) == SCIP_STAGE_PRESOLVING);
5102  assert(SCIPvarGetStatus(varx) == SCIP_VARSTATUS_LOOSE);
5104  assert(SCIPvarGetStatus(vary) == SCIP_VARSTATUS_LOOSE);
5106  assert(!SCIPsetIsZero(set, scalarx));
5107  assert(!SCIPsetIsZero(set, scalary));
5108 
5109  *infeasible = FALSE;
5110  *aggregated = FALSE;
5111 
5112  /* if the variable is not allowed to be aggregated */
5113  if( SCIPvarDoNotAggr(varx) )
5114  {
5115  SCIPsetDebugMsg(set, "variable is not allowed to be aggregated.\n");
5116  return SCIP_OKAY;
5117  }
5118 
5119  /* get rational representation of coefficients */
5120  success = SCIPrealToRational(scalarx, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalarxn, &scalarxd);
5121  if( success )
5122  success = SCIPrealToRational(scalary, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalaryn, &scalaryd);
5123  if( !success )
5124  return SCIP_OKAY;
5125  assert(scalarxd >= 1);
5126  assert(scalaryd >= 1);
5127 
5128  /* multiply equality with smallest common denominator */
5129  scm = SCIPcalcSmaComMul(scalarxd, scalaryd);
5130  a = (scm/scalarxd)*scalarxn;
5131  b = (scm/scalaryd)*scalaryn;
5132  rhs *= scm;
5133 
5134  /* divide equality by the greatest common divisor of a and b */
5135  gcd = SCIPcalcGreComDiv(ABS(a), ABS(b));
5136  a /= gcd;
5137  b /= gcd;
5138  rhs /= gcd;
5139  assert(a != 0);
5140  assert(b != 0);
5141 
5142  /* check, if right hand side is integral */
5143  if( !SCIPsetIsFeasIntegral(set, rhs) )
5144  {
5145  *infeasible = TRUE;
5146  return SCIP_OKAY;
5147  }
5148  c = (SCIP_Longint)(SCIPsetFeasFloor(set, rhs));
5149 
5150  /* check that the scalar and constant in the aggregation are not too large to avoid numerical problems */
5151  if( REALABS((SCIP_Real)(c/a)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) /*lint !e653*/
5152  || REALABS((SCIP_Real)(b)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) /*lint !e653*/
5153  || REALABS((SCIP_Real)(a)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
5154  {
5155  return SCIP_OKAY;
5156  }
5157 
5158  /* check, if we are in an easy case with either |a| = 1 or |b| = 1 */
5159  if( (a == 1 || a == -1) && SCIPvarGetType(vary) == SCIP_VARTYPE_INTEGER )
5160  {
5161  /* aggregate x = - b/a*y + c/a */
5162  /*lint --e{653}*/
5163  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5164  branchcand, eventfilter, eventqueue, vary, (SCIP_Real)(-b/a), (SCIP_Real)(c/a), infeasible, aggregated) );
5165  assert(*aggregated);
5166  return SCIP_OKAY;
5167  }
5168  if( (b == 1 || b == -1) && SCIPvarGetType(varx) == SCIP_VARTYPE_INTEGER )
5169  {
5170  /* aggregate y = - a/b*x + c/b */
5171  /*lint --e{653}*/
5172  SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5173  branchcand, eventfilter, eventqueue, varx, (SCIP_Real)(-a/b), (SCIP_Real)(c/b), infeasible, aggregated) );
5174  assert(*aggregated);
5175  return SCIP_OKAY;
5176  }
5177 
5178  /* Both variables are integers, their coefficients are not multiples of each other, and they don't have any
5179  * common divisor. Let (x',y') be a solution of the equality
5180  * a*x + b*y == c -> a*x == c - b*y
5181  * Then x = -b*z + x', y = a*z + y' with z integral gives all solutions to the equality.
5182  */
5183 
5184  /* find initial solution (x',y'):
5185  * - find y' such that c - b*y' is a multiple of a
5186  * - start in equivalence class c%a
5187  * - step through classes, where each step increases class number by (-b)%a, until class 0 is visited
5188  * - if equivalence class 0 is visited, we are done: y' equals the number of steps taken
5189  * - 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
5190  * - calculate x' with x' = (c - b*y')/a (which must be integral)
5191  *
5192  * Algorithm works for a > 0 only.
5193  */
5194  if( a < 0 )
5195  {
5196  a = -a;
5197  b = -b;
5198  c = -c;
5199  }
5200  assert(a > 0);
5201 
5202  /* search upwards from ysol = 0 */
5203  ysol = 0;
5204  currentclass = c % a;
5205  if( currentclass < 0 )
5206  currentclass += a;
5207  assert(0 <= currentclass && currentclass < a);
5208 
5209  classstep = (-b) % a;
5210 
5211  if( classstep < 0 )
5212  classstep += a;
5213  assert(0 <= classstep && classstep < a);
5214 
5215  while( currentclass != 0 )
5216  {
5217  assert(0 <= currentclass && currentclass < a);
5218  currentclass += classstep;
5219  if( currentclass >= a )
5220  currentclass -= a;
5221  ysol++;
5222  }
5223  assert(ysol < a);
5224  assert(((c - b*ysol) % a) == 0);
5225 
5226  xsol = (c - b*ysol)/a;
5227 
5228  /* determine variable type for new artificial variable:
5229  *
5230  * if both variables are implicit integer the new variable can be implicit too, because the integer implication on
5231  * these both variables should be enforced by some other variables, otherwise the new variable needs to be of
5232  * integral type
5233  */
5236 
5237  /* feasible solutions are (x,y) = (x',y') + z*(-b,a)
5238  * - create new integer variable z with infinite bounds
5239  * - aggregate variable x = -b*z + x'
5240  * - aggregate variable y = a*z + y'
5241  * - the bounds of z are calculated automatically during aggregation
5242  */
5243  (void) SCIPsnprintf(aggvarname, SCIP_MAXSTRLEN, "agg%d", stat->nvaridx);
5244  SCIP_CALL( SCIPvarCreateTransformed(&aggvar, blkmem, set, stat,
5245  aggvarname, -SCIPsetInfinity(set), SCIPsetInfinity(set), 0.0, vartype,
5247  NULL, NULL, NULL, NULL, NULL) );
5248 
5249  SCIP_CALL( SCIPprobAddVar(transprob, blkmem, set, lp, branchcand, eventfilter, eventqueue, aggvar) );
5250 
5251  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5252  branchcand, eventfilter, eventqueue, aggvar, (SCIP_Real)(-b), (SCIP_Real)xsol, infeasible, aggregated) );
5253  assert(*aggregated || *infeasible);
5254 
5255  if( !(*infeasible) )
5256  {
5257  SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5258  branchcand, eventfilter, eventqueue, aggvar, (SCIP_Real)a, (SCIP_Real)ysol, infeasible, aggregated) );
5259  assert(*aggregated || *infeasible);
5260  }
5261 
5262  /* release z */
5263  SCIP_CALL( SCIPvarRelease(&aggvar, blkmem, set, eventqueue, lp) );
5264 
5265  return SCIP_OKAY; /*lint !e438*/
5266 }
5267 
5268 /** performs second step of SCIPaggregateVars():
5269  * the variable to be aggregated is chosen among active problem variables x' and y', preferring a less strict variable
5270  * type as aggregation variable (i.e. continuous variables are preferred over implicit integers, implicit integers
5271  * or integers over binaries). If none of the variables is continuous, it is tried to find an integer
5272  * aggregation (i.e. integral coefficients a'' and b'', such that a''*x' + b''*y' == c''). This can lead to
5273  * the detection of infeasibility (e.g. if c'' is fractional), or to a rejection of the aggregation (denoted by
5274  * aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
5275  *
5276  * @todo check for fixings, infeasibility, bound changes, or domain holes:
5277  * a) if there is no easy aggregation and we have one binary variable and another integer/implicit/binary variable
5278  * b) for implicit integer variables with fractional aggregation scalar (we cannot (for technical reasons) and do
5279  * not want to aggregate implicit integer variables, since we loose the corresponding divisibility property)
5280  */
5282  SCIP_SET* set, /**< global SCIP settings */
5283  BMS_BLKMEM* blkmem, /**< block memory */
5284  SCIP_STAT* stat, /**< problem statistics */
5285  SCIP_PROB* transprob, /**< tranformed problem data */
5286  SCIP_PROB* origprob, /**< original problem data */
5287  SCIP_PRIMAL* primal, /**< primal data */
5288  SCIP_TREE* tree, /**< branch and bound tree */
5289  SCIP_REOPT* reopt, /**< reoptimization data structure */
5290  SCIP_LP* lp, /**< current LP data */
5291  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5292  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5293  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
5294  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5295  SCIP_VAR* varx, /**< variable x in equality a*x + b*y == c */
5296  SCIP_VAR* vary, /**< variable y in equality a*x + b*y == c */
5297  SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
5298  SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
5299  SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
5300  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
5301  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
5302  )
5303 {
5304  SCIP_Bool easyaggr;
5305 
5306  assert(set != NULL);
5307  assert(blkmem != NULL);
5308  assert(stat != NULL);
5309  assert(transprob != NULL);
5310  assert(origprob != NULL);
5311  assert(tree != NULL);
5312  assert(lp != NULL);
5313  assert(cliquetable != NULL);
5314  assert(branchcand != NULL);
5315  assert(eventqueue != NULL);
5316  assert(varx != NULL);
5317  assert(vary != NULL);
5318  assert(varx != vary);
5319  assert(infeasible != NULL);
5320  assert(aggregated != NULL);
5321  assert(SCIPsetGetStage(set) == SCIP_STAGE_PRESOLVING);
5322  assert(SCIPvarGetStatus(varx) == SCIP_VARSTATUS_LOOSE);
5323  assert(SCIPvarGetStatus(vary) == SCIP_VARSTATUS_LOOSE);
5324  assert(!SCIPsetIsZero(set, scalarx));
5325  assert(!SCIPsetIsZero(set, scalary));
5326 
5327  *infeasible = FALSE;
5328  *aggregated = FALSE;
5329 
5330  if( SCIPsetIsZero(set, scalarx / scalary) || SCIPsetIsZero(set, scalary / scalarx) )
5331  return SCIP_OKAY;
5332 
5333  /* prefer aggregating the variable of more general type (preferred aggregation variable is varx) */
5334  if( SCIPvarGetType(vary) > SCIPvarGetType(varx) ||
5335  (SCIPvarGetType(vary) == SCIPvarGetType(varx) && !SCIPvarIsBinary(vary) && SCIPvarIsBinary(varx)) )
5336  {
5337  SCIP_VAR* var;
5338  SCIP_Real scalar;
5339 
5340  /* switch the variables, such that varx is the variable of more general type (cont > implint > int > bin) */
5341  var = vary;
5342  vary = varx;
5343  varx = var;
5344  scalar = scalary;
5345  scalary = scalarx;
5346  scalarx = scalar;
5347  }
5348 
5349  /* don't aggregate if the aggregation would lead to a binary variable aggregated to a non-binary variable */
5350  if( SCIPvarIsBinary(varx) && !SCIPvarIsBinary(vary) )
5351  return SCIP_OKAY;
5352 
5353  assert(SCIPvarGetType(varx) >= SCIPvarGetType(vary));
5354 
5355  /* figure out, which variable should be aggregated */
5356  easyaggr = FALSE;
5357 
5358  /* check if it is an easy aggregation */
5360  {
5361  easyaggr = TRUE;
5362  }
5363  else if( SCIPsetIsFeasIntegral(set, scalary/scalarx) )
5364  {
5365  easyaggr = TRUE;
5366  }
5367  else if( SCIPsetIsFeasIntegral(set, scalarx/scalary) && SCIPvarGetType(vary) == SCIPvarGetType(varx) )
5368  {
5369  /* we have an easy aggregation if we flip the variables x and y */
5370  SCIP_VAR* var;
5371  SCIP_Real scalar;
5372 
5373  /* switch the variables, such that varx is the aggregated variable */
5374  var = vary;
5375  vary = varx;
5376  varx = var;
5377  scalar = scalary;
5378  scalary = scalarx;
5379  scalarx = scalar;
5380  easyaggr = TRUE;
5381  }
5382  else if( SCIPvarGetType(varx) == SCIP_VARTYPE_CONTINUOUS )
5383  {
5384  /* the aggregation is still easy if both variables are continuous */
5385  assert(SCIPvarGetType(vary) == SCIP_VARTYPE_CONTINUOUS); /* otherwise we are in the first case */
5386  easyaggr = TRUE;
5387  }
5388 
5389  /* did we find an "easy" aggregation? */
5390  if( easyaggr )
5391  {
5392  SCIP_Real scalar;
5393  SCIP_Real constant;
5394 
5395  assert(SCIPvarGetType(varx) >= SCIPvarGetType(vary));
5396 
5397  /* calculate aggregation scalar and constant: a*x + b*y == c => x == -b/a * y + c/a */
5398  scalar = -scalary/scalarx;
5399  constant = rhs/scalarx;
5400 
5401  if( REALABS(constant) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
5402  return SCIP_OKAY;
5403 
5404  /* check aggregation for integer feasibility */
5407  && SCIPsetIsFeasIntegral(set, scalar) && !SCIPsetIsFeasIntegral(set, constant) )
5408  {
5409  *infeasible = TRUE;
5410  return SCIP_OKAY;
5411  }
5412 
5413  /* if the aggregation scalar is fractional, we cannot (for technical reasons) and do not want to aggregate implicit integer variables,
5414  * since then we would loose the corresponding divisibility property
5415  */
5416  assert(SCIPvarGetType(varx) != SCIP_VARTYPE_IMPLINT || SCIPsetIsFeasIntegral(set, scalar));
5417 
5418  /* aggregate the variable */
5419  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5420  branchcand, eventfilter, eventqueue, vary, scalar, constant, infeasible, aggregated) );
5421  assert(*aggregated || *infeasible || SCIPvarDoNotAggr(varx));
5422  }
5425  {
5426  /* the variables are both integral: we have to try to find an integer aggregation */
5427  SCIP_CALL( tryAggregateIntVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5428  branchcand, eventfilter, eventqueue, varx, vary, scalarx, scalary, rhs, infeasible, aggregated) );
5429  }
5430 
5431  return SCIP_OKAY;
5432 }
5433 
5434 /** converts variable into multi-aggregated variable */
5436  SCIP_VAR* var, /**< problem variable */
5437  BMS_BLKMEM* blkmem, /**< block memory */
5438  SCIP_SET* set, /**< global SCIP settings */
5439  SCIP_STAT* stat, /**< problem statistics */
5440  SCIP_PROB* transprob, /**< tranformed problem data */
5441  SCIP_PROB* origprob, /**< original problem data */
5442  SCIP_PRIMAL* primal, /**< primal data */
5443  SCIP_TREE* tree, /**< branch and bound tree */
5444  SCIP_REOPT* reopt, /**< reoptimization data structure */
5445  SCIP_LP* lp, /**< current LP data */
5446  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5447  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5448  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
5449  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5450  int naggvars, /**< number n of variables in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5451  SCIP_VAR** aggvars, /**< variables y_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5452  SCIP_Real* scalars, /**< multipliers a_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5453  SCIP_Real constant, /**< constant shift c in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5454  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
5455  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
5456  )
5457 {
5458  SCIP_VAR** tmpvars;
5459  SCIP_Real* tmpscalars;
5460  SCIP_Real obj;
5461  SCIP_Real branchfactor;
5462  int branchpriority;
5463  SCIP_BRANCHDIR branchdirection;
5464  int nlocksdown[NLOCKTYPES];
5465  int nlocksup[NLOCKTYPES];
5466  int v;
5467  SCIP_Real tmpconstant;
5468  SCIP_Real tmpscalar;
5469  int ntmpvars;
5470  int tmpvarssize;
5471  int tmprequiredsize;
5472  int i;
5473 
5474  assert(var != NULL);
5475  assert(var->scip == set->scip);
5476  assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
5477  assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
5478  assert(naggvars == 0 || aggvars != NULL);
5479  assert(naggvars == 0 || scalars != NULL);
5480  assert(infeasible != NULL);
5481  assert(aggregated != NULL);
5482 
5483  SCIPsetDebugMsg(set, "trying multi-aggregating variable <%s> == ...%d vars... %+g\n", var->name, naggvars, constant);
5484 
5485  *infeasible = FALSE;
5486  *aggregated = FALSE;
5487 
5488  switch( SCIPvarGetStatus(var) )
5489  {
5491  if( var->data.original.transvar == NULL )
5492  {
5493  SCIPerrorMessage("cannot multi-aggregate an untransformed original variable\n");
5494  return SCIP_INVALIDDATA;
5495  }
5496  SCIP_CALL( SCIPvarMultiaggregate(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
5497  reopt, lp, cliquetable, branchcand, eventfilter, eventqueue, naggvars, aggvars, scalars, constant, infeasible, aggregated) );
5498  break;
5499 
5500  case SCIP_VARSTATUS_LOOSE:
5501  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
5502 
5503  /* check if we would create a self-reference */
5504  ntmpvars = naggvars;
5505  tmpvarssize = naggvars;
5506  tmpconstant = constant;
5507  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpvars, aggvars, ntmpvars) );
5508  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpscalars, scalars, ntmpvars) );
5509 
5510  /* get all active variables for multi-aggregation */
5511  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize, FALSE) );
5512  if( tmprequiredsize > tmpvarssize )
5513  {
5514  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpvars, tmpvarssize, tmprequiredsize) );
5515  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize, tmprequiredsize) );
5516  tmpvarssize = tmprequiredsize;
5517  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize, FALSE) );
5518  assert( tmprequiredsize <= tmpvarssize );
5519  }
5520 
5521  tmpscalar = 0.0;
5522 
5523  /* iterate over all active variables of the multi-aggregation and filter all variables which are equal to the
5524  * possible multi-aggregated variable
5525  */
5526  for( v = ntmpvars - 1; v >= 0; --v )
5527  {
5528  assert(tmpvars[v] != NULL);
5529  assert(SCIPvarGetStatus(tmpvars[v]) == SCIP_VARSTATUS_LOOSE);
5530 
5531  if( tmpvars[v]->index == var->index )
5532  {
5533  tmpscalar += tmpscalars[v];
5534  tmpvars[v] = tmpvars[ntmpvars - 1];
5535  tmpscalars[v] = tmpscalars[ntmpvars - 1];
5536  --ntmpvars;
5537  }
5538  }
5539 
5540  /* this means that x = x + a_1*y_1 + ... + a_n*y_n + c */
5541  if( SCIPsetIsEQ(set, tmpscalar, 1.0) )
5542  {
5543  if( ntmpvars == 0 )
5544  {
5545  if( SCIPsetIsZero(set, tmpconstant) ) /* x = x */
5546  {
5547  SCIPsetDebugMsg(set, "Possible multi-aggregation was completely resolved and detected to be redundant.\n");
5548  goto TERMINATE;
5549  }
5550  else /* 0 = c and c != 0 */
5551  {
5552  SCIPsetDebugMsg(set, "Multi-aggregation was completely resolved and led to infeasibility.\n");
5553  *infeasible = TRUE;
5554  goto TERMINATE;
5555  }
5556  }
5557  else if( ntmpvars == 1 ) /* 0 = a*y + c => y = -c/a */
5558  {
5559  assert(tmpscalars[0] != 0.0);
5560  assert(tmpvars[0] != NULL);
5561 
5562  SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(tmpvars[0]), -constant/tmpscalars[0]);
5563  SCIP_CALL( SCIPvarFix(tmpvars[0], blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5564  branchcand, eventfilter, eventqueue, cliquetable, -constant/tmpscalars[0], infeasible, aggregated) );
5565  goto TERMINATE;
5566  }
5567  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 */
5568  {
5569  /* both variables are different active problem variables, and both scalars are non-zero: try to aggregate them */
5570  SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
5571  SCIPvarGetName(tmpvars[0]), SCIPvarGetName(tmpvars[1]), tmpscalars[0], tmpscalars[1], -tmpconstant);
5572 
5573  SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
5574  cliquetable, branchcand, eventfilter, eventqueue, tmpvars[0], tmpvars[1], tmpscalars[0],
5575  tmpscalars[1], -tmpconstant, infeasible, aggregated) );
5576 
5577  goto TERMINATE;
5578  }
5579  else
5580  /* @todo: it is possible to multi-aggregate another variable, does it make sense?,
5581  * rest looks like 0 = a_1*y_1 + ... + a_n*y_n + c and has at least three variables
5582  */
5583  goto TERMINATE;
5584  }
5585  /* this means that x = b*x + a_1*y_1 + ... + a_n*y_n + c */
5586  else if( !SCIPsetIsZero(set, tmpscalar) )
5587  {
5588  tmpscalar = 1 - tmpscalar;
5589  tmpconstant /= tmpscalar;
5590  for( v = ntmpvars - 1; v >= 0; --v )
5591  tmpscalars[v] /= tmpscalar;
5592  }
5593 
5594  /* check, if we are in one of the simple cases */
5595  if( ntmpvars == 0 )
5596  {
5597  SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(var), tmpconstant);
5598  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
5599  eventfilter, eventqueue, cliquetable, tmpconstant, infeasible, aggregated) );
5600  goto TERMINATE;
5601  }
5602 
5603  /* if only one aggregation variable is left, we perform a normal aggregation instead of a multi-aggregation */
5604  if( ntmpvars == 1 )
5605  {
5606  SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
5607  SCIPvarGetName(var), SCIPvarGetName(tmpvars[0]), 1.0, -tmpscalars[0], tmpconstant);
5608 
5609  SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
5610  cliquetable, branchcand, eventfilter, eventqueue, var, tmpvars[0], 1.0, -tmpscalars[0], tmpconstant,
5611  infeasible, aggregated) );
5612 
5613  goto TERMINATE;
5614  }
5615 
5616  /**@todo currently we don't perform the multi aggregation if the multi aggregation variable has a non
5617  * empty hole list; this should be changed in the future */
5618  if( SCIPvarGetHolelistGlobal(var) != NULL )
5619  goto TERMINATE;
5620 
5621  /* if the variable is not allowed to be multi-aggregated */
5622  if( SCIPvarDoNotMultaggr(var) )
5623  {
5624  SCIPsetDebugMsg(set, "variable is not allowed to be multi-aggregated.\n");
5625  goto TERMINATE;
5626  }
5627 
5628  /* if the variable to be multi-aggregated has implications or variable bounds (i.e. is the implied variable or
5629  * variable bound variable of another variable), we have to remove it from the other variables implications or
5630  * variable bounds
5631  */
5632  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
5633  assert(var->vlbs == NULL);
5634  assert(var->vubs == NULL);
5635  assert(var->implics == NULL);
5636 
5637  /* set the aggregated variable's objective value to 0.0 */
5638  obj = var->obj;
5639  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
5640 
5641  /* since we change the variable type form loose to multi aggregated, we have to adjust the number of loose
5642  * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
5643  * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
5644  * objective of this variable is set to zero
5645  */
5646  SCIPlpDecNLoosevars(lp);
5647 
5648  /* unlock all rounding locks */
5649  for( i = 0; i < NLOCKTYPES; i++ )
5650  {
5651  nlocksdown[i] = var->nlocksdown[i];
5652  nlocksup[i] = var->nlocksup[i];
5653 
5654  var->nlocksdown[i] = 0;
5655  var->nlocksup[i] = 0;
5656  }
5657 
5658  /* convert variable into multi-aggregated variable */
5659  var->varstatus = SCIP_VARSTATUS_MULTAGGR; /*lint !e641*/
5660  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.vars, tmpvars, ntmpvars) );
5661  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.scalars, tmpscalars, ntmpvars) );
5662  var->data.multaggr.constant = tmpconstant;
5663  var->data.multaggr.nvars = ntmpvars;
5664  var->data.multaggr.varssize = ntmpvars;
5665 
5666  /* mark variable to be non-deletable */
5668 
5669  /* relock the variable, thus increasing the locks of the aggregation variables */
5670  for( i = 0; i < NLOCKTYPES; i++ )
5671  {
5672  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
5673  }
5674 
5675  /* update flags and branching factors and priorities of aggregation variables;
5676  * update preferred branching direction of all aggregation variables that don't have a preferred direction yet
5677  */
5678  branchfactor = var->branchfactor;
5679  branchpriority = var->branchpriority;
5680  branchdirection = (SCIP_BRANCHDIR)var->branchdirection;
5681 
5682  for( v = 0; v < ntmpvars; ++v )
5683  {
5684  assert(tmpvars[v] != NULL);
5685  tmpvars[v]->removable &= var->removable;
5686  branchfactor = MAX(tmpvars[v]->branchfactor, branchfactor);
5687  branchpriority = MAX(tmpvars[v]->branchpriority, branchpriority);
5688 
5689  /* mark variable to be non-deletable */
5690  SCIPvarMarkNotDeletable(tmpvars[v]);
5691  }
5692  for( v = 0; v < ntmpvars; ++v )
5693  {
5694  SCIP_CALL( SCIPvarChgBranchFactor(tmpvars[v], set, branchfactor) );
5695  SCIP_CALL( SCIPvarChgBranchPriority(tmpvars[v], branchpriority) );
5696  if( (SCIP_BRANCHDIR)tmpvars[v]->branchdirection == SCIP_BRANCHDIR_AUTO )
5697  {
5698  if( tmpscalars[v] >= 0.0 )
5699  {
5700  SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], branchdirection) );
5701  }
5702  else
5703  {
5704  SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], SCIPbranchdirOpposite(branchdirection)) );
5705  }
5706  }
5707  }
5708  SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
5709  SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
5710 
5711  if( var->probindex != -1 )
5712  {
5713  /* inform problem about the variable's status change */
5714  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
5715  }
5716 
5717  /* issue VARFIXED event */
5718  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 2) );
5719 
5720  /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
5721  * variables and the problem's objective offset
5722  */
5723  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventfilter, eventqueue, obj) );
5724 
5725  *aggregated = TRUE;
5726 
5727  TERMINATE:
5728  BMSfreeBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize);
5729  BMSfreeBlockMemoryArray(blkmem, &tmpvars, tmpvarssize);
5730 
5731  break;
5732 
5733  case SCIP_VARSTATUS_COLUMN:
5734  SCIPerrorMessage("cannot multi-aggregate a column variable\n");
5735  return SCIP_INVALIDDATA;
5736 
5737  case SCIP_VARSTATUS_FIXED:
5738  SCIPerrorMessage("cannot multi-aggregate a fixed variable\n");
5739  return SCIP_INVALIDDATA;
5740 
5742  SCIPerrorMessage("cannot multi-aggregate an aggregated variable\n");
5743  return SCIP_INVALIDDATA;
5744 
5746  SCIPerrorMessage("cannot multi-aggregate a multiple aggregated variable again\n");
5747  return SCIP_INVALIDDATA;
5748 
5750  /* aggregate negation variable x in x' = offset - x, instead of aggregating x' directly:
5751  * x' = a_1*y_1 + ... + a_n*y_n + c -> x = offset - x' = offset - a_1*y_1 - ... - a_n*y_n - c
5752  */
5753  assert(SCIPsetIsZero(set, var->obj));
5754  assert(var->negatedvar != NULL);
5756  assert(var->negatedvar->negatedvar == var);
5757 
5758  /* switch the signs of the aggregation scalars */
5759  for( v = 0; v < naggvars; ++v )
5760  scalars[v] *= -1.0;
5761 
5762  /* perform the multi aggregation on the negation variable */
5763  SCIP_CALL( SCIPvarMultiaggregate(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5764  cliquetable, branchcand, eventfilter, eventqueue, naggvars, aggvars, scalars,
5765  var->data.negate.constant - constant, infeasible, aggregated) );
5766 
5767  /* switch the signs of the aggregation scalars again, to reset them to their original values */
5768  for( v = 0; v < naggvars; ++v )
5769  scalars[v] *= -1.0;
5770  break;
5771 
5772  default:
5773  SCIPerrorMessage("unknown variable status\n");
5774  return SCIP_INVALIDDATA;
5775  }
5776 
5777  /* check multi-aggregation on debugging solution */
5778  if( *infeasible || *aggregated )
5779  SCIP_CALL( SCIPdebugCheckAggregation(set, var, aggvars, scalars, constant, naggvars) ); /*lint !e506 !e774*/
5780 
5781  return SCIP_OKAY;
5782 }
5783 
5784 /** transformed variables are resolved to their active, fixed, or multi-aggregated problem variable of a variable,
5785  * or for original variables the same variable is returned
5786  */
5787 static
5789  SCIP_VAR* var /**< problem variable */
5790  )
5791 {
5792  SCIP_VAR* retvar;
5793 
5794  assert(var != NULL);
5795 
5796  retvar = var;
5797 
5798  SCIPdebugMessage("get active variable of <%s>\n", var->name);
5799 
5800  while( TRUE ) /*lint !e716 */
5801  {
5802  assert(retvar != NULL);
5803 
5804  switch( SCIPvarGetStatus(retvar) )
5805  {
5807  case SCIP_VARSTATUS_LOOSE:
5808  case SCIP_VARSTATUS_COLUMN:
5809  case SCIP_VARSTATUS_FIXED:
5810  return retvar;
5811 
5813  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
5814  if ( retvar->data.multaggr.nvars == 1 )
5815  retvar = retvar->data.multaggr.vars[0];
5816  else
5817  return retvar;
5818  break;
5819 
5821  retvar = retvar->data.aggregate.var;
5822  break;
5823 
5825  retvar = retvar->negatedvar;
5826  break;
5827 
5828  default:
5829  SCIPerrorMessage("unknown variable status\n");
5830  SCIPABORT();
5831  return NULL; /*lint !e527*/
5832  }
5833  }
5834 }
5835 
5836 /** returns whether variable is not allowed to be aggregated */
5838  SCIP_VAR* var /**< problem variable */
5839  )
5840 {
5841  SCIP_VAR* retvar;
5842 
5843  assert(var != NULL);
5844 
5845  retvar = varGetActiveVar(var);
5846  assert(retvar != NULL);
5847 
5848  switch( SCIPvarGetStatus(retvar) )
5849  {
5851  case SCIP_VARSTATUS_LOOSE:
5852  case SCIP_VARSTATUS_COLUMN:
5853  case SCIP_VARSTATUS_FIXED:
5854  return retvar->donotaggr;
5855 
5857  return FALSE;
5858 
5861  default:
5862  /* aggregated and negated variables should be resolved by varGetActiveVar() */
5863  SCIPerrorMessage("wrong variable status\n");
5864  SCIPABORT();
5865  return FALSE; /*lint !e527 */
5866  }
5867 }
5868 
5869 /** returns whether variable is not allowed to be multi-aggregated */
5871  SCIP_VAR* var /**< problem variable */
5872  )
5873 {
5874  SCIP_VAR* retvar;
5875 
5876  assert(var != NULL);
5877 
5878  retvar = varGetActiveVar(var);
5879  assert(retvar != NULL);
5880 
5881  switch( SCIPvarGetStatus(retvar) )
5882  {
5884  case SCIP_VARSTATUS_LOOSE:
5885  case SCIP_VARSTATUS_COLUMN:
5886  case SCIP_VARSTATUS_FIXED:
5887  return retvar->donotmultaggr;
5888 
5890  return FALSE;
5891 
5894  default:
5895  /* aggregated and negated variables should be resolved by varGetActiveVar() */
5896  SCIPerrorMessage("wrong variable status\n");
5897  SCIPABORT();
5898  return FALSE; /*lint !e527 */
5899  }
5900 }
5901 
5902 /** gets negated variable x' = offset - x of problem variable x; the negated variable is created if not yet existing;
5903  * the negation offset of binary variables is always 1, the offset of other variables is fixed to lb + ub when the
5904  * negated variable is created
5905  */
5907  SCIP_VAR* var, /**< problem variable to negate */
5908  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
5909  SCIP_SET* set, /**< global SCIP settings */
5910  SCIP_STAT* stat, /**< problem statistics */
5911  SCIP_VAR** negvar /**< pointer to store the negated variable */
5912  )
5913 {
5914  assert(var != NULL);
5915  assert(var->scip == set->scip);
5916  assert(negvar != NULL);
5917 
5918  /* check, if we already created the negated variable */
5919  if( var->negatedvar == NULL )
5920  {
5921  char negvarname[SCIP_MAXSTRLEN];
5922 
5923  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED);
5924 
5925  SCIPsetDebugMsg(set, "creating negated variable of <%s>\n", var->name);
5926 
5927  /* negation is only possible for bounded variables */
5928  if( SCIPsetIsInfinity(set, -var->glbdom.lb) || SCIPsetIsInfinity(set, var->glbdom.ub) )
5929  {
5930  SCIPerrorMessage("cannot negate unbounded variable\n");
5931  return SCIP_INVALIDDATA;
5932  }
5933 
5934  (void) SCIPsnprintf(negvarname, SCIP_MAXSTRLEN, "%s_neg", var->name);
5935 
5936  /* create negated variable */
5937  SCIP_CALL( varCreate(negvar, blkmem, set, stat, negvarname, var->glbdom.lb, var->glbdom.ub, 0.0,
5938  SCIPvarGetType(var), var->initial, var->removable, NULL, NULL, NULL, NULL, NULL) );
5939  (*negvar)->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
5940  if( SCIPvarIsBinary(var) )
5941  (*negvar)->data.negate.constant = 1.0;
5942  else
5943  (*negvar)->data.negate.constant = var->glbdom.lb + var->glbdom.ub;
5944 
5945  /* create event filter for transformed variable */
5946  if( SCIPvarIsTransformed(var) )
5947  {
5948  SCIP_CALL( SCIPeventfilterCreate(&(*negvar)->eventfilter, blkmem) );
5949  }
5950 
5951  /* set the bounds corresponding to the negation variable */
5952  (*negvar)->glbdom.lb = (*negvar)->data.negate.constant - var->glbdom.ub;
5953  (*negvar)->glbdom.ub = (*negvar)->data.negate.constant - var->glbdom.lb;
5954  (*negvar)->locdom.lb = (*negvar)->data.negate.constant - var->locdom.ub;
5955  (*negvar)->locdom.ub = (*negvar)->data.negate.constant - var->locdom.lb;
5956  /**@todo create holes in the negated variable corresponding to the holes of the negation variable */
5957 
5958  /* link the variables together */
5959  var->negatedvar = *negvar;
5960  (*negvar)->negatedvar = var;
5961 
5962  /* mark both variables to be non-deletable */
5964  SCIPvarMarkNotDeletable(*negvar);
5965 
5966  /* copy the branch factor and priority, and use the negative preferred branching direction */
5967  (*negvar)->branchfactor = var->branchfactor;
5968  (*negvar)->branchpriority = var->branchpriority;
5969  (*negvar)->branchdirection = SCIPbranchdirOpposite((SCIP_BRANCHDIR)var->branchdirection); /*lint !e641*/
5970 
5971  /* copy donot(mult)aggr status */
5972  (*negvar)->donotaggr = var->donotaggr;
5973  (*negvar)->donotmultaggr = var->donotmultaggr;
5974 
5975  /* copy lazy bounds (they have to be flipped) */
5976  (*negvar)->lazylb = (*negvar)->data.negate.constant - var->lazyub;
5977  (*negvar)->lazyub = (*negvar)->data.negate.constant - var->lazylb;
5978 
5979  /* make negated variable a parent of the negation variable (negated variable is captured as a parent) */
5980  SCIP_CALL( varAddParent(var, blkmem, set, *negvar) );
5981  assert((*negvar)->nuses == 1);
5982  }
5983  assert(var->negatedvar != NULL);
5984 
5985  /* return the negated variable */
5986  *negvar = var->negatedvar;
5987 
5988  /* exactly one variable of the negation pair has to be marked as negated variable */
5990 
5991  return SCIP_OKAY;
5992 }
5993 
5994 /** informs variable that its position in problem's vars array changed */
5995 static
5996 void varSetProbindex(
5997  SCIP_VAR* var, /**< problem variable */
5998  int probindex /**< new problem index of variable (-1 for removal) */
5999  )
6000 {
6001  assert(var != NULL);
6002  assert(probindex >= 0 || var->vlbs == NULL);
6003  assert(probindex >= 0 || var->vubs == NULL);
6004  assert(probindex >= 0 || var->implics == NULL);
6005 
6006  var->probindex = probindex;
6008  {
6009  assert(var->data.col != NULL);
6010  var->data.col->var_probindex = probindex;
6011  }
6012 }
6013 
6014 /** informs variable that its position in problem's vars array changed */
6015 void SCIPvarSetProbindex(
6016  SCIP_VAR* var, /**< problem variable */
6017  int probindex /**< new problem index of variable */
6018  )
6019 {
6020  assert(var != NULL);
6021  assert(probindex >= 0);
6022 
6023  varSetProbindex(var, probindex);
6024 }
6025 
6026 /** gives the variable a new name
6027  *
6028  * @note the old pointer is overwritten, which might result in a memory leakage
6029  */
6031  SCIP_VAR* var, /**< problem variable */
6032  const char* name /**< new name of variable */
6033  )
6034 {
6035  assert(var != NULL);
6036  assert(name != NULL);
6037 
6038  var->name = (char*)name;
6039 }
6040 
6041 /** informs variable that it will be removed from the problem; adjusts probindex and removes variable from the
6042  * implication graph;
6043  * If 'final' is TRUE, the thorough implication graph removal is not performed. Instead, only the
6044  * variable bounds and implication data structures of the variable are freed. Since in the final removal
6045  * of all variables from the transformed problem, this deletes the implication graph completely and is faster
6046  * than removing the variables one by one, each time updating all lists of the other variables.
6047  */
6049  SCIP_VAR* var, /**< problem variable */
6050  BMS_BLKMEM* blkmem, /**< block memory buffer */
6051  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6052  SCIP_SET* set, /**< global SCIP settings */
6053  SCIP_Bool final /**< is this the final removal of all problem variables? */
6054  )
6055 {
6056  assert(SCIPvarGetProbindex(var) >= 0);
6057  assert(var->scip == set->scip);
6058 
6059  /* if the variable is active in the transformed problem, remove it from the implication graph */
6060  if( SCIPvarIsTransformed(var)
6062  {
6063  if( final )
6064  {
6065  /* just destroy the data structures */
6066  SCIPvboundsFree(&var->vlbs, blkmem);
6067  SCIPvboundsFree(&var->vubs, blkmem);
6068  SCIPimplicsFree(&var->implics, blkmem);
6069  }
6070  else
6071  {
6072  /* unlink the variable from all other variables' lists and free the data structures */
6073  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
6074  }
6075  }
6076 
6077  /* mark the variable to be no longer a member of the problem */
6078  varSetProbindex(var, -1);
6079 
6080  return SCIP_OKAY;
6081 }
6082 
6083 /** marks the variable to be deleted from the problem */
6084 void SCIPvarMarkDeleted(
6085  SCIP_VAR* var /**< problem variable */
6086  )
6087 {
6088  assert(var != NULL);
6089  assert(var->probindex != -1);
6090 
6091  var->deleted = TRUE;
6092 }
6093 
6094 /** marks the variable to not to be aggregated */
6096  SCIP_VAR* var /**< problem variable */
6097  )
6098 {
6099  SCIP_VAR* retvar;
6100 
6101  assert(var != NULL);
6102 
6103  retvar = varGetActiveVar(var);
6104  assert(retvar != NULL);
6105 
6106  switch( SCIPvarGetStatus(retvar) )
6107  {
6109  case SCIP_VARSTATUS_LOOSE:
6110  case SCIP_VARSTATUS_COLUMN:
6111  case SCIP_VARSTATUS_FIXED:
6112  retvar->donotaggr = TRUE;
6113  break;
6114 
6116  SCIPerrorMessage("cannot mark a multi-aggregated variable to not be aggregated.\n");
6117  return SCIP_INVALIDDATA;
6118 
6121  default:
6122  /* aggregated and negated variables should be resolved by varGetActiveVar() */
6123  SCIPerrorMessage("wrong variable status\n");
6124  return SCIP_INVALIDDATA;
6125  }
6126 
6127  return SCIP_OKAY;
6128 }
6129 
6130 /** marks the variable to not to be multi-aggregated */
6132  SCIP_VAR* var /**< problem variable */
6133  )
6134 {
6135  SCIP_VAR* retvar;
6136 
6137  assert(var != NULL);
6138 
6139  retvar = varGetActiveVar(var);
6140  assert(retvar != NULL);
6141 
6142  switch( SCIPvarGetStatus(retvar) )
6143  {
6145  case SCIP_VARSTATUS_LOOSE:
6146  case SCIP_VARSTATUS_COLUMN:
6147  case SCIP_VARSTATUS_FIXED:
6148  retvar->donotmultaggr = TRUE;
6149  break;
6150 
6152  SCIPerrorMessage("cannot mark a multi-aggregated variable to not be multi-aggregated.\n");
6153  return SCIP_INVALIDDATA;
6154 
6157  default:
6158  /* aggregated and negated variables should be resolved by varGetActiveVar() */
6159  SCIPerrorMessage("wrong variable status\n");
6160  return SCIP_INVALIDDATA;
6161  }
6162 
6163  return SCIP_OKAY;
6164 }
6165 
6166 /** changes type of variable; cannot be called, if var belongs to a problem */
6168  SCIP_VAR* var, /**< problem variable to change */
6169  BMS_BLKMEM* blkmem, /**< block memory */
6170  SCIP_SET* set, /**< global SCIP settings */
6171  SCIP_PRIMAL* primal, /**< primal data */
6172  SCIP_LP* lp, /**< current LP data */
6173  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6174  SCIP_VARTYPE vartype /**< new type of variable */
6175  )
6176 {
6177  SCIP_EVENT* event;
6178  SCIP_VARTYPE oldtype;
6179 
6180  assert(var != NULL);
6181 
6182  SCIPdebugMessage("change type of <%s> from %d to %d\n", var->name, SCIPvarGetType(var), vartype);
6183 
6184  if( var->probindex >= 0 )
6185  {
6186  SCIPerrorMessage("cannot change type of variable already in the problem\n");
6187  return SCIP_INVALIDDATA;
6188  }
6189 
6190  oldtype = (SCIP_VARTYPE)var->vartype;
6191  var->vartype = vartype; /*lint !e641*/
6192 
6194  {
6195  SCIP_CALL( SCIPeventCreateTypeChanged(&event, blkmem, var, oldtype, vartype) );
6196  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
6197  }
6198 
6199  if( var->negatedvar != NULL )
6200  {
6201  assert(oldtype == (SCIP_VARTYPE)var->negatedvar->vartype
6202  || SCIPvarIsBinary(var) == SCIPvarIsBinary(var->negatedvar));
6203 
6204  var->negatedvar->vartype = vartype; /*lint !e641*/
6205 
6207  {
6208  SCIP_CALL( SCIPeventCreateTypeChanged(&event, blkmem, var->negatedvar, oldtype, vartype) );
6209  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
6210  }
6211  }
6212 
6213  return SCIP_OKAY;
6214 }
6215 
6216 /** appends OBJCHANGED event to the event queue */
6217 static
6219  SCIP_VAR* var, /**< problem variable to change */
6220  BMS_BLKMEM* blkmem, /**< block memory */
6221  SCIP_SET* set, /**< global SCIP settings */
6222  SCIP_PRIMAL* primal, /**< primal data */
6223  SCIP_LP* lp, /**< current LP data */
6224  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6225  SCIP_Real oldobj, /**< old objective value for variable */
6226  SCIP_Real newobj /**< new objective value for variable */
6227  )
6228 {
6229  SCIP_EVENT* event;
6230 
6231  assert(var != NULL);
6232  assert(var->scip == set->scip);
6233  assert(var->eventfilter != NULL);
6235  assert(SCIPvarIsTransformed(var));
6236 
6237  /* In the case where the objcetive value of a variable is very close to epsilon, and it is aggregated
6238  * into a variable with a big objective value, round-off errors might make the assert oldobj != newobj fail.
6239  * Hence, we relax it by letting it pass if the variables are percieved the same and we use very large values
6240  * that make comparison with values close to epsilon inaccurate.
6241  */
6242  assert(!SCIPsetIsEQ(set, oldobj, newobj) ||
6243  (SCIPsetIsEQ(set, oldobj, newobj) && REALABS(newobj) > 1e+15 * SCIPsetEpsilon(set))
6244  );
6245 
6246  SCIP_CALL( SCIPeventCreateObjChanged(&event, blkmem, var, oldobj, newobj) );
6247  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
6248 
6249  return SCIP_OKAY;
6250 }
6251 
6252 /** changes objective value of variable */
6254  SCIP_VAR* var, /**< variable to change */
6255  BMS_BLKMEM* blkmem, /**< block memory */
6256  SCIP_SET* set, /**< global SCIP settings */
6257  SCIP_PROB* prob, /**< problem data */
6258  SCIP_PRIMAL* primal, /**< primal data */
6259  SCIP_LP* lp, /**< current LP data */
6260  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6261  SCIP_Real newobj /**< new objective value for variable */
6262  )
6263 {
6264  SCIP_Real oldobj;
6265 
6266  assert(var != NULL);
6267  assert(set != NULL);
6268  assert(var->scip == set->scip);
6269 
6270  SCIPsetDebugMsg(set, "changing objective value of <%s> from %g to %g\n", var->name, var->obj, newobj);
6271 
6272  if( !SCIPsetIsEQ(set, var->obj, newobj) )
6273  {
6274  switch( SCIPvarGetStatus(var) )
6275  {
6277  if( var->data.original.transvar != NULL )
6278  {
6279  assert(SCIPprobIsTransformed(prob));
6280 
6281  SCIP_CALL( SCIPvarChgObj(var->data.original.transvar, blkmem, set, prob, primal, lp, eventqueue,
6282  (SCIP_Real) prob->objsense * newobj/prob->objscale) );
6283  }
6284  else
6285  assert(set->stage == SCIP_STAGE_PROBLEM);
6286 
6287  var->obj = newobj;
6288  var->unchangedobj = newobj;
6289 
6290  break;
6291 
6292  case SCIP_VARSTATUS_LOOSE:
6293  case SCIP_VARSTATUS_COLUMN:
6294  oldobj = var->obj;
6295  var->obj = newobj;
6296 
6297  /* update unchanged objective value of variable */
6298  if( !lp->divingobjchg )
6299  var->unchangedobj = newobj;
6300 
6301  /* update the number of variables with non-zero objective coefficient;
6302  * we only want to do the update, if the variable is added to the problem;
6303  * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
6304  */
6305  if( SCIPvarIsActive(var) )
6306  SCIPprobUpdateNObjVars(prob, set, oldobj, var->obj);
6307 
6308  SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
6309  break;
6310 
6311  case SCIP_VARSTATUS_FIXED:
6315  SCIPerrorMessage("cannot change objective value of a fixed, aggregated, multi-aggregated, or negated variable\n");
6316  return SCIP_INVALIDDATA;
6317 
6318  default:
6319  SCIPerrorMessage("unknown variable status\n");
6320  return SCIP_INVALIDDATA;
6321  }
6322  }
6323 
6324  return SCIP_OKAY;
6325 }
6326 
6327 /** adds value to objective value of variable */
6329  SCIP_VAR* var, /**< variable to change */
6330  BMS_BLKMEM* blkmem, /**< block memory */
6331  SCIP_SET* set, /**< global SCIP settings */
6332  SCIP_STAT* stat, /**< problem statistics */
6333  SCIP_PROB* transprob, /**< transformed problem data */
6334  SCIP_PROB* origprob, /**< original problem data */
6335  SCIP_PRIMAL* primal, /**< primal data */
6336  SCIP_TREE* tree, /**< branch and bound tree */
6337  SCIP_REOPT* reopt, /**< reoptimization data structure */
6338  SCIP_LP* lp, /**< current LP data */
6339  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
6340  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6341  SCIP_Real addobj /**< additional objective value for variable */
6342  )
6343 {
6344  assert(var != NULL);
6345  assert(set != NULL);
6346  assert(var->scip == set->scip);
6347  assert(set->stage < SCIP_STAGE_INITSOLVE);
6348 
6349  SCIPsetDebugMsg(set, "adding %g to objective value %g of <%s>\n", addobj, var->obj, var->name);
6350 
6351  if( !SCIPsetIsZero(set, addobj) )
6352  {
6353  SCIP_Real oldobj;
6354  int i;
6355 
6356  switch( SCIPvarGetStatus(var) )
6357  {
6359  if( var->data.original.transvar != NULL )
6360  {
6361  SCIP_CALL( SCIPvarAddObj(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
6362  reopt, lp, eventfilter, eventqueue, (SCIP_Real) transprob->objsense * addobj/transprob->objscale) );
6363  }
6364  else
6365  assert(set->stage == SCIP_STAGE_PROBLEM);
6366 
6367  var->obj += addobj;
6368  var->unchangedobj += addobj;
6369  assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
6370 
6371  break;
6372 
6373  case SCIP_VARSTATUS_LOOSE:
6374  case SCIP_VARSTATUS_COLUMN:
6375  oldobj = var->obj;
6376  var->obj += addobj;
6377 
6378  /* update unchanged objective value of variable */
6379  if( !lp->divingobjchg )
6380  {
6381  var->unchangedobj += addobj;
6382  assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
6383  }
6384 
6385  /* update the number of variables with non-zero objective coefficient;
6386  * we only want to do the update, if the variable is added to the problem;
6387  * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
6388  */
6389  if( SCIPvarIsActive(var) )
6390  SCIPprobUpdateNObjVars(transprob, set, oldobj, var->obj);
6391 
6392  SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
6393  break;
6394 
6395  case SCIP_VARSTATUS_FIXED:
6396  assert(SCIPsetIsEQ(set, var->locdom.lb, var->locdom.ub));
6397  SCIPprobAddObjoffset(transprob, var->locdom.lb * addobj);
6398  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6399  break;
6400 
6402  assert(!var->donotaggr);
6403  /* x = a*y + c -> add a*addobj to obj. val. of y, and c*addobj to obj. offset of problem */
6404  SCIPprobAddObjoffset(transprob, var->data.aggregate.constant * addobj);
6405  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6406  SCIP_CALL( SCIPvarAddObj(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
6407  lp, eventfilter, eventqueue, var->data.aggregate.scalar * addobj) );
6408  break;
6409 
6411  assert(!var->donotmultaggr);
6412  /* 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 */
6413  SCIPprobAddObjoffset(transprob, var->data.multaggr.constant * addobj);
6414  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6415  for( i = 0; i < var->data.multaggr.nvars; ++i )
6416  {
6417  SCIP_CALL( SCIPvarAddObj(var->data.multaggr.vars[i], blkmem, set, stat, transprob, origprob, primal, tree,
6418  reopt, lp, eventfilter, eventqueue, var->data.multaggr.scalars[i] * addobj) );
6419  }
6420  break;
6421 
6423  /* x' = offset - x -> add -addobj to obj. val. of x and offset*addobj to obj. offset of problem */
6424  assert(var->negatedvar != NULL);
6426  assert(var->negatedvar->negatedvar == var);
6427  SCIPprobAddObjoffset(transprob, var->data.negate.constant * addobj);
6428  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6429  SCIP_CALL( SCIPvarAddObj(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
6430  eventfilter, eventqueue, -addobj) );
6431  break;
6432 
6433  default:
6434  SCIPerrorMessage("unknown variable status\n");
6435  return SCIP_INVALIDDATA;
6436  }
6437  }
6438 
6439  return SCIP_OKAY;
6440 }
6441 
6442 /** changes objective value of variable in current dive */
6444  SCIP_VAR* var, /**< problem variable to change */
6445  SCIP_SET* set, /**< global SCIP settings */
6446  SCIP_LP* lp, /**< current LP data */
6447  SCIP_Real newobj /**< new objective value for variable */
6448  )
6449 {
6450  assert(var != NULL);
6451  assert(set != NULL);
6452  assert(var->scip == set->scip);
6453  assert(lp != NULL);
6454 
6455  SCIPsetDebugMsg(set, "changing objective of <%s> to %g in current dive\n", var->name, newobj);
6456 
6457  if( SCIPsetIsZero(set, newobj) )
6458  newobj = 0.0;
6459 
6460  /* change objective value of attached variables */
6461  switch( SCIPvarGetStatus(var) )
6462  {
6464  assert(var->data.original.transvar != NULL);
6465  SCIP_CALL( SCIPvarChgObjDive(var->data.original.transvar, set, lp, newobj) );
6466  break;
6467 
6468  case SCIP_VARSTATUS_COLUMN:
6469  assert(var->data.col != NULL);
6470  SCIP_CALL( SCIPcolChgObj(var->data.col, set, lp, newobj) );
6471  break;
6472 
6473  case SCIP_VARSTATUS_LOOSE:
6474  case SCIP_VARSTATUS_FIXED:
6475  /* nothing to do here: only the constant shift in objective function would change */
6476  break;
6477 
6478  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6479  assert(var->data.aggregate.var != NULL);
6480  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
6481  SCIP_CALL( SCIPvarChgObjDive(var->data.aggregate.var, set, lp, newobj / var->data.aggregate.scalar) );
6482  /* the constant can be ignored, because it would only affect the objective shift */
6483  break;
6484 
6486  SCIPerrorMessage("cannot change diving objective value of a multi-aggregated variable\n");
6487  return SCIP_INVALIDDATA;
6488 
6489  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6490  assert(var->negatedvar != NULL);
6492  assert(var->negatedvar->negatedvar == var);
6493  SCIP_CALL( SCIPvarChgObjDive(var->negatedvar, set, lp, -newobj) );
6494  /* the offset can be ignored, because it would only affect the objective shift */
6495  break;
6496 
6497  default:
6498  SCIPerrorMessage("unknown variable status\n");
6499  return SCIP_INVALIDDATA;
6500  }
6501 
6502  return SCIP_OKAY;
6503 }
6504 
6505 /** adjust lower bound to integral value, if variable is integral */
6506 void SCIPvarAdjustLb(
6507  SCIP_VAR* var, /**< problem variable */
6508  SCIP_SET* set, /**< global SCIP settings */
6509  SCIP_Real* lb /**< pointer to lower bound to adjust */
6510  )
6511 {
6512  assert(var != NULL);
6513  assert(set != NULL);
6514  assert(var->scip == set->scip);
6515  assert(lb != NULL);
6516 
6517  SCIPsetDebugMsg(set, "adjust lower bound %g of <%s>\n", *lb, var->name);
6518 
6519  *lb = adjustedLb(set, SCIPvarGetType(var), *lb);
6520 }
6521 
6522 /** adjust upper bound to integral value, if variable is integral */
6523 void SCIPvarAdjustUb(
6524  SCIP_VAR* var, /**< problem variable */
6525  SCIP_SET* set, /**< global SCIP settings */
6526  SCIP_Real* ub /**< pointer to upper bound to adjust */
6527  )
6528 {
6529  assert(var != NULL);
6530  assert(set != NULL);
6531  assert(var->scip == set->scip);
6532  assert(ub != NULL);
6533 
6534  SCIPsetDebugMsg(set, "adjust upper bound %g of <%s>\n", *ub, var->name);
6535 
6536  *ub = adjustedUb(set, SCIPvarGetType(var), *ub);
6537 }
6538 
6539 /** adjust lower or upper bound to integral value, if variable is integral */
6540 void SCIPvarAdjustBd(
6541  SCIP_VAR* var, /**< problem variable */
6542  SCIP_SET* set, /**< global SCIP settings */
6543  SCIP_BOUNDTYPE boundtype, /**< type of bound to adjust */
6544  SCIP_Real* bd /**< pointer to bound to adjust */
6545  )
6546 {
6547  assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
6548 
6549  if( boundtype == SCIP_BOUNDTYPE_LOWER )
6550  SCIPvarAdjustLb(var, set, bd);
6551  else
6552  SCIPvarAdjustUb(var, set, bd);
6553 }
6554 
6555 /** changes lower bound of original variable in original problem */
6557  SCIP_VAR* var, /**< problem variable to change */
6558  SCIP_SET* set, /**< global SCIP settings */
6559  SCIP_Real newbound /**< new bound for variable */
6560  )
6561 {
6562  int i;
6563 
6564  assert(var != NULL);
6565  assert(!SCIPvarIsTransformed(var));
6567  assert(set != NULL);
6568  assert(var->scip == set->scip);
6569  assert(set->stage == SCIP_STAGE_PROBLEM);
6570 
6571  /* check that the bound is feasible */
6572  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsLE(set, newbound, SCIPvarGetUbOriginal(var)));
6573  /* adjust bound to integral value if variable is of integral type */
6574  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6575 
6576  if( SCIPsetIsZero(set, newbound) )
6577  newbound = 0.0;
6578 
6579  /* original domains are only stored for ORIGINAL variables, not for NEGATED */
6581  {
6582  SCIPsetDebugMsg(set, "changing original lower bound of <%s> from %g to %g\n",
6583  var->name, var->data.original.origdom.lb, newbound);
6584 
6585  if( SCIPsetIsEQ(set, var->data.original.origdom.lb, newbound) )
6586  return SCIP_OKAY;
6587 
6588  /* change the bound */
6589  var->data.original.origdom.lb = newbound;
6590  }
6591  else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
6592  {
6593  assert( var->negatedvar != NULL );
6594  SCIP_CALL( SCIPvarChgUbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
6595  }
6596 
6597  /* process parent variables */
6598  for( i = 0; i < var->nparentvars; ++i )
6599  {
6600  SCIP_VAR* parentvar;
6601 
6602  parentvar = var->parentvars[i];
6603  assert(parentvar != NULL);
6604  assert(SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_NEGATED);
6605  assert(parentvar->negatedvar == var);
6606  assert(var->negatedvar == parentvar);
6607 
6608  SCIP_CALL( SCIPvarChgUbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
6609  }
6610 
6611  return SCIP_OKAY;
6612 }
6613 
6614 /** changes upper bound of original variable in original problem */
6616  SCIP_VAR* var, /**< problem variable to change */
6617  SCIP_SET* set, /**< global SCIP settings */
6618  SCIP_Real newbound /**< new bound for variable */
6619  )
6620 {
6621  int i;
6622 
6623  assert(var != NULL);
6624  assert(!SCIPvarIsTransformed(var));
6626  assert(set != NULL);
6627  assert(var->scip == set->scip);
6628  assert(set->stage == SCIP_STAGE_PROBLEM);
6629 
6630  /* check that the bound is feasible */
6631  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsGE(set, newbound, SCIPvarGetLbOriginal(var)));
6632  /* adjust bound to integral value if variable is of integral type */
6633  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
6634 
6635  if( SCIPsetIsZero(set, newbound) )
6636  newbound = 0.0;
6637 
6638  /* original domains are only stored for ORIGINAL variables, not for NEGATED */
6640  {
6641  SCIPsetDebugMsg(set, "changing original upper bound of <%s> from %g to %g\n",
6642  var->name, var->data.original.origdom.ub, newbound);
6643 
6644  if( SCIPsetIsEQ(set, var->data.original.origdom.ub, newbound) )
6645  return SCIP_OKAY;
6646 
6647  /* change the bound */
6648  var->data.original.origdom.ub = newbound;
6649  }
6650  else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
6651  {
6652  assert( var->negatedvar != NULL );
6653  SCIP_CALL( SCIPvarChgLbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
6654  }
6655 
6656  /* process parent variables */
6657  for( i = 0; i < var->nparentvars; ++i )
6658  {
6659  SCIP_VAR* parentvar;
6660 
6661  parentvar = var->parentvars[i];
6662  assert(parentvar != NULL);
6663  assert(SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_NEGATED);
6664  assert(parentvar->negatedvar == var);
6665  assert(var->negatedvar == parentvar);
6666 
6667  SCIP_CALL( SCIPvarChgLbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
6668  }
6669 
6670  return SCIP_OKAY;
6671 }
6672 
6673 /** appends GLBCHANGED event to the event queue */
6674 static
6676  SCIP_VAR* var, /**< problem variable to change */
6677  BMS_BLKMEM* blkmem, /**< block memory */
6678  SCIP_SET* set, /**< global SCIP settings */
6679  SCIP_LP* lp, /**< current LP data */
6680  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6681  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6682  SCIP_Real oldbound, /**< old lower bound for variable */
6683  SCIP_Real newbound /**< new lower bound for variable */
6684  )
6685 {
6686  assert(var != NULL);
6687  assert(var->eventfilter != NULL);
6688  assert(SCIPvarIsTransformed(var));
6689  assert(!SCIPsetIsEQ(set, oldbound, newbound) || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
6690  assert(set != NULL);
6691  assert(var->scip == set->scip);
6692 
6693  /* check, if the variable is being tracked for bound changes
6694  * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
6695  */
6696  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GLBCHANGED) != 0)
6699  {
6700  SCIP_EVENT* event;
6701 
6702  SCIPsetDebugMsg(set, "issue GLBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
6703 
6704  SCIP_CALL( SCIPeventCreateGlbChanged(&event, blkmem, var, oldbound, newbound) );
6705  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
6706  }
6707 
6708  return SCIP_OKAY;
6709 }
6710 
6711 /** appends GUBCHANGED event to the event queue */
6712 static
6714  SCIP_VAR* var, /**< problem variable to change */
6715  BMS_BLKMEM* blkmem, /**< block memory */
6716  SCIP_SET* set, /**< global SCIP settings */
6717  SCIP_LP* lp, /**< current LP data */
6718  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6719  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6720  SCIP_Real oldbound, /**< old lower bound for variable */
6721  SCIP_Real newbound /**< new lower bound for variable */
6722  )
6723 {
6724  assert(var != NULL);
6725  assert(var->eventfilter != NULL);
6726  assert(SCIPvarIsTransformed(var));
6727  assert(!SCIPsetIsEQ(set, oldbound, newbound) || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
6728  assert(set != NULL);
6729  assert(var->scip == set->scip);
6730 
6731  /* check, if the variable is being tracked for bound changes
6732  * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
6733  */
6734  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GUBCHANGED) != 0)
6737  {
6738  SCIP_EVENT* event;
6739 
6740  SCIPsetDebugMsg(set, "issue GUBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
6741 
6742  SCIP_CALL( SCIPeventCreateGubChanged(&event, blkmem, var, oldbound, newbound) );
6743  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
6744  }
6745 
6746  return SCIP_OKAY;
6747 }
6748 
6749 /** appends GHOLEADDED event to the event queue */
6750 static
6752  SCIP_VAR* var, /**< problem variable to change */
6753  BMS_BLKMEM* blkmem, /**< block memory */
6754  SCIP_SET* set, /**< global SCIP settings */
6755  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6756  SCIP_Real left, /**< left bound of open interval in new hole */
6757  SCIP_Real right /**< right bound of open interval in new hole */
6758  )
6759 {
6760  assert(var != NULL);
6761  assert(var->eventfilter != NULL);
6762  assert(SCIPvarIsTransformed(var));
6763  assert(set != NULL);
6764  assert(var->scip == set->scip);
6765  assert(SCIPsetIsLT(set, left, right));
6766 
6767  /* check, if the variable is being tracked for bound changes */
6768  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GHOLEADDED) != 0) )
6769  {
6770  SCIP_EVENT* event;
6771 
6772  SCIPsetDebugMsg(set, "issue GHOLEADDED event for variable <%s>: (%.15g,%.15g)\n", var->name, left, right);
6773 
6774  SCIP_CALL( SCIPeventCreateGholeAdded(&event, blkmem, var, left, right) );
6775  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
6776  }
6777 
6778  return SCIP_OKAY;
6779 }
6780 
6781 /** increases root bound change statistics after a global bound change */
6782 static
6783 void varIncRootboundchgs(
6784  SCIP_VAR* var, /**< problem variable to change */
6785  SCIP_SET* set, /**< global SCIP settings */
6786  SCIP_STAT* stat /**< problem statistics */
6787  )
6788 {
6789  assert(var != NULL);
6790  assert(set != NULL);
6791  assert(var->scip == set->scip);
6792  assert(stat != NULL);
6793 
6794  if( SCIPvarIsActive(var) && SCIPvarIsTransformed(var) && set->stage == SCIP_STAGE_SOLVING )
6795  {
6796  stat->nrootboundchgs++;
6797  stat->nrootboundchgsrun++;
6798  if( SCIPvarIsIntegral(var) && SCIPvarGetLbGlobal(var) + 0.5 > SCIPvarGetUbGlobal(var) )
6799  {
6800  stat->nrootintfixings++;
6801  stat->nrootintfixingsrun++;
6802  }
6803  }
6804 }
6805 
6806 /* forward declaration, because both methods call each other recursively */
6807 
6808 /* performs the current change in upper bound, changes all parents accordingly */
6809 static
6811  SCIP_VAR* var, /**< problem variable to change */
6812  BMS_BLKMEM* blkmem, /**< block memory */
6813  SCIP_SET* set, /**< global SCIP settings */
6814  SCIP_STAT* stat, /**< problem statistics */
6815  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6816  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6817  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6818  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6819  SCIP_Real newbound /**< new bound for variable */
6820  );
6821 
6822 /** performs the current change in lower bound, changes all parents accordingly */
6823 static
6825  SCIP_VAR* var, /**< problem variable to change */
6826  BMS_BLKMEM* blkmem, /**< block memory */
6827  SCIP_SET* set, /**< global SCIP settings */
6828  SCIP_STAT* stat, /**< problem statistics */
6829  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6830  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6831  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6832  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6833  SCIP_Real newbound /**< new bound for variable */
6834  )
6835 {
6836  SCIP_VAR* parentvar;
6837  SCIP_Real oldbound;
6838  int i;
6839 
6840  assert(var != NULL);
6841  /* local domains can violate global bounds but not more than feasibility epsilon */
6842  assert(SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb));
6843  assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
6844  assert(blkmem != NULL);
6845  assert(set != NULL);
6846  assert(var->scip == set->scip);
6847  assert(stat != NULL);
6848 
6849  /* adjust bound to integral value if variable is of integral type */
6850  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6851 
6852  /* check that the bound is feasible */
6853  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound > var->glbdom.ub )
6854  {
6855  /* due to numerics we only want to be feasible in feasibility tolerance */
6856  assert(SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
6857  newbound = var->glbdom.ub;
6858  }
6859  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6860 
6861  assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
6862 
6863  SCIPsetDebugMsg(set, "process changing global lower bound of <%s> from %f to %f\n", var->name, var->glbdom.lb, newbound);
6864 
6865  if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) && !(newbound != var->glbdom.lb && newbound * var->glbdom.lb <= 0.0) ) /*lint !e777*/
6866  return SCIP_OKAY;
6867 
6868  /* check bound on debugging solution */
6869  SCIP_CALL( SCIPdebugCheckLbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
6870 
6871  /* change the bound */
6872  oldbound = var->glbdom.lb;
6873  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
6874  var->glbdom.lb = newbound;
6875  assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
6876  assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
6877 
6878  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6879  {
6880  /* merges overlapping holes into single holes, moves bounds respectively */
6881  domMerge(&var->glbdom, blkmem, set, &newbound, NULL);
6882  }
6883 
6884  /* update the root bound changes counters */
6885  varIncRootboundchgs(var, set, stat);
6886 
6887  /* update the lbchginfos array by replacing worse local bounds with the new global bound and changing the
6888  * redundant bound changes to be branching decisions
6889  */
6890  for( i = 0; i < var->nlbchginfos; ++i )
6891  {
6892  assert(var->lbchginfos[i].var == var);
6893 
6894  if( var->lbchginfos[i].oldbound < var->glbdom.lb )
6895  {
6896  SCIPsetDebugMsg(set, " -> adjust lower bound change <%s>: %g -> %g due to new global lower bound %g\n",
6897  SCIPvarGetName(var), var->lbchginfos[i].oldbound, var->lbchginfos[i].newbound, var->glbdom.lb);
6898  var->lbchginfos[i].oldbound = var->glbdom.lb;
6899  if( SCIPsetIsLE(set, var->lbchginfos[i].newbound, var->glbdom.lb) )
6900  {
6901  /* this bound change is redundant due to the new global bound */
6902  var->lbchginfos[i].newbound = var->glbdom.lb;
6903  var->lbchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
6904  var->lbchginfos[i].redundant = TRUE;
6905  }
6906  else
6907  break; /* from now on, the remaining local bound changes are not redundant */
6908  }
6909  else
6910  break; /* from now on, the remaining local bound changes are not redundant */
6911  }
6912 
6913  /* remove redundant implications and variable bounds */
6915  && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
6916  {
6917  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
6918  }
6919 
6920  /* issue bound change event */
6921  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
6922  if( var->eventfilter != NULL )
6923  {
6924  SCIP_CALL( varEventGlbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
6925  }
6926 
6927  /* process parent variables */
6928  for( i = 0; i < var->nparentvars; ++i )
6929  {
6930  parentvar = var->parentvars[i];
6931  assert(parentvar != NULL);
6932 
6933  switch( SCIPvarGetStatus(parentvar) )
6934  {
6936  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6937  break;
6938 
6939  case SCIP_VARSTATUS_COLUMN:
6940  case SCIP_VARSTATUS_LOOSE:
6941  case SCIP_VARSTATUS_FIXED:
6943  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
6944  return SCIP_INVALIDDATA;
6945 
6946  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6947  assert(parentvar->data.aggregate.var == var);
6948  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
6949  {
6950  SCIP_Real parentnewbound;
6951 
6952  /* a > 0 -> change lower bound of y */
6953  assert(SCIPsetIsInfinity(set, -parentvar->glbdom.lb) || SCIPsetIsInfinity(set, -oldbound)
6954  || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
6955  || (SCIPsetIsZero(set, parentvar->glbdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
6956 
6957  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6958  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6959  else
6960  parentnewbound = newbound;
6961  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6962  }
6963  else
6964  {
6965  SCIP_Real parentnewbound;
6966 
6967  /* a < 0 -> change upper bound of y */
6968  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
6969  assert(SCIPsetIsInfinity(set, parentvar->glbdom.ub) || SCIPsetIsInfinity(set, -oldbound)
6970  || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
6971  || (SCIPsetIsZero(set, parentvar->glbdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
6972 
6973  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6974  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6975  else
6976  parentnewbound = -newbound;
6977  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6978  }
6979  break;
6980 
6981  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6982  assert(parentvar->negatedvar != NULL);
6983  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
6984  assert(parentvar->negatedvar->negatedvar == parentvar);
6985  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6986  parentvar->data.negate.constant - newbound) );
6987  break;
6988 
6989  default:
6990  SCIPerrorMessage("unknown variable status\n");
6991  return SCIP_INVALIDDATA;
6992  }
6993  }
6994 
6995  return SCIP_OKAY;
6996 }
6997 
6998 /** performs the current change in upper bound, changes all parents accordingly */
6999 static
7001  SCIP_VAR* var, /**< problem variable to change */
7002  BMS_BLKMEM* blkmem, /**< block memory */
7003  SCIP_SET* set, /**< global SCIP settings */
7004  SCIP_STAT* stat, /**< problem statistics */
7005  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7006  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7007  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7008  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7009  SCIP_Real newbound /**< new bound for variable */
7010  )
7011 {
7012  SCIP_VAR* parentvar;
7013  SCIP_Real oldbound;
7014  int i;
7015 
7016  assert(var != NULL);
7017  /* local domains can violate global bounds but not more than feasibility epsilon */
7018  assert(SCIPsetIsFeasLE(set, var->glbdom.lb , var->locdom.lb));
7019  assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
7020  assert(blkmem != NULL);
7021  assert(set != NULL);
7022  assert(var->scip == set->scip);
7023  assert(stat != NULL);
7024 
7025  /* adjust bound to integral value if variable is of integral type */
7026  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7027 
7028  /* check that the bound is feasible */
7029  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound < var->glbdom.lb )
7030  {
7031  /* due to numerics we only want to be feasible in feasibility tolerance */
7032  assert(SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
7033  newbound = var->glbdom.lb;
7034  }
7035  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7036 
7037  assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
7038 
7039  SCIPsetDebugMsg(set, "process changing global upper bound of <%s> from %f to %f\n", var->name, var->glbdom.ub, newbound);
7040 
7041  if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) && !(newbound != var->glbdom.ub && newbound * var->glbdom.ub <= 0.0) ) /*lint !e777*/
7042  return SCIP_OKAY;
7043 
7044  /* check bound on debugging solution */
7045  SCIP_CALL( SCIPdebugCheckUbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
7046 
7047  /* change the bound */
7048  oldbound = var->glbdom.ub;
7049  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
7050  var->glbdom.ub = newbound;
7051  assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
7052  assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
7053 
7054  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7055  {
7056  /* merges overlapping holes into single holes, moves bounds respectively */
7057  domMerge(&var->glbdom, blkmem, set, NULL, &newbound);
7058  }
7059 
7060  /* update the root bound changes counters */
7061  varIncRootboundchgs(var, set, stat);
7062 
7063  /* update the ubchginfos array by replacing worse local bounds with the new global bound and changing the
7064  * redundant bound changes to be branching decisions
7065  */
7066  for( i = 0; i < var->nubchginfos; ++i )
7067  {
7068  assert(var->ubchginfos[i].var == var);
7069  if( var->ubchginfos[i].oldbound > var->glbdom.ub )
7070  {
7071  SCIPsetDebugMsg(set, " -> adjust upper bound change <%s>: %g -> %g due to new global upper bound %g\n",
7072  SCIPvarGetName(var), var->ubchginfos[i].oldbound, var->ubchginfos[i].newbound, var->glbdom.ub);
7073  var->ubchginfos[i].oldbound = var->glbdom.ub;
7074  if( SCIPsetIsGE(set, var->ubchginfos[i].newbound, var->glbdom.ub) )
7075  {
7076  /* this bound change is redundant due to the new global bound */
7077  var->ubchginfos[i].newbound = var->glbdom.ub;
7078  var->ubchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
7079  var->ubchginfos[i].redundant = TRUE;
7080  }
7081  else
7082  break; /* from now on, the remaining local bound changes are not redundant */
7083  }
7084  else
7085  break; /* from now on, the remaining local bound changes are not redundant */
7086  }
7087 
7088  /* remove redundant implications and variable bounds */
7090  && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
7091  {
7092  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
7093  }
7094 
7095  /* issue bound change event */
7096  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7097  if( var->eventfilter != NULL )
7098  {
7099  SCIP_CALL( varEventGubChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7100  }
7101 
7102  /* process parent variables */
7103  for( i = 0; i < var->nparentvars; ++i )
7104  {
7105  parentvar = var->parentvars[i];
7106  assert(parentvar != NULL);
7107 
7108  switch( SCIPvarGetStatus(parentvar) )
7109  {
7111  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7112  break;
7113 
7114  case SCIP_VARSTATUS_COLUMN:
7115  case SCIP_VARSTATUS_LOOSE:
7116  case SCIP_VARSTATUS_FIXED:
7118  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7119  return SCIP_INVALIDDATA;
7120 
7121  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7122  assert(parentvar->data.aggregate.var == var);
7123  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7124  {
7125  SCIP_Real parentnewbound;
7126 
7127  /* a > 0 -> change upper bound of y */
7128  assert(SCIPsetIsInfinity(set, parentvar->glbdom.ub) || SCIPsetIsInfinity(set, oldbound)
7129  || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub,
7130  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7131  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7132  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7133  else
7134  parentnewbound = newbound;
7135  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
7136  }
7137  else
7138  {
7139  SCIP_Real parentnewbound;
7140 
7141  /* a < 0 -> change lower bound of y */
7142  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7143  assert(SCIPsetIsInfinity(set, -parentvar->glbdom.lb) || SCIPsetIsInfinity(set, oldbound)
7144  || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb,
7145  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7146  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7147  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7148  else
7149  parentnewbound = -newbound;
7150  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
7151  }
7152  break;
7153 
7154  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7155  assert(parentvar->negatedvar != NULL);
7156  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7157  assert(parentvar->negatedvar->negatedvar == parentvar);
7158  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7159  parentvar->data.negate.constant - newbound) );
7160  break;
7161 
7162  default:
7163  SCIPerrorMessage("unknown variable status\n");
7164  return SCIP_INVALIDDATA;
7165  }
7166  }
7167 
7168  return SCIP_OKAY;
7169 }
7170 
7171 /** changes global lower bound of variable; if possible, adjusts bound to integral value;
7172  * updates local lower bound if the global bound is tighter
7173  */
7175  SCIP_VAR* var, /**< problem variable to change */
7176  BMS_BLKMEM* blkmem, /**< block memory */
7177  SCIP_SET* set, /**< global SCIP settings */
7178  SCIP_STAT* stat, /**< problem statistics */
7179  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7180  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7181  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7182  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7183  SCIP_Real newbound /**< new bound for variable */
7184  )
7185 {
7186  assert(var != NULL);
7187  assert(blkmem != NULL);
7188  assert(set != NULL);
7189  assert(var->scip == set->scip);
7190 
7191  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7192  * of the domain within feastol
7193  */
7194  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
7195 
7196  /* adjust bound to integral value if variable is of integral type */
7197  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7198 
7199  /* check that the adjusted bound is feasible
7200  * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
7201  * here because we reset bounds to their original value!
7202  */
7203  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
7204 
7205  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7206  {
7207  /* we do not want to exceed the upperbound, which could have happened due to numerics */
7208  newbound = MIN(newbound, var->glbdom.ub);
7209  }
7210  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7211 
7212  /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
7213  * SCIPvarFix() allows fixings that are outside of the domain within feastol
7214  */
7215  assert(lp == NULL || SCIPsetIsFeasLE(set, var->glbdom.lb, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
7216 
7217  SCIPsetDebugMsg(set, "changing global lower bound of <%s> from %g to %g\n", var->name, var->glbdom.lb, newbound);
7218 
7219  if( SCIPsetIsEQ(set, var->glbdom.lb, newbound) && !(newbound != var->glbdom.lb && newbound * var->glbdom.lb <= 0.0) ) /*lint !e777*/
7220  return SCIP_OKAY;
7221 
7222  /* change bounds of attached variables */
7223  switch( SCIPvarGetStatus(var) )
7224  {
7226  if( var->data.original.transvar != NULL )
7227  {
7228  SCIP_CALL( SCIPvarChgLbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
7229  cliquetable, newbound) );
7230  }
7231  else
7232  {
7233  assert(set->stage == SCIP_STAGE_PROBLEM);
7234  if( newbound > SCIPvarGetLbLocal(var) )
7235  {
7236  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7237  }
7238  SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7239  }
7240  break;
7241 
7242  case SCIP_VARSTATUS_COLUMN:
7243  case SCIP_VARSTATUS_LOOSE:
7244  if( newbound > SCIPvarGetLbLocal(var) )
7245  {
7246  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7247  }
7248  SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7249  break;
7250 
7251  case SCIP_VARSTATUS_FIXED:
7252  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7253  return SCIP_INVALIDDATA;
7254 
7255  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7256  assert(var->data.aggregate.var != NULL);
7257  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7258  {
7259  SCIP_Real childnewbound;
7260 
7261  /* a > 0 -> change lower bound of y */
7262  assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, -var->data.aggregate.var->glbdom.lb))
7263  || SCIPsetIsFeasEQ(set, var->glbdom.lb,
7265  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7266  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7267  else
7268  childnewbound = newbound;
7269  SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7270  childnewbound) );
7271  }
7272  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7273  {
7274  SCIP_Real childnewbound;
7275 
7276  /* a < 0 -> change upper bound of y */
7277  assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
7278  || SCIPsetIsFeasEQ(set, var->glbdom.lb,
7280  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7281  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7282  else
7283  childnewbound = -newbound;
7284  SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7285  childnewbound) );
7286  }
7287  else
7288  {
7289  SCIPerrorMessage("scalar is zero in aggregation\n");
7290  return SCIP_INVALIDDATA;
7291  }
7292  break;
7293 
7295  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7296  return SCIP_INVALIDDATA;
7297 
7298  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7299  assert(var->negatedvar != NULL);
7301  assert(var->negatedvar->negatedvar == var);
7302  SCIP_CALL( SCIPvarChgUbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7303  var->data.negate.constant - newbound) );
7304  break;
7305 
7306  default:
7307  SCIPerrorMessage("unknown variable status\n");
7308  return SCIP_INVALIDDATA;
7309  }
7310 
7311  return SCIP_OKAY;
7312 }
7313 
7314 /** changes global upper bound of variable; if possible, adjusts bound to integral value;
7315  * updates local upper bound if the global bound is tighter
7316  */
7318  SCIP_VAR* var, /**< problem variable to change */
7319  BMS_BLKMEM* blkmem, /**< block memory */
7320  SCIP_SET* set, /**< global SCIP settings */
7321  SCIP_STAT* stat, /**< problem statistics */
7322  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7323  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7324  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7325  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7326  SCIP_Real newbound /**< new bound for variable */
7327  )
7328 {
7329  assert(var != NULL);
7330  assert(blkmem != NULL);
7331  assert(set != NULL);
7332  assert(var->scip == set->scip);
7333 
7334  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7335  * of the domain within feastol
7336  */
7337  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
7338 
7339  /* adjust bound to integral value if variable is of integral type */
7340  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7341 
7342  /* check that the adjusted bound is feasible
7343  * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
7344  * here because we reset bounds to their original value!
7345  */
7346  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
7347 
7348  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7349  {
7350  /* we do not want to undercut the lowerbound, which could have happened due to numerics */
7351  newbound = MAX(newbound, var->glbdom.lb);
7352  }
7353  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7354 
7355  /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
7356  * SCIPvarFix() allows fixings that are outside of the domain within feastol
7357  */
7358  assert(lp == NULL || SCIPsetIsFeasGE(set, var->glbdom.ub, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
7359 
7360  SCIPsetDebugMsg(set, "changing global upper bound of <%s> from %g to %g\n", var->name, var->glbdom.ub, newbound);
7361 
7362  if( SCIPsetIsEQ(set, var->glbdom.ub, newbound) && !(newbound != var->glbdom.ub && newbound * var->glbdom.ub <= 0.0) ) /*lint !e777*/
7363  return SCIP_OKAY;
7364 
7365  /* change bounds of attached variables */
7366  switch( SCIPvarGetStatus(var) )
7367  {
7369  if( var->data.original.transvar != NULL )
7370  {
7371  SCIP_CALL( SCIPvarChgUbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7372  newbound) );
7373  }
7374  else
7375  {
7376  assert(set->stage == SCIP_STAGE_PROBLEM);
7377  if( newbound < SCIPvarGetUbLocal(var) )
7378  {
7379  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7380  }
7381  SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7382  }
7383  break;
7384 
7385  case SCIP_VARSTATUS_COLUMN:
7386  case SCIP_VARSTATUS_LOOSE:
7387  if( newbound < SCIPvarGetUbLocal(var) )
7388  {
7389  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7390  }
7391  SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7392  break;
7393 
7394  case SCIP_VARSTATUS_FIXED:
7395  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7396  return SCIP_INVALIDDATA;
7397 
7398  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7399  assert(var->data.aggregate.var != NULL);
7400  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7401  {
7402  SCIP_Real childnewbound;
7403 
7404  /* a > 0 -> change lower bound of y */
7405  assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
7406  || SCIPsetIsFeasEQ(set, var->glbdom.ub,
7408  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7409  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7410  else
7411  childnewbound = newbound;
7412  SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7413  childnewbound) );
7414  }
7415  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7416  {
7417  SCIP_Real childnewbound;
7418 
7419  /* a < 0 -> change upper bound of y */
7420  assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, -var->data.aggregate.var->glbdom.lb))
7421  || SCIPsetIsFeasEQ(set, var->glbdom.ub,
7423  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7424  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7425  else
7426  childnewbound = -newbound;
7427  SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7428  childnewbound) );
7429  }
7430  else
7431  {
7432  SCIPerrorMessage("scalar is zero in aggregation\n");
7433  return SCIP_INVALIDDATA;
7434  }
7435  break;
7436 
7438  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7439  return SCIP_INVALIDDATA;
7440 
7441  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7442  assert(var->negatedvar != NULL);
7444  assert(var->negatedvar->negatedvar == var);
7445  SCIP_CALL( SCIPvarChgLbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7446  var->data.negate.constant - newbound) );
7447  break;
7448 
7449  default:
7450  SCIPerrorMessage("unknown variable status\n");
7451  return SCIP_INVALIDDATA;
7452  }
7453 
7454  return SCIP_OKAY;
7455 }
7456 
7457 /** changes lazy lower bound of the variable, this is only possible if the variable is not in the LP yet */
7459  SCIP_VAR* var, /**< problem variable */
7460  SCIP_SET* set, /**< global SCIP settings */
7461  SCIP_Real lazylb /**< the lazy lower bound to be set */
7462  )
7463 {
7464  assert(var != NULL);
7465  assert(var->probindex != -1);
7466  assert(SCIPsetIsFeasGE(set, var->glbdom.ub, lazylb));
7467  assert(SCIPsetIsFeasGE(set, var->lazyub, lazylb));
7468  assert(set != NULL);
7469  assert(var->scip == set->scip);
7470 
7471  /* variable should not be in the LP */
7473  return SCIP_INVALIDCALL;
7474 
7475  var->lazylb = lazylb;
7476 
7477  return SCIP_OKAY;
7478 }
7479 
7480 /** changes lazy upper bound of the variable, this is only possible if the variable is not in the LP yet */
7482  SCIP_VAR* var, /**< problem variable */
7483  SCIP_SET* set, /**< global SCIP settings */
7484  SCIP_Real lazyub /**< the lazy lower bound to be set */
7485  )
7486 {
7487  assert(var != NULL);
7488  assert(var->probindex != -1);
7489  assert(SCIPsetIsFeasGE(set, lazyub, var->glbdom.lb));
7490  assert(SCIPsetIsFeasGE(set, lazyub, var->lazylb));
7491  assert(set != NULL);
7492  assert(var->scip == set->scip);
7493 
7494  /* variable should not be in the LP */
7496  return SCIP_INVALIDCALL;
7497 
7498  var->lazyub = lazyub;
7499 
7500  return SCIP_OKAY;
7501 }
7502 
7503 
7504 /** changes global bound of variable; if possible, adjusts bound to integral value;
7505  * updates local bound if the global bound is tighter
7506  */
7508  SCIP_VAR* var, /**< problem variable to change */
7509  BMS_BLKMEM* blkmem, /**< block memory */
7510  SCIP_SET* set, /**< global SCIP settings */
7511  SCIP_STAT* stat, /**< problem statistics */
7512  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7513  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7514  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7515  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7516  SCIP_Real newbound, /**< new bound for variable */
7517  SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
7518  )
7519 {
7520  /* apply bound change to the LP data */
7521  switch( boundtype )
7522  {
7523  case SCIP_BOUNDTYPE_LOWER:
7524  return SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
7525  case SCIP_BOUNDTYPE_UPPER:
7526  return SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
7527  default:
7528  SCIPerrorMessage("unknown bound type\n");
7529  return SCIP_INVALIDDATA;
7530  }
7531 }
7532 
7533 /** appends LBTIGHTENED or LBRELAXED event to the event queue */
7534 static
7536  SCIP_VAR* var, /**< problem variable to change */
7537  BMS_BLKMEM* blkmem, /**< block memory */
7538  SCIP_SET* set, /**< global SCIP settings */
7539  SCIP_LP* lp, /**< current LP data */
7540  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7541  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7542  SCIP_Real oldbound, /**< old lower bound for variable */
7543  SCIP_Real newbound /**< new lower bound for variable */
7544  )
7545 {
7546  assert(var != NULL);
7547  assert(var->eventfilter != NULL);
7548  assert(SCIPvarIsTransformed(var));
7549  assert(!SCIPsetIsEQ(set, oldbound, newbound) || newbound == var->glbdom.lb || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
7550  assert(set != NULL);
7551  assert(var->scip == set->scip);
7552 
7553  /* check, if the variable is being tracked for bound changes
7554  * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
7555  */
7556  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_LBCHANGED) != 0)
7559  {
7560  SCIP_EVENT* event;
7561 
7562  SCIPsetDebugMsg(set, "issue LBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
7563 
7564  SCIP_CALL( SCIPeventCreateLbChanged(&event, blkmem, var, oldbound, newbound) );
7565  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
7566  }
7567 
7568  return SCIP_OKAY;
7569 }
7570 
7571 /** appends UBTIGHTENED or UBRELAXED event to the event queue */
7572 static
7574  SCIP_VAR* var, /**< problem variable to change */
7575  BMS_BLKMEM* blkmem, /**< block memory */
7576  SCIP_SET* set, /**< global SCIP settings */
7577  SCIP_LP* lp, /**< current LP data */
7578  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7579  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7580  SCIP_Real oldbound, /**< old upper bound for variable */
7581  SCIP_Real newbound /**< new upper bound for variable */
7582  )
7583 {
7584  assert(var != NULL);
7585  assert(var->eventfilter != NULL);
7586  assert(SCIPvarIsTransformed(var));
7587  assert(!SCIPsetIsEQ(set, oldbound, newbound) || newbound == var->glbdom.ub || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
7588  assert(set != NULL);
7589  assert(var->scip == set->scip);
7590 
7591  /* check, if the variable is being tracked for bound changes
7592  * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
7593  */
7594  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_UBCHANGED) != 0)
7597  {
7598  SCIP_EVENT* event;
7599 
7600  SCIPsetDebugMsg(set, "issue UBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
7601 
7602  SCIP_CALL( SCIPeventCreateUbChanged(&event, blkmem, var, oldbound, newbound) );
7603  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
7604  }
7605 
7606  return SCIP_OKAY;
7607 }
7608 
7609 /* forward declaration, because both methods call each other recursively */
7610 
7611 /* performs the current change in upper bound, changes all parents accordingly */
7612 static
7614  SCIP_VAR* var, /**< problem variable to change */
7615  BMS_BLKMEM* blkmem, /**< block memory */
7616  SCIP_SET* set, /**< global SCIP settings */
7617  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7618  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7619  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7620  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7621  SCIP_Real newbound /**< new bound for variable */
7622  );
7623 
7624 /** performs the current change in lower bound, changes all parents accordingly */
7625 static
7627  SCIP_VAR* var, /**< problem variable to change */
7628  BMS_BLKMEM* blkmem, /**< block memory */
7629  SCIP_SET* set, /**< global SCIP settings */
7630  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7631  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7632  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7633  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7634  SCIP_Real newbound /**< new bound for variable */
7635  )
7636 {
7637  SCIP_VAR* parentvar;
7638  SCIP_Real oldbound;
7639  int i;
7640 
7641  assert(var != NULL);
7642  assert(set != NULL);
7643  assert(var->scip == set->scip);
7644  assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)
7645  || SCIPsetIsEQ(set, newbound, var->locdom.ub)))
7646  || (SCIPvarGetType(var) < SCIP_VARTYPE_CONTINUOUS && (SCIPsetIsIntegral(set, newbound)
7647  || SCIPsetIsEQ(set, newbound, var->locdom.ub)))
7649 
7650  /* check that the bound is feasible */
7651  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsLE(set, newbound, var->glbdom.ub));
7652  /* adjust bound to integral value if variable is of integral type */
7653  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7654 
7655  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7656  {
7657  /* we do not want to exceed the upper bound, which could have happened due to numerics */
7658  newbound = MIN(newbound, var->locdom.ub);
7659 
7660  /* we do not want to undercut the global lower bound, which could have happened due to numerics */
7661  newbound = MAX(newbound, var->glbdom.lb);
7662  }
7663  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7664 
7665  SCIPsetDebugMsg(set, "process changing lower bound of <%s> from %g to %g\n", var->name, var->locdom.lb, newbound);
7666 
7667  if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) && var->glbdom.lb != var->locdom.lb ) /*lint !e777*/
7668  newbound = var->glbdom.lb;
7669  else if( SCIPsetIsEQ(set, newbound, var->locdom.lb) && !(newbound != var->locdom.lb && newbound * var->locdom.lb <= 0.0) ) /*lint !e777*/
7670  return SCIP_OKAY;
7671 
7672  /* change the bound */
7673  oldbound = var->locdom.lb;
7674  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->locdom.ub));
7675  var->locdom.lb = newbound;
7676 
7677  /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
7678  * once update the statistic
7679  */
7680  if( stat != NULL )
7681  SCIPstatIncrement(stat, set, domchgcount);
7682 
7683  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7684  {
7685  /* merges overlapping holes into single holes, moves bounds respectively */
7686  domMerge(&var->locdom, blkmem, set, &newbound, NULL);
7687  }
7688 
7689  /* issue bound change event */
7690  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7691  if( var->eventfilter != NULL )
7692  {
7693  SCIP_CALL( varEventLbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7694  }
7695 
7696  /* process parent variables */
7697  for( i = 0; i < var->nparentvars; ++i )
7698  {
7699  parentvar = var->parentvars[i];
7700  assert(parentvar != NULL);
7701 
7702  switch( SCIPvarGetStatus(parentvar) )
7703  {
7705  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
7706  break;
7707 
7708  case SCIP_VARSTATUS_COLUMN:
7709  case SCIP_VARSTATUS_LOOSE:
7710  case SCIP_VARSTATUS_FIXED:
7712  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7713  return SCIP_INVALIDDATA;
7714 
7715  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7716  assert(parentvar->data.aggregate.var == var);
7717  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7718  {
7719  SCIP_Real parentnewbound;
7720 
7721  /* a > 0 -> change lower bound of y */
7722  assert(SCIPsetIsInfinity(set, -parentvar->locdom.lb) || SCIPsetIsInfinity(set, -oldbound)
7723  || SCIPsetIsFeasEQ(set, parentvar->locdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
7724  || (SCIPsetIsZero(set, parentvar->locdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
7725 
7726  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7727  {
7728  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7729  /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
7730  * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
7731  * as a result, the parent's lower bound is set to it's upper bound, and not above
7732  */
7733  if( parentnewbound > parentvar->glbdom.ub )
7734  {
7735  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7736  assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
7737  parentnewbound = parentvar->glbdom.ub;
7738  }
7739  }
7740  else
7741  parentnewbound = newbound;
7742  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7743  }
7744  else
7745  {
7746  SCIP_Real parentnewbound;
7747 
7748  /* a < 0 -> change upper bound of y */
7749  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7750  assert(SCIPsetIsInfinity(set, parentvar->locdom.ub) || SCIPsetIsInfinity(set, -oldbound)
7751  || SCIPsetIsFeasEQ(set, parentvar->locdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
7752  || (SCIPsetIsZero(set, parentvar->locdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
7753 
7754  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7755  {
7756  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7757  /* 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
7758  * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
7759  * as a result, the parent's upper bound is set to it's lower bound, and not below
7760  */
7761  if( parentnewbound < parentvar->glbdom.lb )
7762  {
7763  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7764  assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
7765  parentnewbound = parentvar->glbdom.lb;
7766  }
7767  }
7768  else
7769  parentnewbound = -newbound;
7770  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7771  }
7772  break;
7773 
7774  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
7775  assert(parentvar->negatedvar != NULL);
7776  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7777  assert(parentvar->negatedvar->negatedvar == parentvar);
7778  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
7779  parentvar->data.negate.constant - newbound) );
7780  break;
7781 
7782  default:
7783  SCIPerrorMessage("unknown variable status\n");
7784  return SCIP_INVALIDDATA;
7785  }
7786  }
7787 
7788  return SCIP_OKAY;
7789 }
7790 
7791 /** performs the current change in upper bound, changes all parents accordingly */
7792 static
7794  SCIP_VAR* var, /**< problem variable to change */
7795  BMS_BLKMEM* blkmem, /**< block memory */
7796  SCIP_SET* set, /**< global SCIP settings */
7797  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7798  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7799  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7800  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7801  SCIP_Real newbound /**< new bound for variable */
7802  )
7803 {
7804  SCIP_VAR* parentvar;
7805  SCIP_Real oldbound;
7806  int i;
7807 
7808  assert(var != NULL);
7809  assert(set != NULL);
7810  assert(var->scip == set->scip);
7811  assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)
7812  || SCIPsetIsEQ(set, newbound, var->locdom.lb)))
7813  || (SCIPvarGetType(var) < SCIP_VARTYPE_CONTINUOUS && (SCIPsetIsIntegral(set, newbound)
7814  || SCIPsetIsEQ(set, newbound, var->locdom.lb)))
7816 
7817  /* check that the bound is feasible */
7818  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsGE(set, newbound, var->glbdom.lb));
7819  /* adjust bound to integral value if variable is of integral type */
7820  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7821 
7822  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7823  {
7824  /* we do not want to undercut the lower bound, which could have happened due to numerics */
7825  newbound = MAX(newbound, var->locdom.lb);
7826 
7827  /* we do not want to exceed the global upper bound, which could have happened due to numerics */
7828  newbound = MIN(newbound, var->glbdom.ub);
7829  }
7830  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7831 
7832  SCIPsetDebugMsg(set, "process changing upper bound of <%s> from %g to %g\n", var->name, var->locdom.ub, newbound);
7833 
7834  if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) && var->glbdom.ub != var->locdom.ub ) /*lint !e777*/
7835  newbound = var->glbdom.ub;
7836  else if( SCIPsetIsEQ(set, newbound, var->locdom.ub) && !(newbound != var->locdom.ub && newbound * var->locdom.ub <= 0.0) ) /*lint !e777*/
7837  return SCIP_OKAY;
7838 
7839  /* change the bound */
7840  oldbound = var->locdom.ub;
7841  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->locdom.lb));
7842  var->locdom.ub = newbound;
7843 
7844  /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
7845  * once update the statistic
7846  */
7847  if( stat != NULL )
7848  SCIPstatIncrement(stat, set, domchgcount);
7849 
7850  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7851  {
7852  /* merges overlapping holes into single holes, moves bounds respectively */
7853  domMerge(&var->locdom, blkmem, set, NULL, &newbound);
7854  }
7855 
7856  /* issue bound change event */
7857  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7858  if( var->eventfilter != NULL )
7859  {
7860  SCIP_CALL( varEventUbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7861  }
7862 
7863  /* process parent variables */
7864  for( i = 0; i < var->nparentvars; ++i )
7865  {
7866  parentvar = var->parentvars[i];
7867  assert(parentvar != NULL);
7868 
7869  switch( SCIPvarGetStatus(parentvar) )
7870  {
7872  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
7873  break;
7874 
7875  case SCIP_VARSTATUS_COLUMN:
7876  case SCIP_VARSTATUS_LOOSE:
7877  case SCIP_VARSTATUS_FIXED:
7879  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7880  return SCIP_INVALIDDATA;
7881 
7882  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7883  assert(parentvar->data.aggregate.var == var);
7884  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7885  {
7886  SCIP_Real parentnewbound;
7887 
7888  /* a > 0 -> change upper bound of x */
7889  assert(SCIPsetIsInfinity(set, parentvar->locdom.ub) || SCIPsetIsInfinity(set, oldbound)
7890  || SCIPsetIsFeasEQ(set, parentvar->locdom.ub,
7891  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7892  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7893  {
7894  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7895  /* 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
7896  * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
7897  * as a result, the parent's upper bound is set to it's lower bound, and not below
7898  */
7899  if( parentnewbound < parentvar->glbdom.lb )
7900  {
7901  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7902  assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
7903  parentnewbound = parentvar->glbdom.lb;
7904  }
7905  }
7906  else
7907  parentnewbound = newbound;
7908  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7909  }
7910  else
7911  {
7912  SCIP_Real parentnewbound;
7913 
7914  /* a < 0 -> change lower bound of x */
7915  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7916  assert(SCIPsetIsInfinity(set, -parentvar->locdom.lb) || SCIPsetIsInfinity(set, oldbound)
7917  || SCIPsetIsFeasEQ(set, parentvar->locdom.lb,
7918  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7919  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7920  {
7921  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7922  /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
7923  * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
7924  * as a result, the parent's lower bound is set to it's upper bound, and not above
7925  */
7926  if( parentnewbound > parentvar->glbdom.ub )
7927  {
7928  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7929  assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
7930  parentnewbound = parentvar->glbdom.ub;
7931  }
7932  }
7933  else
7934  parentnewbound = -newbound;
7935  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7936  }
7937  break;
7938 
7939  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
7940  assert(parentvar->negatedvar != NULL);
7941  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7942  assert(parentvar->negatedvar->negatedvar == parentvar);
7943  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
7944  parentvar->data.negate.constant - newbound) );
7945  break;
7946 
7947  default:
7948  SCIPerrorMessage("unknown variable status\n");
7949  return SCIP_INVALIDDATA;
7950  }
7951  }
7952 
7953  return SCIP_OKAY;
7954 }
7955 
7956 /** changes current local lower bound of variable; if possible, adjusts bound to integral value; stores inference
7957  * information in variable
7958  */
7960  SCIP_VAR* var, /**< problem variable to change */
7961  BMS_BLKMEM* blkmem, /**< block memory */
7962  SCIP_SET* set, /**< global SCIP settings */
7963  SCIP_STAT* stat, /**< problem statistics */
7964  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7965  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7966  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7967  SCIP_Real newbound /**< new bound for variable */
7968  )
7969 {
7970  assert(var != NULL);
7971  assert(blkmem != NULL);
7972  assert(set != NULL);
7973  assert(var->scip == set->scip);
7974 
7975  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7976  * of the domain within feastol
7977  */
7978  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
7979 
7980  /* adjust bound to integral value if variable is of integral type */
7981  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7982 
7983  /* check that the adjusted bound is feasible */
7984  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
7985 
7986  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7987  {
7988  /* we do not want to exceed the upperbound, which could have happened due to numerics */
7989  newbound = MIN(newbound, var->locdom.ub);
7990  }
7991  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7992 
7993  SCIPsetDebugMsg(set, "changing lower bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
7994 
7995  if( SCIPsetIsEQ(set, var->locdom.lb, newbound) && (!SCIPsetIsEQ(set, var->glbdom.lb, newbound) || var->locdom.lb == newbound) /*lint !e777*/
7996  && !(newbound != var->locdom.lb && newbound * var->locdom.lb <= 0.0) ) /*lint !e777*/
7997  return SCIP_OKAY;
7998 
7999  /* change bounds of attached variables */
8000  switch( SCIPvarGetStatus(var) )
8001  {
8003  if( var->data.original.transvar != NULL )
8004  {
8005  SCIP_CALL( SCIPvarChgLbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
8006  newbound) );
8007  }
8008  else
8009  {
8010  assert(set->stage == SCIP_STAGE_PROBLEM);
8011  SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8012  }
8013  break;
8014 
8015  case SCIP_VARSTATUS_COLUMN:
8016  case SCIP_VARSTATUS_LOOSE:
8017  SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8018  break;
8019 
8020  case SCIP_VARSTATUS_FIXED:
8021  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8022  return SCIP_INVALIDDATA;
8023 
8024  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8025  assert(var->data.aggregate.var != NULL);
8026  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8027  {
8028  SCIP_Real childnewbound;
8029 
8030  /* a > 0 -> change lower bound of y */
8031  assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, -var->data.aggregate.var->locdom.lb))
8032  || SCIPsetIsFeasEQ(set, var->locdom.lb,
8034  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8035  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8036  else
8037  childnewbound = newbound;
8038  SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
8039  childnewbound) );
8040  }
8041  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8042  {
8043  SCIP_Real childnewbound;
8044 
8045  /* a < 0 -> change upper bound of y */
8046  assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->locdom.ub))
8047  || SCIPsetIsFeasEQ(set, var->locdom.lb,
8049  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8050  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8051  else
8052  childnewbound = -newbound;
8053  SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
8054  childnewbound) );
8055  }
8056  else
8057  {
8058  SCIPerrorMessage("scalar is zero in aggregation\n");
8059  return SCIP_INVALIDDATA;
8060  }
8061  break;
8062 
8064  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8065  return SCIP_INVALIDDATA;
8066 
8067  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8068  assert(var->negatedvar != NULL);
8070  assert(var->negatedvar->negatedvar == var);
8071  SCIP_CALL( SCIPvarChgUbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
8072  var->data.negate.constant - newbound) );
8073  break;
8074 
8075  default:
8076  SCIPerrorMessage("unknown variable status\n");
8077  return SCIP_INVALIDDATA;
8078  }
8079 
8080  return SCIP_OKAY;
8081 }
8082 
8083 /** changes current local upper bound of variable; if possible, adjusts bound to integral value; stores inference
8084  * information in variable
8085  */
8087  SCIP_VAR* var, /**< problem variable to change */
8088  BMS_BLKMEM* blkmem, /**< block memory */
8089  SCIP_SET* set, /**< global SCIP settings */
8090  SCIP_STAT* stat, /**< problem statistics */
8091  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
8092  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
8093  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8094  SCIP_Real newbound /**< new bound for variable */
8095  )
8096 {
8097  assert(var != NULL);
8098  assert(blkmem != NULL);
8099  assert(set != NULL);
8100  assert(var->scip == set->scip);
8101 
8102  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
8103  * of the domain within feastol
8104  */
8105  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
8106 
8107  /* adjust bound to integral value if variable is of integral type */
8108  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
8109 
8110  /* check that the adjusted bound is feasible */
8111  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
8112 
8113  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
8114  {
8115  /* we do not want to undercut the lowerbound, which could have happened due to numerics */
8116  newbound = MAX(newbound, var->locdom.lb);
8117  }
8118  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
8119 
8120  SCIPsetDebugMsg(set, "changing upper bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
8121 
8122  if( SCIPsetIsEQ(set, var->locdom.ub, newbound) && (!SCIPsetIsEQ(set, var->glbdom.ub, newbound) || var->locdom.ub == newbound) /*lint !e777*/
8123  && !(newbound != var->locdom.ub && newbound * var->locdom.ub <= 0.0) ) /*lint !e777*/
8124  return SCIP_OKAY;
8125 
8126  /* change bounds of attached variables */
8127  switch( SCIPvarGetStatus(var) )
8128  {
8130  if( var->data.original.transvar != NULL )
8131  {
8132  SCIP_CALL( SCIPvarChgUbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8133  }
8134  else
8135  {
8136  assert(set->stage == SCIP_STAGE_PROBLEM);
8137  SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8138  }
8139  break;
8140 
8141  case SCIP_VARSTATUS_COLUMN:
8142  case SCIP_VARSTATUS_LOOSE:
8143  SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8144  break;
8145 
8146  case SCIP_VARSTATUS_FIXED:
8147  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8148  return SCIP_INVALIDDATA;
8149 
8150  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8151  assert(var->data.aggregate.var != NULL);
8152  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8153  {
8154  SCIP_Real childnewbound;
8155 
8156  /* a > 0 -> change upper bound of y */
8157  assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, var->data.aggregate.var->locdom.ub))
8158  || SCIPsetIsFeasEQ(set, var->locdom.ub,
8160  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8161  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8162  else
8163  childnewbound = newbound;
8164  SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
8165  childnewbound) );
8166  }
8167  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8168  {
8169  SCIP_Real childnewbound;
8170 
8171  /* a < 0 -> change lower bound of y */
8172  assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, -var->data.aggregate.var->locdom.lb))
8173  || SCIPsetIsFeasEQ(set, var->locdom.ub,
8175  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8176  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8177  else
8178  childnewbound = -newbound;
8179  SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
8180  childnewbound) );
8181  }
8182  else
8183  {
8184  SCIPerrorMessage("scalar is zero in aggregation\n");
8185  return SCIP_INVALIDDATA;
8186  }
8187  break;
8188 
8190  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8191  return SCIP_INVALIDDATA;
8192 
8193  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8194  assert(var->negatedvar != NULL);
8196  assert(var->negatedvar->negatedvar == var);
8197  SCIP_CALL( SCIPvarChgLbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
8198  var->data.negate.constant - newbound) );
8199  break;
8200 
8201  default:
8202  SCIPerrorMessage("unknown variable status\n");
8203  return SCIP_INVALIDDATA;
8204  }
8205 
8206  return SCIP_OKAY;
8207 }
8208 
8209 /** changes current local bound of variable; if possible, adjusts bound to integral value; stores inference
8210  * information in variable
8211  */
8213  SCIP_VAR* var, /**< problem variable to change */
8214  BMS_BLKMEM* blkmem, /**< block memory */
8215  SCIP_SET* set, /**< global SCIP settings */
8216  SCIP_STAT* stat, /**< problem statistics */
8217  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
8218  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
8219  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8220  SCIP_Real newbound, /**< new bound for variable */
8221  SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
8222  )
8223 {
8224  /* apply bound change to the LP data */
8225  switch( boundtype )
8226  {
8227  case SCIP_BOUNDTYPE_LOWER:
8228  return SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
8229  case SCIP_BOUNDTYPE_UPPER:
8230  return SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
8231  default:
8232  SCIPerrorMessage("unknown bound type\n");
8233  return SCIP_INVALIDDATA;
8234  }
8235 }
8236 
8237 /** changes lower bound of variable in current dive; if possible, adjusts bound to integral value */
8239  SCIP_VAR* var, /**< problem variable to change */
8240  SCIP_SET* set, /**< global SCIP settings */
8241  SCIP_LP* lp, /**< current LP data */
8242  SCIP_Real newbound /**< new bound for variable */
8243  )
8244 {
8245  assert(var != NULL);
8246  assert(set != NULL);
8247  assert(var->scip == set->scip);
8248  assert(lp != NULL);
8249  assert(SCIPlpDiving(lp));
8250 
8251  /* adjust bound for integral variables */
8252  SCIPvarAdjustLb(var, set, &newbound);
8253 
8254  SCIPsetDebugMsg(set, "changing lower bound of <%s> to %g in current dive\n", var->name, newbound);
8255 
8256  /* change bounds of attached variables */
8257  switch( SCIPvarGetStatus(var) )
8258  {
8260  assert(var->data.original.transvar != NULL);
8261  SCIP_CALL( SCIPvarChgLbDive(var->data.original.transvar, set, lp, newbound) );
8262  break;
8263 
8264  case SCIP_VARSTATUS_COLUMN:
8265  assert(var->data.col != NULL);
8266  SCIP_CALL( SCIPcolChgLb(var->data.col, set, lp, newbound) );
8267  break;
8268 
8269  case SCIP_VARSTATUS_LOOSE:
8270  SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
8271  return SCIP_INVALIDDATA;
8272 
8273  case SCIP_VARSTATUS_FIXED:
8274  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8275  return SCIP_INVALIDDATA;
8276 
8277  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8278  assert(var->data.aggregate.var != NULL);
8279  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8280  {
8281  SCIP_Real childnewbound;
8282 
8283  /* a > 0 -> change lower bound of y */
8284  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8285  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8286  else
8287  childnewbound = newbound;
8288  SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
8289  }
8290  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8291  {
8292  SCIP_Real childnewbound;
8293 
8294  /* a < 0 -> change upper bound of y */
8295  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8296  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8297  else
8298  childnewbound = -newbound;
8299  SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
8300  }
8301  else
8302  {
8303  SCIPerrorMessage("scalar is zero in aggregation\n");
8304  return SCIP_INVALIDDATA;
8305  }
8306  break;
8307 
8309  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8310  return SCIP_INVALIDDATA;
8311 
8312  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8313  assert(var->negatedvar != NULL);
8315  assert(var->negatedvar->negatedvar == var);
8316  SCIP_CALL( SCIPvarChgUbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
8317  break;
8318 
8319  default:
8320  SCIPerrorMessage("unknown variable status\n");
8321  return SCIP_INVALIDDATA;
8322  }
8323 
8324  return SCIP_OKAY;
8325 }
8326 
8327 /** changes upper bound of variable in current dive; if possible, adjusts bound to integral value */
8329  SCIP_VAR* var, /**< problem variable to change */
8330  SCIP_SET* set, /**< global SCIP settings */
8331  SCIP_LP* lp, /**< current LP data */
8332  SCIP_Real newbound /**< new bound for variable */
8333  )
8334 {
8335  assert(var != NULL);
8336  assert(set != NULL);
8337  assert(var->scip == set->scip);
8338  assert(lp != NULL);
8339  assert(SCIPlpDiving(lp));
8340 
8341  /* adjust bound for integral variables */
8342  SCIPvarAdjustUb(var, set, &newbound);
8343 
8344  SCIPsetDebugMsg(set, "changing upper bound of <%s> to %g in current dive\n", var->name, newbound);
8345 
8346  /* change bounds of attached variables */
8347  switch( SCIPvarGetStatus(var) )
8348  {
8350  assert(var->data.original.transvar != NULL);
8351  SCIP_CALL( SCIPvarChgUbDive(var->data.original.transvar, set, lp, newbound) );
8352  break;
8353 
8354  case SCIP_VARSTATUS_COLUMN:
8355  assert(var->data.col != NULL);
8356  SCIP_CALL( SCIPcolChgUb(var->data.col, set, lp, newbound) );
8357  break;
8358 
8359  case SCIP_VARSTATUS_LOOSE:
8360  SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
8361  return SCIP_INVALIDDATA;
8362 
8363  case SCIP_VARSTATUS_FIXED:
8364  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8365  return SCIP_INVALIDDATA;
8366 
8367  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8368  assert(var->data.aggregate.var != NULL);
8369  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8370  {
8371  SCIP_Real childnewbound;
8372 
8373  /* a > 0 -> change upper bound of y */
8374  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8375  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8376  else
8377  childnewbound = newbound;
8378  SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
8379  }
8380  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8381  {
8382  SCIP_Real childnewbound;
8383 
8384  /* a < 0 -> change lower bound of y */
8385  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8386  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8387  else
8388  childnewbound = -newbound;
8389  SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
8390  }
8391  else
8392  {
8393  SCIPerrorMessage("scalar is zero in aggregation\n");
8394  return SCIP_INVALIDDATA;
8395  }
8396  break;
8397 
8399  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8400  return SCIP_INVALIDDATA;
8401 
8402  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8403  assert(var->negatedvar != NULL);
8405  assert(var->negatedvar->negatedvar == var);
8406  SCIP_CALL( SCIPvarChgLbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
8407  break;
8408 
8409  default:
8410  SCIPerrorMessage("unknown variable status\n");
8411  return SCIP_INVALIDDATA;
8412  }
8413 
8414  return SCIP_OKAY;
8415 }
8416 
8417 /** for a multi-aggregated variable, gives the local lower bound computed by adding the local bounds from all
8418  * aggregation variables, this lower bound may be tighter than the one given by SCIPvarGetLbLocal, since the latter is
8419  * not updated if bounds of aggregation variables are changing
8420  *
8421  * calling this function for a non-multi-aggregated variable is not allowed
8422  */
8424  SCIP_VAR* var, /**< problem variable */
8425  SCIP_SET* set /**< global SCIP settings */
8426  )
8427 {
8428  int i;
8429  SCIP_Real lb;
8430  SCIP_Real bnd;
8431  SCIP_VAR* aggrvar;
8432  SCIP_Bool posinf;
8433  SCIP_Bool neginf;
8434 
8435  assert(var != NULL);
8436  assert(set != NULL);
8437  assert(var->scip == set->scip);
8439 
8440  posinf = FALSE;
8441  neginf = FALSE;
8442  lb = var->data.multaggr.constant;
8443  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8444  {
8445  aggrvar = var->data.multaggr.vars[i];
8446  if( var->data.multaggr.scalars[i] > 0.0 )
8447  {
8448  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbLocal(aggrvar, set) : SCIPvarGetLbLocal(aggrvar);
8449 
8450  if( SCIPsetIsInfinity(set, bnd) )
8451  posinf = TRUE;
8452  else if( SCIPsetIsInfinity(set, -bnd) )
8453  neginf = TRUE;
8454  else
8455  lb += var->data.multaggr.scalars[i] * bnd;
8456  }
8457  else
8458  {
8459  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbLocal(aggrvar, set) : SCIPvarGetUbLocal(aggrvar);
8460 
8461  if( SCIPsetIsInfinity(set, -bnd) )
8462  posinf = TRUE;
8463  else if( SCIPsetIsInfinity(set, bnd) )
8464  neginf = TRUE;
8465  else
8466  lb += var->data.multaggr.scalars[i] * bnd;
8467  }
8468 
8469  /* stop if two diffrent infinities (or a -infinity) were found and return local lower bound of multi aggregated
8470  * variable
8471  */
8472  if( neginf )
8473  return SCIPvarGetLbLocal(var);
8474  }
8475 
8476  /* if positive infinity flag was set to true return infinity */
8477  if( posinf )
8478  return SCIPsetInfinity(set);
8479 
8480  return (MAX(lb, SCIPvarGetLbLocal(var))); /*lint !e666*/
8481 }
8482 
8483 /** for a multi-aggregated variable, gives the local upper bound computed by adding the local bounds from all
8484  * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbLocal, since the latter is
8485  * not updated if bounds of aggregation variables are changing
8486  *
8487  * calling this function for a non-multi-aggregated variable is not allowed
8488  */
8490  SCIP_VAR* var, /**< problem variable */
8491  SCIP_SET* set /**< global SCIP settings */
8492  )
8493 {
8494  int i;
8495  SCIP_Real ub;
8496  SCIP_Real bnd;
8497  SCIP_VAR* aggrvar;
8498  SCIP_Bool posinf;
8499  SCIP_Bool neginf;
8500 
8501  assert(var != NULL);
8502  assert(set != NULL);
8503  assert(var->scip == set->scip);
8505 
8506  posinf = FALSE;
8507  neginf = FALSE;
8508  ub = var->data.multaggr.constant;
8509  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8510  {
8511  aggrvar = var->data.multaggr.vars[i];
8512  if( var->data.multaggr.scalars[i] > 0.0 )
8513  {
8514  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbLocal(aggrvar, set) : SCIPvarGetUbLocal(aggrvar);
8515 
8516  if( SCIPsetIsInfinity(set, bnd) )
8517  posinf = TRUE;
8518  else if( SCIPsetIsInfinity(set, -bnd) )
8519  neginf = TRUE;
8520  else
8521  ub += var->data.multaggr.scalars[i] * bnd;
8522  }
8523  else
8524  {
8525  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbLocal(aggrvar, set) : SCIPvarGetLbLocal(aggrvar);
8526 
8527  if( SCIPsetIsInfinity(set, -bnd) )
8528  posinf = TRUE;
8529  else if( SCIPsetIsInfinity(set, bnd) )
8530  neginf = TRUE;
8531  else
8532  ub += var->data.multaggr.scalars[i] * bnd;
8533  }
8534 
8535  /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
8536  * variable
8537  */
8538  if( posinf )
8539  return SCIPvarGetUbLocal(var);
8540  }
8541 
8542  /* if negative infinity flag was set to true return -infinity */
8543  if( neginf )
8544  return -SCIPsetInfinity(set);
8545 
8546  return (MIN(ub, SCIPvarGetUbLocal(var))); /*lint !e666*/
8547 }
8548 
8549 /** for a multi-aggregated variable, gives the global lower bound computed by adding the global bounds from all
8550  * aggregation variables, this global bound may be tighter than the one given by SCIPvarGetLbGlobal, since the latter is
8551  * not updated if bounds of aggregation variables are changing
8552  *
8553  * calling this function for a non-multi-aggregated variable is not allowed
8554  */
8556  SCIP_VAR* var, /**< problem variable */
8557  SCIP_SET* set /**< global SCIP settings */
8558  )
8559 {
8560  int i;
8561  SCIP_Real lb;
8562  SCIP_Real bnd;
8563  SCIP_VAR* aggrvar;
8564  SCIP_Bool posinf;
8565  SCIP_Bool neginf;
8566 
8567  assert(var != NULL);
8568  assert(set != NULL);
8569  assert(var->scip == set->scip);
8571 
8572  posinf = FALSE;
8573  neginf = FALSE;
8574  lb = var->data.multaggr.constant;
8575  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8576  {
8577  aggrvar = var->data.multaggr.vars[i];
8578  if( var->data.multaggr.scalars[i] > 0.0 )
8579  {
8580  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbGlobal(aggrvar, set) : SCIPvarGetLbGlobal(aggrvar);
8581 
8582  if( SCIPsetIsInfinity(set, bnd) )
8583  posinf = TRUE;
8584  else if( SCIPsetIsInfinity(set, -bnd) )
8585  neginf = TRUE;
8586  else
8587  lb += var->data.multaggr.scalars[i] * bnd;
8588  }
8589  else
8590  {
8591  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbGlobal(aggrvar, set) : SCIPvarGetUbGlobal(aggrvar);
8592 
8593  if( SCIPsetIsInfinity(set, -bnd) )
8594  posinf = TRUE;
8595  else if( SCIPsetIsInfinity(set, bnd) )
8596  neginf = TRUE;
8597  else
8598  lb += var->data.multaggr.scalars[i] * bnd;
8599  }
8600 
8601  /* stop if two diffrent infinities (or a -infinity) were found and return global lower bound of multi aggregated
8602  * variable
8603  */
8604  if( neginf )
8605  return SCIPvarGetLbGlobal(var);
8606  }
8607 
8608  /* if positive infinity flag was set to true return infinity */
8609  if( posinf )
8610  return SCIPsetInfinity(set);
8611 
8612  return (MAX(lb, SCIPvarGetLbGlobal(var))); /*lint !e666*/
8613 }
8614 
8615 /** for a multi-aggregated variable, gives the global upper bound computed by adding the global bounds from all
8616  * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbGlobal, since the latter is
8617  * not updated if bounds of aggregation variables are changing
8618  *
8619  * calling this function for a non-multi-aggregated variable is not allowed
8620  */
8622  SCIP_VAR* var, /**< problem variable */
8623  SCIP_SET* set /**< global SCIP settings */
8624  )
8625 {
8626  int i;
8627  SCIP_Real ub;
8628  SCIP_Real bnd;
8629  SCIP_VAR* aggrvar;
8630  SCIP_Bool posinf;
8631  SCIP_Bool neginf;
8632 
8633  assert(var != NULL);
8634  assert(set != NULL);
8635  assert(var->scip == set->scip);
8637 
8638  posinf = FALSE;
8639  neginf = FALSE;
8640  ub = var->data.multaggr.constant;
8641  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8642  {
8643  aggrvar = var->data.multaggr.vars[i];
8644  if( var->data.multaggr.scalars[i] > 0.0 )
8645  {
8646  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbGlobal(aggrvar, set) : SCIPvarGetUbGlobal(aggrvar);
8647 
8648  if( SCIPsetIsInfinity(set, bnd) )
8649  posinf = TRUE;
8650  else if( SCIPsetIsInfinity(set, -bnd) )
8651  neginf = TRUE;
8652  else
8653  ub += var->data.multaggr.scalars[i] * bnd;
8654  }
8655  else
8656  {
8657  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbGlobal(aggrvar, set) : SCIPvarGetLbGlobal(aggrvar);
8658 
8659  if( SCIPsetIsInfinity(set, -bnd) )
8660  posinf = TRUE;
8661  else if( SCIPsetIsInfinity(set, bnd) )
8662  neginf = TRUE;
8663  else
8664  ub += var->data.multaggr.scalars[i] * bnd;
8665  }
8666 
8667  /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
8668  * variable
8669  */
8670  if( posinf )
8671  return SCIPvarGetUbGlobal(var);
8672  }
8673 
8674  /* if negative infinity flag was set to true return -infinity */
8675  if( neginf )
8676  return -SCIPsetInfinity(set);
8677 
8678  return (MIN(ub, SCIPvarGetUbGlobal(var))); /*lint !e666*/
8679 }
8680 
8681 /** adds a hole to the original domain of the variable */
8683  SCIP_VAR* var, /**< problem variable */
8684  BMS_BLKMEM* blkmem, /**< block memory */
8685  SCIP_SET* set, /**< global SCIP settings */
8686  SCIP_Real left, /**< left bound of open interval in new hole */
8687  SCIP_Real right /**< right bound of open interval in new hole */
8688  )
8689 {
8690  SCIP_Bool added;
8691 
8692  assert(var != NULL);
8693  assert(!SCIPvarIsTransformed(var));
8695  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8696  assert(set != NULL);
8697  assert(var->scip == set->scip);
8698  assert(set->stage == SCIP_STAGE_PROBLEM);
8699 
8700  SCIPsetDebugMsg(set, "adding original hole (%g,%g) to <%s>\n", left, right, var->name);
8701 
8702  if( SCIPsetIsEQ(set, left, right) )
8703  return SCIP_OKAY;
8704 
8705  /* the interval should not be empty */
8706  assert(SCIPsetIsLT(set, left, right));
8707 
8708  /* the the interval bound should already be adjusted */
8709  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8710  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8711 
8712  /* the the interval should lay between the lower and upper bound */
8713  assert(SCIPsetIsGE(set, left, SCIPvarGetLbOriginal(var)));
8714  assert(SCIPsetIsLE(set, right, SCIPvarGetUbOriginal(var)));
8715 
8716  /* add domain hole */
8717  SCIP_CALL( domAddHole(&var->data.original.origdom, blkmem, set, left, right, &added) );
8718 
8719  /* merges overlapping holes into single holes, moves bounds respectively if hole was added */
8720  if( added )
8721  {
8722  domMerge(&var->data.original.origdom, blkmem, set, NULL, NULL);
8723  }
8724 
8725  /**@todo add hole in parent and child variables (just like with bound changes);
8726  * warning! original vars' holes are in original blkmem, transformed vars' holes in transformed blkmem
8727  */
8728 
8729  return SCIP_OKAY;
8730 }
8731 
8732 /** performs the current add of domain, changes all parents accordingly */
8733 static
8735  SCIP_VAR* var, /**< problem variable */
8736  BMS_BLKMEM* blkmem, /**< block memory */
8737  SCIP_SET* set, /**< global SCIP settings */
8738  SCIP_STAT* stat, /**< problem statistics */
8739  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8740  SCIP_Real left, /**< left bound of open interval in new hole */
8741  SCIP_Real right, /**< right bound of open interval in new hole */
8742  SCIP_Bool* added /**< pointer to store whether the hole was added */
8743  )
8744 {
8745  SCIP_VAR* parentvar;
8746  SCIP_Real newlb;
8747  SCIP_Real newub;
8748  int i;
8749 
8750  assert(var != NULL);
8751  assert(added != NULL);
8752  assert(blkmem != NULL);
8753 
8754  /* the interval should not be empty */
8755  assert(SCIPsetIsLT(set, left, right));
8756 
8757  /* the interval bound should already be adjusted */
8758  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8759  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8760 
8761  /* the interval should lay between the lower and upper bound */
8762  assert(SCIPsetIsGE(set, left, SCIPvarGetLbGlobal(var)));
8763  assert(SCIPsetIsLE(set, right, SCIPvarGetUbGlobal(var)));
8764 
8765  /* @todo add debugging mechanism for holes when using a debugging solution */
8766 
8767  /* add hole to hole list */
8768  SCIP_CALL( domAddHole(&var->glbdom, blkmem, set, left, right, added) );
8769 
8770  /* check if the hole is redundant */
8771  if( !(*added) )
8772  return SCIP_OKAY;
8773 
8774  /* current bounds */
8775  newlb = var->glbdom.lb;
8776  newub = var->glbdom.ub;
8777 
8778  /* merge domain holes */
8779  domMerge(&var->glbdom, blkmem, set, &newlb, &newub);
8780 
8781  /* the bound should not be changed */
8782  assert(SCIPsetIsEQ(set, newlb, var->glbdom.lb));
8783  assert(SCIPsetIsEQ(set, newub, var->glbdom.ub));
8784 
8785  /* issue bound change event */
8786  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
8787  if( var->eventfilter != NULL )
8788  {
8789  SCIP_CALL( varEventGholeAdded(var, blkmem, set, eventqueue, left, right) );
8790  }
8791 
8792  /* process parent variables */
8793  for( i = 0; i < var->nparentvars; ++i )
8794  {
8795  SCIP_Real parentnewleft;
8796  SCIP_Real parentnewright;
8797  SCIP_Bool localadded;
8798 
8799  parentvar = var->parentvars[i];
8800  assert(parentvar != NULL);
8801 
8802  switch( SCIPvarGetStatus(parentvar) )
8803  {
8805  parentnewleft = left;
8806  parentnewright = right;
8807  break;
8808 
8809  case SCIP_VARSTATUS_COLUMN:
8810  case SCIP_VARSTATUS_LOOSE:
8811  case SCIP_VARSTATUS_FIXED:
8813  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
8814  return SCIP_INVALIDDATA;
8815 
8816  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8817  assert(parentvar->data.aggregate.var == var);
8818 
8819  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
8820  {
8821  /* a > 0 -> change upper bound of x */
8822  parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8823  parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8824  }
8825  else
8826  {
8827  /* a < 0 -> change lower bound of x */
8828  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
8829 
8830  parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8831  parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8832  }
8833  break;
8834 
8835  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
8836  assert(parentvar->negatedvar != NULL);
8837  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
8838  assert(parentvar->negatedvar->negatedvar == parentvar);
8839 
8840  parentnewright = -left + parentvar->data.negate.constant;
8841  parentnewleft = -right + parentvar->data.negate.constant;
8842  break;
8843 
8844  default:
8845  SCIPerrorMessage("unknown variable status\n");
8846  return SCIP_INVALIDDATA;
8847  }
8848 
8849  SCIPsetDebugMsg(set, "add global hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
8850 
8851  /* perform hole added for parent variable */
8852  assert(blkmem != NULL);
8853  assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
8854  SCIP_CALL( varProcessAddHoleGlobal(parentvar, blkmem, set, stat, eventqueue,
8855  parentnewleft, parentnewright, &localadded) );
8856  assert(localadded);
8857  }
8858 
8859  return SCIP_OKAY;
8860 }
8861 
8862 /** adds a hole to the variable's global and local domain */
8864  SCIP_VAR* var, /**< problem variable */
8865  BMS_BLKMEM* blkmem, /**< block memory */
8866  SCIP_SET* set, /**< global SCIP settings */
8867  SCIP_STAT* stat, /**< problem statistics */
8868  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8869  SCIP_Real left, /**< left bound of open interval in new hole */
8870  SCIP_Real right, /**< right bound of open interval in new hole */
8871  SCIP_Bool* added /**< pointer to store whether the hole was added */
8872  )
8873 {
8874  SCIP_Real childnewleft;
8875  SCIP_Real childnewright;
8876 
8877  assert(var != NULL);
8878  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8879  assert(blkmem != NULL);
8880  assert(added != NULL);
8881 
8882  SCIPsetDebugMsg(set, "adding global hole (%g,%g) to <%s>\n", left, right, var->name);
8883 
8884  /* the interval should not be empty */
8885  assert(SCIPsetIsLT(set, left, right));
8886 
8887  /* the the interval bound should already be adjusted */
8888  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8889  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8890 
8891  /* the the interval should lay between the lower and upper bound */
8892  assert(SCIPsetIsGE(set, left, SCIPvarGetLbGlobal(var)));
8893  assert(SCIPsetIsLE(set, right, SCIPvarGetUbGlobal(var)));
8894 
8895  /* change bounds of attached variables */
8896  switch( SCIPvarGetStatus(var) )
8897  {
8899  if( var->data.original.transvar != NULL )
8900  {
8901  SCIP_CALL( SCIPvarAddHoleGlobal(var->data.original.transvar, blkmem, set, stat, eventqueue,
8902  left, right, added) );
8903  }
8904  else
8905  {
8906  assert(set->stage == SCIP_STAGE_PROBLEM);
8907 
8908  SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
8909  if( *added )
8910  {
8911  SCIP_Bool localadded;
8912 
8913  SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
8914  }
8915  }
8916  break;
8917 
8918  case SCIP_VARSTATUS_COLUMN:
8919  case SCIP_VARSTATUS_LOOSE:
8920  SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
8921  if( *added )
8922  {
8923  SCIP_Bool localadded;
8924 
8925  SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
8926  }
8927  break;
8928 
8929  case SCIP_VARSTATUS_FIXED:
8930  SCIPerrorMessage("cannot add hole of a fixed variable\n");
8931  return SCIP_INVALIDDATA;
8932 
8933  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8934  assert(var->data.aggregate.var != NULL);
8935 
8936  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8937  {
8938  /* a > 0 -> change lower bound of y */
8939  childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8940  childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8941  }
8942  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8943  {
8944  childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8945  childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8946  }
8947  else
8948  {
8949  SCIPerrorMessage("scalar is zero in aggregation\n");
8950  return SCIP_INVALIDDATA;
8951  }
8952  SCIP_CALL( SCIPvarAddHoleGlobal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
8953  childnewleft, childnewright, added) );
8954  break;
8955 
8957  SCIPerrorMessage("cannot add a hole of a multi-aggregated variable.\n");
8958  return SCIP_INVALIDDATA;
8959 
8960  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8961  assert(var->negatedvar != NULL);
8963  assert(var->negatedvar->negatedvar == var);
8964 
8965  childnewright = -left + var->data.negate.constant;
8966  childnewleft = -right + var->data.negate.constant;
8967 
8968  SCIP_CALL( SCIPvarAddHoleGlobal(var->negatedvar, blkmem, set, stat, eventqueue,
8969  childnewleft, childnewright, added) );
8970  break;
8971 
8972  default:
8973  SCIPerrorMessage("unknown variable status\n");
8974  return SCIP_INVALIDDATA;
8975  }
8976 
8977  return SCIP_OKAY;
8978 }
8979 
8980 /** performs the current add of domain, changes all parents accordingly */
8981 static
8983  SCIP_VAR* var, /**< problem variable */
8984  BMS_BLKMEM* blkmem, /**< block memory */
8985  SCIP_SET* set, /**< global SCIP settings */
8986  SCIP_STAT* stat, /**< problem statistics */
8987  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8988  SCIP_Real left, /**< left bound of open interval in new hole */
8989  SCIP_Real right, /**< right bound of open interval in new hole */
8990  SCIP_Bool* added /**< pointer to store whether the hole was added, or NULL */
8991  )
8992 {
8993  SCIP_VAR* parentvar;
8994  SCIP_Real newlb;
8995  SCIP_Real newub;
8996  int i;
8997 
8998  assert(var != NULL);
8999  assert(added != NULL);
9000  assert(blkmem != NULL);
9001 
9002  /* the interval should not be empty */
9003  assert(SCIPsetIsLT(set, left, right));
9004 
9005  /* the the interval bound should already be adjusted */
9006  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
9007  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
9008 
9009  /* the the interval should lay between the lower and upper bound */
9010  assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
9011  assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
9012 
9013  /* add hole to hole list */
9014  SCIP_CALL( domAddHole(&var->locdom, blkmem, set, left, right, added) );
9015 
9016  /* check if the hole is redundant */
9017  if( !(*added) )
9018  return SCIP_OKAY;
9019 
9020  /* current bounds */
9021  newlb = var->locdom.lb;
9022  newub = var->locdom.ub;
9023 
9024  /* merge domain holes */
9025  domMerge(&var->locdom, blkmem, set, &newlb, &newub);
9026 
9027  /* the bound should not be changed */
9028  assert(SCIPsetIsEQ(set, newlb, var->locdom.lb));
9029  assert(SCIPsetIsEQ(set, newub, var->locdom.ub));
9030 
9031 #if 0
9032  /* issue bound change event */
9033  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
9034  if( var->eventfilter != NULL )
9035  {
9036  SCIP_CALL( varEventLholeAdded(var, blkmem, set, lp, branchcand, eventqueue, left, right) );
9037  }
9038 #endif
9039 
9040  /* process parent variables */
9041  for( i = 0; i < var->nparentvars; ++i )
9042  {
9043  SCIP_Real parentnewleft;
9044  SCIP_Real parentnewright;
9045  SCIP_Bool localadded;
9046 
9047  parentvar = var->parentvars[i];
9048  assert(parentvar != NULL);
9049 
9050  switch( SCIPvarGetStatus(parentvar) )
9051  {
9053  parentnewleft = left;
9054  parentnewright = right;
9055  break;
9056 
9057  case SCIP_VARSTATUS_COLUMN:
9058  case SCIP_VARSTATUS_LOOSE:
9059  case SCIP_VARSTATUS_FIXED:
9061  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
9062  return SCIP_INVALIDDATA;
9063 
9064  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
9065  assert(parentvar->data.aggregate.var == var);
9066 
9067  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
9068  {
9069  /* a > 0 -> change upper bound of x */
9070  parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
9071  parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
9072  }
9073  else
9074  {
9075  /* a < 0 -> change lower bound of x */
9076  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
9077 
9078  parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
9079  parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
9080  }
9081  break;
9082 
9083  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
9084  assert(parentvar->negatedvar != NULL);
9085  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
9086  assert(parentvar->negatedvar->negatedvar == parentvar);
9087 
9088  parentnewright = -left + parentvar->data.negate.constant;
9089  parentnewleft = -right + parentvar->data.negate.constant;
9090  break;
9091 
9092  default:
9093  SCIPerrorMessage("unknown variable status\n");
9094  return SCIP_INVALIDDATA;
9095  }
9096 
9097  SCIPsetDebugMsg(set, "add local hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
9098 
9099  /* perform hole added for parent variable */
9100  assert(blkmem != NULL);
9101  assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
9102  SCIP_CALL( varProcessAddHoleLocal(parentvar, blkmem, set, stat, eventqueue,
9103  parentnewleft, parentnewright, &localadded) );
9104  assert(localadded);
9105  }
9106 
9107  return SCIP_OKAY;
9108 }
9109 
9110 /** adds a hole to the variable's current local domain */
9112  SCIP_VAR* var, /**< problem variable */
9113  BMS_BLKMEM* blkmem, /**< block memory */
9114  SCIP_SET* set, /**< global SCIP settings */
9115  SCIP_STAT* stat, /**< problem statistics */
9116  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
9117  SCIP_Real left, /**< left bound of open interval in new hole */
9118  SCIP_Real right, /**< right bound of open interval in new hole */
9119  SCIP_Bool* added /**< pointer to store whether the hole was added */
9120  )
9121 {
9122  SCIP_Real childnewleft;
9123  SCIP_Real childnewright;
9124 
9125  assert(var != NULL);
9126 
9127  SCIPsetDebugMsg(set, "adding local hole (%g,%g) to <%s>\n", left, right, var->name);
9128 
9129  assert(set != NULL);
9130  assert(var->scip == set->scip);
9131  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
9132  assert(blkmem != NULL);
9133  assert(added != NULL);
9134 
9135  /* the interval should not be empty */
9136  assert(SCIPsetIsLT(set, left, right));
9137 
9138  /* the the interval bound should already be adjusted */
9139  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
9140  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
9141 
9142  /* the the interval should lay between the lower and upper bound */
9143  assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
9144  assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
9145 
9146  /* change bounds of attached variables */
9147  switch( SCIPvarGetStatus(var) )
9148  {
9150  if( var->data.original.transvar != NULL )
9151  {
9152  SCIP_CALL( SCIPvarAddHoleLocal(var->data.original.transvar, blkmem, set, stat, eventqueue,
9153  left, right, added) );
9154  }
9155  else
9156  {
9157  assert(set->stage == SCIP_STAGE_PROBLEM);
9158  SCIPstatIncrement(stat, set, domchgcount);
9159  SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
9160  }
9161  break;
9162 
9163  case SCIP_VARSTATUS_COLUMN:
9164  case SCIP_VARSTATUS_LOOSE:
9165  SCIPstatIncrement(stat, set, domchgcount);
9166  SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
9167  break;
9168 
9169  case SCIP_VARSTATUS_FIXED:
9170  SCIPerrorMessage("cannot add domain hole to a fixed variable\n");
9171  return SCIP_INVALIDDATA;
9172 
9173  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
9174  assert(var->data.aggregate.var != NULL);
9175 
9176  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
9177  {
9178  /* a > 0 -> change lower bound of y */
9179  childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
9180  childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
9181  }
9182  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
9183  {
9184  childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
9185  childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
9186  }
9187  else
9188  {
9189  SCIPerrorMessage("scalar is zero in aggregation\n");
9190  return SCIP_INVALIDDATA;
9191  }
9192  SCIP_CALL( SCIPvarAddHoleLocal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
9193  childnewleft, childnewright, added) );
9194  break;
9195 
9197  SCIPerrorMessage("cannot add domain hole to a multi-aggregated variable.\n");
9198  return SCIP_INVALIDDATA;
9199 
9200  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
9201  assert(var->negatedvar != NULL);
9203  assert(var->negatedvar->negatedvar == var);
9204 
9205  childnewright = -left + var->data.negate.constant;
9206  childnewleft = -right + var->data.negate.constant;
9207 
9208  SCIP_CALL( SCIPvarAddHoleLocal(var->negatedvar, blkmem, set, stat, eventqueue, childnewleft, childnewright, added) );
9209  break;
9210 
9211  default:
9212  SCIPerrorMessage("unknown variable status\n");
9213  return SCIP_INVALIDDATA;
9214  }
9215 
9216  return SCIP_OKAY;
9217 }
9218 
9219 /** resets the global and local bounds of original variable to their original values */
9221  SCIP_VAR* var, /**< problem variable */
9222  BMS_BLKMEM* blkmem, /**< block memory */
9223  SCIP_SET* set, /**< global SCIP settings */
9224  SCIP_STAT* stat /**< problem statistics */
9225  )
9226 {
9227  assert(var != NULL);
9228  assert(set != NULL);
9229  assert(var->scip == set->scip);
9230  assert(SCIPvarIsOriginal(var));
9231  /* resetting of bounds on original variables which have a transformed counterpart easily fails if, e.g.,
9232  * the transformed variable has been fixed */
9233  assert(SCIPvarGetTransVar(var) == NULL);
9234 
9235  /* copy the original bounds back to the global and local bounds */
9236  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.lb) );
9237  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.ub) );
9238  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.lb) );
9239  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.ub) );
9240 
9241  /* free the global and local holelists and duplicate the original ones */
9242  /**@todo this has also to be called recursively with methods similar to SCIPvarChgLbGlobal() */
9243  holelistFree(&var->glbdom.holelist, blkmem);
9244  holelistFree(&var->locdom.holelist, blkmem);
9245  SCIP_CALL( holelistDuplicate(&var->glbdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
9246  SCIP_CALL( holelistDuplicate(&var->locdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
9247 
9248  return SCIP_OKAY;
9249 }
9250 
9251 /** issues a IMPLADDED event on the given variable */
9252 static
9254  SCIP_VAR* var, /**< problem variable to change */
9255  BMS_BLKMEM* blkmem, /**< block memory */
9256  SCIP_SET* set, /**< global SCIP settings */
9257  SCIP_EVENTQUEUE* eventqueue /**< event queue */
9258  )
9259 {
9260  SCIP_EVENT* event;
9261 
9262  assert(var != NULL);
9263 
9264  /* issue IMPLADDED event on variable */
9265  SCIP_CALL( SCIPeventCreateImplAdded(&event, blkmem, var) );
9266  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
9267 
9268  return SCIP_OKAY;
9269 }
9270 
9271 /** actually performs the addition of a variable bound to the variable's vbound arrays */
9272 static
9274  SCIP_VAR* var, /**< problem variable x in x <= b*z + d or x >= b*z + d */
9275  BMS_BLKMEM* blkmem, /**< block memory */
9276  SCIP_SET* set, /**< global SCIP settings */
9277  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9278  SCIP_BOUNDTYPE vbtype, /**< type of variable bound (LOWER or UPPER) */
9279  SCIP_VAR* vbvar, /**< variable z in x <= b*z + d or x >= b*z + d */
9280  SCIP_Real vbcoef, /**< coefficient b in x <= b*z + d or x >= b*z + d */
9281  SCIP_Real vbconstant /**< constant d in x <= b*z + d or x >= b*z + d */
9282  )
9283 {
9284  SCIP_Bool added;
9285 
9286  /* It can happen that the variable "var" and the variable "vbvar" are the same variable. For example if a variable
9287  * gets aggregated, the variable bounds (vbound) of that variable are copied to the other variable. A variable bound
9288  * variable of the aggregated variable might be the same as the one its gets aggregated too.
9289  *
9290  * If the variable "var" and the variable "vbvar" are the same, the variable bound which should be added here has to
9291  * be redundant. This is the case since an infeasibility should have be detected in the previous methods. As well as
9292  * the bounds of the variable which should be also already be tightened in the previous methods. Therefore, the
9293  * variable bound can be ignored.
9294  *
9295  * From the way the the variable bound system is implemented (detecting infeasibility, tighten bounds), the
9296  * equivalence of the variables should be checked here.
9297  */
9298  if( var == vbvar )
9299  {
9300  /* in this case the variable bound has to be redundant, this means for possible assignments to this variable; this
9301  * can be checked via the global bounds of the variable */
9302 #ifndef NDEBUG
9303  SCIP_Real lb;
9304  SCIP_Real ub;
9305 
9306  lb = SCIPvarGetLbGlobal(var);
9307  ub = SCIPvarGetUbGlobal(var);
9308 
9309  if(vbtype == SCIP_BOUNDTYPE_LOWER)
9310  {
9311  if( vbcoef > 0.0 )
9312  {
9313  assert(SCIPsetIsGE(set, lb, lb * vbcoef + vbconstant) );
9314  assert(SCIPsetIsGE(set, ub, ub * vbcoef + vbconstant) );
9315  }
9316  else
9317  {
9318  assert(SCIPsetIsGE(set, lb, ub * vbcoef + vbconstant) );
9319  assert(SCIPsetIsGE(set, ub, lb * vbcoef + vbconstant) );
9320  }
9321  }
9322  else
9323  {
9324  assert(vbtype == SCIP_BOUNDTYPE_UPPER);
9325  if( vbcoef > 0.0 )
9326  {
9327  assert(SCIPsetIsLE(set, lb, lb * vbcoef + vbconstant) );
9328  assert(SCIPsetIsLE(set, ub, ub * vbcoef + vbconstant) );
9329  }
9330  else
9331  {
9332  assert(SCIPsetIsLE(set, lb, ub * vbcoef + vbconstant) );
9333  assert(SCIPsetIsLE(set, ub, lb * vbcoef + vbconstant) );
9334  }
9335  }
9336 #endif
9337  SCIPsetDebugMsg(set, "redundant variable bound: <%s> %s %g<%s> %+g\n",
9338  SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
9339 
9340  return SCIP_OKAY;
9341  }
9342 
9343  SCIPsetDebugMsg(set, "adding variable bound: <%s> %s %g<%s> %+g\n",
9344  SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
9345 
9346  /* check variable bound on debugging solution */
9347  SCIP_CALL( SCIPdebugCheckVbound(set, var, vbtype, vbvar, vbcoef, vbconstant) ); /*lint !e506 !e774*/
9348 
9349  /* perform the addition */
9350  if( vbtype == SCIP_BOUNDTYPE_LOWER )
9351  {
9352  SCIP_CALL( SCIPvboundsAdd(&var->vlbs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
9353  }
9354  else
9355  {
9356  SCIP_CALL( SCIPvboundsAdd(&var->vubs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
9357  }
9358  var->closestvblpcount = -1;
9359 
9360  if( added )
9361  {
9362  /* issue IMPLADDED event */
9363  SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
9364  }
9365 
9366  return SCIP_OKAY;
9367 }
9368 
9369 /** checks whether the given implication is redundant or infeasible w.r.t. the implied variables global bounds */
9370 static
9371 void checkImplic(
9372  SCIP_SET* set, /**< global SCIP settings */
9373  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9374  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9375  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9376  SCIP_Bool* redundant, /**< pointer to store whether the implication is redundant */
9377  SCIP_Bool* infeasible /**< pointer to store whether the implication is infeasible */
9378  )
9379 {
9380  SCIP_Real impllb;
9381  SCIP_Real implub;
9382 
9383  assert(redundant != NULL);
9384  assert(infeasible != NULL);
9385 
9386  impllb = SCIPvarGetLbGlobal(implvar);
9387  implub = SCIPvarGetUbGlobal(implvar);
9388  if( impltype == SCIP_BOUNDTYPE_LOWER )
9389  {
9390  *infeasible = SCIPsetIsFeasGT(set, implbound, implub);
9391  *redundant = SCIPsetIsFeasLE(set, implbound, impllb);
9392  }
9393  else
9394  {
9395  *infeasible = SCIPsetIsFeasLT(set, implbound, impllb);
9396  *redundant = SCIPsetIsFeasGE(set, implbound, implub);
9397  }
9398 }
9399 
9400 /** applies the given implication, if it is not redundant */
9401 static
9403  BMS_BLKMEM* blkmem, /**< block memory */
9404  SCIP_SET* set, /**< global SCIP settings */
9405  SCIP_STAT* stat, /**< problem statistics */
9406  SCIP_PROB* transprob, /**< transformed problem */
9407  SCIP_PROB* origprob, /**< original problem */
9408  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9409  SCIP_REOPT* reopt, /**< reoptimization data structure */
9410  SCIP_LP* lp, /**< current LP data */
9411  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9412  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9413  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9414  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9415  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9416  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9417  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9418  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9419  )
9420 {
9421  SCIP_Real implub;
9422  SCIP_Real impllb;
9423 
9424  assert(infeasible != NULL);
9425 
9426  *infeasible = FALSE;
9427 
9428  implub = SCIPvarGetUbGlobal(implvar);
9429  impllb = SCIPvarGetLbGlobal(implvar);
9430  if( impltype == SCIP_BOUNDTYPE_LOWER )
9431  {
9432  if( SCIPsetIsFeasGT(set, implbound, implub) )
9433  {
9434  /* the implication produces a conflict: the problem is infeasible */
9435  *infeasible = TRUE;
9436  }
9437  else if( SCIPsetIsFeasGT(set, implbound, impllb) )
9438  {
9439  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9440  * with the local bound, in this case we need to store the bound change as pending bound change
9441  */
9442  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9443  {
9444  assert(tree != NULL);
9445  assert(transprob != NULL);
9446  assert(SCIPprobIsTransformed(transprob));
9447 
9448  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9449  tree, reopt, lp, branchcand, eventqueue, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
9450  }
9451  else
9452  {
9453  SCIP_CALL( SCIPvarChgLbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
9454  }
9455 
9456  if( nbdchgs != NULL )
9457  (*nbdchgs)++;
9458  }
9459  }
9460  else
9461  {
9462  if( SCIPsetIsFeasLT(set, implbound, impllb) )
9463  {
9464  /* the implication produces a conflict: the problem is infeasible */
9465  *infeasible = TRUE;
9466  }
9467  else if( SCIPsetIsFeasLT(set, implbound, implub) )
9468  {
9469  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9470  * with the local bound, in this case we need to store the bound change as pending bound change
9471  */
9472  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9473  {
9474  assert(tree != NULL);
9475  assert(transprob != NULL);
9476  assert(SCIPprobIsTransformed(transprob));
9477 
9478  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9479  tree, reopt, lp, branchcand, eventqueue, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
9480  }
9481  else
9482  {
9483  SCIP_CALL( SCIPvarChgUbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
9484  }
9485 
9486  if( nbdchgs != NULL )
9487  (*nbdchgs)++;
9488  }
9489  }
9490 
9491  return SCIP_OKAY;
9492 }
9493 
9494 /** actually performs the addition of an implication to the variable's implication arrays,
9495  * and adds the corresponding implication or variable bound to the implied variable;
9496  * if the implication is conflicting, the variable is fixed to the opposite value;
9497  * if the variable is already fixed to the given value, the implication is performed immediately;
9498  * if the implication is redundant with respect to the variables' global bounds, it is ignored
9499  */
9500 static
9502  SCIP_VAR* var, /**< problem variable */
9503  BMS_BLKMEM* blkmem, /**< block memory */
9504  SCIP_SET* set, /**< global SCIP settings */
9505  SCIP_STAT* stat, /**< problem statistics */
9506  SCIP_PROB* transprob, /**< transformed problem */
9507  SCIP_PROB* origprob, /**< original problem */
9508  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9509  SCIP_REOPT* reopt, /**< reoptimization data structure */
9510  SCIP_LP* lp, /**< current LP data */
9511  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9512  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9513  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9514  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9515  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9516  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9517  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9518  SCIP_Bool isshortcut, /**< is the implication a shortcut, i.e., added as part of the transitive closure of another implication? */
9519  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9520  int* nbdchgs, /**< pointer to count the number of performed bound changes, or NULL */
9521  SCIP_Bool* added /**< pointer to store whether an implication was added */
9522  )
9523 {
9524  SCIP_Bool redundant;
9525  SCIP_Bool conflict;
9526 
9527  assert(var != NULL);
9528  assert(SCIPvarIsActive(var));
9530  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
9531  assert(SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED);
9532  assert(infeasible != NULL);
9533  assert(added != NULL);
9534 
9535  /* check implication on debugging solution */
9536  SCIP_CALL( SCIPdebugCheckImplic(set, var, varfixing, implvar, impltype, implbound) ); /*lint !e506 !e774*/
9537 
9538  *infeasible = FALSE;
9539  *added = FALSE;
9540 
9541  /* check, if the implication is redundant or infeasible */
9542  checkImplic(set, implvar, impltype, implbound, &redundant, &conflict);
9543  assert(!redundant || !conflict);
9544  if( redundant )
9545  return SCIP_OKAY;
9546 
9547  if( var == implvar )
9548  {
9549  /* special cases appear were a bound to a variable implies itself to be outside the bounds:
9550  * x == varfixing => x < 0 or x > 1
9551  */
9552  if( SCIPsetIsLT(set, implbound, 0.0) || SCIPsetIsGT(set, implbound, 1.0) )
9553  conflict = TRUE;
9554  else
9555  {
9556  /* variable implies itself: x == varfixing => x == (impltype == SCIP_BOUNDTYPE_LOWER) */
9557  assert(SCIPsetIsZero(set, implbound) || SCIPsetIsEQ(set, implbound, 1.0));
9558  assert(SCIPsetIsZero(set, implbound) == (impltype == SCIP_BOUNDTYPE_UPPER));
9559  assert(SCIPsetIsEQ(set, implbound, 1.0) == (impltype == SCIP_BOUNDTYPE_LOWER));
9560  conflict = conflict || ((varfixing == TRUE) == (impltype == SCIP_BOUNDTYPE_UPPER));
9561  if( !conflict )
9562  return SCIP_OKAY;
9563  }
9564  }
9565 
9566  /* check, if the variable is already fixed */
9567  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
9568  {
9569  /* if the variable is fixed to the given value, perform the implication; otherwise, ignore the implication */
9570  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
9571  {
9572  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
9573  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
9574  }
9575  return SCIP_OKAY;
9576  }
9577 
9578  assert((impltype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, implbound, SCIPvarGetLbGlobal(implvar)))
9579  || (impltype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, implbound, SCIPvarGetUbGlobal(implvar))));
9580 
9581  if( !conflict )
9582  {
9583  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9584 
9585  if( SCIPvarIsBinary(implvar) )
9586  {
9587  SCIP_VAR* vars[2];
9588  SCIP_Bool vals[2];
9589 
9590  assert(SCIPsetIsFeasEQ(set, implbound, 1.0) || SCIPsetIsFeasZero(set, implbound));
9591  assert((impltype == SCIP_BOUNDTYPE_UPPER) == SCIPsetIsFeasZero(set, implbound));
9592 
9593  vars[0] = var;
9594  vars[1] = implvar;
9595  vals[0] = varfixing;
9596  vals[1] = (impltype == SCIP_BOUNDTYPE_UPPER);
9597 
9598  /* add the clique to the clique table */
9599  SCIP_CALL( SCIPcliquetableAdd(cliquetable, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
9600  eventqueue, vars, vals, 2, FALSE, &conflict, nbdchgs) );
9601 
9602  if( !conflict )
9603  return SCIP_OKAY;
9604  }
9605  else
9606  {
9607  /* add implication x == 0/1 -> y <= b / y >= b to the implications list of x */
9608  SCIPsetDebugMsg(set, "adding implication: <%s> == %u ==> <%s> %s %g\n",
9609  SCIPvarGetName(var), varfixing,
9610  SCIPvarGetName(implvar), impltype == SCIP_BOUNDTYPE_UPPER ? "<=" : ">=", implbound);
9611  SCIP_CALL( SCIPimplicsAdd(&var->implics, blkmem, set, stat, varfixing, implvar, impltype, implbound,
9612  isshortcut, &conflict, added) );
9613  }
9614  }
9615  assert(!conflict || !(*added));
9616 
9617  /* on conflict, fix the variable to the opposite value */
9618  if( conflict )
9619  {
9620  SCIPsetDebugMsg(set, " -> implication yields a conflict: fix <%s> == %d\n", SCIPvarGetName(var), !varfixing);
9621 
9622  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9623  * with the local bound, in this case we need to store the bound change as pending bound change
9624  */
9625  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9626  {
9627  assert(tree != NULL);
9628  assert(transprob != NULL);
9629  assert(SCIPprobIsTransformed(transprob));
9630 
9631  if( varfixing )
9632  {
9633  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9634  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
9635  }
9636  else
9637  {
9638  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9639  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
9640  }
9641  }
9642  else
9643  {
9644  if( varfixing )
9645  {
9646  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
9647  }
9648  else
9649  {
9650  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
9651  }
9652  }
9653  if( nbdchgs != NULL )
9654  (*nbdchgs)++;
9655 
9656  return SCIP_OKAY;
9657  }
9658  else if( *added )
9659  {
9660  /* issue IMPLADDED event */
9661  SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
9662  }
9663  else
9664  {
9665  /* the implication was redundant: the inverse is also redundant */
9666  return SCIP_OKAY;
9667  }
9668 
9669  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9670 
9671  /* check, whether implied variable is binary */
9672  if( !SCIPvarIsBinary(implvar) )
9673  {
9674  SCIP_Real lb;
9675  SCIP_Real ub;
9676 
9677  /* add inverse variable bound to the variable bounds of y with global bounds y \in [lb,ub]:
9678  * x == 0 -> y <= b <-> y <= (ub - b)*x + b
9679  * x == 1 -> y <= b <-> y <= (b - ub)*x + ub
9680  * x == 0 -> y >= b <-> y >= (lb - b)*x + b
9681  * x == 1 -> y >= b <-> y >= (b - lb)*x + lb
9682  * for numerical reasons, ignore variable bounds with large absolute coefficient
9683  */
9684  lb = SCIPvarGetLbGlobal(implvar);
9685  ub = SCIPvarGetUbGlobal(implvar);
9686  if( impltype == SCIP_BOUNDTYPE_UPPER )
9687  {
9688  if( REALABS(implbound - ub) <= MAXABSVBCOEF )
9689  {
9690  SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, var,
9691  varfixing ? implbound - ub : ub - implbound, varfixing ? ub : implbound) );
9692  }
9693  }
9694  else
9695  {
9696  if( REALABS(implbound - lb) <= MAXABSVBCOEF )
9697  {
9698  SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, var,
9699  varfixing ? implbound - lb : lb - implbound, varfixing ? lb : implbound) );
9700  }
9701  }
9702  }
9703 
9704  return SCIP_OKAY;
9705 }
9706 
9707 /** adds transitive closure for binary implication x = a -> y = b */
9708 static
9710  SCIP_VAR* var, /**< problem variable */
9711  BMS_BLKMEM* blkmem, /**< block memory */
9712  SCIP_SET* set, /**< global SCIP settings */
9713  SCIP_STAT* stat, /**< problem statistics */
9714  SCIP_PROB* transprob, /**< transformed problem */
9715  SCIP_PROB* origprob, /**< original problem */
9716  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9717  SCIP_REOPT* reopt, /**< reoptimization data structure */
9718  SCIP_LP* lp, /**< current LP data */
9719  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9720  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9721  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9722  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9723  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9724  SCIP_Bool implvarfixing, /**< fixing b in implication */
9725  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9726  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9727  )
9728 {
9729  SCIP_VAR** implvars;
9730  SCIP_BOUNDTYPE* impltypes;
9731  SCIP_Real* implbounds;
9732  int nimpls;
9733  int i;
9734 
9735  *infeasible = FALSE;
9736 
9737  /* binary variable: implications of implvar */
9738  nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
9739  implvars = SCIPimplicsGetVars(implvar->implics, implvarfixing);
9740  impltypes = SCIPimplicsGetTypes(implvar->implics, implvarfixing);
9741  implbounds = SCIPimplicsGetBounds(implvar->implics, implvarfixing);
9742 
9743  /* if variable has too many implications, the implication graph may become too dense */
9744  i = MIN(nimpls, MAXIMPLSCLOSURE) - 1;
9745 
9746  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9747  * implvars[i] is fixed, s.t. the implication y == varfixing -> z <= b / z >= b is deleted; this affects the
9748  * array over which we currently iterate; the only thing that can happen, is that elements of the array are
9749  * deleted; in this case, the subsequent elements are moved to the front; if we iterate from back to front, the
9750  * only thing that can happen is that we add the same implication twice - this does no harm
9751  */
9752  while ( i >= 0 && !(*infeasible) )
9753  {
9754  SCIP_Bool added;
9755 
9756  assert(implvars[i] != implvar);
9757 
9758  /* we have x == varfixing -> y == implvarfixing -> z <= b / z >= b:
9759  * add implication x == varfixing -> z <= b / z >= b to the implications list of x
9760  */
9761  if( SCIPvarIsActive(implvars[i]) )
9762  {
9763  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
9764  eventqueue, varfixing, implvars[i], impltypes[i], implbounds[i], TRUE, infeasible, nbdchgs, &added) );
9765  assert(SCIPimplicsGetNImpls(implvar->implics, implvarfixing) <= nimpls);
9766  nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
9767  i = MIN(i, nimpls); /* some elements from the array could have been removed */
9768  }
9769  --i;
9770  }
9771 
9772  return SCIP_OKAY;
9773 }
9774 
9775 /** adds given implication to the variable's implication list, and adds all implications directly implied by this
9776  * implication to the variable's implication list;
9777  * if the implication is conflicting, the variable is fixed to the opposite value;
9778  * if the variable is already fixed to the given value, the implication is performed immediately;
9779  * if the implication is redundant with respect to the variables' global bounds, it is ignored
9780  */
9781 static
9783  SCIP_VAR* var, /**< problem variable */
9784  BMS_BLKMEM* blkmem, /**< block memory */
9785  SCIP_SET* set, /**< global SCIP settings */
9786  SCIP_STAT* stat, /**< problem statistics */
9787  SCIP_PROB* transprob, /**< transformed problem */
9788  SCIP_PROB* origprob, /**< original problem */
9789  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9790  SCIP_REOPT* reopt, /**< reoptimization data structure */
9791  SCIP_LP* lp, /**< current LP data */
9792  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9793  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9794  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9795  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9796  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9797  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9798  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9799  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
9800  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9801  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9802  )
9803 {
9804  SCIP_Bool added;
9805 
9806  assert(var != NULL);
9807  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
9808  assert(SCIPvarIsActive(var));
9809  assert(implvar != NULL);
9810  assert(SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED);
9811  assert(infeasible != NULL);
9812 
9813  /* add implication x == varfixing -> y <= b / y >= b to the implications list of x */
9814  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
9815  eventqueue, varfixing, implvar, impltype, implbound, FALSE, infeasible, nbdchgs, &added) );
9816 
9817  if( *infeasible || var == implvar || !transitive || !added )
9818  return SCIP_OKAY;
9819 
9820  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9821 
9822  /* add transitive closure */
9823  if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
9824  {
9825  SCIP_Bool implvarfixing;
9826 
9827  implvarfixing = (impltype == SCIP_BOUNDTYPE_LOWER);
9828 
9829  /* binary variable: implications of implvar */
9830  SCIP_CALL( varAddTransitiveBinaryClosureImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9831  cliquetable, branchcand, eventqueue, varfixing, implvar, implvarfixing, infeasible, nbdchgs) );
9832 
9833  /* inverse implication */
9834  if( !(*infeasible) )
9835  {
9836  SCIP_CALL( varAddTransitiveBinaryClosureImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9837  cliquetable, branchcand, eventqueue, !implvarfixing, var, !varfixing, infeasible, nbdchgs) );
9838  }
9839  }
9840  else
9841  {
9842  /* non-binary variable: variable lower bounds of implvar */
9843  if( impltype == SCIP_BOUNDTYPE_UPPER && implvar->vlbs != NULL )
9844  {
9845  SCIP_VAR** vlbvars;
9846  SCIP_Real* vlbcoefs;
9847  SCIP_Real* vlbconstants;
9848  int nvlbvars;
9849  int i;
9850 
9851  nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
9852  vlbvars = SCIPvboundsGetVars(implvar->vlbs);
9853  vlbcoefs = SCIPvboundsGetCoefs(implvar->vlbs);
9854  vlbconstants = SCIPvboundsGetConstants(implvar->vlbs);
9855 
9856  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9857  * vlbvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
9858  * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
9859  * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
9860  * is that we add the same implication twice - this does no harm
9861  */
9862  i = nvlbvars-1;
9863  while ( i >= 0 && !(*infeasible) )
9864  {
9865  assert(vlbvars[i] != implvar);
9866  assert(!SCIPsetIsZero(set, vlbcoefs[i]));
9867 
9868  /* we have x == varfixing -> y <= b and y >= c*z + d:
9869  * c > 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
9870  * c < 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
9871  *
9872  * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
9873  * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
9874  * aggregation variable (the one which will stay active);
9875  *
9876  * W.l.o.g. we consider the variable upper bounds for now. Let "vubvar" be a variable upper bound of
9877  * the aggregated variable "aggvar"; During that copying of that variable upper bound variable
9878  * "vubvar" the variable lower and upper bounds of this variable "vubvar" are also considered; note
9879  * that the "aggvar" can be a variable lower bound variable of the variable "vubvar"; Due to that
9880  * situation it can happen that we reach that code place where "vlbvars[i] == aggvar". In particular
9881  * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
9882  * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
9883  * have to explicitly check that the active variable has not a variable status
9884  * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
9885  */
9886  if( SCIPvarIsActive(vlbvars[i]) && SCIPvarGetStatus(vlbvars[i]) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(vlbvars[i]) != SCIP_VARSTATUS_NEGATED )
9887  {
9888  SCIP_Real vbimplbound;
9889 
9890  vbimplbound = (implbound - vlbconstants[i])/vlbcoefs[i];
9891  if( vlbcoefs[i] >= 0.0 )
9892  {
9893  vbimplbound = adjustedUb(set, SCIPvarGetType(vlbvars[i]), vbimplbound);
9894  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9895  branchcand, eventqueue, varfixing, vlbvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
9896  infeasible, nbdchgs, &added) );
9897  }
9898  else
9899  {
9900  vbimplbound = adjustedLb(set, SCIPvarGetType(vlbvars[i]), vbimplbound);
9901  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9902  branchcand, eventqueue, varfixing, vlbvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
9903  infeasible, nbdchgs, &added) );
9904  }
9905  nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
9906  i = MIN(i, nvlbvars); /* some elements from the array could have been removed */
9907  }
9908  --i;
9909  }
9910  }
9911 
9912  /* non-binary variable: variable upper bounds of implvar */
9913  if( impltype == SCIP_BOUNDTYPE_LOWER && implvar->vubs != NULL )
9914  {
9915  SCIP_VAR** vubvars;
9916  SCIP_Real* vubcoefs;
9917  SCIP_Real* vubconstants;
9918  int nvubvars;
9919  int i;
9920 
9921  nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
9922  vubvars = SCIPvboundsGetVars(implvar->vubs);
9923  vubcoefs = SCIPvboundsGetCoefs(implvar->vubs);
9924  vubconstants = SCIPvboundsGetConstants(implvar->vubs);
9925 
9926  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9927  * vubvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
9928  * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
9929  * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
9930  * is that we add the same implication twice - this does no harm
9931  */
9932  i = nvubvars-1;
9933  while ( i >= 0 && !(*infeasible) )
9934  {
9935  assert(vubvars[i] != implvar);
9936  assert(!SCIPsetIsZero(set, vubcoefs[i]));
9937 
9938  /* we have x == varfixing -> y >= b and y <= c*z + d:
9939  * c > 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
9940  * c < 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
9941  *
9942  * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
9943  * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
9944  * aggregation variable (the one which will stay active);
9945  *
9946  * W.l.o.g. we consider the variable lower bounds for now. Let "vlbvar" be a variable lower bound of
9947  * the aggregated variable "aggvar"; During that copying of that variable lower bound variable
9948  * "vlbvar" the variable lower and upper bounds of this variable "vlbvar" are also considered; note
9949  * that the "aggvar" can be a variable upper bound variable of the variable "vlbvar"; Due to that
9950  * situation it can happen that we reach that code place where "vubvars[i] == aggvar". In particular
9951  * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
9952  * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
9953  * have to explicitly check that the active variable has not a variable status
9954  * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
9955  */
9956  if( SCIPvarIsActive(vubvars[i]) && SCIPvarGetStatus(vubvars[i]) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(vubvars[i]) != SCIP_VARSTATUS_NEGATED )
9957  {
9958  SCIP_Real vbimplbound;
9959 
9960  vbimplbound = (implbound - vubconstants[i])/vubcoefs[i];
9961  if( vubcoefs[i] >= 0.0 )
9962  {
9963  vbimplbound = adjustedLb(set, SCIPvarGetType(vubvars[i]), vbimplbound);
9964  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9965  branchcand, eventqueue, varfixing, vubvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
9966  infeasible, nbdchgs, &added) );
9967  }
9968  else
9969  {
9970  vbimplbound = adjustedUb(set, SCIPvarGetType(vubvars[i]), vbimplbound);
9971  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9972  branchcand, eventqueue, varfixing, vubvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
9973  infeasible, nbdchgs, &added) );
9974  }
9975  nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
9976  i = MIN(i, nvubvars); /* some elements from the array could have been removed */
9977  }
9978  --i;
9979  }
9980  }
9981  }
9982 
9983  return SCIP_OKAY;
9984 }
9985 
9986 /** informs variable x about a globally valid variable lower bound x >= b*z + d with integer variable z;
9987  * if z is binary, the corresponding valid implication for z is also added;
9988  * improves the global bounds of the variable and the vlb variable if possible
9989  */
9991  SCIP_VAR* var, /**< problem variable */
9992  BMS_BLKMEM* blkmem, /**< block memory */
9993  SCIP_SET* set, /**< global SCIP settings */
9994  SCIP_STAT* stat, /**< problem statistics */
9995  SCIP_PROB* transprob, /**< transformed problem */
9996  SCIP_PROB* origprob, /**< original problem */
9997  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9998  SCIP_REOPT* reopt, /**< reoptimization data structure */
9999  SCIP_LP* lp, /**< current LP data */
10000  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10001  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10002  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10003  SCIP_VAR* vlbvar, /**< variable z in x >= b*z + d */
10004  SCIP_Real vlbcoef, /**< coefficient b in x >= b*z + d */
10005  SCIP_Real vlbconstant, /**< constant d in x >= b*z + d */
10006  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
10007  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10008  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
10009  )
10010 {
10011  assert(var != NULL);
10012  assert(set != NULL);
10013  assert(var->scip == set->scip);
10014  assert(SCIPvarGetType(vlbvar) != SCIP_VARTYPE_CONTINUOUS);
10015  assert(infeasible != NULL);
10016 
10017  SCIPsetDebugMsg(set, "adding variable lower bound <%s> >= %g<%s> + %g\n", SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
10018 
10019  *infeasible = FALSE;
10020  if( nbdchgs != NULL )
10021  *nbdchgs = 0;
10022 
10023  switch( SCIPvarGetStatus(var) )
10024  {
10026  assert(var->data.original.transvar != NULL);
10027  SCIP_CALL( SCIPvarAddVlb(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10028  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef, vlbconstant, transitive, infeasible, nbdchgs) );
10029  break;
10030 
10031  case SCIP_VARSTATUS_COLUMN:
10032  case SCIP_VARSTATUS_LOOSE:
10033  case SCIP_VARSTATUS_FIXED:
10034  /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
10035  SCIP_CALL( SCIPvarGetProbvarSum(&vlbvar, set, &vlbcoef, &vlbconstant) );
10036  SCIPsetDebugMsg(set, " -> transformed to variable lower bound <%s> >= %g<%s> + %g\n", SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
10037 
10038  /* if the vlb coefficient is zero, just update the lower bound of the variable */
10039  if( SCIPsetIsZero(set, vlbcoef) )
10040  {
10041  if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetUbGlobal(var)) )
10042  *infeasible = TRUE;
10043  else if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetLbGlobal(var)) )
10044  {
10045  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10046  * with the local bound, in this case we need to store the bound change as pending bound change
10047  */
10048  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10049  {
10050  assert(tree != NULL);
10051  assert(transprob != NULL);
10052  assert(SCIPprobIsTransformed(transprob));
10053 
10054  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10055  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vlbconstant, SCIP_BOUNDTYPE_LOWER, FALSE) );
10056  }
10057  else
10058  {
10059  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vlbconstant) );
10060  }
10061 
10062  if( nbdchgs != NULL )
10063  (*nbdchgs)++;
10064  }
10065  }
10066  else if( var == vlbvar )
10067  {
10068  /* the variables cancels out, the variable bound constraint is either redundant or proves global infeasibility */
10069  if( SCIPsetIsEQ(set, vlbcoef, 1.0) )
10070  {
10071  if( SCIPsetIsPositive(set, vlbconstant) )
10072  *infeasible = TRUE;
10073  return SCIP_OKAY;
10074  }
10075  else
10076  {
10077  SCIP_Real lb = SCIPvarGetLbGlobal(var);
10078  SCIP_Real ub = SCIPvarGetUbGlobal(var);
10079 
10080  /* the variable bound constraint defines a new upper bound */
10081  if( SCIPsetIsGT(set, vlbcoef, 1.0) )
10082  {
10083  SCIP_Real newub = vlbconstant / (1.0 - vlbcoef);
10084 
10085  if( SCIPsetIsFeasLT(set, newub, lb) )
10086  {
10087  *infeasible = TRUE;
10088  return SCIP_OKAY;
10089  }
10090  else if( SCIPsetIsFeasLT(set, newub, ub) )
10091  {
10092  /* bound might be adjusted due to integrality condition */
10093  newub = adjustedUb(set, SCIPvarGetType(var), newub);
10094 
10095  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10096  * with the local bound, in this case we need to store the bound change as pending bound change
10097  */
10098  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10099  {
10100  assert(tree != NULL);
10101  assert(transprob != NULL);
10102  assert(SCIPprobIsTransformed(transprob));
10103 
10104  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10105  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10106  }
10107  else
10108  {
10109  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newub) );
10110  }
10111 
10112  if( nbdchgs != NULL )
10113  (*nbdchgs)++;
10114  }
10115  }
10116  /* the variable bound constraint defines a new lower bound */
10117  else
10118  {
10119  SCIP_Real newlb;
10120 
10121  assert(SCIPsetIsLT(set, vlbcoef, 1.0));
10122 
10123  newlb = vlbconstant / (1.0 - vlbcoef);
10124 
10125  if( SCIPsetIsFeasGT(set, newlb, ub) )
10126  {
10127  *infeasible = TRUE;
10128  return SCIP_OKAY;
10129  }
10130  else if( SCIPsetIsFeasGT(set, newlb, lb) )
10131  {
10132  /* bound might be adjusted due to integrality condition */
10133  newlb = adjustedLb(set, SCIPvarGetType(var), newlb);
10134 
10135  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10136  * with the local bound, in this case we need to store the bound change as pending bound change
10137  */
10138  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10139  {
10140  assert(tree != NULL);
10141  assert(transprob != NULL);
10142  assert(SCIPprobIsTransformed(transprob));
10143 
10144  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10145  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10146  }
10147  else
10148  {
10149  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newlb) );
10150  }
10151 
10152  if( nbdchgs != NULL )
10153  (*nbdchgs)++;
10154  }
10155  }
10156  }
10157  }
10158  else if( SCIPvarIsActive(vlbvar) )
10159  {
10160  SCIP_Real xlb;
10161  SCIP_Real xub;
10162  SCIP_Real zlb;
10163  SCIP_Real zub;
10164  SCIP_Real minvlb;
10165  SCIP_Real maxvlb;
10166 
10168  assert(vlbcoef != 0.0);
10169 
10170  minvlb = -SCIPsetInfinity(set);
10171  maxvlb = SCIPsetInfinity(set);
10172 
10173  xlb = SCIPvarGetLbGlobal(var);
10174  xub = SCIPvarGetUbGlobal(var);
10175  zlb = SCIPvarGetLbGlobal(vlbvar);
10176  zub = SCIPvarGetUbGlobal(vlbvar);
10177 
10178  /* improve global bounds of vlb variable, and calculate minimal and maximal value of variable bound */
10179  if( vlbcoef >= 0.0 )
10180  {
10181  SCIP_Real newzub;
10182 
10183  if( !SCIPsetIsInfinity(set, xub) )
10184  {
10185  /* x >= b*z + d -> z <= (x-d)/b */
10186  newzub = (xub - vlbconstant)/vlbcoef;
10187 
10188  /* return if the new bound is less than -infinity */
10189  if( SCIPsetIsInfinity(set, REALABS(newzub)) )
10190  return SCIP_OKAY;
10191 
10192  if( SCIPsetIsFeasLT(set, newzub, zlb) )
10193  {
10194  *infeasible = TRUE;
10195  return SCIP_OKAY;
10196  }
10197  if( SCIPsetIsFeasLT(set, newzub, zub) )
10198  {
10199  /* bound might be adjusted due to integrality condition */
10200  newzub = adjustedUb(set, SCIPvarGetType(vlbvar), newzub);
10201 
10202  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10203  * with the local bound, in this case we need to store the bound change as pending bound change
10204  */
10205  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10206  {
10207  assert(tree != NULL);
10208  assert(transprob != NULL);
10209  assert(SCIPprobIsTransformed(transprob));
10210 
10211  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10212  tree, reopt, lp, branchcand, eventqueue, cliquetable, vlbvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10213  }
10214  else
10215  {
10216  SCIP_CALL( SCIPvarChgUbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
10217  }
10218  zub = newzub;
10219 
10220  if( nbdchgs != NULL )
10221  (*nbdchgs)++;
10222  }
10223  maxvlb = vlbcoef * zub + vlbconstant;
10224  if( !SCIPsetIsInfinity(set, -zlb) )
10225  minvlb = vlbcoef * zlb + vlbconstant;
10226  }
10227  else
10228  {
10229  if( !SCIPsetIsInfinity(set, zub) )
10230  maxvlb = vlbcoef * zub + vlbconstant;
10231  if( !SCIPsetIsInfinity(set, -zlb) )
10232  minvlb = vlbcoef * zlb + vlbconstant;
10233  }
10234  }
10235  else
10236  {
10237  SCIP_Real newzlb;
10238 
10239  if( !SCIPsetIsInfinity(set, xub) )
10240  {
10241  /* x >= b*z + d -> z >= (x-d)/b */
10242  newzlb = (xub - vlbconstant)/vlbcoef;
10243 
10244  /* return if the new bound is larger than infinity */
10245  if( SCIPsetIsInfinity(set, REALABS(newzlb)) )
10246  return SCIP_OKAY;
10247 
10248  if( SCIPsetIsFeasGT(set, newzlb, zub) )
10249  {
10250  *infeasible = TRUE;
10251  return SCIP_OKAY;
10252  }
10253  if( SCIPsetIsFeasGT(set, newzlb, zlb) )
10254  {
10255  /* bound might be adjusted due to integrality condition */
10256  newzlb = adjustedLb(set, SCIPvarGetType(vlbvar), newzlb);
10257 
10258  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10259  * with the local bound, in this case we need to store the bound change as pending bound change
10260  */
10261  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10262  {
10263  assert(tree != NULL);
10264  assert(transprob != NULL);
10265  assert(SCIPprobIsTransformed(transprob));
10266 
10267  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10268  tree, reopt, lp, branchcand, eventqueue, cliquetable, vlbvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10269  }
10270  else
10271  {
10272  SCIP_CALL( SCIPvarChgLbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
10273  }
10274  zlb = newzlb;
10275 
10276  if( nbdchgs != NULL )
10277  (*nbdchgs)++;
10278  }
10279  maxvlb = vlbcoef * zlb + vlbconstant;
10280  if( !SCIPsetIsInfinity(set, zub) )
10281  minvlb = vlbcoef * zub + vlbconstant;
10282  }
10283  else
10284  {
10285  if( !SCIPsetIsInfinity(set, -zlb) )
10286  maxvlb = vlbcoef * zlb + vlbconstant;
10287  if( !SCIPsetIsInfinity(set, zub) )
10288  minvlb = vlbcoef * zub + vlbconstant;
10289  }
10290  }
10291  if( maxvlb < minvlb )
10292  maxvlb = minvlb;
10293 
10294  /* adjust bounds due to integrality of variable */
10295  minvlb = adjustedLb(set, SCIPvarGetType(var), minvlb);
10296  maxvlb = adjustedLb(set, SCIPvarGetType(var), maxvlb);
10297 
10298  /* check bounds for feasibility */
10299  if( SCIPsetIsFeasGT(set, minvlb, xub) || (var == vlbvar && SCIPsetIsEQ(set, vlbcoef, 1.0) && SCIPsetIsFeasPositive(set, vlbconstant)) )
10300  {
10301  *infeasible = TRUE;
10302  return SCIP_OKAY;
10303  }
10304  /* improve global lower bound of variable */
10305  if( SCIPsetIsFeasGT(set, minvlb, xlb) )
10306  {
10307  /* bound might be adjusted due to integrality condition */
10308  minvlb = adjustedLb(set, SCIPvarGetType(var), minvlb);
10309 
10310  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10311  * with the local bound, in this case we need to store the bound change as pending bound change
10312  */
10313  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10314  {
10315  assert(tree != NULL);
10316  assert(transprob != NULL);
10317  assert(SCIPprobIsTransformed(transprob));
10318 
10319  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10320  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, minvlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10321  }
10322  else
10323  {
10324  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, minvlb) );
10325  }
10326  xlb = minvlb;
10327 
10328  if( nbdchgs != NULL )
10329  (*nbdchgs)++;
10330  }
10331  minvlb = xlb;
10332 
10333  /* improve variable bound for binary z by moving the variable's global bound to the vlb constant */
10334  if( SCIPvarGetType(vlbvar) == SCIP_VARTYPE_BINARY )
10335  {
10336  /* b > 0: x >= (maxvlb - minvlb) * z + minvlb
10337  * b < 0: x >= (minvlb - maxvlb) * z + maxvlb
10338  */
10339 
10340  assert(!SCIPsetIsInfinity(set, maxvlb) && !SCIPsetIsInfinity(set, -minvlb));
10341 
10342  if( vlbcoef >= 0.0 )
10343  {
10344  vlbcoef = maxvlb - minvlb;
10345  vlbconstant = minvlb;
10346  }
10347  else
10348  {
10349  vlbcoef = minvlb - maxvlb;
10350  vlbconstant = maxvlb;
10351  }
10352  }
10353 
10354  /* add variable bound to the variable bounds list */
10355  if( SCIPsetIsFeasGT(set, maxvlb, xlb) )
10356  {
10357  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED);
10358  assert(!SCIPsetIsZero(set, vlbcoef));
10359 
10360  /* if one of the variables is binary, add the corresponding implication to the variable's implication
10361  * list, thereby also adding the variable bound (or implication) to the other variable
10362  */
10363  if( SCIPvarGetType(vlbvar) == SCIP_VARTYPE_BINARY )
10364  {
10365  /* add corresponding implication:
10366  * b > 0, x >= b*z + d <-> z == 1 -> x >= b+d
10367  * b < 0, x >= b*z + d <-> z == 0 -> x >= d
10368  */
10369  SCIP_CALL( varAddTransitiveImplic(vlbvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10370  cliquetable, branchcand, eventqueue, (vlbcoef >= 0.0), var, SCIP_BOUNDTYPE_LOWER, maxvlb, transitive,
10371  infeasible, nbdchgs) );
10372  }
10373  else if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
10374  {
10375  /* add corresponding implication:
10376  * b > 0, x >= b*z + d <-> x == 0 -> z <= -d/b
10377  * b < 0, x >= b*z + d <-> x == 0 -> z >= -d/b
10378  */
10379  SCIP_Real implbound;
10380  implbound = -vlbconstant/vlbcoef;
10381 
10382  /* tighten the implication bound if the variable is integer */
10383  if( SCIPvarIsIntegral(vlbvar) )
10384  {
10385  if( vlbcoef >= 0 )
10386  implbound = SCIPsetFloor(set, implbound);
10387  else
10388  implbound = SCIPsetCeil(set, implbound);
10389  }
10390  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10391  cliquetable, branchcand, eventqueue, FALSE, vlbvar, (vlbcoef >= 0.0 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER),
10392  implbound, transitive, infeasible, nbdchgs) );
10393  }
10394  else
10395  {
10396  SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, vlbvar, vlbcoef, vlbconstant) );
10397  }
10398  }
10399  }
10400  break;
10401 
10403  /* x = a*y + c: x >= b*z + d <=> a*y + c >= b*z + d <=> y >= b/a * z + (d-c)/a, if a > 0
10404  * y <= b/a * z + (d-c)/a, if a < 0
10405  */
10406  assert(var->data.aggregate.var != NULL);
10407  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
10408  {
10409  /* a > 0 -> add variable lower bound */
10410  SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10411  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef/var->data.aggregate.scalar,
10412  (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10413  }
10414  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
10415  {
10416  /* a < 0 -> add variable upper bound */
10417  SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10418  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef/var->data.aggregate.scalar,
10419  (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10420  }
10421  else
10422  {
10423  SCIPerrorMessage("scalar is zero in aggregation\n");
10424  return SCIP_INVALIDDATA;
10425  }
10426  break;
10427 
10429  /* nothing to do here */
10430  break;
10431 
10433  /* x = offset - x': x >= b*z + d <=> offset - x' >= b*z + d <=> x' <= -b*z + (offset-d) */
10434  assert(var->negatedvar != NULL);
10436  assert(var->negatedvar->negatedvar == var);
10437  SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10438  branchcand, eventqueue, vlbvar, -vlbcoef, var->data.negate.constant - vlbconstant, transitive, infeasible,
10439  nbdchgs) );
10440  break;
10441 
10442  default:
10443  SCIPerrorMessage("unknown variable status\n");
10444  return SCIP_INVALIDDATA;
10445  }
10446 
10447  return SCIP_OKAY;
10448 }
10449 
10450 /** informs variable x about a globally valid variable upper bound x <= b*z + d with integer variable z;
10451  * if z is binary, the corresponding valid implication for z is also added;
10452  * updates the global bounds of the variable and the vub variable correspondingly
10453  */
10455  SCIP_VAR* var, /**< problem variable */
10456  BMS_BLKMEM* blkmem, /**< block memory */
10457  SCIP_SET* set, /**< global SCIP settings */
10458  SCIP_STAT* stat, /**< problem statistics */
10459  SCIP_PROB* transprob, /**< transformed problem */
10460  SCIP_PROB* origprob, /**< original problem */
10461  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10462  SCIP_REOPT* reopt, /**< reoptimization data structure */
10463  SCIP_LP* lp, /**< current LP data */
10464  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10465  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10466  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10467  SCIP_VAR* vubvar, /**< variable z in x <= b*z + d */
10468  SCIP_Real vubcoef, /**< coefficient b in x <= b*z + d */
10469  SCIP_Real vubconstant, /**< constant d in x <= b*z + d */
10470  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
10471  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10472  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
10473  )
10474 {
10475  assert(var != NULL);
10476  assert(set != NULL);
10477  assert(var->scip == set->scip);
10478  assert(SCIPvarGetType(vubvar) != SCIP_VARTYPE_CONTINUOUS);
10479  assert(infeasible != NULL);
10480 
10481  SCIPsetDebugMsg(set, "adding variable upper bound <%s> <= %g<%s> + %g\n", SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
10482 
10483  *infeasible = FALSE;
10484  if( nbdchgs != NULL )
10485  *nbdchgs = 0;
10486 
10487  switch( SCIPvarGetStatus(var) )
10488  {
10490  assert(var->data.original.transvar != NULL);
10491  SCIP_CALL( SCIPvarAddVub(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10492  cliquetable, branchcand, eventqueue, vubvar, vubcoef, vubconstant, transitive, infeasible, nbdchgs) );
10493  break;
10494 
10495  case SCIP_VARSTATUS_COLUMN:
10496  case SCIP_VARSTATUS_LOOSE:
10497  case SCIP_VARSTATUS_FIXED:
10498  /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
10499  SCIP_CALL( SCIPvarGetProbvarSum(&vubvar, set, &vubcoef, &vubconstant) );
10500  SCIPsetDebugMsg(set, " -> transformed to variable upper bound <%s> <= %g<%s> + %g\n",
10501  SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
10502 
10503  /* if the vub coefficient is zero, just update the upper bound of the variable */
10504  if( SCIPsetIsZero(set, vubcoef) )
10505  {
10506  if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetLbGlobal(var)) )
10507  *infeasible = TRUE;
10508  else if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetUbGlobal(var)) )
10509  {
10510  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10511  * with the local bound, in this case we need to store the bound change as pending bound change
10512  */
10513  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10514  {
10515  assert(tree != NULL);
10516  assert(transprob != NULL);
10517  assert(SCIPprobIsTransformed(transprob));
10518 
10519  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10520  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vubconstant, SCIP_BOUNDTYPE_UPPER, FALSE) );
10521  }
10522  else
10523  {
10524  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vubconstant) );
10525  }
10526 
10527  if( nbdchgs != NULL )
10528  (*nbdchgs)++;
10529  }
10530  }
10531  else if( var == vubvar )
10532  {
10533  /* the variables cancels out, the variable bound constraint is either redundant or proves global infeasibility */
10534  if( SCIPsetIsEQ(set, vubcoef, 1.0) )
10535  {
10536  if( SCIPsetIsNegative(set, vubconstant) )
10537  *infeasible = TRUE;
10538  return SCIP_OKAY;
10539  }
10540  else
10541  {
10542  SCIP_Real lb = SCIPvarGetLbGlobal(var);
10543  SCIP_Real ub = SCIPvarGetUbGlobal(var);
10544 
10545  /* the variable bound constraint defines a new lower bound */
10546  if( SCIPsetIsGT(set, vubcoef, 1.0) )
10547  {
10548  SCIP_Real newlb = vubconstant / (1.0 - vubcoef);
10549 
10550  if( SCIPsetIsFeasGT(set, newlb, ub) )
10551  {
10552  *infeasible = TRUE;
10553  return SCIP_OKAY;
10554  }
10555  else if( SCIPsetIsFeasGT(set, newlb, lb) )
10556  {
10557  /* bound might be adjusted due to integrality condition */
10558  newlb = adjustedLb(set, SCIPvarGetType(var), newlb);
10559 
10560  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10561  * with the local bound, in this case we need to store the bound change as pending bound change
10562  */
10563  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10564  {
10565  assert(tree != NULL);
10566  assert(transprob != NULL);
10567  assert(SCIPprobIsTransformed(transprob));
10568 
10569  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10570  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10571  }
10572  else
10573  {
10574  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newlb) );
10575  }
10576 
10577  if( nbdchgs != NULL )
10578  (*nbdchgs)++;
10579  }
10580  }
10581  /* the variable bound constraint defines a new upper bound */
10582  else
10583  {
10584  SCIP_Real newub;
10585 
10586  assert(SCIPsetIsLT(set, vubcoef, 1.0));
10587 
10588  newub = vubconstant / (1.0 - vubcoef);
10589 
10590  if( SCIPsetIsFeasLT(set, newub, lb) )
10591  {
10592  *infeasible = TRUE;
10593  return SCIP_OKAY;
10594  }
10595  else if( SCIPsetIsFeasLT(set, newub, ub) )
10596  {
10597  /* bound might be adjusted due to integrality condition */
10598  newub = adjustedUb(set, SCIPvarGetType(var), newub);
10599 
10600  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10601  * with the local bound, in this case we need to store the bound change as pending bound change
10602  */
10603  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10604  {
10605  assert(tree != NULL);
10606  assert(transprob != NULL);
10607  assert(SCIPprobIsTransformed(transprob));
10608 
10609  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10610  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10611  }
10612  else
10613  {
10614  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newub) );
10615  }
10616 
10617  if( nbdchgs != NULL )
10618  (*nbdchgs)++;
10619  }
10620  }
10621  }
10622  }
10623  else if( SCIPvarIsActive(vubvar) )
10624  {
10625  SCIP_Real xlb;
10626  SCIP_Real xub;
10627  SCIP_Real zlb;
10628  SCIP_Real zub;
10629  SCIP_Real minvub;
10630  SCIP_Real maxvub;
10631 
10633  assert(vubcoef != 0.0);
10634 
10635  minvub = -SCIPsetInfinity(set);
10636  maxvub = SCIPsetInfinity(set);
10637 
10638  xlb = SCIPvarGetLbGlobal(var);
10639  xub = SCIPvarGetUbGlobal(var);
10640  zlb = SCIPvarGetLbGlobal(vubvar);
10641  zub = SCIPvarGetUbGlobal(vubvar);
10642 
10643  /* improve global bounds of vub variable, and calculate minimal and maximal value of variable bound */
10644  if( vubcoef >= 0.0 )
10645  {
10646  SCIP_Real newzlb;
10647 
10648  if( !SCIPsetIsInfinity(set, -xlb) )
10649  {
10650  /* x <= b*z + d -> z >= (x-d)/b */
10651  newzlb = (xlb - vubconstant)/vubcoef;
10652  if( SCIPsetIsFeasGT(set, newzlb, zub) )
10653  {
10654  *infeasible = TRUE;
10655  return SCIP_OKAY;
10656  }
10657  if( SCIPsetIsFeasGT(set, newzlb, zlb) )
10658  {
10659  /* bound might be adjusted due to integrality condition */
10660  newzlb = adjustedLb(set, SCIPvarGetType(vubvar), newzlb);
10661 
10662  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10663  * with the local bound, in this case we need to store the bound change as pending bound change
10664  */
10665  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10666  {
10667  assert(tree != NULL);
10668  assert(transprob != NULL);
10669  assert(SCIPprobIsTransformed(transprob));
10670 
10671  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10672  tree, reopt, lp, branchcand, eventqueue, cliquetable, vubvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10673  }
10674  else
10675  {
10676  SCIP_CALL( SCIPvarChgLbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
10677  }
10678  zlb = newzlb;
10679 
10680  if( nbdchgs != NULL )
10681  (*nbdchgs)++;
10682  }
10683  minvub = vubcoef * zlb + vubconstant;
10684  if( !SCIPsetIsInfinity(set, zub) )
10685  maxvub = vubcoef * zub + vubconstant;
10686  }
10687  else
10688  {
10689  if( !SCIPsetIsInfinity(set, zub) )
10690  maxvub = vubcoef * zub + vubconstant;
10691  if( !SCIPsetIsInfinity(set, -zlb) )
10692  minvub = vubcoef * zlb + vubconstant;
10693  }
10694  }
10695  else
10696  {
10697  SCIP_Real newzub;
10698 
10699  if( !SCIPsetIsInfinity(set, -xlb) )
10700  {
10701  /* x <= b*z + d -> z <= (x-d)/b */
10702  newzub = (xlb - vubconstant)/vubcoef;
10703  if( SCIPsetIsFeasLT(set, newzub, zlb) )
10704  {
10705  *infeasible = TRUE;
10706  return SCIP_OKAY;
10707  }
10708  if( SCIPsetIsFeasLT(set, newzub, zub) )
10709  {
10710  /* bound might be adjusted due to integrality condition */
10711  newzub = adjustedUb(set, SCIPvarGetType(vubvar), newzub);
10712 
10713  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10714  * with the local bound, in this case we need to store the bound change as pending bound change
10715  */
10716  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10717  {
10718  assert(tree != NULL);
10719  assert(transprob != NULL);
10720  assert(SCIPprobIsTransformed(transprob));
10721 
10722  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10723  tree, reopt, lp, branchcand, eventqueue, cliquetable, vubvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10724  }
10725  else
10726  {
10727  SCIP_CALL( SCIPvarChgUbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
10728  }
10729  zub = newzub;
10730 
10731  if( nbdchgs != NULL )
10732  (*nbdchgs)++;
10733  }
10734  minvub = vubcoef * zub + vubconstant;
10735  if( !SCIPsetIsInfinity(set, -zlb) )
10736  maxvub = vubcoef * zlb + vubconstant;
10737  }
10738  else
10739  {
10740  if( !SCIPsetIsInfinity(set, zub) )
10741  minvub = vubcoef * zub + vubconstant;
10742  if( !SCIPsetIsInfinity(set, -zlb) )
10743  maxvub = vubcoef * zlb + vubconstant;
10744  }
10745  }
10746  if( minvub > maxvub )
10747  minvub = maxvub;
10748 
10749  /* adjust bounds due to integrality of vub variable */
10750  minvub = adjustedUb(set, SCIPvarGetType(var), minvub);
10751  maxvub = adjustedUb(set, SCIPvarGetType(var), maxvub);
10752 
10753  /* check bounds for feasibility */
10754  if( SCIPsetIsFeasLT(set, maxvub, xlb) || (var == vubvar && SCIPsetIsEQ(set, vubcoef, 1.0) && SCIPsetIsFeasNegative(set, vubconstant)) )
10755  {
10756  *infeasible = TRUE;
10757  return SCIP_OKAY;
10758  }
10759 
10760  /* improve global upper bound of variable */
10761  if( SCIPsetIsFeasLT(set, maxvub, xub) )
10762  {
10763  /* bound might be adjusted due to integrality condition */
10764  maxvub = adjustedUb(set, SCIPvarGetType(var), maxvub);
10765 
10766  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10767  * with the local bound, in this case we need to store the bound change as pending bound change
10768  */
10769  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10770  {
10771  assert(tree != NULL);
10772  assert(transprob != NULL);
10773  assert(SCIPprobIsTransformed(transprob));
10774 
10775  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10776  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, maxvub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10777  }
10778  else
10779  {
10780  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, maxvub) );
10781  }
10782  xub = maxvub;
10783 
10784  if( nbdchgs != NULL )
10785  (*nbdchgs)++;
10786  }
10787  maxvub = xub;
10788 
10789  /* improve variable bound for binary z by moving the variable's global bound to the vub constant */
10790  if( SCIPvarIsBinary(vubvar) )
10791  {
10792  /* b > 0: x <= (maxvub - minvub) * z + minvub
10793  * b < 0: x <= (minvub - maxvub) * z + maxvub
10794  */
10795 
10796  assert(!SCIPsetIsInfinity(set, maxvub) && !SCIPsetIsInfinity(set, -minvub));
10797 
10798  if( vubcoef >= 0.0 )
10799  {
10800  vubcoef = maxvub - minvub;
10801  vubconstant = minvub;
10802  }
10803  else
10804  {
10805  vubcoef = minvub - maxvub;
10806  vubconstant = maxvub;
10807  }
10808  }
10809 
10810  /* add variable bound to the variable bounds list */
10811  if( SCIPsetIsFeasLT(set, minvub, xub) )
10812  {
10813  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED);
10814  assert(!SCIPsetIsZero(set, vubcoef));
10815 
10816  /* if one of the variables is binary, add the corresponding implication to the variable's implication
10817  * list, thereby also adding the variable bound (or implication) to the other variable
10818  */
10819  if( SCIPvarGetType(vubvar) == SCIP_VARTYPE_BINARY )
10820  {
10821  /* add corresponding implication:
10822  * b > 0, x <= b*z + d <-> z == 0 -> x <= d
10823  * b < 0, x <= b*z + d <-> z == 1 -> x <= b+d
10824  */
10825  SCIP_CALL( varAddTransitiveImplic(vubvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10826  cliquetable, branchcand, eventqueue, (vubcoef < 0.0), var, SCIP_BOUNDTYPE_UPPER, minvub, transitive,
10827  infeasible, nbdchgs) );
10828  }
10829  else if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
10830  {
10831  /* add corresponding implication:
10832  * b > 0, x <= b*z + d <-> x == 1 -> z >= (1-d)/b
10833  * b < 0, x <= b*z + d <-> x == 1 -> z <= (1-d)/b
10834  */
10835  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10836  cliquetable, branchcand, eventqueue, TRUE, vubvar, (vubcoef >= 0.0 ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER),
10837  (1.0-vubconstant)/vubcoef, transitive, infeasible, nbdchgs) );
10838  }
10839  else
10840  {
10841  SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, vubvar, vubcoef, vubconstant) );
10842  }
10843  }
10844  }
10845  break;
10846 
10848  /* x = a*y + c: x <= b*z + d <=> a*y + c <= b*z + d <=> y <= b/a * z + (d-c)/a, if a > 0
10849  * y >= b/a * z + (d-c)/a, if a < 0
10850  */
10851  assert(var->data.aggregate.var != NULL);
10852  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
10853  {
10854  /* a > 0 -> add variable upper bound */
10855  SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10856  cliquetable, branchcand, eventqueue, vubvar, vubcoef/var->data.aggregate.scalar,
10857  (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10858  }
10859  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
10860  {
10861  /* a < 0 -> add variable lower bound */
10862  SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10863  cliquetable, branchcand, eventqueue, vubvar, vubcoef/var->data.aggregate.scalar,
10864  (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10865  }
10866  else
10867  {
10868  SCIPerrorMessage("scalar is zero in aggregation\n");
10869  return SCIP_INVALIDDATA;
10870  }
10871  break;
10872 
10874  /* nothing to do here */
10875  break;
10876 
10878  /* x = offset - x': x <= b*z + d <=> offset - x' <= b*z + d <=> x' >= -b*z + (offset-d) */
10879  assert(var->negatedvar != NULL);
10881  assert(var->negatedvar->negatedvar == var);
10882  SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10883  branchcand, eventqueue, vubvar, -vubcoef, var->data.negate.constant - vubconstant, transitive, infeasible,
10884  nbdchgs) );
10885  break;
10886 
10887  default:
10888  SCIPerrorMessage("unknown variable status\n");
10889  return SCIP_INVALIDDATA;
10890  }
10891 
10892  return SCIP_OKAY;
10893 }
10894 
10895 /** informs binary variable x about a globally valid implication: x == 0 or x == 1 ==> y <= b or y >= b;
10896  * also adds the corresponding implication or variable bound to the implied variable;
10897  * if the implication is conflicting, the variable is fixed to the opposite value;
10898  * if the variable is already fixed to the given value, the implication is performed immediately;
10899  * if the implication is redundant with respect to the variables' global bounds, it is ignored
10900  */
10902  SCIP_VAR* var, /**< problem variable */
10903  BMS_BLKMEM* blkmem, /**< block memory */
10904  SCIP_SET* set, /**< global SCIP settings */
10905  SCIP_STAT* stat, /**< problem statistics */
10906  SCIP_PROB* transprob, /**< transformed problem */
10907  SCIP_PROB* origprob, /**< original problem */
10908  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10909  SCIP_REOPT* reopt, /**< reoptimization data structure */
10910  SCIP_LP* lp, /**< current LP data */
10911  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10912  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10913  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10914  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
10915  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
10916  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
10917  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
10918  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
10919  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10920  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
10921  )
10922 {
10923  assert(var != NULL);
10924  assert(set != NULL);
10925  assert(var->scip == set->scip);
10926  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
10927  assert(infeasible != NULL);
10928 
10929  *infeasible = FALSE;
10930  if( nbdchgs != NULL )
10931  *nbdchgs = 0;
10932 
10933  switch( SCIPvarGetStatus(var) )
10934  {
10936  assert(var->data.original.transvar != NULL);
10937  SCIP_CALL( SCIPvarAddImplic(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10938  cliquetable, branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible,
10939  nbdchgs) );
10940  break;
10941 
10942  case SCIP_VARSTATUS_COLUMN:
10943  case SCIP_VARSTATUS_LOOSE:
10944  /* if the variable is fixed (although it has no FIXED status), and varfixing corresponds to the fixed value of
10945  * the variable, the implication can be applied directly;
10946  * otherwise, add implication to the implications list (and add inverse of implication to the implied variable)
10947  */
10948  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
10949  {
10950  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
10951  {
10952  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
10953  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
10954  }
10955  }
10956  else
10957  {
10958  SCIP_CALL( SCIPvarGetProbvarBound(&implvar, &implbound, &impltype) );
10959  SCIPvarAdjustBd(implvar, set, impltype, &implbound);
10960  if( SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED )
10961  {
10962  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10963  branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
10964  }
10965  }
10966  break;
10967 
10968  case SCIP_VARSTATUS_FIXED:
10969  /* if varfixing corresponds to the fixed value of the variable, the implication can be applied directly */
10970  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
10971  {
10972  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
10973  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
10974  }
10975  break;
10976 
10978  /* implication added for x == 1:
10979  * x == 1 && x = 1*z + 0 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10980  * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10981  * implication added for x == 0:
10982  * x == 0 && x = 1*z + 0 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10983  * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10984  *
10985  * use only binary variables z
10986  */
10987  assert(var->data.aggregate.var != NULL);
10988  if( SCIPvarIsBinary(var->data.aggregate.var) )
10989  {
10990  assert( (SCIPsetIsEQ(set, var->data.aggregate.scalar, 1.0) && SCIPsetIsZero(set, var->data.aggregate.constant))
10991  || (SCIPsetIsEQ(set, var->data.aggregate.scalar, -1.0) && SCIPsetIsEQ(set, var->data.aggregate.constant, 1.0)) );
10992 
10993  if( var->data.aggregate.scalar > 0 )
10994  {
10995  SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10996  cliquetable, branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible,
10997  nbdchgs) );
10998  }
10999  else
11000  {
11001  SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11002  cliquetable, branchcand, eventqueue, !varfixing, implvar, impltype, implbound, transitive, infeasible,
11003  nbdchgs) );
11004  }
11005  }
11006  break;
11007 
11009  /* nothing to do here */
11010  break;
11011 
11013  /* implication added for x == 1:
11014  * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
11015  * implication added for x == 0:
11016  * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
11017  */
11018  assert(var->negatedvar != NULL);
11020  assert(var->negatedvar->negatedvar == var);
11021  assert(SCIPvarIsBinary(var->negatedvar));
11022 
11024  {
11025  SCIP_CALL( SCIPvarAddImplic(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11026  cliquetable, branchcand, eventqueue, !varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
11027  }
11028  /* in case one both variables are not of binary type we have to add the implication as variable bounds */
11029  else
11030  {
11031  /* if the implied variable is of binary type exchange the variables */
11032  if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
11033  {
11034  SCIP_CALL( SCIPvarAddImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
11035  branchcand, eventqueue, (impltype == SCIP_BOUNDTYPE_UPPER) ? TRUE : FALSE, var->negatedvar,
11036  varfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER, varfixing ? 1.0 : 0.0, transitive,
11037  infeasible, nbdchgs) );
11038  }
11039  else
11040  {
11041  /* both variables are not of binary type but are implicit binary; in that case we can only add this
11042  * implication as variable bounds
11043  */
11044 
11045  /* add variable lower bound on the negation of var */
11046  if( varfixing )
11047  {
11048  /* (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
11049  * as variable lower bound
11050  */
11051  SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11052  cliquetable, branchcand, eventqueue, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : -1.0,
11053  (impltype == SCIP_BOUNDTYPE_UPPER) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
11054  }
11055  else
11056  {
11057  /* (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
11058  * as variable upper bound
11059  */
11060  SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11061  cliquetable, branchcand, eventqueue, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? -1.0 : 1.0,
11062  (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : 0.0, transitive, infeasible, nbdchgs) );
11063  }
11064 
11065  /* add variable bound on implvar */
11066  if( impltype == SCIP_BOUNDTYPE_UPPER )
11067  {
11068  /* (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
11069  * as variable upper bound
11070  */
11071  SCIP_CALL( SCIPvarAddVub(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
11072  branchcand, eventqueue, var->negatedvar, (varfixing) ? 1.0 : -1.0,
11073  (varfixing) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
11074  }
11075  else
11076  {
11077  /* (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
11078  * as variable upper bound
11079  */
11080  SCIP_CALL( SCIPvarAddVlb(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
11081  branchcand, eventqueue, var->negatedvar, (varfixing) ? -1.0 : 1.0, (varfixing) ? 1.0 : 0.0,
11082  transitive, infeasible, nbdchgs) );
11083  }
11084  }
11085  }
11086  break;
11087 
11088  default:
11089  SCIPerrorMessage("unknown variable status\n");
11090  return SCIP_INVALIDDATA;
11091  }
11092 
11093  return SCIP_OKAY;
11094 }
11095 
11096 /** returns whether there is an implication x == varfixing -> y <= b or y >= b in the implication graph;
11097  * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
11098  * both variables must be active, variable x must be binary
11099  */
11101  SCIP_VAR* var, /**< problem variable x */
11102  SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
11103  SCIP_VAR* implvar, /**< variable y to search for */
11104  SCIP_BOUNDTYPE impltype /**< type of implication y <=/>= b to search for */
11105  )
11106 {
11107  assert(var != NULL);
11108  assert(implvar != NULL);
11109  assert(SCIPvarIsActive(var));
11110  assert(SCIPvarIsActive(implvar));
11111  assert(SCIPvarIsBinary(var));
11112 
11113  return var->implics != NULL && SCIPimplicsContainsImpl(var->implics, varfixing, implvar, impltype);
11114 }
11115 
11116 /** returns whether there is an implication x == varfixing -> y == implvarfixing in the implication graph;
11117  * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
11118  * both variables must be active binary variables
11119  */
11121  SCIP_VAR* var, /**< problem variable x */
11122  SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
11123  SCIP_VAR* implvar, /**< variable y to search for */
11124  SCIP_Bool implvarfixing /**< value of the implied variable to search for */
11125  )
11126 {
11127  assert(SCIPvarIsBinary(implvar));
11128 
11129  return SCIPvarHasImplic(var, varfixing, implvar, implvarfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER);
11130 }
11131 
11132 /** gets the values of b in implications x == varfixing -> y <= b or y >= b in the implication graph;
11133  * the values are set to SCIP_INVALID if there is no implied bound
11134  */
11136  SCIP_VAR* var, /**< problem variable x */
11137  SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
11138  SCIP_VAR* implvar, /**< variable y to search for */
11139  SCIP_Real* lb, /**< buffer to store the value of the implied lower bound */
11140  SCIP_Real* ub /**< buffer to store the value of the implied upper bound */
11141  )
11142 {
11143  int lowerpos;
11144  int upperpos;
11145  SCIP_Real* bounds;
11146 
11147  assert(lb != NULL);
11148  assert(ub != NULL);
11149 
11150  *lb = SCIP_INVALID;
11151  *ub = SCIP_INVALID;
11152 
11153  if( var->implics == NULL )
11154  return;
11155 
11156  SCIPimplicsGetVarImplicPoss(var->implics, varfixing, implvar, &lowerpos, &upperpos);
11157  bounds = SCIPvarGetImplBounds(var, varfixing);
11158 
11159  if( bounds == NULL )
11160  return;
11161 
11162  if( lowerpos >= 0 )
11163  *lb = bounds[lowerpos];
11164 
11165  if( upperpos >= 0 )
11166  *ub = bounds[upperpos];
11167 }
11168 
11169 
11170 /** fixes the bounds of a binary variable to the given value, counting bound changes and detecting infeasibility */
11172  SCIP_VAR* var, /**< problem variable */
11173  BMS_BLKMEM* blkmem, /**< block memory */
11174  SCIP_SET* set, /**< global SCIP settings */
11175  SCIP_STAT* stat, /**< problem statistics */
11176  SCIP_PROB* transprob, /**< transformed problem */
11177  SCIP_PROB* origprob, /**< original problem */
11178  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
11179  SCIP_REOPT* reopt, /**< reoptimization data structure */
11180  SCIP_LP* lp, /**< current LP data */
11181  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
11182  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
11183  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11184  SCIP_Bool value, /**< value to fix variable to */
11185  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
11186  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
11187  )
11188 {
11189  assert(var != NULL);
11190  assert(set != NULL);
11191  assert(var->scip == set->scip);
11192  assert(infeasible != NULL);
11193 
11194  *infeasible = FALSE;
11195 
11196  if( value == FALSE )
11197  {
11198  if( var->glbdom.lb > 0.5 )
11199  *infeasible = TRUE;
11200  else if( var->glbdom.ub > 0.5 )
11201  {
11202  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
11203  * with the local bound, in this case we need to store the bound change as pending bound change
11204  */
11205  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
11206  {
11207  assert(tree != NULL);
11208  assert(transprob != NULL);
11209  assert(SCIPprobIsTransformed(transprob));
11210 
11211  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
11212  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
11213  }
11214  else
11215  {
11216  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
11217  }
11218 
11219  if( nbdchgs != NULL )
11220  (*nbdchgs)++;
11221  }
11222  }
11223  else
11224  {
11225  if( var->glbdom.ub < 0.5 )
11226  *infeasible = TRUE;
11227  else if( var->glbdom.lb < 0.5 )
11228  {
11229  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
11230  * with the local bound, in this case we need to store the bound change as pending bound change
11231  */
11232  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
11233  {
11234  assert(tree != NULL);
11235  assert(transprob != NULL);
11236  assert(SCIPprobIsTransformed(transprob));
11237 
11238  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
11239  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
11240  }
11241  else
11242  {
11243  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
11244  }
11245 
11246  if( nbdchgs != NULL )
11247  (*nbdchgs)++;
11248  }
11249  }
11250 
11251  return SCIP_OKAY;
11252 }
11253 
11254 /** adds the variable to the given clique and updates the list of cliques the binary variable is member of;
11255  * if the variable now appears twice in the clique with the same value, it is fixed to the opposite value;
11256  * if the variable now appears twice in the clique with opposite values, all other variables are fixed to
11257  * the opposite of the value they take in the clique
11258  */
11260  SCIP_VAR* var, /**< problem variable */
11261  BMS_BLKMEM* blkmem, /**< block memory */
11262  SCIP_SET* set, /**< global SCIP settings */
11263  SCIP_STAT* stat, /**< problem statistics */
11264  SCIP_PROB* transprob, /**< transformed problem */
11265  SCIP_PROB* origprob, /**< original problem */
11266  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
11267  SCIP_REOPT* reopt, /**< reoptimization data structure */
11268  SCIP_LP* lp, /**< current LP data */
11269  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
11270  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
11271  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11272  SCIP_Bool value, /**< value of the variable in the clique */
11273  SCIP_CLIQUE* clique, /**< clique the variable should be added to */
11274  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
11275  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
11276  )
11277 {
11278  assert(var != NULL);
11279  assert(set != NULL);
11280  assert(var->scip == set->scip);
11281  assert(SCIPvarIsBinary(var));
11282  assert(infeasible != NULL);
11283 
11284  *infeasible = FALSE;
11285 
11286  /* get corresponding active problem variable */
11287  SCIP_CALL( SCIPvarGetProbvarBinary(&var, &value) );
11292  assert(SCIPvarIsBinary(var));
11293 
11294  /* only column and loose variables may be member of a clique */
11296  {
11297  SCIP_Bool doubleentry;
11298  SCIP_Bool oppositeentry;
11299 
11300  /* add variable to clique */
11301  SCIP_CALL( SCIPcliqueAddVar(clique, blkmem, set, var, value, &doubleentry, &oppositeentry) );
11302 
11303  /* add clique to variable's clique list */
11304  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
11305 
11306  /* check consistency of cliquelist */
11307  SCIPcliquelistCheck(var->cliquelist, var);
11308 
11309  /* if the variable now appears twice with the same value in the clique, it can be fixed to the opposite value */
11310  if( doubleentry )
11311  {
11312  SCIP_CALL( SCIPvarFixBinary(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
11313  eventqueue, cliquetable, !value, infeasible, nbdchgs) );
11314  }
11315 
11316  /* if the variable appears with both values in the clique, all other variables of the clique can be fixed
11317  * to the opposite of the value they take in the clique
11318  */
11319  if( oppositeentry )
11320  {
11321  SCIP_VAR** vars;
11322  SCIP_Bool* values;
11323  int nvars;
11324  int i;
11325 
11326  nvars = SCIPcliqueGetNVars(clique);
11327  vars = SCIPcliqueGetVars(clique);
11328  values = SCIPcliqueGetValues(clique);
11329  for( i = 0; i < nvars && !(*infeasible); ++i )
11330  {
11331  if( vars[i] == var )
11332  continue;
11333 
11334  SCIP_CALL( SCIPvarFixBinary(vars[i], blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
11335  eventqueue, cliquetable, !values[i], infeasible, nbdchgs) );
11336  }
11337  }
11338  }
11339 
11340  return SCIP_OKAY;
11341 }
11342 
11343 /** adds a filled clique to the cliquelists of all corresponding variables */
11345  SCIP_VAR** vars, /**< problem variables */
11346  SCIP_Bool* values, /**< values of the variables in the clique */
11347  int nvars, /**< number of problem variables */
11348  BMS_BLKMEM* blkmem, /**< block memory */
11349  SCIP_SET* set, /**< global SCIP settings */
11350  SCIP_CLIQUE* clique /**< clique that contains all given variables and values */
11351  )
11352 {
11353  SCIP_VAR* var;
11354  int v;
11355 
11356  assert(vars != NULL);
11357  assert(values != NULL);
11358  assert(nvars > 0);
11359  assert(set != NULL);
11360  assert(blkmem != NULL);
11361  assert(clique != NULL);
11362 
11363  for( v = nvars - 1; v >= 0; --v )
11364  {
11365  var = vars[v];
11366  assert(SCIPvarIsBinary(var));
11368 
11369  /* add clique to variable's clique list */
11370  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, values[v], clique) );
11371 
11372  /* check consistency of cliquelist */
11373  SCIPcliquelistCheck(var->cliquelist, var);
11374  }
11375 
11376  return SCIP_OKAY;
11377 }
11378 
11379 /** adds a clique to the list of cliques of the given binary variable, but does not change the clique
11380  * itself
11381  */
11383  SCIP_VAR* var, /**< problem variable */
11384  BMS_BLKMEM* blkmem, /**< block memory */
11385  SCIP_SET* set, /**< global SCIP settings */
11386  SCIP_Bool value, /**< value of the variable in the clique */
11387  SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
11388  )
11389 {
11390  assert(var != NULL);
11391  assert(SCIPvarIsBinary(var));
11393 
11394  /* add clique to variable's clique list */
11395  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
11396 
11397  return SCIP_OKAY;
11398 }
11399 
11400 
11401 /** deletes a clique from the list of cliques the binary variable is member of, but does not change the clique
11402  * itself
11403  */
11405  SCIP_VAR* var, /**< problem variable */
11406  BMS_BLKMEM* blkmem, /**< block memory */
11407  SCIP_Bool value, /**< value of the variable in the clique */
11408  SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
11409  )
11410 {
11411  assert(var != NULL);
11412  assert(SCIPvarIsBinary(var));
11413 
11414  /* delete clique from variable's clique list */
11415  SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
11416 
11417  return SCIP_OKAY;
11418 }
11419 
11420 /** deletes the variable from the given clique and updates the list of cliques the binary variable is member of */
11422  SCIP_VAR* var, /**< problem variable */
11423  BMS_BLKMEM* blkmem, /**< block memory */
11424  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11425  SCIP_Bool value, /**< value of the variable in the clique */
11426  SCIP_CLIQUE* clique /**< clique the variable should be removed from */
11427  )
11428 {
11429  assert(var != NULL);
11430  assert(SCIPvarIsBinary(var));
11431 
11432  /* get corresponding active problem variable */
11433  SCIP_CALL( SCIPvarGetProbvarBinary(&var, &value) );
11438  assert(SCIPvarIsBinary(var));
11439 
11440  /* only column and loose variables may be member of a clique */
11442  {
11443  /* delete clique from variable's clique list */
11444  SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
11445 
11446  /* delete variable from clique */
11447  SCIPcliqueDelVar(clique, cliquetable, var, value);
11448 
11449  /* check consistency of cliquelist */
11450  SCIPcliquelistCheck(var->cliquelist, var);
11451  }
11452 
11453  return SCIP_OKAY;
11454 }
11455 
11456 /** returns whether there is a clique that contains both given variable/value pairs;
11457  * the variables must be active binary variables;
11458  * if regardimplics is FALSE, only the cliques in the clique table are looked at;
11459  * if regardimplics is TRUE, both the cliques and the implications of the implication graph are regarded
11460  *
11461  * @note a variable with it's negated variable are NOT! in a clique
11462  * @note a variable with itself are in a clique
11463  */
11465  SCIP_VAR* var1, /**< first variable */
11466  SCIP_Bool value1, /**< value of first variable */
11467  SCIP_VAR* var2, /**< second variable */
11468  SCIP_Bool value2, /**< value of second variable */
11469  SCIP_Bool regardimplics /**< should the implication graph also be searched for a clique? */
11470  )
11471 {
11472  assert(var1 != NULL);
11473  assert(var2 != NULL);
11474  assert(SCIPvarIsActive(var1));
11475  assert(SCIPvarIsActive(var2));
11476  assert(SCIPvarIsBinary(var1));
11477  assert(SCIPvarIsBinary(var2));
11478 
11479  return (SCIPcliquelistsHaveCommonClique(var1->cliquelist, value1, var2->cliquelist, value2)
11480  || (regardimplics && SCIPvarHasImplic(var1, value1, var2, value2 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER)));
11481 }
11482 
11483 /** actually changes the branch factor of the variable and of all parent variables */
11484 static
11486  SCIP_VAR* var, /**< problem variable */
11487  SCIP_SET* set, /**< global SCIP settings */
11488  SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
11489  )
11490 {
11491  SCIP_VAR* parentvar;
11492  SCIP_Real eps;
11493  int i;
11494 
11495  assert(var != NULL);
11496  assert(set != NULL);
11497  assert(var->scip == set->scip);
11498 
11499  /* only use positive values */
11500  eps = SCIPsetEpsilon(set);
11501  branchfactor = MAX(branchfactor, eps);
11502 
11503  SCIPsetDebugMsg(set, "process changing branch factor of <%s> from %f to %f\n", var->name, var->branchfactor, branchfactor);
11504 
11505  if( SCIPsetIsEQ(set, branchfactor, var->branchfactor) )
11506  return SCIP_OKAY;
11507 
11508  /* change the branch factor */
11509  var->branchfactor = branchfactor;
11510 
11511  /* process parent variables */
11512  for( i = 0; i < var->nparentvars; ++i )
11513  {
11514  parentvar = var->parentvars[i];
11515  assert(parentvar != NULL);
11516 
11517  switch( SCIPvarGetStatus(parentvar) )
11518  {
11520  /* do not change priorities across the border between transformed and original problem */
11521  break;
11522 
11523  case SCIP_VARSTATUS_COLUMN:
11524  case SCIP_VARSTATUS_LOOSE:
11525  case SCIP_VARSTATUS_FIXED:
11527  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11528  SCIPABORT();
11529  return SCIP_INVALIDDATA; /*lint !e527*/
11530 
11533  SCIP_CALL( varProcessChgBranchFactor(parentvar, set, branchfactor) );
11534  break;
11535 
11536  default:
11537  SCIPerrorMessage("unknown variable status\n");
11538  SCIPABORT();
11539  return SCIP_ERROR; /*lint !e527*/
11540  }
11541  }
11542 
11543  return SCIP_OKAY;
11544 }
11545 
11546 /** sets the branch factor of the variable; this value can be used in the branching methods to scale the score
11547  * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
11548  */
11550  SCIP_VAR* var, /**< problem variable */
11551  SCIP_SET* set, /**< global SCIP settings */
11552  SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
11553  )
11554 {
11555  int v;
11556 
11557  assert(var != NULL);
11558  assert(set != NULL);
11559  assert(var->scip == set->scip);
11560  assert(branchfactor >= 0.0);
11561 
11562  SCIPdebugMessage("changing branch factor of <%s> from %g to %g\n", var->name, var->branchfactor, branchfactor);
11563 
11564  if( SCIPsetIsEQ(set, var->branchfactor, branchfactor) )
11565  return SCIP_OKAY;
11566 
11567  /* change priorities of attached variables */
11568  switch( SCIPvarGetStatus(var) )
11569  {
11571  if( var->data.original.transvar != NULL )
11572  {
11573  SCIP_CALL( SCIPvarChgBranchFactor(var->data.original.transvar, set, branchfactor) );
11574  }
11575  else
11576  {
11577  assert(set->stage == SCIP_STAGE_PROBLEM);
11578  var->branchfactor = branchfactor;
11579  }
11580  break;
11581 
11582  case SCIP_VARSTATUS_COLUMN:
11583  case SCIP_VARSTATUS_LOOSE:
11584  case SCIP_VARSTATUS_FIXED:
11585  SCIP_CALL( varProcessChgBranchFactor(var, set, branchfactor) );
11586  break;
11587 
11589  assert(!var->donotaggr);
11590  assert(var->data.aggregate.var != NULL);
11591  SCIP_CALL( SCIPvarChgBranchFactor(var->data.aggregate.var, set, branchfactor) );
11592  break;
11593 
11595  assert(!var->donotmultaggr);
11596  for( v = 0; v < var->data.multaggr.nvars; ++v )
11597  {
11598  SCIP_CALL( SCIPvarChgBranchFactor(var->data.multaggr.vars[v], set, branchfactor) );
11599  }
11600  break;
11601 
11603  assert(var->negatedvar != NULL);
11605  assert(var->negatedvar->negatedvar == var);
11606  SCIP_CALL( SCIPvarChgBranchFactor(var->negatedvar, set, branchfactor) );
11607  break;
11608 
11609  default:
11610  SCIPerrorMessage("unknown variable status\n");
11611  SCIPABORT();
11612  return SCIP_ERROR; /*lint !e527*/
11613  }
11614 
11615  return SCIP_OKAY;
11616 }
11617 
11618 /** actually changes the branch priority of the variable and of all parent variables */
11619 static
11621  SCIP_VAR* var, /**< problem variable */
11622  int branchpriority /**< branching priority of the variable */
11623  )
11624 {
11625  SCIP_VAR* parentvar;
11626  int i;
11627 
11628  assert(var != NULL);
11629 
11630  SCIPdebugMessage("process changing branch priority of <%s> from %d to %d\n",
11631  var->name, var->branchpriority, branchpriority);
11632 
11633  if( branchpriority == var->branchpriority )
11634  return SCIP_OKAY;
11635 
11636  /* change the branch priority */
11637  var->branchpriority = branchpriority;
11638 
11639  /* process parent variables */
11640  for( i = 0; i < var->nparentvars; ++i )
11641  {
11642  parentvar = var->parentvars[i];
11643  assert(parentvar != NULL);
11644 
11645  switch( SCIPvarGetStatus(parentvar) )
11646  {
11648  /* do not change priorities across the border between transformed and original problem */
11649  break;
11650 
11651  case SCIP_VARSTATUS_COLUMN:
11652  case SCIP_VARSTATUS_LOOSE:
11653  case SCIP_VARSTATUS_FIXED:
11655  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11656  SCIPABORT();
11657  return SCIP_INVALIDDATA; /*lint !e527*/
11658 
11661  SCIP_CALL( varProcessChgBranchPriority(parentvar, branchpriority) );
11662  break;
11663 
11664  default:
11665  SCIPerrorMessage("unknown variable status\n");
11666  return SCIP_ERROR;
11667  }
11668  }
11669 
11670  return SCIP_OKAY;
11671 }
11672 
11673 /** sets the branch priority of the variable; variables with higher branch priority are always preferred to variables
11674  * with lower priority in selection of branching variable
11675  */
11677  SCIP_VAR* var, /**< problem variable */
11678  int branchpriority /**< branching priority of the variable */
11679  )
11680 {
11681  int v;
11682 
11683  assert(var != NULL);
11684 
11685  SCIPdebugMessage("changing branch priority of <%s> from %d to %d\n", var->name, var->branchpriority, branchpriority);
11686 
11687  if( var->branchpriority == branchpriority )
11688  return SCIP_OKAY;
11689 
11690  /* change priorities of attached variables */
11691  switch( SCIPvarGetStatus(var) )
11692  {
11694  if( var->data.original.transvar != NULL )
11695  {
11696  SCIP_CALL( SCIPvarChgBranchPriority(var->data.original.transvar, branchpriority) );
11697  }
11698  else
11699  var->branchpriority = branchpriority;
11700  break;
11701 
11702  case SCIP_VARSTATUS_COLUMN:
11703  case SCIP_VARSTATUS_LOOSE:
11704  case SCIP_VARSTATUS_FIXED:
11705  SCIP_CALL( varProcessChgBranchPriority(var, branchpriority) );
11706  break;
11707 
11709  assert(!var->donotaggr);
11710  assert(var->data.aggregate.var != NULL);
11711  SCIP_CALL( SCIPvarChgBranchPriority(var->data.aggregate.var, branchpriority) );
11712  break;
11713 
11715  assert(!var->donotmultaggr);
11716  for( v = 0; v < var->data.multaggr.nvars; ++v )
11717  {
11718  SCIP_CALL( SCIPvarChgBranchPriority(var->data.multaggr.vars[v], branchpriority) );
11719  }
11720  break;
11721 
11723  assert(var->negatedvar != NULL);
11725  assert(var->negatedvar->negatedvar == var);
11726  SCIP_CALL( SCIPvarChgBranchPriority(var->negatedvar, branchpriority) );
11727  break;
11728 
11729  default:
11730  SCIPerrorMessage("unknown variable status\n");
11731  SCIPABORT();
11732  return SCIP_ERROR; /*lint !e527*/
11733  }
11734 
11735  return SCIP_OKAY;
11736 }
11737 
11738 /** actually changes the branch direction of the variable and of all parent variables */
11739 static
11741  SCIP_VAR* var, /**< problem variable */
11742  SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
11743  )
11744 {
11745  SCIP_VAR* parentvar;
11746  int i;
11747 
11748  assert(var != NULL);
11749 
11750  SCIPdebugMessage("process changing branch direction of <%s> from %u to %d\n",
11751  var->name, var->branchdirection, branchdirection);
11752 
11753  if( branchdirection == (SCIP_BRANCHDIR)var->branchdirection )
11754  return SCIP_OKAY;
11755 
11756  /* change the branch direction */
11757  var->branchdirection = branchdirection; /*lint !e641*/
11758 
11759  /* process parent variables */
11760  for( i = 0; i < var->nparentvars; ++i )
11761  {
11762  parentvar = var->parentvars[i];
11763  assert(parentvar != NULL);
11764 
11765  switch( SCIPvarGetStatus(parentvar) )
11766  {
11768  /* do not change directions across the border between transformed and original problem */
11769  break;
11770 
11771  case SCIP_VARSTATUS_COLUMN:
11772  case SCIP_VARSTATUS_LOOSE:
11773  case SCIP_VARSTATUS_FIXED:
11775  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11776  SCIPABORT();
11777  return SCIP_INVALIDDATA; /*lint !e527*/
11778 
11780  if( parentvar->data.aggregate.scalar > 0.0 )
11781  {
11782  SCIP_CALL( varProcessChgBranchDirection(parentvar, branchdirection) );
11783  }
11784  else
11785  {
11786  SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
11787  }
11788  break;
11789 
11791  SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
11792  break;
11793 
11794  default:
11795  SCIPerrorMessage("unknown variable status\n");
11796  SCIPABORT();
11797  return SCIP_ERROR; /*lint !e527*/
11798  }
11799  }
11800 
11801  return SCIP_OKAY;
11802 }
11803 
11804 /** sets the branch direction of the variable; variables with higher branch direction are always preferred to variables
11805  * with lower direction in selection of branching variable
11806  */
11808  SCIP_VAR* var, /**< problem variable */
11809  SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
11810  )
11811 {
11812  int v;
11813 
11814  assert(var != NULL);
11815 
11816  SCIPdebugMessage("changing branch direction of <%s> from %u to %d\n", var->name, var->branchdirection, branchdirection);
11817 
11818  if( (SCIP_BRANCHDIR)var->branchdirection == branchdirection )
11819  return SCIP_OKAY;
11820 
11821  /* change directions of attached variables */
11822  switch( SCIPvarGetStatus(var) )
11823  {
11825  if( var->data.original.transvar != NULL )
11826  {
11827  SCIP_CALL( SCIPvarChgBranchDirection(var->data.original.transvar, branchdirection) );
11828  }
11829  else
11830  var->branchdirection = branchdirection; /*lint !e641*/
11831  break;
11832 
11833  case SCIP_VARSTATUS_COLUMN:
11834  case SCIP_VARSTATUS_LOOSE:
11835  case SCIP_VARSTATUS_FIXED:
11836  SCIP_CALL( varProcessChgBranchDirection(var, branchdirection) );
11837  break;
11838 
11840  assert(!var->donotaggr);
11841  assert(var->data.aggregate.var != NULL);
11842  if( var->data.aggregate.scalar > 0.0 )
11843  {
11844  SCIP_CALL( SCIPvarChgBranchDirection(var->data.aggregate.var, branchdirection) );
11845  }
11846  else
11847  {
11849  }
11850  break;
11851 
11853  assert(!var->donotmultaggr);
11854  for( v = 0; v < var->data.multaggr.nvars; ++v )
11855  {
11856  /* only update branching direction of aggregation variables, if they don't have a preferred direction yet */
11857  assert(var->data.multaggr.vars[v] != NULL);
11859  {
11860  if( var->data.multaggr.scalars[v] > 0.0 )
11861  {
11862  SCIP_CALL( SCIPvarChgBranchDirection(var->data.multaggr.vars[v], branchdirection) );
11863  }
11864  else
11865  {
11867  }
11868  }
11869  }
11870  break;
11871 
11873  assert(var->negatedvar != NULL);
11875  assert(var->negatedvar->negatedvar == var);
11877  break;
11878 
11879  default:
11880  SCIPerrorMessage("unknown variable status\n");
11881  SCIPABORT();
11882  return SCIP_ERROR; /*lint !e527*/
11883  }
11884 
11885  return SCIP_OKAY;
11886 }
11887 
11888 /** compares the index of two variables, only active, fixed or negated variables are allowed, if a variable
11889  * is negated then the index of the corresponding active variable is taken, returns -1 if first is
11890  * smaller than, and +1 if first is greater than second variable index; returns 0 if both indices
11891  * are equal, which means both variables are equal
11892  */
11894  SCIP_VAR* var1, /**< first problem variable */
11895  SCIP_VAR* var2 /**< second problem variable */
11896  )
11897 {
11898  assert(var1 != NULL);
11899  assert(var2 != NULL);
11902 
11904  var1 = SCIPvarGetNegatedVar(var1);
11906  var2 = SCIPvarGetNegatedVar(var2);
11907 
11908  assert(var1 != NULL);
11909  assert(var2 != NULL);
11910 
11911  if( SCIPvarGetIndex(var1) < SCIPvarGetIndex(var2) )
11912  return -1;
11913  else if( SCIPvarGetIndex(var1) > SCIPvarGetIndex(var2) )
11914  return +1;
11915 
11916  assert(var1 == var2);
11917  return 0;
11918 }
11919 
11920 /** comparison method for sorting active and negated variables by non-decreasing index, active and negated
11921  * variables are handled as the same variables
11922  */
11923 SCIP_DECL_SORTPTRCOMP(SCIPvarCompActiveAndNegated)
11925  return SCIPvarCompareActiveAndNegated((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
11926 }
11927 
11928 /** compares the index of two variables, returns -1 if first is smaller than, and +1 if first is greater than second
11929  * variable index; returns 0 if both indices are equal, which means both variables are equal
11930  */
11931 int SCIPvarCompare(
11932  SCIP_VAR* var1, /**< first problem variable */
11933  SCIP_VAR* var2 /**< second problem variable */
11934  )
11935 {
11936  assert(var1 != NULL);
11937  assert(var2 != NULL);
11938 
11939  if( var1->index < var2->index )
11940  return -1;
11941  else if( var1->index > var2->index )
11942  return +1;
11943  else
11944  {
11945  assert(var1 == var2);
11946  return 0;
11947  }
11948 }
11949 
11950 /** comparison method for sorting variables by non-decreasing index */
11951 SCIP_DECL_SORTPTRCOMP(SCIPvarComp)
11953  return SCIPvarCompare((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
11954 }
11955 
11956 /** comparison method for sorting variables by non-decreasing objective coefficient */
11957 SCIP_DECL_SORTPTRCOMP(SCIPvarCompObj)
11959  SCIP_Real obj1;
11960  SCIP_Real obj2;
11961 
11962  obj1 = SCIPvarGetObj((SCIP_VAR*)elem1);
11963  obj2 = SCIPvarGetObj((SCIP_VAR*)elem2);
11964 
11965  if( obj1 < obj2 )
11966  return -1;
11967  else if( obj1 > obj2 )
11968  return +1;
11969  else
11970  return 0;
11971 }
11972 
11973 /** hash key retrieval function for variables */
11974 SCIP_DECL_HASHGETKEY(SCIPvarGetHashkey)
11975 { /*lint --e{715}*/
11976  return elem;
11977 }
11978 
11979 /** returns TRUE iff the indices of both variables are equal */
11980 SCIP_DECL_HASHKEYEQ(SCIPvarIsHashkeyEq)
11981 { /*lint --e{715}*/
11982  if( key1 == key2 )
11983  return TRUE;
11984  return FALSE;
11985 }
11986 
11987 /** returns the hash value of the key */
11988 SCIP_DECL_HASHKEYVAL(SCIPvarGetHashkeyVal)
11989 { /*lint --e{715}*/
11990  assert( SCIPvarGetIndex((SCIP_VAR*) key) >= 0 );
11991  return (unsigned int) SCIPvarGetIndex((SCIP_VAR*) key);
11992 }
11993 
11994 /** return for given variables all their active counterparts; all active variables will be pairwise different */
11996  SCIP_SET* set, /**< global SCIP settings */
11997  SCIP_VAR** vars, /**< variable array with given variables and as output all active
11998  * variables, if enough slots exist
11999  */
12000  int* nvars, /**< number of given variables, and as output number of active variables,
12001  * if enough slots exist
12002  */
12003  int varssize, /**< available slots in vars array */
12004  int* requiredsize /**< pointer to store the required array size for the active variables */
12005  )
12006 {
12007  SCIP_VAR** activevars;
12008  int nactivevars;
12009  int activevarssize;
12010 
12011  SCIP_VAR* var;
12012  int v;
12013 
12014  SCIP_VAR** tmpvars;
12015  SCIP_VAR** multvars;
12016  int tmpvarssize;
12017  int ntmpvars;
12018  int noldtmpvars;
12019  int nmultvars;
12020 
12021  assert(set != NULL);
12022  assert(nvars != NULL);
12023  assert(vars != NULL || *nvars == 0);
12024  assert(varssize >= *nvars);
12025  assert(requiredsize != NULL);
12026 
12027  *requiredsize = 0;
12028 
12029  if( *nvars == 0 )
12030  return SCIP_OKAY;
12031 
12032  nactivevars = 0;
12033  activevarssize = *nvars;
12034  ntmpvars = *nvars;
12035  tmpvarssize = *nvars;
12036 
12037  /* temporary memory */
12038  SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
12039  /* coverity[copy_paste_error] */
12040  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
12041 
12042  noldtmpvars = ntmpvars;
12043 
12044  /* sort all variables to combine equal variables easily */
12045  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
12046  for( v = ntmpvars - 1; v > 0; --v )
12047  {
12048  /* combine same variables */
12049  if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
12050  {
12051  --ntmpvars;
12052  tmpvars[v] = tmpvars[ntmpvars];
12053  }
12054  }
12055  /* sort all variables again to combine equal variables later on */
12056  if( noldtmpvars > ntmpvars )
12057  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
12058 
12059  /* collect for each variable the representation in active variables */
12060  while( ntmpvars >= 1 )
12061  {
12062  --ntmpvars;
12063  var = tmpvars[ntmpvars];
12064  assert( var != NULL );
12065 
12066  switch( SCIPvarGetStatus(var) )
12067  {
12069  if( var->data.original.transvar == NULL )
12070  {
12071  SCIPerrorMessage("original variable has no transformed variable attached\n");
12072  SCIPABORT();
12073  return SCIP_INVALIDDATA; /*lint !e527*/
12074  }
12075  tmpvars[ntmpvars] = var->data.original.transvar;
12076  ++ntmpvars;
12077  break;
12078 
12080  tmpvars[ntmpvars] = var->data.aggregate.var;
12081  ++ntmpvars;
12082  break;
12083 
12085  tmpvars[ntmpvars] = var->negatedvar;
12086  ++ntmpvars;
12087  break;
12088 
12089  case SCIP_VARSTATUS_LOOSE:
12090  case SCIP_VARSTATUS_COLUMN:
12091  /* check for space in temporary memory */
12092  if( nactivevars >= activevarssize )
12093  {
12094  activevarssize *= 2;
12095  SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
12096  assert(nactivevars < activevarssize);
12097  }
12098  activevars[nactivevars] = var;
12099  nactivevars++;
12100  break;
12101 
12103  /* x = a_1*y_1 + ... + a_n*y_n + c */
12104  nmultvars = var->data.multaggr.nvars;
12105  multvars = var->data.multaggr.vars;
12106 
12107  /* check for space in temporary memory */
12108  if( nmultvars + ntmpvars > tmpvarssize )
12109  {
12110  while( nmultvars + ntmpvars > tmpvarssize )
12111  tmpvarssize *= 2;
12112  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
12113  assert(nmultvars + ntmpvars <= tmpvarssize);
12114  }
12115 
12116  /* copy all multi-aggregation variables into our working array */
12117  BMScopyMemoryArray(&tmpvars[ntmpvars], multvars, nmultvars); /*lint !e866*/
12118 
12119  /* get active, fixed or multi-aggregated corresponding variables for all new ones */
12120  SCIPvarsGetProbvar(&tmpvars[ntmpvars], nmultvars);
12121 
12122  ntmpvars += nmultvars;
12123  noldtmpvars = ntmpvars;
12124 
12125  /* sort all variables to combine equal variables easily */
12126  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
12127  for( v = ntmpvars - 1; v > 0; --v )
12128  {
12129  /* combine same variables */
12130  if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
12131  {
12132  --ntmpvars;
12133  tmpvars[v] = tmpvars[ntmpvars];
12134  }
12135  }
12136  /* sort all variables again to combine equal variables later on */
12137  if( noldtmpvars > ntmpvars )
12138  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
12139 
12140  break;
12141 
12142  case SCIP_VARSTATUS_FIXED:
12143  /* no need for memorizing fixed variables */
12144  break;
12145 
12146  default:
12147  SCIPerrorMessage("unknown variable status\n");
12148  SCIPABORT();
12149  return SCIP_INVALIDDATA; /*lint !e527*/
12150  }
12151  }
12152 
12153  /* sort variable array by variable index */
12154  SCIPsortPtr((void**)activevars, SCIPvarComp, nactivevars);
12155 
12156  /* eliminate duplicates and count required size */
12157  v = nactivevars - 1;
12158  while( v > 0 )
12159  {
12160  /* combine both variable since they are the same */
12161  if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
12162  {
12163  --nactivevars;
12164  activevars[v] = activevars[nactivevars];
12165  }
12166  --v;
12167  }
12168  *requiredsize = nactivevars;
12169 
12170  if( varssize >= *requiredsize )
12171  {
12172  assert(vars != NULL);
12173 
12174  *nvars = *requiredsize;
12175  BMScopyMemoryArray(vars, activevars, nactivevars);
12176  }
12177 
12178  SCIPsetFreeBufferArray(set, &tmpvars);
12179  SCIPsetFreeBufferArray(set, &activevars);
12180 
12181  return SCIP_OKAY;
12182 }
12183 
12184 /** gets corresponding active, fixed, or multi-aggregated problem variables of given variables,
12185  * @note the content of the given array will/might change
12186  */
12187 void SCIPvarsGetProbvar(
12188  SCIP_VAR** vars, /**< array of problem variables */
12189  int nvars /**< number of variables */
12190  )
12191 {
12192  int v;
12193 
12194  assert(vars != NULL || nvars == 0);
12195 
12196  for( v = nvars - 1; v >= 0; --v )
12197  {
12198  assert(vars != NULL);
12199  assert(vars[v] != NULL);
12200 
12201  vars[v] = SCIPvarGetProbvar(vars[v]);
12202  assert(vars[v] != NULL);
12203  }
12204 }
12205 
12206 /** gets corresponding active, fixed, or multi-aggregated problem variable of a variable */
12208  SCIP_VAR* var /**< problem variable */
12209  )
12210 {
12211  SCIP_VAR* retvar;
12212 
12213  assert(var != NULL);
12214 
12215  retvar = var;
12216 
12217  SCIPdebugMessage("get problem variable of <%s>\n", var->name);
12218 
12219  while( TRUE ) /*lint !e716 */
12220  {
12221  assert(retvar != NULL);
12222 
12223  switch( SCIPvarGetStatus(retvar) )
12224  {
12226  if( retvar->data.original.transvar == NULL )
12227  {
12228  SCIPerrorMessage("original variable has no transformed variable attached\n");
12229  SCIPABORT();
12230  return NULL; /*lint !e527 */
12231  }
12232  retvar = retvar->data.original.transvar;
12233  break;
12234 
12235  case SCIP_VARSTATUS_LOOSE:
12236  case SCIP_VARSTATUS_COLUMN:
12237  case SCIP_VARSTATUS_FIXED:
12238  return retvar;
12239 
12241  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12242  if ( retvar->data.multaggr.nvars == 1 )
12243  retvar = retvar->data.multaggr.vars[0];
12244  else
12245  return retvar;
12246  break;
12247 
12249  retvar = retvar->data.aggregate.var;
12250  break;
12251 
12253  retvar = retvar->negatedvar;
12254  break;
12255 
12256  default:
12257  SCIPerrorMessage("unknown variable status\n");
12258  SCIPABORT();
12259  return NULL; /*lint !e527*/
12260  }
12261  }
12262 }
12263 
12264 /** gets corresponding active, fixed, or multi-aggregated problem variables of binary variables and updates the given
12265  * negation status of each variable
12266  */
12268  SCIP_VAR*** vars, /**< pointer to binary problem variables */
12269  SCIP_Bool** negatedarr, /**< pointer to corresponding array to update the negation status */
12270  int nvars /**< number of variables and values in vars and negated array */
12271  )
12272 {
12273  SCIP_VAR** var;
12274  SCIP_Bool* negated;
12275  int v;
12276 
12277  assert(vars != NULL);
12278  assert(*vars != NULL || nvars == 0);
12279  assert(negatedarr != NULL);
12280  assert(*negatedarr != NULL || nvars == 0);
12281 
12282  for( v = nvars - 1; v >= 0; --v )
12283  {
12284  var = &((*vars)[v]);
12285  negated = &((*negatedarr)[v]);
12286 
12287  /* get problem variable */
12288  SCIP_CALL( SCIPvarGetProbvarBinary(var, negated) );
12289  }
12290 
12291  return SCIP_OKAY;
12292 }
12293 
12294 
12295 /** gets corresponding active, fixed, or multi-aggregated problem variable of a binary variable and updates the given
12296  * negation status (this means you have to assign a value to SCIP_Bool negated before calling this method, usually
12297  * FALSE is used)
12298  */
12300  SCIP_VAR** var, /**< pointer to binary problem variable */
12301  SCIP_Bool* negated /**< pointer to update the negation status */
12302  )
12303 {
12305 #ifndef NDEBUG
12306  SCIP_Real constant = 0.0;
12307  SCIP_Bool orignegated;
12308 #endif
12309 
12310  assert(var != NULL);
12311  assert(*var != NULL);
12312  assert(negated != NULL);
12313  assert(SCIPvarIsBinary(*var));
12314 
12315 #ifndef NDEBUG
12316  orignegated = *negated;
12317 #endif
12318 
12319  while( !active && *var != NULL )
12320  {
12321  switch( SCIPvarGetStatus(*var) )
12322  {
12324  if( (*var)->data.original.transvar == NULL )
12325  return SCIP_OKAY;
12326  *var = (*var)->data.original.transvar;
12327  break;
12328 
12329  case SCIP_VARSTATUS_LOOSE:
12330  case SCIP_VARSTATUS_COLUMN:
12331  case SCIP_VARSTATUS_FIXED:
12332  active = TRUE;
12333  break;
12334 
12336  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12337  if ( (*var)->data.multaggr.nvars == 1 )
12338  {
12339  assert( (*var)->data.multaggr.vars != NULL );
12340  assert( (*var)->data.multaggr.scalars != NULL );
12341  assert( SCIPvarIsBinary((*var)->data.multaggr.vars[0]) );
12342  assert(!EPSZ((*var)->data.multaggr.scalars[0], 1e-06));
12343 
12344  /* if not all variables were fully propagated, it might happen that a variable is multi-aggregated to
12345  * another variable which needs to be fixed
12346  *
12347  * e.g. x = y - 1 => (x = 0 && y = 1)
12348  * e.g. x = y + 1 => (x = 1 && y = 0)
12349  *
12350  * is this special case we need to return the muti-aggregation
12351  */
12352  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)) )
12353  {
12354  assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06));
12355  }
12356  else
12357  {
12358  /* @note due to fixations, a multi-aggregation can have a constant of zero and a negative scalar or even
12359  * a scalar in absolute value unequal to one, in this case this aggregation variable needs to be
12360  * fixed to zero, but this should be done by another enforcement; so not depending on the scalar,
12361  * we will return the aggregated variable;
12362  */
12363  if( !EPSEQ(REALABS((*var)->data.multaggr.scalars[0]), 1.0, 1e-06) )
12364  {
12365  active = TRUE;
12366  break;
12367  }
12368 
12369  /* @note it may also happen that the constant is larger than 1 or smaller than 0, in that case the
12370  * aggregation variable needs to be fixed to one, but this should be done by another enforcement;
12371  * so if this is the case, we will return the aggregated variable
12372  */
12373  assert(EPSZ((*var)->data.multaggr.constant, 1e-06) || EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06)
12374  || EPSZ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1e-06)
12375  || EPSEQ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1.0, 1e-06));
12376 
12377  if( !EPSZ((*var)->data.multaggr.constant, 1e-06) && !EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06) )
12378  {
12379  active = TRUE;
12380  break;
12381  }
12382 
12383  assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06) || EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
12384 
12385  if( EPSZ((*var)->data.multaggr.constant, 1e-06) )
12386  {
12387  /* if the scalar is negative, either the aggregation variable is already fixed to zero or has at
12388  * least one uplock (that hopefully will enforce this fixation to zero); can it happen that this
12389  * variable itself is multi-aggregated again?
12390  */
12391  assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06) ?
12392  ((SCIPvarGetUbGlobal((*var)->data.multaggr.vars[0]) < 0.5) ||
12393  SCIPvarGetNLocksUpType((*var)->data.multaggr.vars[0], SCIP_LOCKTYPE_MODEL) > 0) : TRUE);
12394  }
12395  else
12396  {
12397  assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
12398 #ifndef NDEBUG
12399  constant += (*negated) != orignegated ? -1.0 : 1.0;
12400 #endif
12401 
12402  *negated = !(*negated);
12403  }
12404  *var = (*var)->data.multaggr.vars[0];
12405  break;
12406  }
12407  }
12408  active = TRUE; /*lint !e838*/
12409  break;
12410 
12411  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
12412  assert((*var)->data.aggregate.var != NULL);
12413  assert(EPSEQ((*var)->data.aggregate.scalar, 1.0, 1e-06) || EPSEQ((*var)->data.aggregate.scalar, -1.0, 1e-06));
12414  assert(EPSLE((*var)->data.aggregate.var->glbdom.ub - (*var)->data.aggregate.var->glbdom.lb, 1.0, 1e-06));
12415 #ifndef NDEBUG
12416  constant += (*negated) != orignegated ? -(*var)->data.aggregate.constant : (*var)->data.aggregate.constant;
12417 #endif
12418 
12419  *negated = ((*var)->data.aggregate.scalar > 0.0) ? *negated : !(*negated);
12420  *var = (*var)->data.aggregate.var;
12421  break;
12422 
12423  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
12424  assert((*var)->negatedvar != NULL);
12425 #ifndef NDEBUG
12426  constant += (*negated) != orignegated ? -1.0 : 1.0;
12427 #endif
12428 
12429  *negated = !(*negated);
12430  *var = (*var)->negatedvar;
12431  break;
12432 
12433  default:
12434  SCIPerrorMessage("unknown variable status\n");
12435  return SCIP_INVALIDDATA;
12436  }
12437  }
12438  assert(active == (*var != NULL));
12439 
12440  if( active )
12441  {
12442  assert(SCIPvarIsBinary(*var));
12443  assert(EPSZ(constant, 1e-06) || EPSEQ(constant, 1.0, 1e-06));
12444  assert(EPSZ(constant, 1e-06) == ((*negated) == orignegated));
12445 
12446  return SCIP_OKAY;
12447  }
12448  else
12449  {
12450  SCIPerrorMessage("active variable path leads to NULL pointer\n");
12451  return SCIP_INVALIDDATA;
12452  }
12453 }
12454 
12455 /** transforms given variable, boundtype and bound to the corresponding active, fixed, or multi-aggregated variable
12456  * values
12457  */
12459  SCIP_VAR** var, /**< pointer to problem variable */
12460  SCIP_Real* bound, /**< pointer to bound value to transform */
12461  SCIP_BOUNDTYPE* boundtype /**< pointer to type of bound: lower or upper bound */
12462  )
12463 {
12464  assert(var != NULL);
12465  assert(*var != NULL);
12466  assert(bound != NULL);
12467  assert(boundtype != NULL);
12468 
12469  SCIPdebugMessage("get probvar bound %g of type %d of variable <%s>\n", *bound, *boundtype, (*var)->name);
12470 
12471  switch( SCIPvarGetStatus(*var) )
12472  {
12474  if( (*var)->data.original.transvar == NULL )
12475  {
12476  SCIPerrorMessage("original variable has no transformed variable attached\n");
12477  return SCIP_INVALIDDATA;
12478  }
12479  *var = (*var)->data.original.transvar;
12480  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12481  break;
12482 
12483  case SCIP_VARSTATUS_LOOSE:
12484  case SCIP_VARSTATUS_COLUMN:
12485  case SCIP_VARSTATUS_FIXED:
12486  break;
12487 
12489  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12490  if ( (*var)->data.multaggr.nvars == 1 )
12491  {
12492  assert( (*var)->data.multaggr.vars != NULL );
12493  assert( (*var)->data.multaggr.scalars != NULL );
12494  assert( (*var)->data.multaggr.scalars[0] != 0.0 );
12495 
12496  (*bound) /= (*var)->data.multaggr.scalars[0];
12497  (*bound) -= (*var)->data.multaggr.constant/(*var)->data.multaggr.scalars[0];
12498  if ( (*var)->data.multaggr.scalars[0] < 0.0 )
12499  {
12500  if ( *boundtype == SCIP_BOUNDTYPE_LOWER )
12501  *boundtype = SCIP_BOUNDTYPE_UPPER;
12502  else
12503  *boundtype = SCIP_BOUNDTYPE_LOWER;
12504  }
12505  *var = (*var)->data.multaggr.vars[0];
12506  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12507  }
12508  break;
12509 
12510  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
12511  assert((*var)->data.aggregate.var != NULL);
12512  assert((*var)->data.aggregate.scalar != 0.0);
12513 
12514  (*bound) /= (*var)->data.aggregate.scalar;
12515  (*bound) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12516  if( (*var)->data.aggregate.scalar < 0.0 )
12517  {
12518  if( *boundtype == SCIP_BOUNDTYPE_LOWER )
12519  *boundtype = SCIP_BOUNDTYPE_UPPER;
12520  else
12521  *boundtype = SCIP_BOUNDTYPE_LOWER;
12522  }
12523  *var = (*var)->data.aggregate.var;
12524  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12525  break;
12526 
12527  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12528  assert((*var)->negatedvar != NULL);
12529  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12530  assert((*var)->negatedvar->negatedvar == *var);
12531  (*bound) = (*var)->data.negate.constant - *bound;
12532  if( *boundtype == SCIP_BOUNDTYPE_LOWER )
12533  *boundtype = SCIP_BOUNDTYPE_UPPER;
12534  else
12535  *boundtype = SCIP_BOUNDTYPE_LOWER;
12536  *var = (*var)->negatedvar;
12537  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12538  break;
12539 
12540  default:
12541  SCIPerrorMessage("unknown variable status\n");
12542  return SCIP_INVALIDDATA;
12543  }
12544 
12545  return SCIP_OKAY;
12546 }
12547 
12548 /** transforms given variable and domain hole to the corresponding active, fixed, or multi-aggregated variable
12549  * values
12550  */
12552  SCIP_VAR** var, /**< pointer to problem variable */
12553  SCIP_Real* left, /**< pointer to left bound of open interval in hole to transform */
12554  SCIP_Real* right /**< pointer to right bound of open interval in hole to transform */
12555  )
12556 {
12557  assert(var != NULL);
12558  assert(*var != NULL);
12559  assert(left != NULL);
12560  assert(right != NULL);
12561 
12562  SCIPdebugMessage("get probvar hole (%g,%g) of variable <%s>\n", *left, *right, (*var)->name);
12563 
12564  switch( SCIPvarGetStatus(*var) )
12565  {
12567  if( (*var)->data.original.transvar == NULL )
12568  {
12569  SCIPerrorMessage("original variable has no transformed variable attached\n");
12570  return SCIP_INVALIDDATA;
12571  }
12572  *var = (*var)->data.original.transvar;
12573  SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
12574  break;
12575 
12576  case SCIP_VARSTATUS_LOOSE:
12577  case SCIP_VARSTATUS_COLUMN:
12578  case SCIP_VARSTATUS_FIXED:
12580  break;
12581 
12582  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
12583  assert((*var)->data.aggregate.var != NULL);
12584  assert((*var)->data.aggregate.scalar != 0.0);
12585 
12586  /* scale back */
12587  (*left) /= (*var)->data.aggregate.scalar;
12588  (*right) /= (*var)->data.aggregate.scalar;
12589 
12590  /* shift back */
12591  (*left) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12592  (*right) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12593 
12594  *var = (*var)->data.aggregate.var;
12595 
12596  /* check if the interval bounds have to swapped */
12597  if( (*var)->data.aggregate.scalar < 0.0 )
12598  {
12599  SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
12600  }
12601  else
12602  {
12603  SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
12604  }
12605  break;
12606 
12607  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12608  assert((*var)->negatedvar != NULL);
12609  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12610  assert((*var)->negatedvar->negatedvar == *var);
12611 
12612  /* shift and scale back */
12613  (*left) = (*var)->data.negate.constant - (*left);
12614  (*right) = (*var)->data.negate.constant - (*right);
12615 
12616  *var = (*var)->negatedvar;
12617 
12618  /* through the negated variable the left and right interval bound have to swapped */
12619  SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
12620  break;
12621 
12622  default:
12623  SCIPerrorMessage("unknown variable status\n");
12624  return SCIP_INVALIDDATA;
12625  }
12626 
12627  return SCIP_OKAY;
12628 }
12629 
12630 /** transforms given variable, scalar and constant to the corresponding active, fixed, or
12631  * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed variable,
12632  * "scalar" will be 0.0 and the value of the sum will be stored in "constant"; a multi-aggregation
12633  * with only one active variable (this can happen due to fixings after the multi-aggregation),
12634  * is treated like an aggregation; if the multi-aggregation constant is infinite, "scalar" will be 0.0
12635  */
12637  SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
12638  SCIP_SET* set, /**< global SCIP settings */
12639  SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
12640  SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
12641  )
12642 {
12643  assert(var != NULL);
12644  assert(scalar != NULL);
12645  assert(constant != NULL);
12646 
12647  while( *var != NULL )
12648  {
12649  switch( SCIPvarGetStatus(*var) )
12650  {
12652  if( (*var)->data.original.transvar == NULL )
12653  {
12654  SCIPerrorMessage("original variable has no transformed variable attached\n");
12655  return SCIP_INVALIDDATA;
12656  }
12657  *var = (*var)->data.original.transvar;
12658  break;
12659 
12660  case SCIP_VARSTATUS_LOOSE:
12661  case SCIP_VARSTATUS_COLUMN:
12662  return SCIP_OKAY;
12663 
12664  case SCIP_VARSTATUS_FIXED: /* x = c' => a*x + c == (a*c' + c) */
12665  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12666  {
12667  if( SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)) )
12668  {
12669  assert(*scalar != 0.0);
12670  if( (*scalar) * (*var)->glbdom.lb > 0.0 )
12671  (*constant) = SCIPsetInfinity(set);
12672  else
12673  (*constant) = -SCIPsetInfinity(set);
12674  }
12675  else
12676  (*constant) += *scalar * (*var)->glbdom.lb;
12677  }
12678 #ifndef NDEBUG
12679  else
12680  {
12681  assert(!SCIPsetIsInfinity(set, (*constant)) || !((*scalar) * (*var)->glbdom.lb < 0.0 &&
12682  (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
12683  assert(!SCIPsetIsInfinity(set, -(*constant)) || !((*scalar) * (*var)->glbdom.lb > 0.0 &&
12684  (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
12685  }
12686 #endif
12687  *scalar = 0.0;
12688  return SCIP_OKAY;
12689 
12691  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12692  if ( (*var)->data.multaggr.nvars == 1 )
12693  {
12694  assert((*var)->data.multaggr.vars != NULL);
12695  assert((*var)->data.multaggr.scalars != NULL);
12696  assert((*var)->data.multaggr.vars[0] != NULL);
12697  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12698  {
12699  /* the multi-aggregation constant can be infinite, if one of the multi-aggregation variables
12700  * was fixed to +/-infinity; ensure that the constant is set to +/-infinity, too, and the scalar
12701  * is set to 0.0, because the multi-aggregated variable can be seen as fixed, too
12702  */
12703  if( SCIPsetIsInfinity(set, (*var)->data.multaggr.constant)
12704  || SCIPsetIsInfinity(set, -((*var)->data.multaggr.constant)) )
12705  {
12706  if( (*scalar) * (*var)->data.multaggr.constant > 0 )
12707  {
12708  assert(!SCIPsetIsInfinity(set, -(*constant)));
12709  (*constant) = SCIPsetInfinity(set);
12710  }
12711  else
12712  {
12713  assert(!SCIPsetIsInfinity(set, *constant));
12714  (*constant) = -SCIPsetInfinity(set);
12715  }
12716  (*scalar) = 0.0;
12717  }
12718  else
12719  (*constant) += *scalar * (*var)->data.multaggr.constant;
12720  }
12721  (*scalar) *= (*var)->data.multaggr.scalars[0];
12722  *var = (*var)->data.multaggr.vars[0];
12723  break;
12724  }
12725  return SCIP_OKAY;
12726 
12727  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
12728  assert((*var)->data.aggregate.var != NULL);
12729  assert(!SCIPsetIsInfinity(set, (*var)->data.aggregate.constant)
12730  && !SCIPsetIsInfinity(set, (*var)->data.aggregate.constant));
12731  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12732  (*constant) += *scalar * (*var)->data.aggregate.constant;
12733  (*scalar) *= (*var)->data.aggregate.scalar;
12734  *var = (*var)->data.aggregate.var;
12735  break;
12736 
12737  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
12738  assert((*var)->negatedvar != NULL);
12739  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12740  assert((*var)->negatedvar->negatedvar == *var);
12741  assert(!SCIPsetIsInfinity(set, (*var)->data.negate.constant)
12742  && !SCIPsetIsInfinity(set, (*var)->data.negate.constant));
12743  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12744  (*constant) += *scalar * (*var)->data.negate.constant;
12745  (*scalar) *= -1.0;
12746  *var = (*var)->negatedvar;
12747  break;
12748 
12749  default:
12750  SCIPerrorMessage("unknown variable status\n");
12751  SCIPABORT();
12752  return SCIP_INVALIDDATA; /*lint !e527*/
12753  }
12754  }
12755  *scalar = 0.0;
12756 
12757  return SCIP_OKAY;
12758 }
12759 
12760 /** retransforms given variable, scalar and constant to the corresponding original variable, scalar
12761  * and constant, if possible; if the retransformation is impossible, NULL is returned as variable
12762  */
12764  SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
12765  SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
12766  SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
12767  )
12768 {
12769  SCIP_VAR* parentvar;
12770 
12771  assert(var != NULL);
12772  assert(*var != NULL);
12773  assert(scalar != NULL);
12774  assert(constant != NULL);
12775 
12776  while( !SCIPvarIsOriginal(*var) )
12777  {
12778  /* if the variable has no parent variables, it was generated during solving and has no corresponding original
12779  * var
12780  */
12781  if( (*var)->nparentvars == 0 )
12782  {
12783  /* negated variables do not need to have a parent variables, and negated variables can exist in original
12784  * space
12785  */
12787  ((*var)->negatedvar->nparentvars == 0 || (*var)->negatedvar->parentvars[0] != *var) )
12788  {
12789  *scalar *= -1.0;
12790  *constant -= (*var)->data.negate.constant * (*scalar);
12791  *var = (*var)->negatedvar;
12792 
12793  continue;
12794  }
12795  /* if the variables does not have any parent the variables was created during solving and has no original
12796  * counterpart
12797  */
12798  else
12799  {
12800  *var = NULL;
12801 
12802  return SCIP_OKAY;
12803  }
12804  }
12805 
12806  /* follow the link to the first parent variable */
12807  parentvar = (*var)->parentvars[0];
12808  assert(parentvar != NULL);
12809 
12810  switch( SCIPvarGetStatus(parentvar) )
12811  {
12813  break;
12814 
12815  case SCIP_VARSTATUS_COLUMN:
12816  case SCIP_VARSTATUS_LOOSE:
12817  case SCIP_VARSTATUS_FIXED:
12819  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
12820  return SCIP_INVALIDDATA;
12821 
12822  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + b -> y = (x-b)/a, s*y + c = (s/a)*x + c-b*s/a */
12823  assert(parentvar->data.aggregate.var == *var);
12824  assert(parentvar->data.aggregate.scalar != 0.0);
12825  *scalar /= parentvar->data.aggregate.scalar;
12826  *constant -= parentvar->data.aggregate.constant * (*scalar);
12827  break;
12828 
12829  case SCIP_VARSTATUS_NEGATED: /* x = b - y -> y = b - x, s*y + c = -s*x + c+b*s */
12830  assert(parentvar->negatedvar != NULL);
12831  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
12832  assert(parentvar->negatedvar->negatedvar == parentvar);
12833  *scalar *= -1.0;
12834  *constant -= parentvar->data.negate.constant * (*scalar);
12835  break;
12836 
12837  default:
12838  SCIPerrorMessage("unknown variable status\n");
12839  return SCIP_INVALIDDATA;
12840  }
12841 
12842  assert( parentvar != NULL );
12843  *var = parentvar;
12844  }
12845 
12846  return SCIP_OKAY;
12847 }
12848 
12849 /** returns whether the given variable is the direct counterpart of an original problem variable */
12851  SCIP_VAR* var /**< problem variable */
12852  )
12853 {
12854  SCIP_VAR* parentvar;
12855  assert(var != NULL);
12856 
12857  if( !SCIPvarIsTransformed(var) || var->nparentvars < 1 )
12858  return FALSE;
12859 
12860  assert(var->parentvars != NULL);
12861  parentvar = var->parentvars[0];
12862  assert(parentvar != NULL);
12863 
12864  /* we follow the aggregation tree to the root unless an original variable has been found - the first entries in the parentlist are candidates */
12865  while( parentvar->nparentvars >= 1 && SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL )
12866  parentvar = parentvar->parentvars[0];
12867  assert( parentvar != NULL );
12868 
12869  return ( SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_ORIGINAL );
12870 }
12871 
12872 /** gets objective value of variable in current SCIP_LP; the value can be different from the objective value stored in
12873  * the variable's own data due to diving, that operate only on the LP without updating the variables
12874  */
12876  SCIP_VAR* var /**< problem variable */
12877  )
12878 {
12879  assert(var != NULL);
12880 
12881  /* get bounds of attached variables */
12882  switch( SCIPvarGetStatus(var) )
12883  {
12885  assert(var->data.original.transvar != NULL);
12886  return SCIPvarGetObjLP(var->data.original.transvar);
12887 
12888  case SCIP_VARSTATUS_COLUMN:
12889  assert(var->data.col != NULL);
12890  return SCIPcolGetObj(var->data.col);
12891 
12892  case SCIP_VARSTATUS_LOOSE:
12893  case SCIP_VARSTATUS_FIXED:
12894  return var->obj;
12895 
12896  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12897  assert(var->data.aggregate.var != NULL);
12898  return var->data.aggregate.scalar * SCIPvarGetObjLP(var->data.aggregate.var);
12899 
12901  SCIPerrorMessage("cannot get the objective value of a multiple aggregated variable\n");
12902  SCIPABORT();
12903  return 0.0; /*lint !e527*/
12904 
12905  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12906  assert(var->negatedvar != NULL);
12908  assert(var->negatedvar->negatedvar == var);
12909  return -SCIPvarGetObjLP(var->negatedvar);
12910 
12911  default:
12912  SCIPerrorMessage("unknown variable status\n");
12913  SCIPABORT();
12914  return 0.0; /*lint !e527*/
12915  }
12916 }
12917 
12918 /** gets lower bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
12919  * data due to diving or conflict analysis, that operate only on the LP without updating the variables
12920  */
12922  SCIP_VAR* var, /**< problem variable */
12923  SCIP_SET* set /**< global SCIP settings */
12924  )
12925 {
12926  assert(var != NULL);
12927  assert(set != NULL);
12928  assert(var->scip == set->scip);
12929 
12930  /* get bounds of attached variables */
12931  switch( SCIPvarGetStatus(var) )
12932  {
12934  assert(var->data.original.transvar != NULL);
12935  return SCIPvarGetLbLP(var->data.original.transvar, set);
12936 
12937  case SCIP_VARSTATUS_COLUMN:
12938  assert(var->data.col != NULL);
12939  return SCIPcolGetLb(var->data.col);
12940 
12941  case SCIP_VARSTATUS_LOOSE:
12942  case SCIP_VARSTATUS_FIXED:
12943  return var->locdom.lb;
12944 
12945  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12946  assert(var->data.aggregate.var != NULL);
12947  if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set)))
12948  || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set))) )
12949  {
12950  return -SCIPsetInfinity(set);
12951  }
12952  else if( var->data.aggregate.scalar > 0.0 )
12953  {
12954  /* a > 0 -> get lower bound of y */
12955  return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12956  }
12957  else if( var->data.aggregate.scalar < 0.0 )
12958  {
12959  /* a < 0 -> get upper bound of y */
12960  return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12961  }
12962  else
12963  {
12964  SCIPerrorMessage("scalar is zero in aggregation\n");
12965  SCIPABORT();
12966  return SCIP_INVALID; /*lint !e527*/
12967  }
12968 
12970  /**@todo get the sides of the corresponding linear constraint */
12971  SCIPerrorMessage("getting the bounds of a multiple aggregated variable is not implemented yet\n");
12972  SCIPABORT();
12973  return SCIP_INVALID; /*lint !e527*/
12974 
12975  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12976  assert(var->negatedvar != NULL);
12978  assert(var->negatedvar->negatedvar == var);
12979  return var->data.negate.constant - SCIPvarGetUbLP(var->negatedvar, set);
12980 
12981  default:
12982  SCIPerrorMessage("unknown variable status\n");
12983  SCIPABORT();
12984  return SCIP_INVALID; /*lint !e527*/
12985  }
12986 }
12987 
12988 /** gets upper bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
12989  * data due to diving or conflict analysis, that operate only on the LP without updating the variables
12990  */
12992  SCIP_VAR* var, /**< problem variable */
12993  SCIP_SET* set /**< global SCIP settings */
12994  )
12995 {
12996  assert(var != NULL);
12997  assert(set != NULL);
12998  assert(var->scip == set->scip);
12999 
13000  /* get bounds of attached variables */
13001  switch( SCIPvarGetStatus(var) )
13002  {
13004  assert(var->data.original.transvar != NULL);
13005  return SCIPvarGetUbLP(var->data.original.transvar, set);
13006 
13007  case SCIP_VARSTATUS_COLUMN:
13008  assert(var->data.col != NULL);
13009  return SCIPcolGetUb(var->data.col);
13010 
13011  case SCIP_VARSTATUS_LOOSE:
13012  case SCIP_VARSTATUS_FIXED:
13013  return var->locdom.ub;
13014 
13015  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
13016  assert(var->data.aggregate.var != NULL);
13017  if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set)))
13018  || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set))) )
13019  {
13020  return SCIPsetInfinity(set);
13021  }
13022  if( var->data.aggregate.scalar > 0.0 )
13023  {
13024  /* a > 0 -> get upper bound of y */
13025  return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
13026  }
13027  else if( var->data.aggregate.scalar < 0.0 )
13028  {
13029  /* a < 0 -> get lower bound of y */
13030  return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
13031  }
13032  else
13033  {
13034  SCIPerrorMessage("scalar is zero in aggregation\n");
13035  SCIPABORT();
13036  return SCIP_INVALID; /*lint !e527*/
13037  }
13038 
13040  SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
13041  SCIPABORT();
13042  return SCIP_INVALID; /*lint !e527*/
13043 
13044  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13045  assert(var->negatedvar != NULL);
13047  assert(var->negatedvar->negatedvar == var);
13048  return var->data.negate.constant - SCIPvarGetLbLP(var->negatedvar, set);
13049 
13050  default:
13051  SCIPerrorMessage("unknown variable status\n");
13052  SCIPABORT();
13053  return SCIP_INVALID; /*lint !e527*/
13054  }
13055 }
13056 
13057 /** gets primal LP solution value of variable */
13059  SCIP_VAR* var /**< problem variable */
13060  )
13061 {
13062  assert(var != NULL);
13063 
13064  switch( SCIPvarGetStatus(var) )
13065  {
13067  if( var->data.original.transvar == NULL )
13068  return SCIP_INVALID;
13069  return SCIPvarGetLPSol(var->data.original.transvar);
13070 
13071  case SCIP_VARSTATUS_LOOSE:
13072  return SCIPvarGetBestBoundLocal(var);
13073 
13074  case SCIP_VARSTATUS_COLUMN:
13075  assert(var->data.col != NULL);
13076  return SCIPcolGetPrimsol(var->data.col);
13077 
13078  case SCIP_VARSTATUS_FIXED:
13079  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13080  return var->locdom.lb;
13081 
13083  {
13084  SCIP_Real lpsolval;
13085 
13086  assert(!var->donotaggr);
13087  assert(var->data.aggregate.var != NULL);
13088  lpsolval = SCIPvarGetLPSol(var->data.aggregate.var);
13089 
13090  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13091  * corresponding infinity value instead of performing an arithmetical transformation (compare method
13092  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13093  * (or is called by) a public interface method; instead, we only assert that values are finite
13094  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13095  * positives and negatives if the parameter <numerics/infinity> is modified by the user
13096  */
13097  assert(lpsolval > -SCIP_DEFAULT_INFINITY);
13098  assert(lpsolval < +SCIP_DEFAULT_INFINITY);
13099  return var->data.aggregate.scalar * lpsolval + var->data.aggregate.constant;
13100  }
13102  {
13103  SCIP_Real primsol;
13104  int i;
13105 
13106  assert(!var->donotmultaggr);
13107  assert(var->data.multaggr.vars != NULL);
13108  assert(var->data.multaggr.scalars != NULL);
13109  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13110  * assert(var->data.multaggr.nvars >= 2);
13111  */
13112  primsol = var->data.multaggr.constant;
13113  for( i = 0; i < var->data.multaggr.nvars; ++i )
13114  primsol += var->data.multaggr.scalars[i] * SCIPvarGetLPSol(var->data.multaggr.vars[i]);
13115  return primsol;
13116  }
13117  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13118  assert(var->negatedvar != NULL);
13120  assert(var->negatedvar->negatedvar == var);
13121  return var->data.negate.constant - SCIPvarGetLPSol(var->negatedvar);
13122 
13123  default:
13124  SCIPerrorMessage("unknown variable status\n");
13125  SCIPABORT();
13126  return SCIP_INVALID; /*lint !e527*/
13127  }
13128 }
13129 
13130 /** gets primal NLP solution value of variable */
13132  SCIP_VAR* var /**< problem variable */
13133  )
13134 {
13135  SCIP_Real solval;
13136  int i;
13137 
13138  assert(var != NULL);
13139 
13140  /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
13141  switch( SCIPvarGetStatus(var) )
13142  {
13144  return SCIPvarGetNLPSol(var->data.original.transvar);
13145 
13146  case SCIP_VARSTATUS_LOOSE:
13147  case SCIP_VARSTATUS_COLUMN:
13148  return var->nlpsol;
13149 
13150  case SCIP_VARSTATUS_FIXED:
13151  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
13152  assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
13153  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
13154  return SCIPvarGetLbGlobal(var);
13155 
13156  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13157  solval = SCIPvarGetNLPSol(var->data.aggregate.var);
13158  return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
13159 
13161  solval = var->data.multaggr.constant;
13162  for( i = 0; i < var->data.multaggr.nvars; ++i )
13163  solval += var->data.multaggr.scalars[i] * SCIPvarGetNLPSol(var->data.multaggr.vars[i]);
13164  return solval;
13165 
13167  solval = SCIPvarGetNLPSol(var->negatedvar);
13168  return var->data.negate.constant - solval;
13169 
13170  default:
13171  SCIPerrorMessage("unknown variable status\n");
13172  SCIPABORT();
13173  return SCIP_INVALID; /*lint !e527*/
13174  }
13175 }
13176 
13177 /** gets pseudo solution value of variable at current node */
13178 static
13180  SCIP_VAR* var /**< problem variable */
13181  )
13182 {
13183  SCIP_Real pseudosol;
13184  int i;
13185 
13186  assert(var != NULL);
13187 
13188  switch( SCIPvarGetStatus(var) )
13189  {
13191  if( var->data.original.transvar == NULL )
13192  return SCIP_INVALID;
13194 
13195  case SCIP_VARSTATUS_LOOSE:
13196  case SCIP_VARSTATUS_COLUMN:
13197  return SCIPvarGetBestBoundLocal(var);
13198 
13199  case SCIP_VARSTATUS_FIXED:
13200  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13201  return var->locdom.lb;
13202 
13204  {
13205  SCIP_Real pseudosolval;
13206  assert(!var->donotaggr);
13207  assert(var->data.aggregate.var != NULL);
13208  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13209  * corresponding infinity value instead of performing an arithmetical transformation (compare method
13210  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13211  * (or is called by) a public interface method; instead, we only assert that values are finite
13212  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13213  * positives and negatives if the parameter <numerics/infinity> is modified by the user
13214  */
13215  pseudosolval = SCIPvarGetPseudoSol(var->data.aggregate.var);
13216  assert(pseudosolval > -SCIP_DEFAULT_INFINITY);
13217  assert(pseudosolval < +SCIP_DEFAULT_INFINITY);
13218  return var->data.aggregate.scalar * pseudosolval + var->data.aggregate.constant;
13219  }
13221  assert(!var->donotmultaggr);
13222  assert(var->data.multaggr.vars != NULL);
13223  assert(var->data.multaggr.scalars != NULL);
13224  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13225  * assert(var->data.multaggr.nvars >= 2);
13226  */
13227  pseudosol = var->data.multaggr.constant;
13228  for( i = 0; i < var->data.multaggr.nvars; ++i )
13229  pseudosol += var->data.multaggr.scalars[i] * SCIPvarGetPseudoSol(var->data.multaggr.vars[i]);
13230  return pseudosol;
13231 
13232  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13233  assert(var->negatedvar != NULL);
13235  assert(var->negatedvar->negatedvar == var);
13236  return var->data.negate.constant - SCIPvarGetPseudoSol(var->negatedvar);
13237 
13238  default:
13239  SCIPerrorMessage("unknown variable status\n");
13240  SCIPABORT();
13241  return SCIP_INVALID; /*lint !e527*/
13242  }
13243 }
13244 
13245 /** gets current LP or pseudo solution value of variable */
13247  SCIP_VAR* var, /**< problem variable */
13248  SCIP_Bool getlpval /**< should the LP solution value be returned? */
13249  )
13250 {
13251  if( getlpval )
13252  return SCIPvarGetLPSol(var);
13253  else
13254  return SCIPvarGetPseudoSol(var);
13255 }
13256 
13257 /** remembers the current solution as root solution in the problem variables */
13258 void SCIPvarStoreRootSol(
13259  SCIP_VAR* var, /**< problem variable */
13260  SCIP_Bool roothaslp /**< is the root solution from LP? */
13261  )
13262 {
13263  assert(var != NULL);
13264 
13265  var->rootsol = SCIPvarGetSol(var, roothaslp);
13266 }
13267 
13268 /** updates the current solution as best root solution of the given variable if it is better */
13270  SCIP_VAR* var, /**< problem variable */
13271  SCIP_SET* set, /**< global SCIP settings */
13272  SCIP_Real rootsol, /**< root solution value */
13273  SCIP_Real rootredcost, /**< root reduced cost */
13274  SCIP_Real rootlpobjval /**< objective value of the root LP */
13275  )
13276 {
13277  assert(var != NULL);
13278  assert(set != NULL);
13279  assert(var->scip == set->scip);
13280 
13281  /* if reduced cost are zero nothing to update */
13282  if( SCIPsetIsDualfeasZero(set, rootredcost) )
13283  return;
13284 
13285  /* check if we have already a best combination stored */
13286  if( !SCIPsetIsDualfeasZero(set, var->bestrootredcost) )
13287  {
13288  SCIP_Real currcutoffbound;
13289  SCIP_Real cutoffbound;
13290  SCIP_Real bound;
13291 
13292  /* compute the cutoff bound which would improve the corresponding bound with the current stored root solution,
13293  * root reduced cost, and root LP objective value combination
13294  */
13295  if( var->bestrootredcost > 0.0 )
13296  bound = SCIPvarGetUbGlobal(var);
13297  else
13298  bound = SCIPvarGetLbGlobal(var);
13299 
13300  currcutoffbound = (bound - var->bestrootsol) * var->bestrootredcost + var->bestrootlpobjval;
13301 
13302  /* compute the cutoff bound which would improve the corresponding bound with new root solution, root reduced
13303  * cost, and root LP objective value combination
13304  */
13305  if( rootredcost > 0.0 )
13306  bound = SCIPvarGetUbGlobal(var);
13307  else
13308  bound = SCIPvarGetLbGlobal(var);
13309 
13310  cutoffbound = (bound - rootsol) * rootredcost + rootlpobjval;
13311 
13312  /* check if an improving root solution, root reduced cost, and root LP objective value is at hand */
13313  if( cutoffbound > currcutoffbound )
13314  {
13315  SCIPsetDebugMsg(set, "-> <%s> update potential cutoff bound <%g> -> <%g>\n",
13316  SCIPvarGetName(var), currcutoffbound, cutoffbound);
13317 
13318  var->bestrootsol = rootsol;
13319  var->bestrootredcost = rootredcost;
13320  var->bestrootlpobjval = rootlpobjval;
13321  }
13322  }
13323  else
13324  {
13325  SCIPsetDebugMsg(set, "-> <%s> initialize best root reduced cost information\n", SCIPvarGetName(var));
13326  SCIPsetDebugMsg(set, " -> rootsol <%g>\n", rootsol);
13327  SCIPsetDebugMsg(set, " -> rootredcost <%g>\n", rootredcost);
13328  SCIPsetDebugMsg(set, " -> rootlpobjval <%g>\n", rootlpobjval);
13329 
13330  var->bestrootsol = rootsol;
13331  var->bestrootredcost = rootredcost;
13332  var->bestrootlpobjval = rootlpobjval;
13333  }
13334 }
13335 
13336 /** returns the solution of the variable in the last root node's relaxation, if the root relaxation is not yet
13337  * completely solved, zero is returned
13338  */
13340  SCIP_VAR* var /**< problem variable */
13341  )
13342 {
13343  SCIP_Real rootsol;
13344  int i;
13345 
13346  assert(var != NULL);
13347 
13348  switch( SCIPvarGetStatus(var) )
13349  {
13351  if( var->data.original.transvar == NULL )
13352  return 0.0;
13353  return SCIPvarGetRootSol(var->data.original.transvar);
13354 
13355  case SCIP_VARSTATUS_LOOSE:
13356  case SCIP_VARSTATUS_COLUMN:
13357  return var->rootsol;
13358 
13359  case SCIP_VARSTATUS_FIXED:
13360  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13361  return var->locdom.lb;
13362 
13364  assert(!var->donotaggr);
13365  assert(var->data.aggregate.var != NULL);
13366  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13367  * corresponding infinity value instead of performing an arithmetical transformation (compare method
13368  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13369  * (or is called by) a public interface method; instead, we only assert that values are finite
13370  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13371  * positives and negatives if the parameter <numerics/infinity> is modified by the user
13372  */
13376 
13378  assert(!var->donotmultaggr);
13379  assert(var->data.multaggr.vars != NULL);
13380  assert(var->data.multaggr.scalars != NULL);
13381  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13382  * assert(var->data.multaggr.nvars >= 2);
13383  */
13384  rootsol = var->data.multaggr.constant;
13385  for( i = 0; i < var->data.multaggr.nvars; ++i )
13386  rootsol += var->data.multaggr.scalars[i] * SCIPvarGetRootSol(var->data.multaggr.vars[i]);
13387  return rootsol;
13388 
13389  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13390  assert(var->negatedvar != NULL);
13392  assert(var->negatedvar->negatedvar == var);
13393  return var->data.negate.constant - SCIPvarGetRootSol(var->negatedvar);
13394 
13395  default:
13396  SCIPerrorMessage("unknown variable status\n");
13397  SCIPABORT();
13398  return SCIP_INVALID; /*lint !e527*/
13399  }
13400 }
13401 
13402 /** returns for given variable the reduced cost */
13403 static
13405  SCIP_VAR* var, /**< problem variable */
13406  SCIP_SET* set, /**< global SCIP settings */
13407  SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
13408  SCIP_STAT* stat, /**< problem statistics */
13409  SCIP_LP* lp /**< current LP data */
13410  )
13411 {
13413  {
13414  SCIP_COL* col;
13415  SCIP_Real primsol;
13416  SCIP_BASESTAT basestat;
13417  SCIP_Bool lpissolbasic;
13418 
13419  col = SCIPvarGetCol(var);
13420  assert(col != NULL);
13421 
13422  basestat = SCIPcolGetBasisStatus(col);
13423  lpissolbasic = SCIPlpIsSolBasic(lp);
13424  primsol = SCIPcolGetPrimsol(col);
13425 
13426  if( (lpissolbasic && (basestat == SCIP_BASESTAT_LOWER || basestat == SCIP_BASESTAT_UPPER)) ||
13427  (!lpissolbasic && (SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol) || SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol))) )
13428  {
13429  SCIP_Real redcost = SCIPcolGetRedcost(col, stat, lp);
13430 
13431  assert(((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)) ||
13432  (lpissolbasic && basestat == SCIP_BASESTAT_LOWER)) ? (!SCIPsetIsDualfeasNegative(set, redcost) ||
13434  assert(((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)) ||
13435  (lpissolbasic && basestat == SCIP_BASESTAT_UPPER)) ? (!SCIPsetIsDualfeasPositive(set, redcost) ||
13436  SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var))) : TRUE);
13437 
13438  if( (varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_LOWER) ||
13439  (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)))) ||
13440  (!varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_UPPER) ||
13441  (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)))) )
13442  return redcost;
13443  else
13444  return 0.0;
13445  }
13446 
13447  return 0.0;
13448  }
13449 
13450  return 0.0;
13451 }
13452 
13453 #define MAX_CLIQUELENGTH 50
13454 /** returns for the given binary variable the reduced cost which are given by the variable itself and its implication if
13455  * the binary variable is fixed to the given value
13456  */
13458  SCIP_VAR* var, /**< problem variable */
13459  SCIP_SET* set, /**< global SCIP settings */
13460  SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
13461  SCIP_STAT* stat, /**< problem statistics */
13462  SCIP_PROB* prob, /**< transformed problem, or NULL */
13463  SCIP_LP* lp /**< current LP data */
13464  )
13465 {
13466  SCIP_Real implredcost;
13467  int ncliques;
13468  int nvars;
13469 
13470  assert(SCIPvarIsBinary(var));
13471  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
13472 
13473  /* get reduced cost of given variable */
13474  implredcost = getImplVarRedcost(var, set, varfixing, stat, lp);
13475 
13476 #ifdef SCIP_MORE_DEBUG
13477  SCIPsetDebugMsg(set, "variable <%s> itself has reduced cost of %g\n", SCIPvarGetName(var), implredcost);
13478 #endif
13479 
13480  /* the following algorithm is expensive */
13481  ncliques = SCIPvarGetNCliques(var, varfixing);
13482 
13483  if( ncliques > 0 )
13484  {
13485  SCIP_CLIQUE** cliques;
13486  SCIP_CLIQUE* clique;
13487  SCIP_VAR** clqvars;
13488  SCIP_VAR** probvars;
13489  SCIP_VAR* clqvar;
13490  SCIP_Bool* clqvalues;
13491  int* entries;
13492  int* ids;
13493  SCIP_Real redcost;
13494  SCIP_Bool cleanedup;
13495  int nclqvars;
13496  int nentries;
13497  int nids;
13498  int id;
13499  int c;
13500  int v;
13501 
13502  assert(prob != NULL);
13503  assert(SCIPprobIsTransformed(prob));
13504 
13505  nentries = SCIPprobGetNVars(prob) - SCIPprobGetNContVars(prob) + 1;
13506 
13507  SCIP_CALL_ABORT( SCIPsetAllocBufferArray(set, &ids, nentries) );
13508  nids = 0;
13509  SCIP_CALL_ABORT( SCIPsetAllocCleanBufferArray(set, &entries, nentries) );
13510 
13511  cliques = SCIPvarGetCliques(var, varfixing);
13512  assert(cliques != NULL);
13513 
13514  for( c = ncliques - 1; c >= 0; --c )
13515  {
13516  clique = cliques[c];
13517  assert(clique != NULL);
13518  nclqvars = SCIPcliqueGetNVars(clique);
13519  assert(nclqvars > 0);
13520 
13521  if( nclqvars > MAX_CLIQUELENGTH )
13522  continue;
13523 
13524  clqvars = SCIPcliqueGetVars(clique);
13525  clqvalues = SCIPcliqueGetValues(clique);
13526  assert(clqvars != NULL);
13527  assert(clqvalues != NULL);
13528 
13529  cleanedup = SCIPcliqueIsCleanedUp(clique);
13530 
13531  for( v = nclqvars - 1; v >= 0; --v )
13532  {
13533  clqvar = clqvars[v];
13534  assert(clqvar != NULL);
13535 
13536  /* ignore binary variable which are fixed */
13537  if( clqvar != var && (cleanedup || SCIPvarIsActive(clqvar)) &&
13538  (SCIPvarGetLbLocal(clqvar) < 0.5 && SCIPvarGetUbLocal(clqvar) > 0.5) )
13539  {
13540  int probindex = SCIPvarGetProbindex(clqvar) + 1;
13541  assert(0 < probindex && probindex < nentries);
13542 
13543 #if 0
13544  /* check that the variable was not yet visited or does not appear with two contradicting implications, ->
13545  * can appear since there is no guarantee that all these infeasible bounds were found
13546  */
13547  assert(!entries[probindex] || entries[probindex] == (clqvalues[v] ? probindex : -probindex));
13548 #endif
13549  if( entries[probindex] == 0 )
13550  {
13551  ids[nids] = probindex;
13552  ++nids;
13553 
13554  /* mark variable as visited */
13555  entries[probindex] = (clqvalues[v] ? probindex : -probindex);
13556  }
13557  }
13558  }
13559  }
13560 
13561  probvars = SCIPprobGetVars(prob);
13562  assert(probvars != NULL);
13563 
13564  /* add all implied reduced cost */
13565  for( v = nids - 1; v >= 0; --v )
13566  {
13567  id = ids[v];
13568  assert(0 < id && id < nentries);
13569  assert(entries[id] != 0);
13570  assert(probvars[id - 1] != NULL);
13571  assert(SCIPvarIsActive(probvars[id - 1]));
13572  assert(SCIPvarIsBinary(probvars[id - 1]));
13573  assert(SCIPvarGetLbLocal(probvars[id - 1]) < 0.5 && SCIPvarGetUbLocal(probvars[id - 1]) > 0.5);
13574 
13575  if( (entries[id] > 0) != varfixing )
13576  redcost = getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
13577  else
13578  redcost = -getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
13579 
13580  if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
13581  implredcost += redcost;
13582 
13583  /* reset entries clear buffer array */
13584  entries[id] = 0;
13585  }
13586 
13587  SCIPsetFreeCleanBufferArray(set, &entries);
13588  SCIPsetFreeBufferArray(set, &ids);
13589  }
13590 
13591 #ifdef SCIP_MORE_DEBUG
13592  SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) has implied reduced cost of %g\n", SCIPvarGetName(var), ncliques,
13593  implredcost);
13594 #endif
13595 
13596  /* collect non-binary implication information */
13597  nvars = SCIPimplicsGetNImpls(var->implics, varfixing);
13598 
13599  if( nvars > 0 )
13600  {
13601  SCIP_VAR** vars;
13602  SCIP_VAR* implvar;
13603  SCIP_COL* col;
13604  SCIP_Real* bounds;
13605  SCIP_BOUNDTYPE* boundtypes;
13606  SCIP_Real redcost;
13607  SCIP_Real lb;
13608  SCIP_Real ub;
13609  SCIP_Bool lpissolbasic;
13610  int v;
13611 
13612  vars = SCIPimplicsGetVars(var->implics, varfixing);
13613  boundtypes = SCIPimplicsGetTypes(var->implics, varfixing);
13614  bounds = SCIPimplicsGetBounds(var->implics, varfixing);
13615  lpissolbasic = SCIPlpIsSolBasic(lp);
13616 
13617  for( v = nvars - 1; v >= 0; --v )
13618  {
13619  implvar = vars[v];
13620  assert(implvar != NULL);
13621 
13622  lb = SCIPvarGetLbLocal(implvar);
13623  ub = SCIPvarGetUbLocal(implvar);
13624 
13625  /* ignore binary variable which are fixed or not of column status */
13626  if( SCIPvarGetStatus(implvar) != SCIP_VARSTATUS_COLUMN || SCIPsetIsFeasEQ(set, lb, ub) )
13627  continue;
13628 
13629  col = SCIPvarGetCol(implvar);
13630  assert(col != NULL);
13631  redcost = 0.0;
13632 
13633  /* solved lp with basis information or not? */
13634  if( lpissolbasic )
13635  {
13636  SCIP_BASESTAT basestat = SCIPcolGetBasisStatus(col);
13637 
13638  /* check if the implication is not not yet applied */
13639  if( basestat == SCIP_BASESTAT_LOWER && boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGT(set, bounds[v], lb) )
13640  {
13641  redcost = SCIPcolGetRedcost(col, stat, lp);
13642  assert(!SCIPsetIsDualfeasNegative(set, redcost));
13643 
13644  if( !varfixing )
13645  redcost *= (lb - bounds[v]);
13646  else
13647  redcost *= (bounds[v] - lb);
13648  }
13649  else if( basestat == SCIP_BASESTAT_UPPER && boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLT(set, bounds[v], ub) )
13650  {
13651  redcost = SCIPcolGetRedcost(col, stat, lp);
13652  assert(!SCIPsetIsDualfeasPositive(set, redcost));
13653 
13654  if( varfixing )
13655  redcost *= (bounds[v] - ub);
13656  else
13657  redcost *= (ub - bounds[v]);
13658  }
13659  }
13660  else
13661  {
13662  SCIP_Real primsol = SCIPcolGetPrimsol(col);
13663 
13664  /* check if the implication is not not yet applied */
13665  if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasEQ(set, lb, primsol) && SCIPsetIsFeasGT(set, bounds[v], lb) )
13666  {
13667  redcost = SCIPcolGetRedcost(col, stat, lp);
13668  assert(!SCIPsetIsDualfeasNegative(set, redcost));
13669 
13670  if( varfixing )
13671  redcost *= (lb - bounds[v]);
13672  else
13673  redcost *= (bounds[v] - lb);
13674  }
13675  else if( boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasEQ(set, ub, primsol) && SCIPsetIsFeasLT(set, bounds[v], ub) )
13676  {
13677  redcost = SCIPcolGetRedcost(col, stat, lp);
13678  assert(!SCIPsetIsDualfeasPositive(set, redcost));
13679 
13680  if( varfixing )
13681  redcost *= (bounds[v] - ub);
13682  else
13683  redcost *= (ub - bounds[v]);
13684  }
13685  }
13686 
13687  /* improve implied reduced cost */
13688  if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
13689  implredcost += redcost;
13690  }
13691  }
13692 
13693 #ifdef SCIP_MORE_DEBUG
13694  SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) and implications (%d) has implied reduced cost of %g\n",
13695  SCIPvarGetName(var), ncliques, nvars, implredcost);
13696 #endif
13697 
13698  return implredcost;
13699 }
13700 
13701 /** returns the best solution (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation, if
13702  * the root relaxation is not yet completely solved, zero is returned
13703  */
13705  SCIP_VAR* var /**< problem variable */
13706  )
13707 {
13708  SCIP_Real rootsol;
13709  int i;
13710 
13711  assert(var != NULL);
13712 
13713  switch( SCIPvarGetStatus(var) )
13714  {
13716  if( var->data.original.transvar == NULL )
13717  return 0.0;
13719 
13720  case SCIP_VARSTATUS_LOOSE:
13721  case SCIP_VARSTATUS_COLUMN:
13722  return var->bestrootsol;
13723 
13724  case SCIP_VARSTATUS_FIXED:
13725  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13726  return var->locdom.lb;
13727 
13729  assert(!var->donotaggr);
13730  assert(var->data.aggregate.var != NULL);
13731  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13732  * corresponding infinity value instead of performing an arithmetical transformation (compare method
13733  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13734  * (or is called by) a public interface method; instead, we only assert that values are finite
13735  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13736  * positives and negatives if the parameter <numerics/infinity> is modified by the user
13737  */
13741 
13743  assert(!var->donotmultaggr);
13744  assert(var->data.multaggr.vars != NULL);
13745  assert(var->data.multaggr.scalars != NULL);
13746  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13747  * assert(var->data.multaggr.nvars >= 2);
13748  */
13749  rootsol = var->data.multaggr.constant;
13750  for( i = 0; i < var->data.multaggr.nvars; ++i )
13751  rootsol += var->data.multaggr.scalars[i] * SCIPvarGetBestRootSol(var->data.multaggr.vars[i]);
13752  return rootsol;
13753 
13754  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13755  assert(var->negatedvar != NULL);
13757  assert(var->negatedvar->negatedvar == var);
13758  return var->data.negate.constant - SCIPvarGetBestRootSol(var->negatedvar);
13759 
13760  default:
13761  SCIPerrorMessage("unknown variable status\n");
13762  SCIPABORT();
13763  return 0.0; /*lint !e527*/
13764  }
13765 }
13766 
13767 /** returns the best reduced costs (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation,
13768  * if the root relaxation is not yet completely solved, or the variable was no column of the root LP, SCIP_INVALID is
13769  * returned
13770  */
13772  SCIP_VAR* var /**< problem variable */
13773  )
13774 {
13775  assert(var != NULL);
13776 
13777  switch( SCIPvarGetStatus(var) )
13778  {
13780  if( var->data.original.transvar == NULL )
13781  return SCIP_INVALID;
13783 
13784  case SCIP_VARSTATUS_LOOSE:
13785  case SCIP_VARSTATUS_COLUMN:
13786  return var->bestrootredcost;
13787 
13788  case SCIP_VARSTATUS_FIXED:
13792  return 0.0;
13793 
13794  default:
13795  SCIPerrorMessage("unknown variable status\n");
13796  SCIPABORT();
13797  return 0.0; /*lint !e527*/
13798  }
13799 }
13800 
13801 /** returns the best objective value (w.r.t. root reduced cost propagation) of the root LP which belongs the root
13802  * reduced cost which is accessible via SCIPvarGetRootRedcost() or the variable was no column of the root LP,
13803  * SCIP_INVALID is returned
13804  */
13806  SCIP_VAR* var /**< problem variable */
13807  )
13808 {
13809  assert(var != NULL);
13810 
13811  switch( SCIPvarGetStatus(var) )
13812  {
13814  if( var->data.original.transvar == NULL )
13815  return SCIP_INVALID;
13817 
13818  case SCIP_VARSTATUS_LOOSE:
13819  case SCIP_VARSTATUS_COLUMN:
13820  return var->bestrootlpobjval;
13821 
13822  case SCIP_VARSTATUS_FIXED:
13826  return SCIP_INVALID;
13827 
13828  default:
13829  SCIPerrorMessage("unknown variable status\n");
13830  SCIPABORT();
13831  return SCIP_INVALID; /*lint !e527*/
13832  }
13833 }
13834 
13835 /** set the given solution as the best root solution w.r.t. root reduced cost propagation in the variables */
13837  SCIP_VAR* var, /**< problem variable */
13838  SCIP_Real rootsol, /**< root solution value */
13839  SCIP_Real rootredcost, /**< root reduced cost */
13840  SCIP_Real rootlpobjval /**< objective value of the root LP */
13841  )
13842 {
13843  assert(var != NULL);
13844 
13845  var->bestrootsol = rootsol;
13846  var->bestrootredcost = rootredcost;
13847  var->bestrootlpobjval = rootlpobjval;
13848 }
13849 
13850 /** stores the solution value as relaxation solution in the problem variable */
13852  SCIP_VAR* var, /**< problem variable */
13853  SCIP_SET* set, /**< global SCIP settings */
13854  SCIP_RELAXATION* relaxation, /**< global relaxation data */
13855  SCIP_Real solval, /**< solution value in the current relaxation solution */
13856  SCIP_Bool updateobj /**< should the objective value be updated? */
13857  )
13858 {
13859  assert(var != NULL);
13860  assert(relaxation != NULL);
13861  assert(set != NULL);
13862  assert(var->scip == set->scip);
13863 
13864  /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
13865  switch( SCIPvarGetStatus(var) )
13866  {
13868  SCIP_CALL( SCIPvarSetRelaxSol(var->data.original.transvar, set, relaxation, solval, updateobj) );
13869  break;
13870 
13871  case SCIP_VARSTATUS_LOOSE:
13872  case SCIP_VARSTATUS_COLUMN:
13873  if( updateobj )
13874  SCIPrelaxationSolObjAdd(relaxation, var->obj * (solval - var->relaxsol));
13875  var->relaxsol = solval;
13876  break;
13877 
13878  case SCIP_VARSTATUS_FIXED:
13879  if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
13880  {
13881  SCIPerrorMessage("cannot set relaxation solution value for variable <%s> fixed to %.15g to different value %.15g\n",
13882  SCIPvarGetName(var), var->glbdom.lb, solval);
13883  return SCIP_INVALIDDATA;
13884  }
13885  break;
13886 
13887  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13888  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
13889  SCIP_CALL( SCIPvarSetRelaxSol(var->data.aggregate.var, set, relaxation,
13890  (solval - var->data.aggregate.constant)/var->data.aggregate.scalar, updateobj) );
13891  break;
13893  SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
13894  return SCIP_INVALIDDATA;
13895 
13897  SCIP_CALL( SCIPvarSetRelaxSol(var->negatedvar, set, relaxation, var->data.negate.constant - solval, updateobj) );
13898  break;
13899 
13900  default:
13901  SCIPerrorMessage("unknown variable status\n");
13902  return SCIP_INVALIDDATA;
13903  }
13904 
13905  return SCIP_OKAY;
13906 }
13907 
13908 /** returns the solution value of the problem variable in the relaxation solution
13909  *
13910  * @todo Inline this function - similar to SCIPvarGetLPSol_rec.
13911  */
13913  SCIP_VAR* var, /**< problem variable */
13914  SCIP_SET* set /**< global SCIP settings */
13915  )
13916 {
13917  SCIP_Real solvalsum;
13918  SCIP_Real solval;
13919  int i;
13920 
13921  assert(var != NULL);
13922  assert(set != NULL);
13923  assert(var->scip == set->scip);
13924 
13925  /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
13926  switch( SCIPvarGetStatus(var) )
13927  {
13929  return SCIPvarGetRelaxSol(var->data.original.transvar, set);
13930 
13931  case SCIP_VARSTATUS_LOOSE:
13932  case SCIP_VARSTATUS_COLUMN:
13933  return var->relaxsol;
13934 
13935  case SCIP_VARSTATUS_FIXED:
13936  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
13937  assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
13938  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
13939  return SCIPvarGetLbGlobal(var);
13940 
13941  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13942  solval = SCIPvarGetRelaxSol(var->data.aggregate.var, set);
13943  if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
13944  {
13945  if( var->data.aggregate.scalar * solval > 0.0 )
13946  return SCIPsetInfinity(set);
13947  if( var->data.aggregate.scalar * solval < 0.0 )
13948  return -SCIPsetInfinity(set);
13949  }
13950  return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
13951 
13953  solvalsum = var->data.multaggr.constant;
13954  for( i = 0; i < var->data.multaggr.nvars; ++i )
13955  {
13956  solval = SCIPvarGetRelaxSol(var->data.multaggr.vars[i], set);
13957  if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
13958  {
13959  if( var->data.multaggr.scalars[i] * solval > 0.0 )
13960  return SCIPsetInfinity(set);
13961  if( var->data.multaggr.scalars[i] * solval < 0.0 )
13962  return -SCIPsetInfinity(set);
13963  }
13964  solvalsum += var->data.multaggr.scalars[i] * solval;
13965  }
13966  return solvalsum;
13967 
13969  solval = SCIPvarGetRelaxSol(var->negatedvar, set);
13970  if( SCIPsetIsInfinity(set, solval) )
13971  return -SCIPsetInfinity(set);
13972  if( SCIPsetIsInfinity(set, -solval) )
13973  return SCIPsetInfinity(set);
13974  return var->data.negate.constant - solval;
13975 
13976  default:
13977  SCIPerrorMessage("unknown variable status\n");
13978  SCIPABORT();
13979  return SCIP_INVALID; /*lint !e527*/
13980  }
13981 }
13982 
13983 /** returns the solution value of the transformed problem variable in the relaxation solution */
13985  SCIP_VAR* var /**< problem variable */
13986  )
13987 {
13988  assert(var != NULL);
13990 
13991  return var->relaxsol;
13992 }
13993 
13994 /** stores the solution value as NLP solution in the problem variable */
13996  SCIP_VAR* var, /**< problem variable */
13997  SCIP_SET* set, /**< global SCIP settings */
13998  SCIP_Real solval /**< solution value in the current NLP solution */
13999  )
14000 {
14001  assert(var != NULL);
14002  assert(set != NULL);
14003  assert(var->scip == set->scip);
14004 
14005  /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
14006  switch( SCIPvarGetStatus(var) )
14007  {
14009  SCIP_CALL( SCIPvarSetNLPSol(var->data.original.transvar, set, solval) );
14010  break;
14011 
14012  case SCIP_VARSTATUS_LOOSE:
14013  case SCIP_VARSTATUS_COLUMN:
14014  var->nlpsol = solval;
14015  break;
14016 
14017  case SCIP_VARSTATUS_FIXED:
14018  if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
14019  {
14020  SCIPerrorMessage("cannot set NLP solution value for variable <%s> fixed to %.15g to different value %.15g\n",
14021  SCIPvarGetName(var), var->glbdom.lb, solval);
14022  SCIPABORT();
14023  return SCIP_INVALIDCALL; /*lint !e527*/
14024  }
14025  break;
14026 
14027  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
14028  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
14029  SCIP_CALL( SCIPvarSetNLPSol(var->data.aggregate.var, set, (solval - var->data.aggregate.constant)/var->data.aggregate.scalar) );
14030  break;
14031 
14033  SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
14034  SCIPABORT();
14035  return SCIP_INVALIDCALL; /*lint !e527*/
14036 
14038  SCIP_CALL( SCIPvarSetNLPSol(var->negatedvar, set, var->data.negate.constant - solval) );
14039  break;
14040 
14041  default:
14042  SCIPerrorMessage("unknown variable status\n");
14043  SCIPABORT();
14044  return SCIP_ERROR; /*lint !e527*/
14045  }
14046 
14047  return SCIP_OKAY;
14048 }
14049 
14050 /** returns a weighted average solution value of the variable in all feasible primal solutions found so far */
14052  SCIP_VAR* var /**< problem variable */
14053  )
14054 {
14055  SCIP_Real avgsol;
14056  int i;
14057 
14058  assert(var != NULL);
14059 
14060  switch( SCIPvarGetStatus(var) )
14061  {
14063  if( var->data.original.transvar == NULL )
14064  return 0.0;
14065  return SCIPvarGetAvgSol(var->data.original.transvar);
14066 
14067  case SCIP_VARSTATUS_LOOSE:
14068  case SCIP_VARSTATUS_COLUMN:
14069  avgsol = var->primsolavg;
14070  avgsol = MAX(avgsol, var->glbdom.lb);
14071  avgsol = MIN(avgsol, var->glbdom.ub);
14072  return avgsol;
14073 
14074  case SCIP_VARSTATUS_FIXED:
14075  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
14076  return var->locdom.lb;
14077 
14079  assert(!var->donotaggr);
14080  assert(var->data.aggregate.var != NULL);
14081  return var->data.aggregate.scalar * SCIPvarGetAvgSol(var->data.aggregate.var)
14082  + var->data.aggregate.constant;
14083 
14085  assert(!var->donotmultaggr);
14086  assert(var->data.multaggr.vars != NULL);
14087  assert(var->data.multaggr.scalars != NULL);
14088  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
14089  * assert(var->data.multaggr.nvars >= 2);
14090  */
14091  avgsol = var->data.multaggr.constant;
14092  for( i = 0; i < var->data.multaggr.nvars; ++i )
14093  avgsol += var->data.multaggr.scalars[i] * SCIPvarGetAvgSol(var->data.multaggr.vars[i]);
14094  return avgsol;
14095 
14096  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
14097  assert(var->negatedvar != NULL);
14099  assert(var->negatedvar->negatedvar == var);
14100  return var->data.negate.constant - SCIPvarGetAvgSol(var->negatedvar);
14101 
14102  default:
14103  SCIPerrorMessage("unknown variable status\n");
14104  SCIPABORT();
14105  return 0.0; /*lint !e527*/
14106  }
14107 }
14108 
14109 /** returns solution value and index of variable lower bound that is closest to the variable's value in the given primal solution
14110  * or current LP solution if no primal solution is given; returns an index of -1 if no variable lower bound is available
14111  */
14113  SCIP_VAR* var, /**< active problem variable */
14114  SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
14115  SCIP_SET* set, /**< global SCIP settings */
14116  SCIP_STAT* stat, /**< problem statistics */
14117  SCIP_Real* closestvlb, /**< pointer to store the value of the closest variable lower bound */
14118  int* closestvlbidx /**< pointer to store the index of the closest variable lower bound */
14119  )
14120 {
14121  int nvlbs;
14122 
14123  assert(var != NULL);
14124  assert(stat != NULL);
14125  assert(set != NULL);
14126  assert(var->scip == set->scip);
14127  assert(closestvlb != NULL);
14128  assert(closestvlbidx != NULL);
14129 
14130  *closestvlbidx = -1;
14131  *closestvlb = SCIP_REAL_MIN;
14132 
14133  nvlbs = SCIPvarGetNVlbs(var);
14134  if( nvlbs > 0 )
14135  {
14136  SCIP_VAR** vlbvars;
14137  SCIP_Real* vlbcoefs;
14138  SCIP_Real* vlbconsts;
14139  int i;
14140 
14141  vlbvars = SCIPvarGetVlbVars(var);
14142  vlbcoefs = SCIPvarGetVlbCoefs(var);
14143  vlbconsts = SCIPvarGetVlbConstants(var);
14144 
14145  /* check for cached values */
14146  if( var->closestvblpcount == stat->lpcount && var->closestvlbidx != -1 && sol == NULL)
14147  {
14148  i = var->closestvlbidx;
14149  assert(0 <= i && i < nvlbs);
14150  assert(SCIPvarIsActive(vlbvars[i]));
14151  *closestvlbidx = i;
14152  *closestvlb = vlbcoefs[i] * SCIPvarGetLPSol(vlbvars[i]) + vlbconsts[i];
14153  }
14154  else
14155  {
14156  /* search best VUB */
14157  for( i = 0; i < nvlbs; i++ )
14158  {
14159  if( SCIPvarIsActive(vlbvars[i]) )
14160  {
14161  SCIP_Real vlbsol;
14162 
14163  vlbsol = vlbcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vlbvars[i]) : SCIPsolGetVal(sol, set, stat, vlbvars[i])) + vlbconsts[i];
14164  if( vlbsol > *closestvlb )
14165  {
14166  *closestvlb = vlbsol;
14167  *closestvlbidx = i;
14168  }
14169  }
14170  }
14171 
14172  if( sol == NULL )
14173  {
14174  /* update cached value */
14175  if( var->closestvblpcount != stat->lpcount )
14176  var->closestvubidx = -1;
14177  var->closestvlbidx = *closestvlbidx;
14178  var->closestvblpcount = stat->lpcount;
14179  }
14180  }
14181  }
14182 }
14183 
14184 /** returns solution value and index of variable upper bound that is closest to the variable's value in the given primal solution;
14185  * or current LP solution if no primal solution is given; returns an index of -1 if no variable upper bound is available
14186  */
14188  SCIP_VAR* var, /**< active problem variable */
14189  SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
14190  SCIP_SET* set, /**< global SCIP settings */
14191  SCIP_STAT* stat, /**< problem statistics */
14192  SCIP_Real* closestvub, /**< pointer to store the value of the closest variable upper bound */
14193  int* closestvubidx /**< pointer to store the index of the closest variable upper bound */
14194  )
14195 {
14196  int nvubs;
14197 
14198  assert(var != NULL);
14199  assert(set != NULL);
14200  assert(var->scip == set->scip);
14201  assert(closestvub != NULL);
14202  assert(closestvubidx != NULL);
14203 
14204  *closestvubidx = -1;
14205  *closestvub = SCIP_REAL_MAX;
14206 
14207  nvubs = SCIPvarGetNVubs(var);
14208  if( nvubs > 0 )
14209  {
14210  SCIP_VAR** vubvars;
14211  SCIP_Real* vubcoefs;
14212  SCIP_Real* vubconsts;
14213  int i;
14214 
14215  vubvars = SCIPvarGetVubVars(var);
14216  vubcoefs = SCIPvarGetVubCoefs(var);
14217  vubconsts = SCIPvarGetVubConstants(var);
14218 
14219  /* check for cached values */
14220  if( var->closestvblpcount == stat->lpcount && var->closestvubidx != -1 && sol == NULL)
14221  {
14222  i = var->closestvubidx;
14223  assert(0 <= i && i < nvubs);
14224  assert(SCIPvarIsActive(vubvars[i]));
14225  *closestvubidx = i;
14226  *closestvub = vubcoefs[i] * SCIPvarGetLPSol(vubvars[i]) + vubconsts[i];
14227  }
14228  else
14229  {
14230  /* search best VUB */
14231  for( i = 0; i < nvubs; i++ )
14232  {
14233  if( SCIPvarIsActive(vubvars[i]) )
14234  {
14235  SCIP_Real vubsol;
14236 
14237  vubsol = vubcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vubvars[i]) : SCIPsolGetVal(sol, set, stat, vubvars[i])) + vubconsts[i];
14238  if( vubsol < *closestvub )
14239  {
14240  *closestvub = vubsol;
14241  *closestvubidx = i;
14242  }
14243  }
14244  }
14245 
14246  if( sol == NULL )
14247  {
14248  /* update cached value */
14249  if( var->closestvblpcount != stat->lpcount )
14250  var->closestvlbidx = -1;
14251  var->closestvubidx = *closestvubidx;
14252  var->closestvblpcount = stat->lpcount;
14253  }
14254  }
14255  }
14256 }
14257 
14258 /** resolves variable to columns and adds them with the coefficient to the row */
14260  SCIP_VAR* var, /**< problem variable */
14261  BMS_BLKMEM* blkmem, /**< block memory */
14262  SCIP_SET* set, /**< global SCIP settings */
14263  SCIP_STAT* stat, /**< problem statistics */
14264  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
14265  SCIP_PROB* prob, /**< problem data */
14266  SCIP_LP* lp, /**< current LP data */
14267  SCIP_ROW* row, /**< LP row */
14268  SCIP_Real val /**< value of coefficient */
14269  )
14270 {
14271  int i;
14272 
14273  assert(var != NULL);
14274  assert(set != NULL);
14275  assert(var->scip == set->scip);
14276  assert(row != NULL);
14277  assert(!SCIPsetIsInfinity(set, REALABS(val)));
14278 
14279  SCIPsetDebugMsg(set, "adding coefficient %g<%s> to row <%s>\n", val, var->name, row->name);
14280 
14281  if ( SCIPsetIsZero(set, val) )
14282  return SCIP_OKAY;
14283 
14284  switch( SCIPvarGetStatus(var) )
14285  {
14287  if( var->data.original.transvar == NULL )
14288  {
14289  SCIPerrorMessage("cannot add untransformed original variable <%s> to LP row <%s>\n", var->name, row->name);
14290  return SCIP_INVALIDDATA;
14291  }
14292  SCIP_CALL( SCIPvarAddToRow(var->data.original.transvar, blkmem, set, stat, eventqueue, prob, lp, row, val) );
14293  return SCIP_OKAY;
14294 
14295  case SCIP_VARSTATUS_LOOSE:
14296  /* add globally fixed variables as constant */
14297  if( SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub) )
14298  {
14299  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->glbdom.lb) );
14300  return SCIP_OKAY;
14301  }
14302  /* convert loose variable into column */
14303  SCIP_CALL( SCIPvarColumn(var, blkmem, set, stat, prob, lp) );
14304  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
14305  /*lint -fallthrough*/
14306 
14307  case SCIP_VARSTATUS_COLUMN:
14308  assert(var->data.col != NULL);
14309  assert(var->data.col->var == var);
14310  SCIP_CALL( SCIProwIncCoef(row, blkmem, set, eventqueue, lp, var->data.col, val) );
14311  return SCIP_OKAY;
14312 
14313  case SCIP_VARSTATUS_FIXED:
14314  assert(var->glbdom.lb == var->glbdom.ub); /*lint !e777*/
14315  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
14316  assert(var->locdom.lb == var->glbdom.lb); /*lint !e777*/
14317  assert(!SCIPsetIsInfinity(set, REALABS(var->locdom.lb)));
14318  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->locdom.lb) );
14319  return SCIP_OKAY;
14320 
14322  assert(!var->donotaggr);
14323  assert(var->data.aggregate.var != NULL);
14324  SCIP_CALL( SCIPvarAddToRow(var->data.aggregate.var, blkmem, set, stat, eventqueue, prob, lp,
14325  row, var->data.aggregate.scalar * val) );
14326  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.aggregate.constant * val) );
14327  return SCIP_OKAY;
14328 
14330  assert(!var->donotmultaggr);
14331  assert(var->data.multaggr.vars != NULL);
14332  assert(var->data.multaggr.scalars != NULL);
14333  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
14334  * assert(var->data.multaggr.nvars >= 2);
14335  */
14336  for( i = 0; i < var->data.multaggr.nvars; ++i )
14337  {
14338  SCIP_CALL( SCIPvarAddToRow(var->data.multaggr.vars[i], blkmem, set, stat, eventqueue, prob, lp,
14339  row, var->data.multaggr.scalars[i] * val) );
14340  }
14341  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.multaggr.constant * val) );
14342  return SCIP_OKAY;
14343 
14344  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
14345  assert(var->negatedvar != NULL);
14347  assert(var->negatedvar->negatedvar == var);
14348  SCIP_CALL( SCIPvarAddToRow(var->negatedvar, blkmem, set, stat, eventqueue, prob, lp, row, -val) );
14349  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.negate.constant * val) );
14350  return SCIP_OKAY;
14351 
14352  default:
14353  SCIPerrorMessage("unknown variable status\n");
14354  return SCIP_INVALIDDATA;
14355  }
14356 }
14357 
14358 /* optionally, define this compiler flag to write complete variable histories to a file */
14359 #ifdef SCIP_HISTORYTOFILE
14360 SCIP_Longint counter = 0l;
14361 const char* historypath="."; /* allows for user-defined path; use '.' for calling directory of SCIP */
14362 #include "scip/scip.h"
14363 #endif
14364 
14365 /** updates the pseudo costs of the given variable and the global pseudo costs after a change of
14366  * "solvaldelta" in the variable's solution value and resulting change of "objdelta" in the in the LP's objective value
14367  */
14369  SCIP_VAR* var, /**< problem variable */
14370  SCIP_SET* set, /**< global SCIP settings */
14371  SCIP_STAT* stat, /**< problem statistics */
14372  SCIP_Real solvaldelta, /**< difference of variable's new LP value - old LP value */
14373  SCIP_Real objdelta, /**< difference of new LP's objective value - old LP's objective value */
14374  SCIP_Real weight /**< weight in (0,1] of this update in pseudo cost sum */
14375  )
14376 {
14377  SCIP_Real oldrootpseudocosts;
14378  assert(var != NULL);
14379  assert(set != NULL);
14380  assert(var->scip == set->scip);
14381  assert(stat != NULL);
14382 
14383  /* check if history statistics should be collected for a variable */
14384  if( !stat->collectvarhistory )
14385  return SCIP_OKAY;
14386 
14387  switch( SCIPvarGetStatus(var) )
14388  {
14390  if( var->data.original.transvar == NULL )
14391  {
14392  SCIPerrorMessage("cannot update pseudo costs of original untransformed variable\n");
14393  return SCIP_INVALIDDATA;
14394  }
14395  SCIP_CALL( SCIPvarUpdatePseudocost(var->data.original.transvar, set, stat, solvaldelta, objdelta, weight) );
14396  return SCIP_OKAY;
14397 
14398  case SCIP_VARSTATUS_LOOSE:
14399  case SCIP_VARSTATUS_COLUMN:
14400  /* store old pseudo-costs for root LP best-estimate update */
14401  oldrootpseudocosts = SCIPvarGetMinPseudocostScore(var, stat, set, SCIPvarGetRootSol(var));
14402 
14403  /* update history */
14404  SCIPhistoryUpdatePseudocost(var->history, set, solvaldelta, objdelta, weight);
14405  SCIPhistoryUpdatePseudocost(var->historycrun, set, solvaldelta, objdelta, weight);
14406  SCIPhistoryUpdatePseudocost(stat->glbhistory, set, solvaldelta, objdelta, weight);
14407  SCIPhistoryUpdatePseudocost(stat->glbhistorycrun, set, solvaldelta, objdelta, weight);
14408 
14409  /* update root LP best-estimate */
14410  SCIP_CALL( SCIPstatUpdateVarRootLPBestEstimate(stat, set, var, oldrootpseudocosts) );
14411 
14412  /* append history to file */
14413 #ifdef SCIP_HISTORYTOFILE
14414  {
14415  FILE* f;
14416  char filename[256];
14417  SCIP_NODE* currentnode;
14418  SCIP_NODE* parentnode;
14419  currentnode = SCIPgetFocusNode(set->scip);
14420  parentnode = SCIPnodeGetParent(currentnode);
14421 
14422  sprintf(filename, "%s/%s.pse", historypath, SCIPgetProbName(set->scip));
14423  f = fopen(filename, "a");
14424  if( NULL != f )
14425  {
14426  fprintf(f, "%lld %s \t %lld \t %lld \t %lld \t %d \t %15.9f \t %.3f\n",
14427  ++counter,
14428  SCIPvarGetName(var),
14429  SCIPnodeGetNumber(currentnode),
14430  parentnode != NULL ? SCIPnodeGetNumber(parentnode) : -1,
14431  SCIPgetNLPIterations(set->scip),
14432  SCIPgetDepth(set->scip),
14433  objdelta,
14434  solvaldelta);
14435  fclose(f);
14436  }
14437  }
14438 #endif
14439  return SCIP_OKAY;
14440 
14441  case SCIP_VARSTATUS_FIXED:
14442  SCIPerrorMessage("cannot update pseudo cost values of a fixed variable\n");
14443  return SCIP_INVALIDDATA;
14444 
14446  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
14448  solvaldelta/var->data.aggregate.scalar, objdelta, weight) );
14449  return SCIP_OKAY;
14450 
14452  SCIPerrorMessage("cannot update pseudo cost values of a multi-aggregated variable\n");
14453  return SCIP_INVALIDDATA;
14454 
14456  SCIP_CALL( SCIPvarUpdatePseudocost(var->negatedvar, set, stat, -solvaldelta, objdelta, weight) );
14457  return SCIP_OKAY;
14458 
14459  default:
14460  SCIPerrorMessage("unknown variable status\n");
14461  return SCIP_INVALIDDATA;
14462  }
14463 }
14464 
14465 /** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value */
14467  SCIP_VAR* var, /**< problem variable */
14468  SCIP_STAT* stat, /**< problem statistics */
14469  SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
14470  )
14471 {
14472  SCIP_BRANCHDIR dir;
14473 
14474  assert(var != NULL);
14475  assert(stat != NULL);
14476 
14477  switch( SCIPvarGetStatus(var) )
14478  {
14480  if( var->data.original.transvar == NULL )
14481  return SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
14482  else
14483  return SCIPvarGetPseudocost(var->data.original.transvar, stat, solvaldelta);
14484 
14485  case SCIP_VARSTATUS_LOOSE:
14486  case SCIP_VARSTATUS_COLUMN:
14487  dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
14488 
14489  return SCIPhistoryGetPseudocostCount(var->history, dir) > 0.0
14490  ? SCIPhistoryGetPseudocost(var->history, solvaldelta)
14491  : SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
14492 
14493  case SCIP_VARSTATUS_FIXED:
14494  return 0.0;
14495 
14497  return SCIPvarGetPseudocost(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
14498 
14500  return 0.0;
14501 
14503  return SCIPvarGetPseudocost(var->negatedvar, stat, -solvaldelta);
14504 
14505  default:
14506  SCIPerrorMessage("unknown variable status\n");
14507  SCIPABORT();
14508  return 0.0; /*lint !e527*/
14509  }
14510 }
14511 
14512 /** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value,
14513  * only using the pseudo cost information of the current run
14514  */
14516  SCIP_VAR* var, /**< problem variable */
14517  SCIP_STAT* stat, /**< problem statistics */
14518  SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
14519  )
14520 {
14521  SCIP_BRANCHDIR dir;
14522 
14523  assert(var != NULL);
14524  assert(stat != NULL);
14525 
14526  switch( SCIPvarGetStatus(var) )
14527  {
14529  if( var->data.original.transvar == NULL )
14530  return SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
14531  else
14532  return SCIPvarGetPseudocostCurrentRun(var->data.original.transvar, stat, solvaldelta);
14533 
14534  case SCIP_VARSTATUS_LOOSE:
14535  case SCIP_VARSTATUS_COLUMN:
14536  dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
14537 
14538  return SCIPhistoryGetPseudocostCount(var->historycrun, dir) > 0.0
14539  ? SCIPhistoryGetPseudocost(var->historycrun, solvaldelta)
14540  : SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
14541 
14542  case SCIP_VARSTATUS_FIXED:
14543  return 0.0;
14544 
14546  return SCIPvarGetPseudocostCurrentRun(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
14547 
14549  return 0.0;
14550 
14552  return SCIPvarGetPseudocostCurrentRun(var->negatedvar, stat, -solvaldelta);
14553 
14554  default:
14555  SCIPerrorMessage("unknown variable status\n");
14556  SCIPABORT();
14557  return 0.0; /*lint !e527*/
14558  }
14559 }
14560 
14561 /** gets the variable's (possible fractional) number of pseudo cost updates for the given direction */
14563  SCIP_VAR* var, /**< problem variable */
14564  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14565  )
14566 {
14567  assert(var != NULL);
14568  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14569 
14570  switch( SCIPvarGetStatus(var) )
14571  {
14573  if( var->data.original.transvar == NULL )
14574  return 0.0;
14575  else
14576  return SCIPvarGetPseudocostCount(var->data.original.transvar, dir);
14577 
14578  case SCIP_VARSTATUS_LOOSE:
14579  case SCIP_VARSTATUS_COLUMN:
14580  return SCIPhistoryGetPseudocostCount(var->history, dir);
14581 
14582  case SCIP_VARSTATUS_FIXED:
14583  return 0.0;
14584 
14586  if( var->data.aggregate.scalar > 0.0 )
14587  return SCIPvarGetPseudocostCount(var->data.aggregate.var, dir);
14588  else
14590 
14592  return 0.0;
14593 
14596 
14597  default:
14598  SCIPerrorMessage("unknown variable status\n");
14599  SCIPABORT();
14600  return 0.0; /*lint !e527*/
14601  }
14602 }
14603 
14604 /** gets the variable's (possible fractional) number of pseudo cost updates for the given direction,
14605  * only using the pseudo cost information of the current run
14606  */
14608  SCIP_VAR* var, /**< problem variable */
14609  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14610  )
14611 {
14612  assert(var != NULL);
14613  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14614 
14615  switch( SCIPvarGetStatus(var) )
14616  {
14618  if( var->data.original.transvar == NULL )
14619  return 0.0;
14620  else
14622 
14623  case SCIP_VARSTATUS_LOOSE:
14624  case SCIP_VARSTATUS_COLUMN:
14625  return SCIPhistoryGetPseudocostCount(var->historycrun, dir);
14626 
14627  case SCIP_VARSTATUS_FIXED:
14628  return 0.0;
14629 
14631  if( var->data.aggregate.scalar > 0.0 )
14633  else
14635 
14637  return 0.0;
14638 
14641 
14642  default:
14643  SCIPerrorMessage("unknown variable status\n");
14644  SCIPABORT();
14645  return 0.0; /*lint !e527*/
14646  }
14647 }
14648 
14649 /** compares both possible directions for rounding the given solution value and returns the minimum pseudo-costs of the variable */
14651  SCIP_VAR* var, /**< problem variable */
14652  SCIP_STAT* stat, /**< problem statistics */
14653  SCIP_SET* set, /**< global SCIP settings */
14654  SCIP_Real solval /**< solution value, e.g., LP solution value */
14655  )
14656 {
14657  SCIP_Real upscore;
14658  SCIP_Real downscore;
14659  SCIP_Real solvaldeltaup;
14660  SCIP_Real solvaldeltadown;
14661 
14662  /* LP root estimate only works for variables with fractional LP root solution */
14663  if( SCIPsetIsFeasIntegral(set, solval) )
14664  return 0.0;
14665 
14666  /* no min pseudo-cost score is calculated as long as the variable was not initialized in a direction */
14668  return 0.0;
14669 
14670  /* compute delta's to ceil and floor of root LP solution value */
14671  solvaldeltaup = SCIPsetCeil(set, solval) - solval;
14672  solvaldeltadown = SCIPsetFloor(set, solval) - solval;
14673 
14674  upscore = SCIPvarGetPseudocost(var, stat, solvaldeltaup);
14675  downscore = SCIPvarGetPseudocost(var, stat, solvaldeltadown);
14676 
14677  return MIN(upscore, downscore);
14678 }
14679 
14680 /** gets the an estimate of the variable's pseudo cost variance in direction \p dir */
14682  SCIP_VAR* var, /**< problem variable */
14683  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
14684  SCIP_Bool onlycurrentrun /**< return pseudo cost variance only for current branch and bound run */
14685  )
14686 {
14687  assert(var != NULL);
14688  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14689 
14690  switch( SCIPvarGetStatus(var) )
14691  {
14693  if( var->data.original.transvar == NULL )
14694  return 0.0;
14695  else
14696  return SCIPvarGetPseudocostVariance(var->data.original.transvar, dir, onlycurrentrun);
14697 
14698  case SCIP_VARSTATUS_LOOSE:
14699  case SCIP_VARSTATUS_COLUMN:
14700  if( onlycurrentrun )
14702  else
14703  return SCIPhistoryGetPseudocostVariance(var->history, dir);
14704 
14705  case SCIP_VARSTATUS_FIXED:
14706  return 0.0;
14707 
14709  if( var->data.aggregate.scalar > 0.0 )
14710  return SCIPvarGetPseudocostVariance(var->data.aggregate.var, dir, onlycurrentrun);
14711  else
14712  return SCIPvarGetPseudocostVariance(var->data.aggregate.var, SCIPbranchdirOpposite(dir), onlycurrentrun);
14713 
14715  return 0.0;
14716 
14718  return SCIPvarGetPseudocostVariance(var->negatedvar, SCIPbranchdirOpposite(dir), onlycurrentrun);
14719 
14720  default:
14721  SCIPerrorMessage("unknown variable status\n");
14722  SCIPABORT();
14723  return 0.0; /*lint !e527*/
14724  }
14725 }
14726 
14727 /** calculates a confidence bound for this variable under the assumption of normally distributed pseudo costs
14728  *
14729  * The confidence bound \f$ \theta \geq 0\f$ denotes the interval borders \f$ [X - \theta, \ X + \theta]\f$, which contains
14730  * the true pseudo costs of the variable, i.e., the expected value of the normal distribution, with a probability
14731  * of 2 * clevel - 1.
14732  *
14733  * @return value of confidence bound for this variable
14734  */
14736  SCIP_VAR* var, /**< variable in question */
14737  SCIP_SET* set, /**< global SCIP settings */
14738  SCIP_BRANCHDIR dir, /**< the branching direction for the confidence bound */
14739  SCIP_Bool onlycurrentrun, /**< should only the current run be taken into account */
14740  SCIP_CONFIDENCELEVEL clevel /**< confidence level for the interval */
14741  )
14742 {
14743  SCIP_Real confidencebound;
14744 
14745  confidencebound = SCIPvarGetPseudocostVariance(var, dir, onlycurrentrun);
14746  if( SCIPsetIsFeasPositive(set, confidencebound) )
14747  {
14748  SCIP_Real count;
14749 
14750  if( onlycurrentrun )
14751  count = SCIPvarGetPseudocostCountCurrentRun(var, dir);
14752  else
14753  count = SCIPvarGetPseudocostCount(var, dir);
14754  /* assertion is valid because variance is positive */
14755  assert(count >= 1.9);
14756 
14757  confidencebound /= count; /*lint !e414 division by zero can obviously not occur */
14758  confidencebound = sqrt(confidencebound);
14759 
14760  /* the actual, underlying distribution of the mean is a student-t-distribution with degrees of freedom equal to
14761  * the number of pseudo cost evaluations of this variable in the respective direction. */
14762  confidencebound *= SCIPstudentTGetCriticalValue(clevel, (int)SCIPsetFloor(set, count) - 1);
14763  }
14764  else
14765  confidencebound = 0.0;
14766 
14767  return confidencebound;
14768 }
14769 
14770 /** check if the current pseudo cost relative error in a direction violates the given threshold. The Relative
14771  * Error is calculated at a specific confidence level
14772  */
14774  SCIP_VAR* var, /**< variable in question */
14775  SCIP_SET* set, /**< global SCIP settings */
14776  SCIP_STAT* stat, /**< problem statistics */
14777  SCIP_Real threshold, /**< threshold for relative errors to be considered reliable (enough) */
14778  SCIP_CONFIDENCELEVEL clevel /**< a given confidence level */
14779  )
14780 {
14781  SCIP_Real downsize;
14782  SCIP_Real upsize;
14783  SCIP_Real size;
14784  SCIP_Real relerrorup;
14785  SCIP_Real relerrordown;
14786  SCIP_Real relerror;
14787 
14788  /* check, if the pseudo cost score of the variable is reliable */
14791  size = MIN(downsize, upsize);
14792 
14793  /* Pseudo costs relative error can only be reliable if both directions have been tried at least twice */
14794  if( size <= 1.9 )
14795  return FALSE;
14796 
14797  /* use the relative error between the current mean pseudo cost value of the candidate and its upper
14798  * confidence interval bound at confidence level of 95% for individual variable reliability.
14799  * this is only possible if we have at least 2 measurements and therefore a valid variance estimate.
14800  */
14801  if( downsize >= 1.9 )
14802  {
14803  SCIP_Real normval;
14804 
14805  relerrordown = SCIPvarCalcPscostConfidenceBound(var, set, SCIP_BRANCHDIR_DOWNWARDS, TRUE, clevel);
14806  normval = SCIPvarGetPseudocostCurrentRun(var, stat, -1.0);
14807  normval = MAX(1.0, normval);
14808 
14809  relerrordown /= normval;
14810  }
14811  else
14812  relerrordown = 0.0;
14813 
14814  if( upsize >= 1.9 )
14815  {
14816  SCIP_Real normval;
14817 
14818  relerrorup = SCIPvarCalcPscostConfidenceBound(var, set, SCIP_BRANCHDIR_UPWARDS, TRUE, clevel);
14819  normval = SCIPvarGetPseudocostCurrentRun(var, stat, +1.0);
14820  normval = MAX(1.0, normval);
14821  relerrorup /= normval;
14822  }
14823  else
14824  relerrorup = 0.0;
14825 
14826  /* consider the relative error threshold violated, if it is violated in at least one branching direction */
14827  relerror = MAX(relerrorup, relerrordown);
14828 
14829  return (relerror <= threshold);
14830 }
14831 
14832 /** check if variable pseudo-costs have a significant difference in location. The significance depends on
14833  * the choice of \p clevel and on the kind of tested hypothesis. The one-sided hypothesis, which
14834  * should be rejected, is that fracy * mu_y >= fracx * mu_x, where mu_y and mu_x denote the
14835  * unknown location means of the underlying pseudo-cost distributions of x and y.
14836  *
14837  * This method is applied best if variable x has a better pseudo-cost score than y. The method hypothesizes that y were actually
14838  * better than x (despite the current information), meaning that y can be expected to yield branching
14839  * decisions as least as good as x in the long run. If the method returns TRUE, the current history information is
14840  * sufficient to safely rely on the alternative hypothesis that x yields indeed a better branching score (on average)
14841  * than y.
14842  *
14843  * @note The order of x and y matters for the one-sided hypothesis
14844  *
14845  * @note set \p onesided to FALSE if you are not sure which variable is better. The hypothesis tested then reads
14846  * fracy * mu_y == fracx * mu_x vs the alternative hypothesis fracy * mu_y != fracx * mu_x.
14847  *
14848  * @return TRUE if the hypothesis can be safely rejected at the given confidence level
14849  */
14851  SCIP_SET* set, /**< global SCIP settings */
14852  SCIP_STAT* stat, /**< problem statistics */
14853  SCIP_VAR* varx, /**< variable x */
14854  SCIP_Real fracx, /**< the fractionality of variable x */
14855  SCIP_VAR* vary, /**< variable y */
14856  SCIP_Real fracy, /**< the fractionality of variable y */
14857  SCIP_BRANCHDIR dir, /**< branching direction */
14858  SCIP_CONFIDENCELEVEL clevel, /**< confidence level for rejecting hypothesis */
14859  SCIP_Bool onesided /**< should a one-sided hypothesis y >= x be tested? */
14860  )
14861 {
14862  SCIP_Real meanx;
14863  SCIP_Real meany;
14864  SCIP_Real variancex;
14865  SCIP_Real variancey;
14866  SCIP_Real countx;
14867  SCIP_Real county;
14868  SCIP_Real tresult;
14869  SCIP_Real realdirection;
14870 
14871  if( varx == vary )
14872  return FALSE;
14873 
14874  countx = SCIPvarGetPseudocostCount(varx, dir);
14875  county = SCIPvarGetPseudocostCount(vary, dir);
14876 
14877  /* if not at least 2 measurements were taken, return FALSE */
14878  if( countx <= 1.9 || county <= 1.9 )
14879  return FALSE;
14880 
14881  realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
14882 
14883  meanx = fracx * SCIPvarGetPseudocost(varx, stat, realdirection);
14884  meany = fracy * SCIPvarGetPseudocost(vary, stat, realdirection);
14885 
14886  variancex = SQR(fracx) * SCIPvarGetPseudocostVariance(varx, dir, FALSE);
14887  variancey = SQR(fracy) * SCIPvarGetPseudocostVariance(vary, dir, FALSE);
14888 
14889  /* if there is no variance, the means are taken from a constant distribution */
14890  if( SCIPsetIsFeasEQ(set, variancex + variancey, 0.0) )
14891  return (onesided ? SCIPsetIsFeasGT(set, meanx, meany) : !SCIPsetIsFeasEQ(set, meanx, meany));
14892 
14893  tresult = SCIPcomputeTwoSampleTTestValue(meanx, meany, variancex, variancey, countx, county);
14894 
14895  /* for the two-sided hypothesis, just take the absolute of t */
14896  if( !onesided )
14897  tresult = REALABS(tresult);
14898 
14899  return (tresult >= SCIPstudentTGetCriticalValue(clevel, (int)(countx + county - 2)));
14900 }
14901 
14902 /** tests at a given confidence level whether the variable pseudo-costs only have a small probability to
14903  * exceed a \p threshold. This is useful to determine if past observations provide enough evidence
14904  * to skip an expensive strong-branching step if there is already a candidate that has been proven to yield an improvement
14905  * of at least \p threshold.
14906  *
14907  * @note use \p clevel to adjust the level of confidence. For SCIP_CONFIDENCELEVEL_MIN, the method returns TRUE if
14908  * the estimated probability to exceed \p threshold is less than 25 %.
14909  *
14910  * @see SCIP_Confidencelevel for a list of available levels. The used probability limits refer to the one-sided levels
14911  * of confidence.
14912  *
14913  * @return TRUE if the variable pseudo-cost probabilistic model is likely to be smaller than \p threshold
14914  * at the given confidence level \p clevel.
14915  */
14917  SCIP_SET* set, /**< global SCIP settings */
14918  SCIP_STAT* stat, /**< problem statistics */
14919  SCIP_VAR* var, /**< variable x */
14920  SCIP_Real frac, /**< the fractionality of variable x */
14921  SCIP_Real threshold, /**< the threshold to test against */
14922  SCIP_BRANCHDIR dir, /**< branching direction */
14923  SCIP_CONFIDENCELEVEL clevel /**< confidence level for rejecting hypothesis */
14924  )
14925 {
14926  SCIP_Real mean;
14927  SCIP_Real variance;
14928  SCIP_Real count;
14929  SCIP_Real realdirection;
14930  SCIP_Real probability;
14931  SCIP_Real problimit;
14932 
14933  count = SCIPvarGetPseudocostCount(var, dir);
14934 
14935  /* if not at least 2 measurements were taken, return FALSE */
14936  if( count <= 1.9 )
14937  return FALSE;
14938 
14939  realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
14940 
14941  mean = frac * SCIPvarGetPseudocost(var, stat, realdirection);
14942  variance = SQR(frac) * SCIPvarGetPseudocostVariance(var, dir, FALSE);
14943 
14944  /* if mean is at least threshold, it has at least a 50% probability to exceed threshold, we therefore return FALSE */
14945  if( SCIPsetIsFeasGE(set, mean, threshold) )
14946  return FALSE;
14947 
14948  /* if there is no variance, the means are taken from a constant distribution */
14949  if( SCIPsetIsFeasEQ(set, variance, 0.0) )
14950  return SCIPsetIsFeasLT(set, mean, threshold);
14951 
14952  /* obtain probability of a normally distributed random variable at given mean and variance to yield at most threshold */
14953  probability = SCIPnormalCDF(mean, variance, threshold);
14954 
14955  /* determine a probability limit corresponding to the given confidence level */
14956  switch( clevel )
14957  {
14959  problimit = 0.75;
14960  break;
14962  problimit = 0.875;
14963  break;
14965  problimit = 0.9;
14966  break;
14968  problimit = 0.95;
14969  break;
14971  problimit = 0.975;
14972  break;
14973  default:
14974  problimit = -1;
14975  SCIPerrorMessage("Confidence level set to unknown value <%d>", (int)clevel);
14976  SCIPABORT();
14977  break;
14978  }
14979 
14980  return (probability >= problimit);
14981 }
14982 
14983 /** find the corresponding history entry if already existing, otherwise create new entry */
14984 static
14986  SCIP_VAR* var, /**< problem variable */
14987  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14988  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14989  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14990  SCIP_HISTORY** history /**< pointer to store the value based history, or NULL */
14991  )
14992 {
14993  assert(var != NULL);
14994  assert(blkmem != NULL);
14995  assert(set != NULL);
14996  assert(history != NULL);
14997 
14998  (*history) = NULL;
14999 
15000  if( var->valuehistory == NULL )
15001  {
15002  SCIP_CALL( SCIPvaluehistoryCreate(&var->valuehistory, blkmem) );
15003  }
15004 
15005  SCIP_CALL( SCIPvaluehistoryFind(var->valuehistory, blkmem, set, value, history) );
15006 
15007  return SCIP_OKAY;
15008 }
15009 
15010 /** check if value based history should be used */
15011 static
15013  SCIP_VAR* var, /**< problem variable */
15014  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15015  SCIP_SET* set /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15016  )
15017 {
15018  /* check if the domain value is unknown (not specific) */
15019  if( value == SCIP_UNKNOWN ) /*lint !e777*/
15020  return FALSE;
15021 
15022  assert(set != NULL);
15023 
15024  /* check if value based history should be collected */
15025  if( !set->history_valuebased )
15026  return FALSE;
15027 
15028  /* value based history is not collected for binary variable since the standard history already contains all information */
15029  if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
15030  return FALSE;
15031 
15032  /* value based history is not collected for continuous variables */
15034  return FALSE;
15035 
15036  return TRUE;
15037 }
15038 
15039 /** increases VSIDS of the variable by the given weight */
15041  SCIP_VAR* var, /**< problem variable */
15042  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15043  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15044  SCIP_STAT* stat, /**< problem statistics */
15045  SCIP_BRANCHDIR dir, /**< branching direction */
15046  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15047  SCIP_Real weight /**< weight of this update in VSIDS */
15048  )
15049 {
15050  assert(var != NULL);
15051  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15052 
15053  /* check if history statistics should be collected for a variable */
15054  if( !stat->collectvarhistory )
15055  return SCIP_OKAY;
15056 
15057  if( SCIPsetIsZero(set, weight) )
15058  return SCIP_OKAY;
15059 
15060  switch( SCIPvarGetStatus(var) )
15061  {
15063  if( var->data.original.transvar == NULL )
15064  {
15065  SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
15066  return SCIP_INVALIDDATA;
15067  }
15068  SCIP_CALL( SCIPvarIncVSIDS(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
15069  return SCIP_OKAY;
15070 
15071  case SCIP_VARSTATUS_LOOSE:
15072  case SCIP_VARSTATUS_COLUMN:
15073  {
15074  SCIPhistoryIncVSIDS(var->history, dir, weight);
15075  SCIPhistoryIncVSIDS(var->historycrun, dir, weight);
15076 
15077  if( useValuehistory(var, value, set) )
15078  {
15079  SCIP_HISTORY* history;
15080 
15081  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15082  assert(history != NULL);
15083 
15084  SCIPhistoryIncVSIDS(history, dir, weight);
15085  SCIPsetDebugMsg(set, "variable (<%s> %s %g) + <%g> = <%g>\n", SCIPvarGetName(var), dir == SCIP_BRANCHDIR_UPWARDS ? ">=" : "<=",
15086  value, weight, SCIPhistoryGetVSIDS(history, dir));
15087  }
15088 
15089  return SCIP_OKAY;
15090  }
15091  case SCIP_VARSTATUS_FIXED:
15092  SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
15093  return SCIP_INVALIDDATA;
15094 
15096  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15097 
15098  if( var->data.aggregate.scalar > 0.0 )
15099  {
15100  SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
15101  }
15102  else
15103  {
15104  assert(var->data.aggregate.scalar < 0.0);
15105  SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15106  }
15107  return SCIP_OKAY;
15108 
15110  SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
15111  return SCIP_INVALIDDATA;
15112 
15114  value = 1.0 - value;
15115 
15116  SCIP_CALL( SCIPvarIncVSIDS(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15117  return SCIP_OKAY;
15118 
15119  default:
15120  SCIPerrorMessage("unknown variable status\n");
15121  return SCIP_INVALIDDATA;
15122  }
15123 }
15124 
15125 /** scales the VSIDS of the variable by the given scalar */
15127  SCIP_VAR* var, /**< problem variable */
15128  SCIP_Real scalar /**< scalar to multiply the VSIDSs with */
15129  )
15130 {
15131  assert(var != NULL);
15132 
15133  switch( SCIPvarGetStatus(var) )
15134  {
15136  if( var->data.original.transvar == NULL )
15137  {
15138  SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
15139  return SCIP_INVALIDDATA;
15140  }
15142  return SCIP_OKAY;
15143 
15144  case SCIP_VARSTATUS_LOOSE:
15145  case SCIP_VARSTATUS_COLUMN:
15146  {
15147  SCIPhistoryScaleVSIDS(var->history, scalar);
15148  SCIPhistoryScaleVSIDS(var->historycrun, scalar);
15150 
15151  return SCIP_OKAY;
15152  }
15153  case SCIP_VARSTATUS_FIXED:
15154  SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
15155  return SCIP_INVALIDDATA;
15156 
15158  SCIP_CALL( SCIPvarScaleVSIDS(var->data.aggregate.var, scalar) );
15159  return SCIP_OKAY;
15160 
15162  SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
15163  return SCIP_INVALIDDATA;
15164 
15166  SCIP_CALL( SCIPvarScaleVSIDS(var->negatedvar, scalar) );
15167  return SCIP_OKAY;
15168 
15169  default:
15170  SCIPerrorMessage("unknown variable status\n");
15171  return SCIP_INVALIDDATA;
15172  }
15173 }
15174 
15175 /** increases the number of active conflicts by one and the overall length of the variable by the given length */
15177  SCIP_VAR* var, /**< problem variable */
15178  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15179  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15180  SCIP_STAT* stat, /**< problem statistics */
15181  SCIP_BRANCHDIR dir, /**< branching direction */
15182  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15183  SCIP_Real length /**< length of the conflict */
15184  )
15185 {
15186  assert(var != NULL);
15187  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15188 
15189  /* check if history statistics should be collected for a variable */
15190  if( !stat->collectvarhistory )
15191  return SCIP_OKAY;
15192 
15193  switch( SCIPvarGetStatus(var) )
15194  {
15196  if( var->data.original.transvar == NULL )
15197  {
15198  SCIPerrorMessage("cannot update conflict score of original untransformed variable\n");
15199  return SCIP_INVALIDDATA;
15200  }
15201  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.original.transvar, blkmem, set, stat, dir, value, length) );
15202  return SCIP_OKAY;
15203 
15204  case SCIP_VARSTATUS_LOOSE:
15205  case SCIP_VARSTATUS_COLUMN:
15206  {
15207  SCIPhistoryIncNActiveConflicts(var->history, dir, length);
15208  SCIPhistoryIncNActiveConflicts(var->historycrun, dir, length);
15209 
15210  if( useValuehistory(var, value, set) )
15211  {
15212  SCIP_HISTORY* history;
15213 
15214  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15215  assert(history != NULL);
15216 
15217  SCIPhistoryIncNActiveConflicts(history, dir, length);
15218  }
15219 
15220  return SCIP_OKAY;
15221  }
15222  case SCIP_VARSTATUS_FIXED:
15223  SCIPerrorMessage("cannot update conflict score of a fixed variable\n");
15224  return SCIP_INVALIDDATA;
15225 
15227  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15228 
15229  if( var->data.aggregate.scalar > 0.0 )
15230  {
15231  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, dir, value, length) );
15232  }
15233  else
15234  {
15235  assert(var->data.aggregate.scalar < 0.0);
15236  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
15237  }
15238  return SCIP_OKAY;
15239 
15241  SCIPerrorMessage("cannot update conflict score of a multi-aggregated variable\n");
15242  return SCIP_INVALIDDATA;
15243 
15245  value = 1.0 - value;
15246 
15247  SCIP_CALL( SCIPvarIncNActiveConflicts(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
15248  return SCIP_OKAY;
15249 
15250  default:
15251  SCIPerrorMessage("unknown variable status\n");
15252  return SCIP_INVALIDDATA;
15253  }
15254 }
15255 
15256 /** gets the number of active conflicts containing this variable in given direction */
15258  SCIP_VAR* var, /**< problem variable */
15259  SCIP_STAT* stat, /**< problem statistics */
15260  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15261  )
15262 {
15263  assert(var != NULL);
15264  assert(stat != NULL);
15265  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15266 
15267  switch( SCIPvarGetStatus(var) )
15268  {
15270  if( var->data.original.transvar == NULL )
15271  return 0;
15272  else
15273  return SCIPvarGetNActiveConflicts(var->data.original.transvar, stat, dir);
15274 
15275  case SCIP_VARSTATUS_LOOSE:
15276  case SCIP_VARSTATUS_COLUMN:
15277  return SCIPhistoryGetNActiveConflicts(var->history, dir);
15278 
15279  case SCIP_VARSTATUS_FIXED:
15280  return 0;
15281 
15283  if( var->data.aggregate.scalar > 0.0 )
15284  return SCIPvarGetNActiveConflicts(var->data.aggregate.var, stat, dir);
15285  else
15287 
15289  return 0;
15290 
15293 
15294  default:
15295  SCIPerrorMessage("unknown variable status\n");
15296  SCIPABORT();
15297  return 0; /*lint !e527*/
15298  }
15299 }
15300 
15301 /** gets the number of active conflicts containing this variable in given direction
15302  * in the current run
15303  */
15305  SCIP_VAR* var, /**< problem variable */
15306  SCIP_STAT* stat, /**< problem statistics */
15307  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15308  )
15309 {
15310  assert(var != NULL);
15311  assert(stat != NULL);
15312  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15313 
15314  switch( SCIPvarGetStatus(var) )
15315  {
15317  if( var->data.original.transvar == NULL )
15318  return 0;
15319  else
15321 
15322  case SCIP_VARSTATUS_LOOSE:
15323  case SCIP_VARSTATUS_COLUMN:
15324  return SCIPhistoryGetNActiveConflicts(var->historycrun, dir);
15325 
15326  case SCIP_VARSTATUS_FIXED:
15327  return 0;
15328 
15330  if( var->data.aggregate.scalar > 0.0 )
15331  return SCIPvarGetNActiveConflictsCurrentRun(var->data.aggregate.var, stat, dir);
15332  else
15334 
15336  return 0;
15337 
15340 
15341  default:
15342  SCIPerrorMessage("unknown variable status\n");
15343  SCIPABORT();
15344  return 0; /*lint !e527*/
15345  }
15346 }
15347 
15348 /** gets the average conflict length in given direction due to branching on the variable */
15350  SCIP_VAR* var, /**< problem variable */
15351  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15352  )
15353 {
15354  assert(var != NULL);
15355  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15356 
15357  switch( SCIPvarGetStatus(var) )
15358  {
15360  if( var->data.original.transvar == NULL )
15361  return 0.0;
15362  else
15364 
15365  case SCIP_VARSTATUS_LOOSE:
15366  case SCIP_VARSTATUS_COLUMN:
15367  return SCIPhistoryGetAvgConflictlength(var->history, dir);
15368  case SCIP_VARSTATUS_FIXED:
15369  return 0.0;
15370 
15372  if( var->data.aggregate.scalar > 0.0 )
15373  return SCIPvarGetAvgConflictlength(var->data.aggregate.var, dir);
15374  else
15376 
15378  return 0.0;
15379 
15382 
15383  default:
15384  SCIPerrorMessage("unknown variable status\n");
15385  SCIPABORT();
15386  return 0.0; /*lint !e527*/
15387  }
15388 }
15389 
15390 /** gets the average conflict length in given direction due to branching on the variable
15391  * in the current run
15392  */
15394  SCIP_VAR* var, /**< problem variable */
15395  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15396  )
15397 {
15398  assert(var != NULL);
15399  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15400 
15401  switch( SCIPvarGetStatus(var) )
15402  {
15404  if( var->data.original.transvar == NULL )
15405  return 0.0;
15406  else
15408 
15409  case SCIP_VARSTATUS_LOOSE:
15410  case SCIP_VARSTATUS_COLUMN:
15411  return SCIPhistoryGetAvgConflictlength(var->historycrun, dir);
15412 
15413  case SCIP_VARSTATUS_FIXED:
15414  return 0.0;
15415 
15417  if( var->data.aggregate.scalar > 0.0 )
15419  else
15421 
15423  return 0.0;
15424 
15427 
15428  default:
15429  SCIPerrorMessage("unknown variable status\n");
15430  SCIPABORT();
15431  return 0.0; /*lint !e527*/
15432  }
15433 }
15434 
15435 /** increases the number of branchings counter of the variable */
15437  SCIP_VAR* var, /**< problem variable */
15438  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15439  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15440  SCIP_STAT* stat, /**< problem statistics */
15441  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
15442  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15443  int depth /**< depth at which the bound change took place */
15444  )
15445 {
15446  assert(var != NULL);
15447  assert(stat != NULL);
15448  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15449 
15450  /* check if history statistics should be collected for a variable */
15451  if( !stat->collectvarhistory )
15452  return SCIP_OKAY;
15453 
15454  switch( SCIPvarGetStatus(var) )
15455  {
15457  if( var->data.original.transvar == NULL )
15458  {
15459  SCIPerrorMessage("cannot update branching counter of original untransformed variable\n");
15460  return SCIP_INVALIDDATA;
15461  }
15462  SCIP_CALL( SCIPvarIncNBranchings(var->data.original.transvar, blkmem, set, stat, dir, value, depth) );
15463  return SCIP_OKAY;
15464 
15465  case SCIP_VARSTATUS_LOOSE:
15466  case SCIP_VARSTATUS_COLUMN:
15467  {
15468  SCIPhistoryIncNBranchings(var->history, dir, depth);
15469  SCIPhistoryIncNBranchings(var->historycrun, dir, depth);
15470  SCIPhistoryIncNBranchings(stat->glbhistory, dir, depth);
15471  SCIPhistoryIncNBranchings(stat->glbhistorycrun, dir, depth);
15472 
15473  if( useValuehistory(var, value, set) )
15474  {
15475  SCIP_HISTORY* history;
15476 
15477  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15478  assert(history != NULL);
15479 
15480  SCIPhistoryIncNBranchings(history, dir, depth);
15481  }
15482 
15483  return SCIP_OKAY;
15484  }
15485  case SCIP_VARSTATUS_FIXED:
15486  SCIPerrorMessage("cannot update branching counter of a fixed variable\n");
15487  return SCIP_INVALIDDATA;
15488 
15490  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15491 
15492  if( var->data.aggregate.scalar > 0.0 )
15493  {
15494  SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, dir, value, depth) );
15495  }
15496  else
15497  {
15498  assert(var->data.aggregate.scalar < 0.0);
15499  SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
15500  }
15501  return SCIP_OKAY;
15502 
15504  SCIPerrorMessage("cannot update branching counter of a multi-aggregated variable\n");
15505  return SCIP_INVALIDDATA;
15506 
15508  value = 1.0 - value;
15509 
15510  SCIP_CALL( SCIPvarIncNBranchings(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
15511  return SCIP_OKAY;
15512 
15513  default:
15514  SCIPerrorMessage("unknown variable status\n");
15515  return SCIP_INVALIDDATA;
15516  }
15517 }
15518 
15519 /** increases the inference sum of the variable by the given weight */
15521  SCIP_VAR* var, /**< problem variable */
15522  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15523  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15524  SCIP_STAT* stat, /**< problem statistics */
15525  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
15526  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15527  SCIP_Real weight /**< weight of this update in inference score */
15528  )
15529 {
15530  assert(var != NULL);
15531  assert(stat != NULL);
15532  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15533 
15534  /* check if history statistics should be collected for a variable */
15535  if( !stat->collectvarhistory )
15536  return SCIP_OKAY;
15537 
15538  switch( SCIPvarGetStatus(var) )
15539  {
15541  if( var->data.original.transvar == NULL )
15542  {
15543  SCIPerrorMessage("cannot update inference counter of original untransformed variable\n");
15544  return SCIP_INVALIDDATA;
15545  }
15546  SCIP_CALL( SCIPvarIncInferenceSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
15547  return SCIP_OKAY;
15548 
15549  case SCIP_VARSTATUS_LOOSE:
15550  case SCIP_VARSTATUS_COLUMN:
15551  {
15552  SCIPhistoryIncInferenceSum(var->history, dir, weight);
15553  SCIPhistoryIncInferenceSum(var->historycrun, dir, weight);
15554  SCIPhistoryIncInferenceSum(stat->glbhistory, dir, weight);
15555  SCIPhistoryIncInferenceSum(stat->glbhistorycrun, dir, weight);
15556 
15557  if( useValuehistory(var, value, set) )
15558  {
15559  SCIP_HISTORY* history;
15560 
15561  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15562  assert(history != NULL);
15563 
15564  SCIPhistoryIncInferenceSum(history, dir, weight);
15565  }
15566 
15567  return SCIP_OKAY;
15568  }
15569  case SCIP_VARSTATUS_FIXED:
15570  SCIPerrorMessage("cannot update inference counter of a fixed variable\n");
15571  return SCIP_INVALIDDATA;
15572 
15574  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15575 
15576  if( var->data.aggregate.scalar > 0.0 )
15577  {
15578  SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
15579  }
15580  else
15581  {
15582  assert(var->data.aggregate.scalar < 0.0);
15583  SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15584  }
15585  return SCIP_OKAY;
15586 
15588  SCIPerrorMessage("cannot update inference counter of a multi-aggregated variable\n");
15589  return SCIP_INVALIDDATA;
15590 
15592  value = 1.0 - value;
15593 
15594  SCIP_CALL( SCIPvarIncInferenceSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15595  return SCIP_OKAY;
15596 
15597  default:
15598  SCIPerrorMessage("unknown variable status\n");
15599  return SCIP_INVALIDDATA;
15600  }
15601 }
15602 
15603 /** increases the cutoff sum of the variable by the given weight */
15605  SCIP_VAR* var, /**< problem variable */
15606  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15607  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15608  SCIP_STAT* stat, /**< problem statistics */
15609  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
15610  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15611  SCIP_Real weight /**< weight of this update in cutoff score */
15612  )
15613 {
15614  assert(var != NULL);
15615  assert(stat != NULL);
15616  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15617 
15618  /* check if history statistics should be collected for a variable */
15619  if( !stat->collectvarhistory )
15620  return SCIP_OKAY;
15621 
15622  switch( SCIPvarGetStatus(var) )
15623  {
15625  if( var->data.original.transvar == NULL )
15626  {
15627  SCIPerrorMessage("cannot update cutoff sum of original untransformed variable\n");
15628  return SCIP_INVALIDDATA;
15629  }
15630  SCIP_CALL( SCIPvarIncCutoffSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
15631  return SCIP_OKAY;
15632 
15633  case SCIP_VARSTATUS_LOOSE:
15634  case SCIP_VARSTATUS_COLUMN:
15635  {
15636  SCIPhistoryIncCutoffSum(var->history, dir, weight);
15637  SCIPhistoryIncCutoffSum(var->historycrun, dir, weight);
15638  SCIPhistoryIncCutoffSum(stat->glbhistory, dir, weight);
15639  SCIPhistoryIncCutoffSum(stat->glbhistorycrun, dir, weight);
15640 
15641  if( useValuehistory(var, value, set) )
15642  {
15643  SCIP_HISTORY* history;
15644 
15645  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15646  assert(history != NULL);
15647 
15648  SCIPhistoryIncCutoffSum(history, dir, weight);
15649  }
15650 
15651  return SCIP_OKAY;
15652  }
15653  case SCIP_VARSTATUS_FIXED:
15654  SCIPerrorMessage("cannot update cutoff sum of a fixed variable\n");
15655  return SCIP_INVALIDDATA;
15656 
15658  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15659 
15660  if( var->data.aggregate.scalar > 0.0 )
15661  {
15662  SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
15663  }
15664  else
15665  {
15666  assert(var->data.aggregate.scalar < 0.0);
15667  SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15668  }
15669  return SCIP_OKAY;
15670 
15672  SCIPerrorMessage("cannot update cutoff sum of a multi-aggregated variable\n");
15673  return SCIP_INVALIDDATA;
15674 
15676  value = 1.0 - value;
15677 
15678  SCIP_CALL( SCIPvarIncCutoffSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15679  return SCIP_OKAY;
15680 
15681  default:
15682  SCIPerrorMessage("unknown variable status\n");
15683  return SCIP_INVALIDDATA;
15684  }
15685 }
15686 
15687 /** returns the number of times, a bound of the variable was changed in given direction due to branching */
15689  SCIP_VAR* var, /**< problem variable */
15690  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15691  )
15692 {
15693  assert(var != NULL);
15694  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15695 
15696  switch( SCIPvarGetStatus(var) )
15697  {
15699  if( var->data.original.transvar == NULL )
15700  return 0;
15701  else
15702  return SCIPvarGetNBranchings(var->data.original.transvar, dir);
15703 
15704  case SCIP_VARSTATUS_LOOSE:
15705  case SCIP_VARSTATUS_COLUMN:
15706  return SCIPhistoryGetNBranchings(var->history, dir);
15707 
15708  case SCIP_VARSTATUS_FIXED:
15709  return 0;
15710 
15712  if( var->data.aggregate.scalar > 0.0 )
15713  return SCIPvarGetNBranchings(var->data.aggregate.var, dir);
15714  else
15716 
15718  return 0;
15719 
15722 
15723  default:
15724  SCIPerrorMessage("unknown variable status\n");
15725  SCIPABORT();
15726  return 0; /*lint !e527*/
15727  }
15728 }
15729 
15730 /** returns the number of times, a bound of the variable was changed in given direction due to branching
15731  * in the current run
15732  */
15734  SCIP_VAR* var, /**< problem variable */
15735  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15736  )
15737 {
15738  assert(var != NULL);
15739  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15740 
15741  switch( SCIPvarGetStatus(var) )
15742  {
15744  if( var->data.original.transvar == NULL )
15745  return 0;
15746  else
15748 
15749  case SCIP_VARSTATUS_LOOSE:
15750  case SCIP_VARSTATUS_COLUMN:
15751  return SCIPhistoryGetNBranchings(var->historycrun, dir);
15752 
15753  case SCIP_VARSTATUS_FIXED:
15754  return 0;
15755 
15757  if( var->data.aggregate.scalar > 0.0 )
15759  else
15761 
15763  return 0;
15764 
15767 
15768  default:
15769  SCIPerrorMessage("unknown variable status\n");
15770  SCIPABORT();
15771  return 0; /*lint !e527*/
15772  }
15773 }
15774 
15775 /** returns the average depth of bound changes in given direction due to branching on the variable */
15777  SCIP_VAR* var, /**< problem variable */
15778  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15779  )
15780 {
15781  assert(var != NULL);
15782  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15783 
15784  switch( SCIPvarGetStatus(var) )
15785  {
15787  if( var->data.original.transvar == NULL )
15788  return 0.0;
15789  else
15790  return SCIPvarGetAvgBranchdepth(var->data.original.transvar, dir);
15791 
15792  case SCIP_VARSTATUS_LOOSE:
15793  case SCIP_VARSTATUS_COLUMN:
15794  return SCIPhistoryGetAvgBranchdepth(var->history, dir);
15795 
15796  case SCIP_VARSTATUS_FIXED:
15797  return 0.0;
15798 
15800  if( var->data.aggregate.scalar > 0.0 )
15801  return SCIPvarGetAvgBranchdepth(var->data.aggregate.var, dir);
15802  else
15804 
15806  return 0.0;
15807 
15810 
15811  default:
15812  SCIPerrorMessage("unknown variable status\n");
15813  SCIPABORT();
15814  return 0.0; /*lint !e527*/
15815  }
15816 }
15817 
15818 /** returns the average depth of bound changes in given direction due to branching on the variable
15819  * in the current run
15820  */
15822  SCIP_VAR* var, /**< problem variable */
15823  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15824  )
15825 {
15826  assert(var != NULL);
15827  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15828 
15829  switch( SCIPvarGetStatus(var) )
15830  {
15832  if( var->data.original.transvar == NULL )
15833  return 0.0;
15834  else
15836 
15837  case SCIP_VARSTATUS_LOOSE:
15838  case SCIP_VARSTATUS_COLUMN:
15839  return SCIPhistoryGetAvgBranchdepth(var->historycrun, dir);
15840 
15841  case SCIP_VARSTATUS_FIXED:
15842  return 0.0;
15843 
15845  if( var->data.aggregate.scalar > 0.0 )
15847  else
15850 
15852  return 0.0;
15853 
15856  dir == SCIP_BRANCHDIR_DOWNWARDS ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
15857 
15858  default:
15859  SCIPerrorMessage("unknown variable status\n");
15860  SCIPABORT();
15861  return 0.0; /*lint !e527*/
15862  }
15863 }
15864 
15865 /** returns the variable's VSIDS score */
15867  SCIP_VAR* var, /**< problem variable */
15868  SCIP_STAT* stat, /**< problem statistics */
15869  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15870  )
15871 {
15872  assert(var != NULL);
15873  assert(stat != NULL);
15874  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15875 
15877  return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
15878 
15879  switch( SCIPvarGetStatus(var) )
15880  {
15882  if( var->data.original.transvar == NULL )
15883  return 0.0;
15884  else
15885  return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
15886 
15887  case SCIP_VARSTATUS_LOOSE:
15888  case SCIP_VARSTATUS_COLUMN:
15889  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE); /* column case already handled in if condition above */
15890  return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
15891 
15892  case SCIP_VARSTATUS_FIXED:
15893  return 0.0;
15894 
15896  if( var->data.aggregate.scalar > 0.0 )
15897  return SCIPvarGetVSIDS(var->data.aggregate.var, stat, dir);
15898  else
15899  /* coverity[overrun-local] */
15900  return SCIPvarGetVSIDS(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
15901 
15903  return 0.0;
15904 
15906  /* coverity[overrun-local] */
15907  return SCIPvarGetVSIDS(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15908 
15909  default:
15910  SCIPerrorMessage("unknown variable status\n");
15911  SCIPABORT();
15912  return 0.0; /*lint !e527*/
15913  }
15914 }
15915 
15916 /** returns the variable's VSIDS score only using conflicts of the current run */
15918  SCIP_VAR* var, /**< problem variable */
15919  SCIP_STAT* stat, /**< problem statistics */
15920  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15921  )
15922 {
15923  assert(var != NULL);
15924  assert(stat != NULL);
15925  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15926 
15927  if( dir != SCIP_BRANCHDIR_DOWNWARDS && dir != SCIP_BRANCHDIR_UPWARDS )
15928  {
15929  SCIPerrorMessage("invalid branching direction %d when asking for VSIDS value\n", dir);
15930  return SCIP_INVALID;
15931  }
15932 
15933  switch( SCIPvarGetStatus(var) )
15934  {
15936  if( var->data.original.transvar == NULL )
15937  return 0.0;
15938  else
15939  return SCIPvarGetVSIDSCurrentRun(var->data.original.transvar, stat, dir);
15940 
15941  case SCIP_VARSTATUS_LOOSE:
15942  case SCIP_VARSTATUS_COLUMN:
15943  return SCIPhistoryGetVSIDS(var->historycrun, dir)/stat->vsidsweight;
15944 
15945  case SCIP_VARSTATUS_FIXED:
15946  return 0.0;
15947 
15949  if( var->data.aggregate.scalar > 0.0 )
15950  return SCIPvarGetVSIDSCurrentRun(var->data.aggregate.var, stat, dir);
15951  else
15953 
15955  return 0.0;
15956 
15959 
15960  default:
15961  SCIPerrorMessage("unknown variable status\n");
15962  SCIPABORT();
15963  return 0.0; /*lint !e527*/
15964  }
15965 }
15966 
15967 /** returns the number of inferences branching on this variable in given direction triggered */
15969  SCIP_VAR* var, /**< problem variable */
15970  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15971  )
15972 {
15973  assert(var != NULL);
15974  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15975 
15976  switch( SCIPvarGetStatus(var) )
15977  {
15979  if( var->data.original.transvar == NULL )
15980  return 0.0;
15981  else
15982  return SCIPvarGetInferenceSum(var->data.original.transvar, dir);
15983 
15984  case SCIP_VARSTATUS_LOOSE:
15985  case SCIP_VARSTATUS_COLUMN:
15986  return SCIPhistoryGetInferenceSum(var->history, dir);
15987 
15988  case SCIP_VARSTATUS_FIXED:
15989  return 0.0;
15990 
15992  if( var->data.aggregate.scalar > 0.0 )
15993  return SCIPvarGetInferenceSum(var->data.aggregate.var, dir);
15994  else
15996 
15998  return 0.0;
15999 
16002 
16003  default:
16004  SCIPerrorMessage("unknown variable status\n");
16005  SCIPABORT();
16006  return 0.0; /*lint !e527*/
16007  }
16008 }
16009 
16010 /** returns the number of inferences branching on this variable in given direction triggered
16011  * in the current run
16012  */
16014  SCIP_VAR* var, /**< problem variable */
16015  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16016  )
16017 {
16018  assert(var != NULL);
16019  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16020 
16021  switch( SCIPvarGetStatus(var) )
16022  {
16024  if( var->data.original.transvar == NULL )
16025  return 0.0;
16026  else
16028 
16029  case SCIP_VARSTATUS_LOOSE:
16030  case SCIP_VARSTATUS_COLUMN:
16031  return SCIPhistoryGetInferenceSum(var->historycrun, dir);
16032 
16033  case SCIP_VARSTATUS_FIXED:
16034  return 0.0;
16035 
16037  if( var->data.aggregate.scalar > 0.0 )
16039  else
16041 
16043  return 0.0;
16044 
16047 
16048  default:
16049  SCIPerrorMessage("unknown variable status\n");
16050  SCIPABORT();
16051  return 0.0; /*lint !e527*/
16052  }
16053 }
16054 
16055 /** returns the average number of inferences found after branching on the variable in given direction */
16057  SCIP_VAR* var, /**< problem variable */
16058  SCIP_STAT* stat, /**< problem statistics */
16059  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16060  )
16061 {
16062  assert(var != NULL);
16063  assert(stat != NULL);
16064  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16065 
16066  switch( SCIPvarGetStatus(var) )
16067  {
16069  if( var->data.original.transvar == NULL )
16070  return SCIPhistoryGetAvgInferences(stat->glbhistory, dir);
16071  else
16072  return SCIPvarGetAvgInferences(var->data.original.transvar, stat, dir);
16073 
16074  case SCIP_VARSTATUS_LOOSE:
16075  case SCIP_VARSTATUS_COLUMN:
16076  if( SCIPhistoryGetNBranchings(var->history, dir) > 0 )
16077  return SCIPhistoryGetAvgInferences(var->history, dir);
16078  else
16079  {
16080  int nimpls;
16081  int ncliques;
16082 
16083  nimpls = SCIPvarGetNImpls(var, dir == SCIP_BRANCHDIR_UPWARDS);
16084  ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
16085  return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistory, dir); /*lint !e790*/
16086  }
16087 
16088  case SCIP_VARSTATUS_FIXED:
16089  return 0.0;
16090 
16092  if( var->data.aggregate.scalar > 0.0 )
16093  return SCIPvarGetAvgInferences(var->data.aggregate.var, stat, dir);
16094  else
16096 
16098  return 0.0;
16099 
16101  return SCIPvarGetAvgInferences(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
16102 
16103  default:
16104  SCIPerrorMessage("unknown variable status\n");
16105  SCIPABORT();
16106  return 0.0; /*lint !e527*/
16107  }
16108 }
16109 
16110 /** returns the average number of inferences found after branching on the variable in given direction
16111  * in the current run
16112  */
16114  SCIP_VAR* var, /**< problem variable */
16115  SCIP_STAT* stat, /**< problem statistics */
16116  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16117  )
16118 {
16119  assert(var != NULL);
16120  assert(stat != NULL);
16121  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16122 
16123  switch( SCIPvarGetStatus(var) )
16124  {
16126  if( var->data.original.transvar == NULL )
16127  return SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir);
16128  else
16129  return SCIPvarGetAvgInferencesCurrentRun(var->data.original.transvar, stat, dir);
16130 
16131  case SCIP_VARSTATUS_LOOSE:
16132  case SCIP_VARSTATUS_COLUMN:
16133  if( SCIPhistoryGetNBranchings(var->historycrun, dir) > 0 )
16134  return SCIPhistoryGetAvgInferences(var->historycrun, dir);
16135  else
16136  {
16137  int nimpls;
16138  int ncliques;
16139 
16140  nimpls = SCIPvarGetNImpls(var, dir == SCIP_BRANCHDIR_UPWARDS);
16141  ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
16142  return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir); /*lint !e790*/
16143  }
16144 
16145  case SCIP_VARSTATUS_FIXED:
16146  return 0.0;
16147 
16149  if( var->data.aggregate.scalar > 0.0 )
16150  return SCIPvarGetAvgInferencesCurrentRun(var->data.aggregate.var, stat, dir);
16151  else
16153 
16155  return 0.0;
16156 
16159 
16160  default:
16161  SCIPerrorMessage("unknown variable status\n");
16162  SCIPABORT();
16163  return 0.0; /*lint !e527*/
16164  }
16165 }
16166 
16167 /** returns the number of cutoffs branching on this variable in given direction produced */
16169  SCIP_VAR* var, /**< problem variable */
16170  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16171  )
16172 {
16173  assert(var != NULL);
16174  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16175 
16176  switch( SCIPvarGetStatus(var) )
16177  {
16179  if( var->data.original.transvar == NULL )
16180  return 0;
16181  else
16182  return SCIPvarGetCutoffSum(var->data.original.transvar, dir);
16183 
16184  case SCIP_VARSTATUS_LOOSE:
16185  case SCIP_VARSTATUS_COLUMN:
16186  return SCIPhistoryGetCutoffSum(var->history, dir);
16187 
16188  case SCIP_VARSTATUS_FIXED:
16189  return 0;
16190 
16192  if( var->data.aggregate.scalar > 0.0 )
16193  return SCIPvarGetCutoffSum(var->data.aggregate.var, dir);
16194  else
16196 
16198  return 0;
16199 
16202 
16203  default:
16204  SCIPerrorMessage("unknown variable status\n");
16205  SCIPABORT();
16206  return 0; /*lint !e527*/
16207  }
16208 }
16209 
16210 /** returns the number of cutoffs branching on this variable in given direction produced in the current run */
16212  SCIP_VAR* var, /**< problem variable */
16213  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16214  )
16215 {
16216  assert(var != NULL);
16217  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16218 
16219  switch( SCIPvarGetStatus(var) )
16220  {
16222  if( var->data.original.transvar == NULL )
16223  return 0;
16224  else
16226 
16227  case SCIP_VARSTATUS_LOOSE:
16228  case SCIP_VARSTATUS_COLUMN:
16229  return SCIPhistoryGetCutoffSum(var->historycrun, dir);
16230 
16231  case SCIP_VARSTATUS_FIXED:
16232  return 0;
16233 
16235  if( var->data.aggregate.scalar > 0.0 )
16236  return SCIPvarGetCutoffSumCurrentRun(var->data.aggregate.var, dir);
16237  else
16239 
16241  return 0;
16242 
16245 
16246  default:
16247  SCIPerrorMessage("unknown variable status\n");
16248  SCIPABORT();
16249  return 0; /*lint !e527*/
16250  }
16251 }
16252 
16253 /** returns the average number of cutoffs found after branching on the variable in given direction */
16255  SCIP_VAR* var, /**< problem variable */
16256  SCIP_STAT* stat, /**< problem statistics */
16257  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16258  )
16259 {
16260  assert(var != NULL);
16261  assert(stat != NULL);
16262  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16263 
16264  switch( SCIPvarGetStatus(var) )
16265  {
16267  if( var->data.original.transvar == NULL )
16268  return SCIPhistoryGetAvgCutoffs(stat->glbhistory, dir);
16269  else
16270  return SCIPvarGetAvgCutoffs(var->data.original.transvar, stat, dir);
16271 
16272  case SCIP_VARSTATUS_LOOSE:
16273  case SCIP_VARSTATUS_COLUMN:
16274  return SCIPhistoryGetNBranchings(var->history, dir) > 0
16275  ? SCIPhistoryGetAvgCutoffs(var->history, dir)
16276  : SCIPhistoryGetAvgCutoffs(stat->glbhistory, dir);
16277 
16278  case SCIP_VARSTATUS_FIXED:
16279  return 0.0;
16280 
16282  if( var->data.aggregate.scalar > 0.0 )
16283  return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, dir);
16284  else
16285  return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
16286 
16288  return 0.0;
16289 
16291  return SCIPvarGetAvgCutoffs(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
16292 
16293  default:
16294  SCIPerrorMessage("unknown variable status\n");
16295  SCIPABORT();
16296  return 0.0; /*lint !e527*/
16297  }
16298 }
16299 
16300 /** returns the average number of cutoffs found after branching on the variable in given direction in the current run */
16302  SCIP_VAR* var, /**< problem variable */
16303  SCIP_STAT* stat, /**< problem statistics */
16304  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16305  )
16306 {
16307  assert(var != NULL);
16308  assert(stat != NULL);
16309  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16310 
16311  switch( SCIPvarGetStatus(var) )
16312  {
16314  if( var->data.original.transvar == NULL )
16315  return SCIPhistoryGetAvgCutoffs(stat->glbhistorycrun, dir);
16316  else
16317  return SCIPvarGetAvgCutoffsCurrentRun(var->data.original.transvar, stat, dir);
16318 
16319  case SCIP_VARSTATUS_LOOSE:
16320  case SCIP_VARSTATUS_COLUMN:
16321  return SCIPhistoryGetNBranchings(var->historycrun, dir) > 0
16324 
16325  case SCIP_VARSTATUS_FIXED:
16326  return 0.0;
16327 
16329  if( var->data.aggregate.scalar > 0.0 )
16330  return SCIPvarGetAvgCutoffsCurrentRun(var->data.aggregate.var, stat, dir);
16331  else
16333 
16335  return 0.0;
16336 
16339 
16340  default:
16341  SCIPerrorMessage("unknown variable status\n");
16342  SCIPABORT();
16343  return 0.0; /*lint !e527*/
16344  }
16345 }
16346 
16347 
16348 
16349 
16350 /*
16351  * information methods for bound changes
16352  */
16353 
16354 /** creates an artificial bound change information object with depth = INT_MAX and pos = -1 */
16356  SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
16357  BMS_BLKMEM* blkmem, /**< block memory */
16358  SCIP_VAR* var, /**< active variable that changed the bounds */
16359  SCIP_BOUNDTYPE boundtype, /**< type of bound for var: lower or upper bound */
16360  SCIP_Real oldbound, /**< old value for bound */
16361  SCIP_Real newbound /**< new value for bound */
16362  )
16363 {
16364  assert(bdchginfo != NULL);
16365 
16366  SCIP_ALLOC( BMSallocBlockMemory(blkmem, bdchginfo) );
16367  (*bdchginfo)->oldbound = oldbound;
16368  (*bdchginfo)->newbound = newbound;
16369  (*bdchginfo)->var = var;
16370  (*bdchginfo)->inferencedata.var = var;
16371  (*bdchginfo)->inferencedata.reason.prop = NULL;
16372  (*bdchginfo)->inferencedata.info = 0;
16373  (*bdchginfo)->bdchgidx.depth = INT_MAX;
16374  (*bdchginfo)->bdchgidx.pos = -1;
16375  (*bdchginfo)->pos = 0;
16376  (*bdchginfo)->boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
16377  (*bdchginfo)->boundtype = boundtype; /*lint !e641*/
16378  (*bdchginfo)->inferboundtype = boundtype; /*lint !e641*/
16379  (*bdchginfo)->redundant = FALSE;
16380 
16381  return SCIP_OKAY;
16382 }
16383 
16384 /** frees a bound change information object */
16385 void SCIPbdchginfoFree(
16386  SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
16387  BMS_BLKMEM* blkmem /**< block memory */
16388  )
16389 {
16390  assert(bdchginfo != NULL);
16391 
16392  BMSfreeBlockMemory(blkmem, bdchginfo);
16393 }
16394 
16395 /** returns the bound change information for the last lower bound change on given active problem variable before or
16396  * after the bound change with the given index was applied;
16397  * returns NULL, if no change to the lower bound was applied up to this point of time
16398  */
16400  SCIP_VAR* var, /**< active problem variable */
16401  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16402  SCIP_Bool after /**< should the bound change with given index be included? */
16403  )
16404 {
16405  int i;
16406 
16407  assert(var != NULL);
16408  assert(SCIPvarIsActive(var));
16409 
16410  /* search the correct bound change information for the given bound change index */
16411  if( after )
16412  {
16413  for( i = var->nlbchginfos-1; i >= 0; --i )
16414  {
16415  assert(var->lbchginfos[i].var == var);
16417  assert(var->lbchginfos[i].pos == i);
16418 
16419  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16420  if( var->lbchginfos[i].redundant )
16421  return NULL;
16422  assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
16423 
16424  /* if we reached the bound change index, return the current bound change info */
16425  if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->lbchginfos[i].bdchgidx) )
16426  return &var->lbchginfos[i];
16427  }
16428  }
16429  else
16430  {
16431  for( i = var->nlbchginfos-1; i >= 0; --i )
16432  {
16433  assert(var->lbchginfos[i].var == var);
16435  assert(var->lbchginfos[i].pos == i);
16436 
16437  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16438  if( var->lbchginfos[i].redundant )
16439  return NULL;
16440  assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
16441 
16442  /* if we reached the bound change index, return the current bound change info */
16443  if( SCIPbdchgidxIsEarlier(&var->lbchginfos[i].bdchgidx, bdchgidx) )
16444  return &var->lbchginfos[i];
16445  }
16446  }
16447 
16448  return NULL;
16449 }
16450 
16451 /** returns the bound change information for the last upper bound change on given active problem variable before or
16452  * after the bound change with the given index was applied;
16453  * returns NULL, if no change to the upper bound was applied up to this point of time
16454  */
16456  SCIP_VAR* var, /**< active problem variable */
16457  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16458  SCIP_Bool after /**< should the bound change with given index be included? */
16459  )
16460 {
16461  int i;
16462 
16463  assert(var != NULL);
16464  assert(SCIPvarIsActive(var));
16465 
16466  /* search the correct bound change information for the given bound change index */
16467  if( after )
16468  {
16469  for( i = var->nubchginfos-1; i >= 0; --i )
16470  {
16471  assert(var->ubchginfos[i].var == var);
16473  assert(var->ubchginfos[i].pos == i);
16474 
16475  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16476  if( var->ubchginfos[i].redundant )
16477  return NULL;
16478  assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
16479 
16480  /* if we reached the bound change index, return the current bound change info */
16481  if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->ubchginfos[i].bdchgidx) )
16482  return &var->ubchginfos[i];
16483  }
16484  }
16485  else
16486  {
16487  for( i = var->nubchginfos-1; i >= 0; --i )
16488  {
16489  assert(var->ubchginfos[i].var == var);
16491  assert(var->ubchginfos[i].pos == i);
16492 
16493  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16494  if( var->ubchginfos[i].redundant )
16495  return NULL;
16496  assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
16497 
16498  /* if we reached the bound change index, return the current bound change info */
16499  if( SCIPbdchgidxIsEarlier(&var->ubchginfos[i].bdchgidx, bdchgidx) )
16500  return &var->ubchginfos[i];
16501  }
16502  }
16503 
16504  return NULL;
16505 }
16506 
16507 /** returns the bound change information for the last lower or upper bound change on given active problem variable
16508  * before or after the bound change with the given index was applied;
16509  * returns NULL, if no change to the lower/upper bound was applied up to this point of time
16510  */
16512  SCIP_VAR* var, /**< active problem variable */
16513  SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
16514  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16515  SCIP_Bool after /**< should the bound change with given index be included? */
16516  )
16517 {
16518  if( boundtype == SCIP_BOUNDTYPE_LOWER )
16519  return SCIPvarGetLbchgInfo(var, bdchgidx, after);
16520  else
16521  {
16522  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16523  return SCIPvarGetUbchgInfo(var, bdchgidx, after);
16524  }
16525 }
16526 
16527 /** returns lower bound of variable directly before or after the bound change given by the bound change index
16528  * was applied
16529  *
16530  * @deprecated Please use SCIPgetVarLbAtIndex()
16531  */
16533  SCIP_VAR* var, /**< problem variable */
16534  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16535  SCIP_Bool after /**< should the bound change with given index be included? */
16536  )
16537 {
16538  SCIP_VARSTATUS varstatus;
16539  assert(var != NULL);
16540 
16541  varstatus = SCIPvarGetStatus(var);
16542 
16543  /* get bounds of attached variables */
16544  switch( varstatus )
16545  {
16547  assert(var->data.original.transvar != NULL);
16548  return SCIPvarGetLbAtIndex(var->data.original.transvar, bdchgidx, after);
16549 
16550  case SCIP_VARSTATUS_LOOSE:
16551  case SCIP_VARSTATUS_COLUMN:
16552  if( bdchgidx == NULL )
16553  return SCIPvarGetLbLocal(var);
16554  else
16555  {
16556  SCIP_BDCHGINFO* bdchginfo;
16557 
16558  bdchginfo = SCIPvarGetLbchgInfo(var, bdchgidx, after);
16559  if( bdchginfo != NULL )
16560  return SCIPbdchginfoGetNewbound(bdchginfo);
16561  else
16562  return var->glbdom.lb;
16563  }
16564  case SCIP_VARSTATUS_FIXED:
16565  return var->glbdom.lb;
16566 
16567  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
16568  assert(var->data.aggregate.var != NULL);
16569  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
16570  * corresponding infinity value instead of performing an arithmetical transformation (compare method
16571  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
16572  * (or is called by) a public interface method; instead, we only assert that values are finite
16573  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
16574  * positives and negatives if the parameter <numerics/infinity> is modified by the user
16575  */
16576  if( var->data.aggregate.scalar > 0.0 )
16577  {
16578  /* a > 0 -> get lower bound of y */
16579  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16580  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16581  return var->data.aggregate.scalar * SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after)
16582  + var->data.aggregate.constant;
16583  }
16584  else if( var->data.aggregate.scalar < 0.0 )
16585  {
16586  /* a < 0 -> get upper bound of y */
16587  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16588  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16589  return var->data.aggregate.scalar * SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after)
16590  + var->data.aggregate.constant;
16591  }
16592  else
16593  {
16594  SCIPerrorMessage("scalar is zero in aggregation\n");
16595  SCIPABORT();
16596  return SCIP_INVALID; /*lint !e527*/
16597  }
16598 
16600  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
16601  if ( var->data.multaggr.nvars == 1 )
16602  {
16603  assert(var->data.multaggr.vars != NULL);
16604  assert(var->data.multaggr.scalars != NULL);
16605  assert(var->data.multaggr.vars[0] != NULL);
16606 
16607  if( var->data.multaggr.scalars[0] > 0.0 )
16608  {
16609  /* a > 0 -> get lower bound of y */
16610  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16611  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16612  return var->data.multaggr.scalars[0] * SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16613  + var->data.multaggr.constant;
16614  }
16615  else if( var->data.multaggr.scalars[0] < 0.0 )
16616  {
16617  /* a < 0 -> get upper bound of y */
16618  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16619  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16620  return var->data.multaggr.scalars[0] * SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16621  + var->data.multaggr.constant;
16622  }
16623  else
16624  {
16625  SCIPerrorMessage("scalar is zero in multi-aggregation\n");
16626  SCIPABORT();
16627  return SCIP_INVALID; /*lint !e527*/
16628  }
16629  }
16630  SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
16631  SCIPABORT();
16632  return SCIP_INVALID; /*lint !e527*/
16633 
16634  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
16635  assert(var->negatedvar != NULL);
16637  assert(var->negatedvar->negatedvar == var);
16638  return var->data.negate.constant - SCIPvarGetUbAtIndex(var->negatedvar, bdchgidx, after);
16639  default:
16640  SCIPerrorMessage("unknown variable status\n");
16641  SCIPABORT();
16642  return SCIP_INVALID; /*lint !e527*/
16643  }
16644 }
16645 
16646 /** returns upper bound of variable directly before or after the bound change given by the bound change index
16647  * was applied
16648  *
16649  * @deprecated Please use SCIPgetVarUbAtIndex()
16650  */
16652  SCIP_VAR* var, /**< problem variable */
16653  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16654  SCIP_Bool after /**< should the bound change with given index be included? */
16655  )
16656 {
16657  SCIP_VARSTATUS varstatus;
16658  assert(var != NULL);
16659 
16660  varstatus = SCIPvarGetStatus(var);
16661 
16662  /* get bounds of attached variables */
16663  switch( varstatus )
16664  {
16666  assert(var->data.original.transvar != NULL);
16667  return SCIPvarGetUbAtIndex(var->data.original.transvar, bdchgidx, after);
16668 
16669  case SCIP_VARSTATUS_COLUMN:
16670  case SCIP_VARSTATUS_LOOSE:
16671  if( bdchgidx == NULL )
16672  return SCIPvarGetUbLocal(var);
16673  else
16674  {
16675  SCIP_BDCHGINFO* bdchginfo;
16676 
16677  bdchginfo = SCIPvarGetUbchgInfo(var, bdchgidx, after);
16678  if( bdchginfo != NULL )
16679  return SCIPbdchginfoGetNewbound(bdchginfo);
16680  else
16681  return var->glbdom.ub;
16682  }
16683 
16684  case SCIP_VARSTATUS_FIXED:
16685  return var->glbdom.ub;
16686 
16687  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
16688  assert(var->data.aggregate.var != NULL);
16689  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
16690  * corresponding infinity value instead of performing an arithmetical transformation (compare method
16691  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
16692  * (or is called by) a public interface method; instead, we only assert that values are finite
16693  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
16694  * positives and negatives if the parameter <numerics/infinity> is modified by the user
16695  */
16696  if( var->data.aggregate.scalar > 0.0 )
16697  {
16698  /* a > 0 -> get lower bound of y */
16699  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16700  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16701  return var->data.aggregate.scalar * SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after)
16702  + var->data.aggregate.constant;
16703  }
16704  else if( var->data.aggregate.scalar < 0.0 )
16705  {
16706  /* a < 0 -> get upper bound of y */
16707  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16708  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16709  return var->data.aggregate.scalar * SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after)
16710  + var->data.aggregate.constant;
16711  }
16712  else
16713  {
16714  SCIPerrorMessage("scalar is zero in aggregation\n");
16715  SCIPABORT();
16716  return SCIP_INVALID; /*lint !e527*/
16717  }
16718 
16720  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
16721  if ( var->data.multaggr.nvars == 1 )
16722  {
16723  assert(var->data.multaggr.vars != NULL);
16724  assert(var->data.multaggr.scalars != NULL);
16725  assert(var->data.multaggr.vars[0] != NULL);
16726 
16727  if( var->data.multaggr.scalars[0] > 0.0 )
16728  {
16729  /* a > 0 -> get lower bound of y */
16730  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16731  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16732  return var->data.multaggr.scalars[0] * SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16733  + var->data.multaggr.constant;
16734  }
16735  else if( var->data.multaggr.scalars[0] < 0.0 )
16736  {
16737  /* a < 0 -> get upper bound of y */
16738  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16739  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16740  return var->data.multaggr.scalars[0] * SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16741  + var->data.multaggr.constant;
16742  }
16743  else
16744  {
16745  SCIPerrorMessage("scalar is zero in multi-aggregation\n");
16746  SCIPABORT();
16747  return SCIP_INVALID; /*lint !e527*/
16748  }
16749  }
16750  SCIPerrorMessage("cannot get the bounds of a multiple aggregated variable.\n");
16751  SCIPABORT();
16752  return SCIP_INVALID; /*lint !e527*/
16753 
16754  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
16755  assert(var->negatedvar != NULL);
16757  assert(var->negatedvar->negatedvar == var);
16758  return var->data.negate.constant - SCIPvarGetLbAtIndex(var->negatedvar, bdchgidx, after);
16759 
16760  default:
16761  SCIPerrorMessage("unknown variable status\n");
16762  SCIPABORT();
16763  return SCIP_INVALID; /*lint !e527*/
16764  }
16765 }
16766 
16767 /** returns lower or upper bound of variable directly before or after the bound change given by the bound change index
16768  * was applied
16769  *
16770  * @deprecated Please use SCIPgetVarBdAtIndex()
16771  */
16773  SCIP_VAR* var, /**< problem variable */
16774  SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
16775  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16776  SCIP_Bool after /**< should the bound change with given index be included? */
16777  )
16778 {
16779  if( boundtype == SCIP_BOUNDTYPE_LOWER )
16780  return SCIPvarGetLbAtIndex(var, bdchgidx, after);
16781  else
16782  {
16783  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16784  return SCIPvarGetUbAtIndex(var, bdchgidx, after);
16785  }
16786 }
16787 
16788 /** returns whether the binary variable was fixed at the time given by the bound change index
16789  *
16790  * @deprecated Please use SCIPgetVarWasFixedAtIndex()
16791  */
16793  SCIP_VAR* var, /**< problem variable */
16794  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16795  SCIP_Bool after /**< should the bound change with given index be included? */
16796  )
16797 {
16798  assert(var != NULL);
16799  assert(SCIPvarIsBinary(var));
16800 
16801  /* check the current bounds first in order to decide at which bound change information we have to look
16802  * (which is expensive because we have to follow the aggregation tree to the active variable)
16803  */
16804  return ((SCIPvarGetLbLocal(var) > 0.5 && SCIPvarGetLbAtIndex(var, bdchgidx, after) > 0.5)
16805  || (SCIPvarGetUbLocal(var) < 0.5 && SCIPvarGetUbAtIndex(var, bdchgidx, after) < 0.5));
16806 }
16807 
16808 /** bound change index representing the initial time before any bound changes took place */
16809 static SCIP_BDCHGIDX initbdchgidx = {-2, 0};
16811 /** bound change index representing the presolving stage */
16812 static SCIP_BDCHGIDX presolvebdchgidx = {-1, 0};
16814 /** returns the last bound change index, at which the bounds of the given variable were tightened */
16816  SCIP_VAR* var /**< problem variable */
16817  )
16818 {
16819  SCIP_BDCHGIDX* lbchgidx;
16820  SCIP_BDCHGIDX* ubchgidx;
16821 
16822  assert(var != NULL);
16823 
16824  var = SCIPvarGetProbvar(var);
16825 
16826  /* check, if variable is original without transformed variable */
16827  if( var == NULL )
16828  return &initbdchgidx;
16829 
16830  /* check, if variable was fixed in presolving */
16831  if( !SCIPvarIsActive(var) )
16832  return &presolvebdchgidx;
16833 
16835 
16836  /* get depths of last bound change information for the lower and upper bound */
16837  lbchgidx = (var->nlbchginfos > 0 && !var->lbchginfos[var->nlbchginfos-1].redundant
16838  ? &var->lbchginfos[var->nlbchginfos-1].bdchgidx : &initbdchgidx);
16839  ubchgidx = (var->nubchginfos > 0 && !var->ubchginfos[var->nubchginfos-1].redundant
16840  ? &var->ubchginfos[var->nubchginfos-1].bdchgidx : &initbdchgidx);
16841 
16842  if( SCIPbdchgidxIsEarlierNonNull(lbchgidx, ubchgidx) )
16843  return ubchgidx;
16844  else
16845  return lbchgidx;
16846 }
16847 
16848 /** returns the last depth level, at which the bounds of the given variable were tightened;
16849  * returns -2, if the variable's bounds are still the global bounds
16850  * returns -1, if the variable was fixed in presolving
16851  */
16853  SCIP_VAR* var /**< problem variable */
16854  )
16855 {
16856  SCIP_BDCHGIDX* bdchgidx;
16857 
16858  bdchgidx = SCIPvarGetLastBdchgIndex(var);
16859  assert(bdchgidx != NULL);
16860 
16861  return bdchgidx->depth;
16862 }
16863 
16864 /** returns at which depth in the tree a bound change was applied to the variable that conflicts with the
16865  * given bound; returns -1 if the bound does not conflict with the current local bounds of the variable
16866  */
16868  SCIP_VAR* var, /**< problem variable */
16869  SCIP_SET* set, /**< global SCIP settings */
16870  SCIP_BOUNDTYPE boundtype, /**< bound type of the conflicting bound */
16871  SCIP_Real bound /**< conflicting bound */
16872  )
16873 {
16874  int i;
16875 
16876  assert(var != NULL);
16877  assert(set != NULL);
16878  assert(var->scip == set->scip);
16879 
16880  if( boundtype == SCIP_BOUNDTYPE_LOWER )
16881  {
16882  /* check if the bound is in conflict with the current local bounds */
16883  if( SCIPsetIsLE(set, bound, var->locdom.ub) )
16884  return -1;
16885 
16886  /* check if the bound is in conflict with the global bound */
16887  if( SCIPsetIsGT(set, bound, var->glbdom.ub) )
16888  return 0;
16889 
16890  /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
16891  assert(var->nubchginfos > 0);
16892  assert(SCIPsetIsGT(set, bound, var->ubchginfos[var->nubchginfos-1].newbound));
16893 
16894  /* search for the first conflicting bound change */
16895  for( i = var->nubchginfos-1; i > 0 && SCIPsetIsGT(set, bound, var->ubchginfos[i-1].newbound); --i )
16896  {
16897  assert(var->ubchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
16899  }
16900  assert(SCIPsetIsGT(set, bound, var->ubchginfos[i].newbound)); /* bound change i is conflicting */
16901  assert(i == 0 || SCIPsetIsLE(set, bound, var->ubchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
16902 
16903  /* return the depth at which the first conflicting bound change took place */
16904  return var->ubchginfos[i].bdchgidx.depth;
16905  }
16906  else
16907  {
16908  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16909 
16910  /* check if the bound is in conflict with the current local bounds */
16911  if( SCIPsetIsGE(set, bound, var->locdom.lb) )
16912  return -1;
16913 
16914  /* check if the bound is in conflict with the global bound */
16915  if( SCIPsetIsLT(set, bound, var->glbdom.lb) )
16916  return 0;
16917 
16918  /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
16919  assert(var->nlbchginfos > 0);
16920  assert(SCIPsetIsLT(set, bound, var->lbchginfos[var->nlbchginfos-1].newbound));
16921 
16922  /* search for the first conflicting bound change */
16923  for( i = var->nlbchginfos-1; i > 0 && SCIPsetIsLT(set, bound, var->lbchginfos[i-1].newbound); --i )
16924  {
16925  assert(var->lbchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
16927  }
16928  assert(SCIPsetIsLT(set, bound, var->lbchginfos[i].newbound)); /* bound change i is conflicting */
16929  assert(i == 0 || SCIPsetIsGE(set, bound, var->lbchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
16930 
16931  /* return the depth at which the first conflicting bound change took place */
16932  return var->lbchginfos[i].bdchgidx.depth;
16933  }
16934 }
16935 
16936 /** returns whether the first binary variable was fixed earlier than the second one;
16937  * returns FALSE, if the first variable is not fixed, and returns TRUE, if the first variable is fixed, but the
16938  * second one is not fixed
16939  */
16941  SCIP_VAR* var1, /**< first binary variable */
16942  SCIP_VAR* var2 /**< second binary variable */
16943  )
16944 {
16945  SCIP_BDCHGIDX* bdchgidx1;
16946  SCIP_BDCHGIDX* bdchgidx2;
16947 
16948  assert(var1 != NULL);
16949  assert(var2 != NULL);
16950  assert(SCIPvarIsBinary(var1));
16951  assert(SCIPvarIsBinary(var2));
16952 
16953  var1 = SCIPvarGetProbvar(var1);
16954  var2 = SCIPvarGetProbvar(var2);
16955  assert(var1 != NULL);
16956  assert(var2 != NULL);
16957 
16958  /* check, if variables are globally fixed */
16959  if( !SCIPvarIsActive(var2) || var2->glbdom.lb > 0.5 || var2->glbdom.ub < 0.5 )
16960  return FALSE;
16961  if( !SCIPvarIsActive(var1) || var1->glbdom.lb > 0.5 || var1->glbdom.ub < 0.5 )
16962  return TRUE;
16963 
16966  assert(SCIPvarIsBinary(var1));
16967  assert(SCIPvarIsBinary(var2));
16968  assert(var1->nlbchginfos + var1->nubchginfos <= 1);
16969  assert(var2->nlbchginfos + var2->nubchginfos <= 1);
16970  assert(var1->nlbchginfos == 0 || !var1->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
16971  assert(var1->nubchginfos == 0 || !var1->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
16972  assert(var2->nlbchginfos == 0 || !var2->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
16973  assert(var2->nubchginfos == 0 || !var2->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
16974 
16975  if( var1->nlbchginfos == 1 )
16976  bdchgidx1 = &var1->lbchginfos[0].bdchgidx;
16977  else if( var1->nubchginfos == 1 )
16978  bdchgidx1 = &var1->ubchginfos[0].bdchgidx;
16979  else
16980  bdchgidx1 = NULL;
16981 
16982  if( var2->nlbchginfos == 1 )
16983  bdchgidx2 = &var2->lbchginfos[0].bdchgidx;
16984  else if( var2->nubchginfos == 1 )
16985  bdchgidx2 = &var2->ubchginfos[0].bdchgidx;
16986  else
16987  bdchgidx2 = NULL;
16988 
16989  return SCIPbdchgidxIsEarlier(bdchgidx1, bdchgidx2);
16990 }
16991 
16992 
16993 
16994 /*
16995  * Hash functions
16996  */
16997 
16998 /** gets the key (i.e. the name) of the given variable */
16999 SCIP_DECL_HASHGETKEY(SCIPhashGetKeyVar)
17000 { /*lint --e{715}*/
17001  SCIP_VAR* var = (SCIP_VAR*)elem;
17002 
17003  assert(var != NULL);
17004  return var->name;
17005 }
17006 
17007 
17008 
17009 
17010 /*
17011  * simple functions implemented as defines
17012  */
17013 
17014 /* In debug mode, the following methods are implemented as function calls to ensure
17015  * type validity.
17016  * In optimized mode, the methods are implemented as defines to improve performance.
17017  * However, we want to have them in the library anyways, so we have to undef the defines.
17018  */
17019 
17020 #undef SCIPboundchgGetNewbound
17021 #undef SCIPboundchgGetVar
17022 #undef SCIPboundchgGetBoundchgtype
17023 #undef SCIPboundchgGetBoundtype
17024 #undef SCIPboundchgIsRedundant
17025 #undef SCIPdomchgGetNBoundchgs
17026 #undef SCIPdomchgGetBoundchg
17027 #undef SCIPholelistGetLeft
17028 #undef SCIPholelistGetRight
17029 #undef SCIPholelistGetNext
17030 #undef SCIPvarGetName
17031 #undef SCIPvarGetNUses
17032 #undef SCIPvarGetData
17033 #undef SCIPvarSetData
17034 #undef SCIPvarSetDelorigData
17035 #undef SCIPvarSetTransData
17036 #undef SCIPvarSetDeltransData
17037 #undef SCIPvarGetStatus
17038 #undef SCIPvarIsOriginal
17039 #undef SCIPvarIsTransformed
17040 #undef SCIPvarIsNegated
17041 #undef SCIPvarGetType
17042 #undef SCIPvarIsBinary
17043 #undef SCIPvarIsIntegral
17044 #undef SCIPvarIsInitial
17045 #undef SCIPvarIsRemovable
17046 #undef SCIPvarIsDeleted
17047 #undef SCIPvarIsDeletable
17048 #undef SCIPvarMarkDeletable
17049 #undef SCIPvarMarkNotDeletable
17050 #undef SCIPvarIsActive
17051 #undef SCIPvarGetIndex
17052 #undef SCIPvarGetProbindex
17053 #undef SCIPvarGetTransVar
17054 #undef SCIPvarGetCol
17055 #undef SCIPvarIsInLP
17056 #undef SCIPvarGetAggrVar
17057 #undef SCIPvarGetAggrScalar
17058 #undef SCIPvarGetAggrConstant
17059 #undef SCIPvarGetMultaggrNVars
17060 #undef SCIPvarGetMultaggrVars
17061 #undef SCIPvarGetMultaggrScalars
17062 #undef SCIPvarGetMultaggrConstant
17063 #undef SCIPvarGetNegatedVar
17064 #undef SCIPvarGetNegationVar
17065 #undef SCIPvarGetNegationConstant
17066 #undef SCIPvarGetObj
17067 #undef SCIPvarGetLbOriginal
17068 #undef SCIPvarGetUbOriginal
17069 #undef SCIPvarGetHolelistOriginal
17070 #undef SCIPvarGetLbGlobal
17071 #undef SCIPvarGetUbGlobal
17072 #undef SCIPvarGetHolelistGlobal
17073 #undef SCIPvarGetBestBoundGlobal
17074 #undef SCIPvarGetWorstBoundGlobal
17075 #undef SCIPvarGetLbLocal
17076 #undef SCIPvarGetUbLocal
17077 #undef SCIPvarGetHolelistLocal
17078 #undef SCIPvarGetBestBoundLocal
17079 #undef SCIPvarGetWorstBoundLocal
17080 #undef SCIPvarGetBestBoundType
17081 #undef SCIPvarGetWorstBoundType
17082 #undef SCIPvarGetLbLazy
17083 #undef SCIPvarGetUbLazy
17084 #undef SCIPvarGetBranchFactor
17085 #undef SCIPvarGetBranchPriority
17086 #undef SCIPvarGetBranchDirection
17087 #undef SCIPvarGetNVlbs
17088 #undef SCIPvarGetVlbVars
17089 #undef SCIPvarGetVlbCoefs
17090 #undef SCIPvarGetVlbConstants
17091 #undef SCIPvarGetNVubs
17092 #undef SCIPvarGetVubVars
17093 #undef SCIPvarGetVubCoefs
17094 #undef SCIPvarGetVubConstants
17095 #undef SCIPvarGetNImpls
17096 #undef SCIPvarGetImplVars
17097 #undef SCIPvarGetImplTypes
17098 #undef SCIPvarGetImplBounds
17099 #undef SCIPvarGetImplIds
17100 #undef SCIPvarGetNCliques
17101 #undef SCIPvarGetCliques
17102 #undef SCIPvarGetLPSol
17103 #undef SCIPvarGetNLPSol
17104 #undef SCIPvarGetBdchgInfoLb
17105 #undef SCIPvarGetNBdchgInfosLb
17106 #undef SCIPvarGetBdchgInfoUb
17107 #undef SCIPvarGetNBdchgInfosUb
17108 #undef SCIPvarGetValuehistory
17109 #undef SCIPvarGetPseudoSol
17110 #undef SCIPvarCatchEvent
17111 #undef SCIPvarDropEvent
17112 #undef SCIPvarGetVSIDS
17113 #undef SCIPvarGetCliqueComponentIdx
17114 #undef SCIPvarIsRelaxationOnly
17115 #undef SCIPvarMarkRelaxationOnly
17116 #undef SCIPbdchgidxGetPos
17117 #undef SCIPbdchgidxIsEarlierNonNull
17118 #undef SCIPbdchgidxIsEarlier
17119 #undef SCIPbdchginfoGetOldbound
17120 #undef SCIPbdchginfoGetNewbound
17121 #undef SCIPbdchginfoGetVar
17122 #undef SCIPbdchginfoGetChgtype
17123 #undef SCIPbdchginfoGetBoundtype
17124 #undef SCIPbdchginfoGetDepth
17125 #undef SCIPbdchginfoGetPos
17126 #undef SCIPbdchginfoGetIdx
17127 #undef SCIPbdchginfoGetInferVar
17128 #undef SCIPbdchginfoGetInferCons
17129 #undef SCIPbdchginfoGetInferProp
17130 #undef SCIPbdchginfoGetInferInfo
17131 #undef SCIPbdchginfoGetInferBoundtype
17132 #undef SCIPbdchginfoIsRedundant
17133 #undef SCIPbdchginfoHasInferenceReason
17134 #undef SCIPbdchginfoIsTighter
17135 
17136 
17137 /** returns the new value of the bound in the bound change data */
17139  SCIP_BOUNDCHG* boundchg /**< bound change data */
17140  )
17141 {
17142  assert(boundchg != NULL);
17143 
17144  return boundchg->newbound;
17145 }
17146 
17147 /** returns the variable of the bound change in the bound change data */
17149  SCIP_BOUNDCHG* boundchg /**< bound change data */
17150  )
17151 {
17152  assert(boundchg != NULL);
17153 
17154  return boundchg->var;
17155 }
17156 
17157 /** returns the bound change type of the bound change in the bound change data */
17159  SCIP_BOUNDCHG* boundchg /**< bound change data */
17160  )
17161 {
17162  assert(boundchg != NULL);
17163 
17164  return (SCIP_BOUNDCHGTYPE)(boundchg->boundchgtype);
17165 }
17166 
17167 /** returns the bound type of the bound change in the bound change data */
17169  SCIP_BOUNDCHG* boundchg /**< bound change data */
17170  )
17171 {
17172  assert(boundchg != NULL);
17173 
17174  return (SCIP_BOUNDTYPE)(boundchg->boundtype);
17175 }
17176 
17177 /** returns whether the bound change is redundant due to a more global bound that is at least as strong */
17179  SCIP_BOUNDCHG* boundchg /**< bound change data */
17180  )
17181 {
17182  assert(boundchg != NULL);
17183 
17184  return boundchg->redundant;
17185 }
17186 
17187 /** returns the number of bound changes in the domain change data */
17189  SCIP_DOMCHG* domchg /**< domain change data */
17190  )
17191 {
17192  return domchg != NULL ? domchg->domchgbound.nboundchgs : 0;
17193 }
17194 
17195 /** returns a particular bound change in the domain change data */
17197  SCIP_DOMCHG* domchg, /**< domain change data */
17198  int pos /**< position of the bound change in the domain change data */
17199  )
17200 {
17201  assert(domchg != NULL);
17202  assert(0 <= pos && pos < (int)domchg->domchgbound.nboundchgs);
17203 
17204  return &domchg->domchgbound.boundchgs[pos];
17205 }
17206 
17207 /** returns left bound of open interval in hole */
17209  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
17210  )
17211 {
17212  assert(holelist != NULL);
17213 
17214  return holelist->hole.left;
17215 }
17216 
17217 /** returns right bound of open interval in hole */
17219  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
17220  )
17221 {
17222  assert(holelist != NULL);
17223 
17224  return holelist->hole.right;
17225 }
17226 
17227 /** returns next hole in list */
17229  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
17230  )
17231 {
17232  assert(holelist != NULL);
17233 
17234  return holelist->next;
17235 }
17236 
17237 /** returns the name of the variable
17238  *
17239  * @note to change the name of a variable, use SCIPchgVarName() from scip.h
17240  */
17241 const char* SCIPvarGetName(
17242  SCIP_VAR* var /**< problem variable */
17243  )
17244 {
17245  assert(var != NULL);
17246 
17247  return var->name;
17248 }
17249 
17250 /** gets number of times, the variable is currently captured */
17251 int SCIPvarGetNUses(
17252  SCIP_VAR* var /**< problem variable */
17253  )
17254 {
17255  assert(var != NULL);
17256 
17257  return var->nuses;
17258 }
17259 
17260 /** returns the user data of the variable */
17262  SCIP_VAR* var /**< problem variable */
17263  )
17264 {
17265  assert(var != NULL);
17266 
17267  return var->vardata;
17268 }
17269 
17270 /** sets the user data for the variable */
17271 void SCIPvarSetData(
17272  SCIP_VAR* var, /**< problem variable */
17273  SCIP_VARDATA* vardata /**< user variable data */
17274  )
17275 {
17276  assert(var != NULL);
17277 
17278  var->vardata = vardata;
17279 }
17280 
17281 /** sets method to free user data for the original variable */
17283  SCIP_VAR* var, /**< problem variable */
17284  SCIP_DECL_VARDELORIG ((*vardelorig)) /**< frees user data of original variable */
17285  )
17286 {
17287  assert(var != NULL);
17288  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
17289 
17290  var->vardelorig = vardelorig;
17291 }
17292 
17293 /** sets method to transform user data of the variable */
17294 void SCIPvarSetTransData(
17295  SCIP_VAR* var, /**< problem variable */
17296  SCIP_DECL_VARTRANS ((*vartrans)) /**< creates transformed user data by transforming original user data */
17297  )
17298 {
17299  assert(var != NULL);
17300  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
17301 
17302  var->vartrans = vartrans;
17303 }
17304 
17305 /** sets method to free transformed user data for the variable */
17307  SCIP_VAR* var, /**< problem variable */
17308  SCIP_DECL_VARDELTRANS ((*vardeltrans)) /**< frees user data of transformed variable */
17309  )
17310 {
17311  assert(var != NULL);
17312 
17313  var->vardeltrans = vardeltrans;
17314 }
17315 
17316 /** sets method to copy this variable into sub-SCIPs */
17317 void SCIPvarSetCopyData(
17318  SCIP_VAR* var, /**< problem variable */
17319  SCIP_DECL_VARCOPY ((*varcopy)) /**< copy method of the variable */
17320  )
17321 {
17322  assert(var != NULL);
17323 
17324  var->varcopy = varcopy;
17325 }
17326 
17327 /** sets the initial flag of a variable; only possible for original or loose variables */
17329  SCIP_VAR* var, /**< problem variable */
17330  SCIP_Bool initial /**< initial flag */
17331  )
17332 {
17333  assert(var != NULL);
17334 
17336  return SCIP_INVALIDCALL;
17337 
17338  var->initial = initial;
17339 
17340  return SCIP_OKAY;
17341 }
17342 
17343 /** sets the removable flag of a variable; only possible for original or loose variables */
17345  SCIP_VAR* var, /**< problem variable */
17346  SCIP_Bool removable /**< removable flag */
17347  )
17348 {
17349  assert(var != NULL);
17350 
17352  return SCIP_INVALIDCALL;
17353 
17354  var->removable = removable;
17355 
17356  return SCIP_OKAY;
17357 }
17358 
17359 /** gets status of variable */
17361  SCIP_VAR* var /**< problem variable */
17362  )
17363 {
17364  assert(var != NULL);
17365 
17366  return (SCIP_VARSTATUS)(var->varstatus);
17367 }
17368 
17369 /** returns whether the variable belongs to the original problem */
17371  SCIP_VAR* var /**< problem variable */
17372  )
17373 {
17374  assert(var != NULL);
17375  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED || var->negatedvar != NULL);
17376 
17380 }
17381 
17382 /** returns whether the variable belongs to the transformed problem */
17384  SCIP_VAR* var /**< problem variable */
17385  )
17386 {
17387  assert(var != NULL);
17388  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED || var->negatedvar != NULL);
17389 
17393 }
17394 
17395 /** returns whether the variable was created by negation of a different variable */
17397  SCIP_VAR* var /**< problem variable */
17398  )
17399 {
17400  assert(var != NULL);
17401 
17402  return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17403 }
17404 
17405 /** gets type of variable */
17407  SCIP_VAR* var /**< problem variable */
17408  )
17409 {
17410  assert(var != NULL);
17411 
17412  return (SCIP_VARTYPE)(var->vartype);
17413 }
17414 
17415 /** returns TRUE if the variable is of binary type; this is the case if:
17416  * (1) variable type is binary
17417  * (2) variable type is integer or implicit integer and
17418  * (i) the global lower bound is greater than or equal to zero
17419  * (ii) the global upper bound is less than or equal to one
17420  */
17422  SCIP_VAR* var /**< problem variable */
17423  )
17424 {
17425  assert(var != NULL);
17426 
17427  return (SCIPvarGetType(var) == SCIP_VARTYPE_BINARY ||
17428  (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && var->glbdom.lb >= 0.0 && var->glbdom.ub <= 1.0));
17429 }
17430 
17431 /** returns whether variable is of integral type (binary, integer, or implicit integer) */
17433  SCIP_VAR* var /**< problem variable */
17434  )
17435 {
17436  assert(var != NULL);
17437 
17438  return (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
17439 }
17440 
17441 /** returns whether variable's column should be present in the initial root LP */
17443  SCIP_VAR* var /**< problem variable */
17444  )
17445 {
17446  assert(var != NULL);
17447 
17448  return var->initial;
17449 }
17450 
17451 /** returns whether variable's column is removable from the LP (due to aging or cleanup) */
17453  SCIP_VAR* var /**< problem variable */
17454  )
17455 {
17456  assert(var != NULL);
17457 
17458  return var->removable;
17459 }
17460 
17461 /** returns whether the variable was deleted from the problem */
17463  SCIP_VAR* var /**< problem variable */
17464  )
17465 {
17466  assert(var != NULL);
17467 
17468  return var->deleted;
17469 }
17470 
17471 /** marks the variable to be deletable, i.e., it may be deleted completely from the problem;
17472  * method can only be called before the variable is added to the problem by SCIPaddVar() or SCIPaddPricedVar()
17473  */
17475  SCIP_VAR* var /**< problem variable */
17476  )
17477 {
17478  assert(var != NULL);
17479  assert(var->probindex == -1);
17480 
17481  var->deletable = TRUE;
17482 }
17483 
17484 /** marks the variable to be not deletable from the problem */
17487  )
17488 {
17489  assert(var != NULL);
17490 
17491  var->deletable = FALSE;
17492 }
17493 
17494 /** marks variable to be deleted from global structures (cliques etc.) when cleaning up
17495  *
17496  * @note: this is not equivalent to marking the variable itself for deletion, this is done by using SCIPvarMarkDeletable()
17497  */
17499  SCIP_VAR* var /**< problem variable */
17500  )
17501 {
17502  assert(var != NULL);
17503 
17504  var->delglobalstructs = TRUE;
17505 }
17506 
17507 /** returns whether the variable was flagged for deletion from global structures (cliques etc.) */
17509  SCIP_VAR* var /**< problem variable */
17510  )
17511 {
17512  assert(var != NULL);
17513 
17514  return var->delglobalstructs;
17515 }
17516 
17517 /** returns whether a variable has been introduced to define a relaxation
17518  *
17519  * These variables are only valid for the current SCIP solve round,
17520  * they are not contained in any (checked) constraints, but may be used
17521  * in cutting planes, for example.
17522  * Relaxation-only variables are not copied by SCIPcopyVars and cuts
17523  * that contain these variables are not added as linear constraints when
17524  * restarting or transferring information from a copied SCIP to a SCIP.
17525  * Also conflicts with relaxation-only variables are not generated at
17526  * the moment.
17527  */
17529  SCIP_VAR* var /**< problem variable */
17530  )
17531 {
17532  assert(var != NULL);
17533 
17534  return var->relaxationonly;
17535 }
17536 
17537 /** marks that this variable has only been introduced to define a relaxation
17538  *
17539  * The variable must not have a coefficient in the objective and must be deletable.
17540  * If it is not marked deletable, it will be marked as deletable, which is only possible
17541  * before the variable is added to a problem.
17542  *
17543  * @see SCIPvarIsRelaxationOnly
17544  * @see SCIPvarMarkDeletable
17545  */
17547  SCIP_VAR* var /**< problem variable */
17548  )
17549 {
17550  assert(var != NULL);
17551  assert(SCIPvarGetObj(var) == 0.0);
17552 
17553  if( !SCIPvarIsDeletable(var) )
17554  SCIPvarMarkDeletable(var);
17555 
17556  var->relaxationonly = TRUE;
17557 }
17558 
17559 /** returns whether variable is allowed to be deleted completely from the problem */
17562  )
17563 {
17564  assert(var != NULL);
17565 
17566  return var->deletable;
17567 }
17568 
17569 /** returns whether variable is an active (neither fixed nor aggregated) variable */
17571  SCIP_VAR* var /**< problem variable */
17572  )
17573 {
17574  assert(var != NULL);
17575 
17576  return (var->probindex >= 0);
17577 }
17578 
17579 /** gets unique index of variable */
17580 int SCIPvarGetIndex(
17581  SCIP_VAR* var /**< problem variable */
17582  )
17583 {
17584  assert(var != NULL);
17585 
17586  return var->index;
17587 }
17588 
17589 /** gets position of variable in problem, or -1 if variable is not active */
17591  SCIP_VAR* var /**< problem variable */
17592  )
17593 {
17594  assert(var != NULL);
17595 
17596  return var->probindex;
17597 }
17598 
17599 /** gets transformed variable of ORIGINAL variable */
17601  SCIP_VAR* var /**< problem variable */
17602  )
17603 {
17604  assert(var != NULL);
17605  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
17606 
17607  return var->data.original.transvar;
17608 }
17609 
17610 /** gets column of COLUMN variable */
17612  SCIP_VAR* var /**< problem variable */
17613  )
17614 {
17615  assert(var != NULL);
17616  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
17617 
17618  return var->data.col;
17619 }
17620 
17621 /** returns whether the variable is a COLUMN variable that is member of the current LP */
17623  SCIP_VAR* var /**< problem variable */
17624  )
17625 {
17626  assert(var != NULL);
17627 
17628  return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN && SCIPcolIsInLP(var->data.col));
17629 }
17630 
17631 /** gets aggregation variable y of an aggregated variable x = a*y + c */
17633  SCIP_VAR* var /**< problem variable */
17634  )
17635 {
17636  assert(var != NULL);
17638  assert(!var->donotaggr);
17639 
17640  return var->data.aggregate.var;
17641 }
17642 
17643 /** gets aggregation scalar a of an aggregated variable x = a*y + c */
17645  SCIP_VAR* var /**< problem variable */
17646  )
17647 {
17648  assert(var != NULL);
17650  assert(!var->donotaggr);
17651 
17652  return var->data.aggregate.scalar;
17653 }
17654 
17655 /** gets aggregation constant c of an aggregated variable x = a*y + c */
17657  SCIP_VAR* var /**< problem variable */
17658  )
17659 {
17660  assert(var != NULL);
17662  assert(!var->donotaggr);
17663 
17664  return var->data.aggregate.constant;
17665 }
17666 
17667 /** gets number n of aggregation variables of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17669  SCIP_VAR* var /**< problem variable */
17670  )
17671 {
17672  assert(var != NULL);
17673  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17674  assert(!var->donotmultaggr);
17675 
17676  return var->data.multaggr.nvars;
17677 }
17678 
17679 /** gets vector of aggregation variables y of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17681  SCIP_VAR* var /**< problem variable */
17682  )
17683 {
17684  assert(var != NULL);
17685  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17686  assert(!var->donotmultaggr);
17687 
17688  return var->data.multaggr.vars;
17689 }
17690 
17691 /** gets vector of aggregation scalars a of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17693  SCIP_VAR* var /**< problem variable */
17694  )
17695 {
17696  assert(var != NULL);
17697  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17698  assert(!var->donotmultaggr);
17699 
17700  return var->data.multaggr.scalars;
17701 }
17702 
17703 /** gets aggregation constant c of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17705  SCIP_VAR* var /**< problem variable */
17706  )
17707 {
17708  assert(var != NULL);
17709  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17710  assert(!var->donotmultaggr);
17711 
17712  return var->data.multaggr.constant;
17713 }
17714 
17715 /** gets the negation of the given variable; may return NULL, if no negation is existing yet */
17717  SCIP_VAR* var /**< negated problem variable */
17718  )
17719 {
17720  assert(var != NULL);
17721 
17722  return var->negatedvar;
17723 }
17724 
17725 /** gets the negation variable x of a negated variable x' = offset - x */
17727  SCIP_VAR* var /**< negated problem variable */
17728  )
17729 {
17730  assert(var != NULL);
17731  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17732 
17733  return var->negatedvar;
17734 }
17735 
17736 /** gets the negation offset of a negated variable x' = offset - x */
17738  SCIP_VAR* var /**< negated problem variable */
17739  )
17740 {
17741  assert(var != NULL);
17742  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17743 
17744  return var->data.negate.constant;
17745 }
17746 
17747 /** gets objective function value of variable */
17749  SCIP_VAR* var /**< problem variable */
17750  )
17751 {
17752  assert(var != NULL);
17753 
17754  return var->obj;
17755 }
17756 
17757 /** gets the unchanged objective function value of a variable (ignoring temproray changes performed in probing mode) */
17759  SCIP_VAR* var /**< problem variable */
17760  )
17761 {
17762  assert(var != NULL);
17763 
17764  return var->unchangedobj;
17765 }
17766 
17767 /** gets corresponding objective value of active, fixed, or multi-aggregated problem variable of given variable
17768  * e.g. obj(x) = 1 this method returns for ~x the value -1
17769  */
17771  SCIP_VAR* var, /**< problem variable */
17772  SCIP_Real* aggrobj /**< pointer to store the aggregated objective value */
17773  )
17774 {
17775  SCIP_VAR* probvar = var;
17776  SCIP_Real mult = 1.0;
17777 
17778  assert(probvar != NULL);
17779  assert(aggrobj != NULL);
17780 
17781  while( probvar != NULL )
17782  {
17783  switch( SCIPvarGetStatus(probvar) )
17784  {
17786  case SCIP_VARSTATUS_LOOSE:
17787  case SCIP_VARSTATUS_COLUMN:
17788  (*aggrobj) = mult * SCIPvarGetObj(probvar);
17789  return SCIP_OKAY;
17790 
17791  case SCIP_VARSTATUS_FIXED:
17792  assert(SCIPvarGetObj(probvar) == 0.0);
17793  (*aggrobj) = 0.0;
17794  return SCIP_OKAY;
17795 
17797  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
17798  if ( probvar->data.multaggr.nvars == 1 )
17799  {
17800  assert( probvar->data.multaggr.vars != NULL );
17801  assert( probvar->data.multaggr.scalars != NULL );
17802  assert( probvar->data.multaggr.vars[0] != NULL );
17803  mult *= probvar->data.multaggr.scalars[0];
17804  probvar = probvar->data.multaggr.vars[0];
17805  break;
17806  }
17807  else
17808  {
17809  SCIP_Real tmpobj;
17810  int v;
17811 
17812  (*aggrobj) = 0.0;
17813 
17814  for( v = probvar->data.multaggr.nvars - 1; v >= 0; --v )
17815  {
17816  SCIP_CALL( SCIPvarGetAggregatedObj(probvar->data.multaggr.vars[v], &tmpobj) );
17817  (*aggrobj) += probvar->data.multaggr.scalars[v] * tmpobj;
17818  }
17819  return SCIP_OKAY;
17820  }
17821 
17822  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
17823  assert(probvar->data.aggregate.var != NULL);
17824  mult *= probvar->data.aggregate.scalar;
17825  probvar = probvar->data.aggregate.var;
17826  break;
17827 
17828  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
17829  assert(probvar->negatedvar != NULL);
17830  assert(SCIPvarGetStatus(probvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
17831  assert(probvar->negatedvar->negatedvar == probvar);
17832  mult *= -1.0;
17833  probvar = probvar->negatedvar;
17834  break;
17835 
17836  default:
17837  SCIPABORT();
17838  return SCIP_INVALIDDATA; /*lint !e527*/
17839  }
17840  }
17841 
17842  return SCIP_INVALIDDATA;
17843 }
17844 
17845 /** gets original lower bound of original problem variable (i.e. the bound set in problem creation) */
17847  SCIP_VAR* var /**< original problem variable */
17848  )
17849 {
17850  assert(var != NULL);
17851  assert(SCIPvarIsOriginal(var));
17852 
17854  return var->data.original.origdom.lb;
17855  else
17856  {
17857  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17858  assert(var->negatedvar != NULL);
17860 
17861  return var->data.negate.constant - var->negatedvar->data.original.origdom.ub;
17862  }
17863 }
17864 
17865 /** gets original upper bound of original problem variable (i.e. the bound set in problem creation) */
17867  SCIP_VAR* var /**< original problem variable */
17868  )
17869 {
17870  assert(var != NULL);
17871  assert(SCIPvarIsOriginal(var));
17872 
17874  return var->data.original.origdom.ub;
17875  else
17876  {
17877  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17878  assert(var->negatedvar != NULL);
17880 
17881  return var->data.negate.constant - var->negatedvar->data.original.origdom.lb;
17882  }
17883 }
17884 
17885 /** gets the original hole list of an original variable */
17887  SCIP_VAR* var /**< problem variable */
17888  )
17889 {
17890  assert(var != NULL);
17891  assert(SCIPvarIsOriginal(var));
17892 
17894  return var->data.original.origdom.holelist;
17895 
17896  return NULL;
17897 }
17898 
17899 /** gets global lower bound of variable */
17901  SCIP_VAR* var /**< problem variable */
17902  )
17903 {
17904  assert(var != NULL);
17905 
17906  return var->glbdom.lb;
17907 }
17908 
17909 /** gets global upper bound of variable */
17911  SCIP_VAR* var /**< problem variable */
17912  )
17913 {
17914  assert(var != NULL);
17915 
17916  return var->glbdom.ub;
17917 }
17918 
17919 /** gets the global hole list of an active variable */
17921  SCIP_VAR* var /**< problem variable */
17922  )
17923 {
17924  assert(var != NULL);
17925 
17926  return var->glbdom.holelist;
17927 }
17928 
17929 /** gets best global bound of variable with respect to the objective function */
17931  SCIP_VAR* var /**< problem variable */
17932  )
17933 {
17934  assert(var != NULL);
17935 
17936  if( var->obj >= 0.0 )
17937  return var->glbdom.lb;
17938  else
17939  return var->glbdom.ub;
17940 }
17941 
17942 /** gets worst global bound of variable with respect to the objective function */
17944  SCIP_VAR* var /**< problem variable */
17945  )
17946 {
17947  assert(var != NULL);
17948 
17949  if( var->obj >= 0.0 )
17950  return var->glbdom.ub;
17951  else
17952  return var->glbdom.lb;
17953 }
17954 
17955 /** gets current lower bound of variable */
17957  SCIP_VAR* var /**< problem variable */
17958  )
17959 {
17960  assert(var != NULL);
17961 
17962  return var->locdom.lb;
17963 }
17964 
17965 /** gets current upper bound of variable */
17967  SCIP_VAR* var /**< problem variable */
17968  )
17969 {
17970  assert(var != NULL);
17971 
17972  return var->locdom.ub;
17973 }
17974 
17975 /** gets the current hole list of an active variable */
17977  SCIP_VAR* var /**< problem variable */
17978  )
17979 {
17980  assert(var != NULL);
17981 
17982  return var->locdom.holelist;
17983 }
17984 
17985 /** gets best local bound of variable with respect to the objective function */
17987  SCIP_VAR* var /**< problem variable */
17988  )
17989 {
17990  assert(var != NULL);
17991 
17992  if( var->obj >= 0.0 )
17993  return var->locdom.lb;
17994  else
17995  return var->locdom.ub;
17996 }
17997 
17998 /** gets worst local bound of variable with respect to the objective function */
18000  SCIP_VAR* var /**< problem variable */
18001  )
18002 {
18003  assert(var != NULL);
18004 
18005  if( var->obj >= 0.0 )
18006  return var->locdom.ub;
18007  else
18008  return var->locdom.lb;
18009 }
18010 
18011 /** gets type (lower or upper) of best bound of variable with respect to the objective function */
18013  SCIP_VAR* var /**< problem variable */
18014  )
18015 {
18016  assert(var != NULL);
18017 
18018  if( var->obj >= 0.0 )
18019  return SCIP_BOUNDTYPE_LOWER;
18020  else
18021  return SCIP_BOUNDTYPE_UPPER;
18022 }
18023 
18024 /** gets type (lower or upper) of worst bound of variable with respect to the objective function */
18026  SCIP_VAR* var /**< problem variable */
18027  )
18028 {
18029  assert(var != NULL);
18030 
18031  if( var->obj >= 0.0 )
18032  return SCIP_BOUNDTYPE_UPPER;
18033  else
18034  return SCIP_BOUNDTYPE_LOWER;
18035 }
18036 
18037 /** gets lazy lower bound of variable, returns -infinity if the variable has no lazy lower bound */
18039  SCIP_VAR* var /**< problem variable */
18040  )
18041 {
18042  assert(var != NULL);
18043 
18044  return var->lazylb;
18045 }
18046 
18047 /** gets lazy upper bound of variable, returns infinity if the variable has no lazy upper bound */
18049  SCIP_VAR* var /**< problem variable */
18050  )
18051 {
18052  assert(var != NULL);
18053 
18054  return var->lazyub;
18055 }
18056 
18057 /** gets the branch factor of the variable; this value can be used in the branching methods to scale the score
18058  * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
18059  */
18061  SCIP_VAR* var /**< problem variable */
18062  )
18063 {
18064  assert(var != NULL);
18065 
18066  return var->branchfactor;
18067 }
18068 
18069 /** gets the branch priority of the variable; variables with higher priority should always be preferred to variables
18070  * with lower priority
18071  */
18073  SCIP_VAR* var /**< problem variable */
18074  )
18075 {
18076  assert(var != NULL);
18077 
18078  return var->branchpriority;
18079 }
18080 
18081 /** gets the preferred branch direction of the variable (downwards, upwards, or auto) */
18083  SCIP_VAR* var /**< problem variable */
18084  )
18085 {
18086  assert(var != NULL);
18087 
18088  return (SCIP_BRANCHDIR)var->branchdirection;
18089 }
18090 
18091 /** gets number of variable lower bounds x >= b_i*z_i + d_i of given variable x */
18092 int SCIPvarGetNVlbs(
18093  SCIP_VAR* var /**< problem variable */
18094  )
18095 {
18096  assert(var != NULL);
18097 
18098  return SCIPvboundsGetNVbds(var->vlbs);
18099 }
18100 
18101 /** gets array with bounding variables z_i in variable lower bounds x >= b_i*z_i + d_i of given variable x;
18102  * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
18103  */
18105  SCIP_VAR* var /**< problem variable */
18106  )
18107 {
18108  assert(var != NULL);
18109 
18110  return SCIPvboundsGetVars(var->vlbs);
18111 }
18112 
18113 /** gets array with bounding coefficients b_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
18115  SCIP_VAR* var /**< problem variable */
18116  )
18117 {
18118  assert(var != NULL);
18119 
18120  return SCIPvboundsGetCoefs(var->vlbs);
18121 }
18122 
18123 /** gets array with bounding constants d_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
18125  SCIP_VAR* var /**< problem variable */
18126  )
18127 {
18128  assert(var != NULL);
18129 
18130  return SCIPvboundsGetConstants(var->vlbs);
18131 }
18132 
18133 /** gets number of variable upper bounds x <= b_i*z_i + d_i of given variable x */
18134 int SCIPvarGetNVubs(
18135  SCIP_VAR* var /**< problem variable */
18136  )
18137 {
18138  assert(var != NULL);
18139 
18140  return SCIPvboundsGetNVbds(var->vubs);
18141 }
18142 
18143 /** gets array with bounding variables z_i in variable upper bounds x <= b_i*z_i + d_i of given variable x;
18144  * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
18145  */
18147  SCIP_VAR* var /**< problem variable */
18148  )
18149 {
18150  assert(var != NULL);
18151 
18152  return SCIPvboundsGetVars(var->vubs);
18153 }
18154 
18155 /** gets array with bounding coefficients b_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
18157  SCIP_VAR* var /**< problem variable */
18158  )
18159 {
18160  assert(var != NULL);
18161 
18162  return SCIPvboundsGetCoefs(var->vubs);
18163 }
18164 
18165 /** gets array with bounding constants d_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
18167  SCIP_VAR* var /**< problem variable */
18168  )
18169 {
18170  assert(var != NULL);
18171 
18172  return SCIPvboundsGetConstants(var->vubs);
18173 }
18174 
18175 /** gets number of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
18176  * there are no implications for nonbinary variable x
18177  */
18178 int SCIPvarGetNImpls(
18179  SCIP_VAR* var, /**< active problem variable */
18180  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
18181  )
18182 {
18183  assert(var != NULL);
18184  assert(SCIPvarIsActive(var));
18185 
18186  return SCIPimplicsGetNImpls(var->implics, varfixing);
18187 }
18188 
18189 /** gets array with implication variables y of implications y <= b or y >= b for x == 0 or x == 1 of given active
18190  * problem variable x, there are no implications for nonbinary variable x;
18191  * the implications are sorted such that implications with binary implied variables precede the ones with non-binary
18192  * implied variables, and as a second criteria, the implied variables are sorted by increasing variable index
18193  * (see SCIPvarGetIndex())
18194  */
18196  SCIP_VAR* var, /**< active problem variable */
18197  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
18198  )
18199 {
18200  assert(var != NULL);
18201  assert(SCIPvarIsActive(var));
18202 
18203  return SCIPimplicsGetVars(var->implics, varfixing);
18204 }
18205 
18206 /** gets array with implication types of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
18207  * variable x (SCIP_BOUNDTYPE_UPPER if y <= b, SCIP_BOUNDTYPE_LOWER if y >= b),
18208  * there are no implications for nonbinary variable x
18209  */
18211  SCIP_VAR* var, /**< active problem variable */
18212  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
18213  )
18214 {
18215  assert(var != NULL);
18216  assert(SCIPvarIsActive(var));
18217 
18218  return SCIPimplicsGetTypes(var->implics, varfixing);
18219 }
18220 
18221 /** gets array with implication bounds b of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
18222  * variable x, there are no implications for nonbinary variable x
18223  */
18225  SCIP_VAR* var, /**< active problem variable */
18226  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
18227  )
18228 {
18229  assert(var != NULL);
18230  assert(SCIPvarIsActive(var));
18231 
18232  return SCIPimplicsGetBounds(var->implics, varfixing);
18233 }
18234 
18235 /** Gets array with unique ids of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
18236  * there are no implications for nonbinary variable x.
18237  * If an implication is a shortcut, i.e., it was added as part of the transitive closure of another implication,
18238  * its id is negative, otherwise it is nonnegative.
18239  */
18240 int* SCIPvarGetImplIds(
18241  SCIP_VAR* var, /**< active problem variable */
18242  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
18243  )
18244 {
18245  assert(var != NULL);
18246  assert(SCIPvarIsActive(var));
18247 
18248  return SCIPimplicsGetIds(var->implics, varfixing);
18249 }
18250 
18251 /** gets number of cliques, the active variable is contained in */
18252 int SCIPvarGetNCliques(
18253  SCIP_VAR* var, /**< active problem variable */
18254  SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
18255  )
18256 {
18257  assert(var != NULL);
18258 
18259  return SCIPcliquelistGetNCliques(var->cliquelist, varfixing);
18260 }
18261 
18262 /** gets array of cliques, the active variable is contained in */
18264  SCIP_VAR* var, /**< active problem variable */
18265  SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
18266  )
18267 {
18268  assert(var != NULL);
18269 
18270  return SCIPcliquelistGetCliques(var->cliquelist, varfixing);
18271 }
18272 
18273 /** gets primal LP solution value of variable */
18275  SCIP_VAR* var /**< problem variable */
18276  )
18277 {
18278  assert(var != NULL);
18279 
18281  return SCIPcolGetPrimsol(var->data.col);
18282  else
18283  return SCIPvarGetLPSol_rec(var);
18284 }
18285 
18286 /** gets primal NLP solution value of variable */
18288  SCIP_VAR* var /**< problem variable */
18289  )
18290 {
18291  assert(var != NULL);
18292 
18294  return var->nlpsol;
18295  else
18296  return SCIPvarGetNLPSol_rec(var);
18297 }
18298 
18299 /** return lower bound change info at requested position */
18301  SCIP_VAR* var, /**< problem variable */
18302  int pos /**< requested position */
18303  )
18304 {
18305  assert(pos >= 0);
18306  assert(pos < var->nlbchginfos);
18307 
18308  return &var->lbchginfos[pos];
18309 }
18310 
18311 /** gets the number of lower bound change info array */
18313  SCIP_VAR* var /**< problem variable */
18314  )
18315 {
18316  return var->nlbchginfos;
18317 }
18318 
18319 /** return upper bound change info at requested position */
18321  SCIP_VAR* var, /**< problem variable */
18322  int pos /**< requested position */
18323  )
18324 {
18325  assert(pos >= 0);
18326  assert(pos < var->nubchginfos);
18327 
18328  return &var->ubchginfos[pos];
18329 }
18330 
18331 /** gets the number upper bound change info array */
18333  SCIP_VAR* var /**< problem variable */
18334  )
18335 {
18336  assert(var != NULL);
18337 
18338  return var->nubchginfos;
18339 }
18340 
18341 /** returns the value based history for the variable */
18343  SCIP_VAR* var /**< problem variable */
18344  )
18345 {
18346  assert(var != NULL);
18347 
18348  return var->valuehistory;
18349 }
18350 
18351 /** gets pseudo solution value of variable */
18353  SCIP_VAR* var /**< problem variable */
18354  )
18355 {
18356  assert(var != NULL);
18357 
18359  return SCIPvarGetBestBoundLocal(var);
18360  else
18361  return SCIPvarGetPseudoSol_rec(var);
18362 }
18363 
18364 /** returns the variable's VSIDS score */
18366  SCIP_VAR* var, /**< problem variable */
18367  SCIP_STAT* stat, /**< problem statistics */
18368  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
18369  )
18370 {
18371  assert(var != NULL);
18372 
18374  return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
18375  else
18376  return SCIPvarGetVSIDS_rec(var, stat, dir);
18377 }
18378 
18379 /** includes event handler with given data in variable's event filter */
18381  SCIP_VAR* var, /**< problem variable */
18382  BMS_BLKMEM* blkmem, /**< block memory */
18383  SCIP_SET* set, /**< global SCIP settings */
18384  SCIP_EVENTTYPE eventtype, /**< event type to catch */
18385  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
18386  SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
18387  int* filterpos /**< pointer to store position of event filter entry, or NULL */
18388  )
18389 {
18390  assert(var != NULL);
18391  assert(set != NULL);
18392  assert(var->scip == set->scip);
18393  assert(var->eventfilter != NULL);
18394  assert((eventtype & ~SCIP_EVENTTYPE_VARCHANGED) == 0);
18395  assert((eventtype & SCIP_EVENTTYPE_VARCHANGED) != 0);
18396  assert(SCIPvarIsTransformed(var));
18397 
18398  SCIPsetDebugMsg(set, "catch event of type 0x%" SCIP_EVENTTYPE_FORMAT " of variable <%s> with handler %p and data %p\n",
18399  eventtype, var->name, (void*)eventhdlr, (void*)eventdata);
18400 
18401  SCIP_CALL( SCIPeventfilterAdd(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
18402 
18403  return SCIP_OKAY;
18404 }
18405 
18406 /** deletes event handler with given data from variable's event filter */
18408  SCIP_VAR* var, /**< problem variable */
18409  BMS_BLKMEM* blkmem, /**< block memory */
18410  SCIP_SET* set, /**< global SCIP settings */
18411  SCIP_EVENTTYPE eventtype, /**< event type mask of dropped event */
18412  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
18413  SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
18414  int filterpos /**< position of event filter entry returned by SCIPvarCatchEvent(), or -1 */
18415  )
18416 {
18417  assert(var != NULL);
18418  assert(set != NULL);
18419  assert(var->scip == set->scip);
18420  assert(var->eventfilter != NULL);
18421  assert(SCIPvarIsTransformed(var));
18422 
18423  SCIPsetDebugMsg(set, "drop event of variable <%s> with handler %p and data %p\n", var->name, (void*)eventhdlr,
18424  (void*)eventdata);
18425 
18426  SCIP_CALL( SCIPeventfilterDel(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
18427 
18428  return SCIP_OKAY;
18429 }
18430 
18431 /** returns the position of the bound change index */
18432 int SCIPbdchgidxGetPos(
18433  SCIP_BDCHGIDX* bdchgidx /**< bound change index */
18434  )
18435 {
18436  assert(bdchgidx != NULL);
18437 
18438  return bdchgidx->pos;
18439 }
18440 
18441 /** returns whether first bound change index belongs to an earlier applied bound change than second one */
18443  SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index */
18444  SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index */
18445  )
18446 {
18447  assert(bdchgidx1 != NULL);
18448  assert(bdchgidx1->depth >= -2);
18449  assert(bdchgidx1->pos >= 0);
18450  assert(bdchgidx2 != NULL);
18451  assert(bdchgidx2->depth >= -2);
18452  assert(bdchgidx2->pos >= 0);
18453 
18454  return (bdchgidx1->depth < bdchgidx2->depth)
18455  || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
18456 }
18457 
18458 /** returns whether first bound change index belongs to an earlier applied bound change than second one;
18459  * if a bound change index is NULL, the bound change index represents the current time, i.e. the time after the
18460  * last bound change was applied to the current node
18461  */
18463  SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index, or NULL */
18464  SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index, or NULL */
18465  )
18466 {
18467  assert(bdchgidx1 == NULL || bdchgidx1->depth >= -2);
18468  assert(bdchgidx1 == NULL || bdchgidx1->pos >= 0);
18469  assert(bdchgidx2 == NULL || bdchgidx2->depth >= -2);
18470  assert(bdchgidx2 == NULL || bdchgidx2->pos >= 0);
18471 
18472  if( bdchgidx1 == NULL )
18473  return FALSE;
18474  else if( bdchgidx2 == NULL )
18475  return TRUE;
18476  else
18477  return (bdchgidx1->depth < bdchgidx2->depth)
18478  || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
18479 }
18480 
18481 /** returns old bound that was overwritten for given bound change information */
18483  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18484  )
18485 {
18486  assert(bdchginfo != NULL);
18487 
18488  return bdchginfo->oldbound;
18489 }
18490 
18491 /** returns new bound installed for given bound change information */
18493  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18494  )
18495 {
18496  assert(bdchginfo != NULL);
18497 
18498  return bdchginfo->newbound;
18499 }
18500 
18501 /** returns variable that belongs to the given bound change information */
18503  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18504  )
18505 {
18506  assert(bdchginfo != NULL);
18507 
18508  return bdchginfo->var;
18509 }
18510 
18511 /** returns whether the bound change information belongs to a branching decision or a deduction */
18513  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18514  )
18515 {
18516  assert(bdchginfo != NULL);
18517 
18518  return (SCIP_BOUNDCHGTYPE)(bdchginfo->boundchgtype);
18519 }
18520 
18521 /** returns whether the bound change information belongs to a lower or upper bound change */
18523  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18524  )
18525 {
18526  assert(bdchginfo != NULL);
18527 
18528  return (SCIP_BOUNDTYPE)(bdchginfo->boundtype);
18529 }
18530 
18531 /** returns depth level of given bound change information */
18533  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18534  )
18535 {
18536  assert(bdchginfo != NULL);
18537 
18538  return bdchginfo->bdchgidx.depth;
18539 }
18540 
18541 /** returns bound change position in its depth level of given bound change information */
18543  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18544  )
18545 {
18546  assert(bdchginfo != NULL);
18547 
18548  return bdchginfo->bdchgidx.pos;
18549 }
18550 
18551 /** returns bound change index of given bound change information */
18553  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18554  )
18555 {
18556  assert(bdchginfo != NULL);
18557 
18558  return &bdchginfo->bdchgidx;
18559 }
18560 
18561 /** returns inference variable of given bound change information */
18563  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18564  )
18565 {
18566  assert(bdchginfo != NULL);
18569 
18570  return bdchginfo->inferencedata.var;
18571 }
18572 
18573 /** returns inference constraint of given bound change information */
18575  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18576  )
18577 {
18578  assert(bdchginfo != NULL);
18580  assert(bdchginfo->inferencedata.reason.cons != NULL);
18581 
18582  return bdchginfo->inferencedata.reason.cons;
18583 }
18584 
18585 /** returns inference propagator of given bound change information, or NULL if no propagator was responsible */
18587  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18588  )
18589 {
18590  assert(bdchginfo != NULL);
18592 
18593  return bdchginfo->inferencedata.reason.prop;
18594 }
18595 
18596 /** returns inference user information of given bound change information */
18598  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18599  )
18600 {
18601  assert(bdchginfo != NULL);
18604 
18605  return bdchginfo->inferencedata.info;
18606 }
18607 
18608 /** returns inference bound of inference variable of given bound change information */
18610  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18611  )
18612 {
18613  assert(bdchginfo != NULL);
18616 
18617  return (SCIP_BOUNDTYPE)(bdchginfo->inferboundtype);
18618 }
18619 
18620 /** returns the relaxed bound change type */
18622  SCIP_BDCHGINFO* bdchginfo /**< bound change to add to the conflict set */
18623  )
18624 {
18625  return ((SCIP_BOUNDTYPE)(bdchginfo->boundtype) == SCIP_BOUNDTYPE_LOWER ? bdchginfo->var->conflictrelaxedlb : bdchginfo->var->conflictrelaxedub);
18626 }
18627 
18628 
18629 /** returns whether the bound change information belongs to a redundant bound change */
18631  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18632  )
18633 {
18634  assert(bdchginfo != NULL);
18635  assert(bdchginfo->redundant == (bdchginfo->oldbound == bdchginfo->newbound)); /*lint !e777*/
18636 
18637  return bdchginfo->redundant;
18638 }
18639 
18640 /** returns whether the bound change has an inference reason (constraint or propagator), that can be resolved */
18642  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18643  )
18644 {
18645  assert(bdchginfo != NULL);
18646 
18649  && bdchginfo->inferencedata.reason.prop != NULL);
18650 }
18651 
18652 /** for two bound change informations belonging to the same variable and bound, returns whether the first bound change
18653  * has a tighter new bound as the second bound change
18654  */
18656  SCIP_BDCHGINFO* bdchginfo1, /**< first bound change information */
18657  SCIP_BDCHGINFO* bdchginfo2 /**< second bound change information */
18658  )
18659 {
18660  assert(bdchginfo1 != NULL);
18661  assert(bdchginfo2 != NULL);
18662  assert(bdchginfo1->var == bdchginfo2->var);
18663  assert(bdchginfo1->boundtype == bdchginfo2->boundtype);
18664 
18665  return (SCIPbdchginfoGetBoundtype(bdchginfo1) == SCIP_BOUNDTYPE_LOWER
18666  ? bdchginfo1->newbound > bdchginfo2->newbound
18667  : bdchginfo1->newbound < bdchginfo2->newbound);
18668 }
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:18622
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:15394
SCIP_Real SCIPvarGetWorstBoundLocal(SCIP_VAR *var)
Definition: var.c:18000
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6215
SCIP_Real * SCIPvarGetVlbCoefs(SCIP_VAR *var)
Definition: var.c:18115
#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:14113
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:18026
static void checkImplic(SCIP_SET *set, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool *redundant, SCIP_Bool *infeasible)
Definition: var.c:9372
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:15521
SCIP_Bool SCIPvarsHaveCommonClique(SCIP_VAR *var1, SCIP_Bool value1, SCIP_VAR *var2, SCIP_Bool value2, SCIP_Bool regardimplics)
Definition: var.c:11465
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:3380
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:15041
static SCIP_RETCODE varEventImplAdded(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:9254
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:10455
SCIP_Real SCIPvarGetBdAtIndex(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16773
SCIP_PROP * SCIPbdchginfoGetInferProp(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18587
void SCIPvarMarkNotDeletable(SCIP_VAR *var)
Definition: var.c:17486
void SCIPvarUpdateBestRootSol(SCIP_VAR *var, SCIP_SET *set, SCIP_Real rootsol, SCIP_Real rootredcost, SCIP_Real rootlpobjval)
Definition: var.c:13270
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:13996
int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:3296
public methods for branching and inference history structure
SCIP_Bool SCIPlpDiving(SCIP_LP *lp)
Definition: lp.c:17847
int nubchginfos
Definition: struct_var.h:269
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoLb(SCIP_VAR *var, int pos)
Definition: var.c:18301
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition: var.c:17693
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:16302
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:18061
unsigned int inferboundtype
Definition: struct_var.h:102
SCIP_Real SCIPbdchginfoGetOldbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18483
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:18083
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:18049
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:6825
SCIP_Bool SCIPsetIsFeasEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6613
int SCIPvarGetNVlbs(SCIP_VAR *var)
Definition: var.c:18093
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18503
#define SCIPsetDuplicateBufferArray(set, ptr, source, num)
Definition: set.h:1736
SCIP_Real SCIPvarGetWorstBoundGlobal(SCIP_VAR *var)
Definition: var.c:17944
#define SCIP_DECL_VARTRANS(x)
Definition: type_var.h:151
SCIP_RETCODE SCIPvarChgLbGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Real newbound)
Definition: var.c:7175
enum SCIP_BaseStat SCIP_BASESTAT
Definition: type_lpi.h:96
SCIP_Bool SCIPvarDoNotMultaggr(SCIP_VAR *var)
Definition: var.c:5871
SCIP_RETCODE SCIPvarCreateTransformed(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
Definition: var.c:2118
public methods for implications, variable bounds, and cliques
SCIP_Real SCIPvarGetPseudocostCountCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14608
methods for implications, variable bounds, and cliques
int SCIPvarGetLastBdchgDepth(SCIP_VAR *var)
Definition: var.c:16853
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:17901
SCIP_Real SCIPvarGetAvgBranchdepth(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15777
SCIP_RETCODE SCIPvarGetProbvarBinary(SCIP_VAR **var, SCIP_Bool *negated)
Definition: var.c:12300
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:14774
#define SCIP_MAXSTRLEN
Definition: def.h:302
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:3354
SCIP_DOM origdom
Definition: struct_var.h:178
SCIP_BASESTAT SCIPcolGetBasisStatus(SCIP_COL *col)
Definition: lp.c:17031
SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition: var.c:17443
SCIP_RETCODE SCIPeventCreateImplAdded(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition: event.c:814
SCIP_VAR ** SCIPimplicsGetVars(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3331
SCIP_RETCODE SCIPvarChgLbOriginal(SCIP_VAR *var, SCIP_SET *set, SCIP_Real newbound)
Definition: var.c:6557
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:17681
static long bound
#define SCIPdebugCheckImplic(set, var, varfixing, implvar, impltype, implbound)
Definition: debug.h:292
static void printHolelist(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, SCIP_HOLELIST *holelist, const char *name)
Definition: var.c:2973
#define MAXABSVBCOEF
Definition: var.c:80
#define 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:13405
SCIP_RETCODE SCIPbdchginfoCreate(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_Real oldbound, SCIP_Real newbound)
Definition: var.c:16356
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:17957
SCIP_RETCODE SCIPvarChgLbLazy(SCIP_VAR *var, SCIP_SET *set, SCIP_Real lazylb)
Definition: var.c:7459
SCIP_Real constant
Definition: struct_var.h:193
SCIP_CLIQUE ** SCIPvarGetCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18264
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:8556
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:18343
int SCIPcliquelistGetNCliques(SCIP_CLIQUELIST *cliquelist, SCIP_Bool value)
Definition: implics.c:3446
SCIP_NODE * SCIPnodeGetParent(SCIP_NODE *node)
Definition: tree.c:7724
void SCIPprobAddObjoffset(SCIP_PROB *prob, SCIP_Real addval)
Definition: prob.c:1440
void SCIPvarSetTransData(SCIP_VAR *var, SCIP_DECL_VARTRANS((*vartrans)))
Definition: var.c:17295
SCIP_RETCODE SCIPvarChgUbOriginal(SCIP_VAR *var, SCIP_SET *set, SCIP_Real newbound)
Definition: var.c:6616
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:8864
SCIP_RETCODE SCIPvarParseOriginal(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, const char *str, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARCOPY((*varcopy)), SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_VARDATA *vardata, char **endptr, SCIP_Bool *success)
Definition: var.c:2497
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:17422
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:6752
SCIP_VAR ** SCIPvboundsGetVars(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3298
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:3698
SCIP_Real SCIPvarGetSol(SCIP_VAR *var, SCIP_Bool getlpval)
Definition: var.c:13247
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:18463
SCIP_Bool SCIPvarWasFixedAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16793
SCIP_Real SCIPvarGetBestBoundLocal(SCIP_VAR *var)
Definition: var.c:17987
SCIP_Real SCIPvarGetRootSol(SCIP_VAR *var)
Definition: var.c:13340
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:6132
SCIP_RETCODE SCIPvarScaleVSIDS(SCIP_VAR *var, SCIP_Real scalar)
Definition: var.c:15127
SCIP_Real SCIPvarGetLbLP(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:12922
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:17169
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:18381
SCIP_RETCODE SCIPcolCreate(SCIP_COL **col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var, int len, SCIP_ROW **rows, SCIP_Real *vals, SCIP_Bool removable)
Definition: lp.c:3279
SCIP_HOLELIST * newlist
Definition: struct_var.h:68
SCIP_Real right
Definition: struct_var.h:54
void SCIPvaluehistoryScaleVSIDS(SCIP_VALUEHISTORY *valuehistory, SCIP_Real scalar)
Definition: history.c:326
void SCIPvarSetProbindex(SCIP_VAR *var, int probindex)
Definition: var.c:6016
#define NLOCKTYPES
Definition: type_var.h:94
SCIP_RETCODE SCIPhistoryCreate(SCIP_HISTORY **history, BMS_BLKMEM *blkmem)
Definition: history.c:51
SCIP_HOLELIST * SCIPholelistGetNext(SCIP_HOLELIST *holelist)
Definition: var.c:17229
#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:17837
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:18313
static SCIP_RETCODE varAddUbchginfo(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real oldbound, SCIP_Real newbound, int depth, int pos, SCIP_VAR *infervar, SCIP_CONS *infercons, SCIP_PROP *inferprop, int inferinfo, SCIP_BOUNDTYPE inferboundtype, SCIP_BOUNDCHGTYPE boundchgtype)
Definition: var.c:555
struct SCIP_VarData SCIP_VARDATA
Definition: type_var.h:120
SCIP_RETCODE SCIPdomchgUndo(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:1349
SCIP_Real SCIPcolGetUb(SCIP_COL *col)
Definition: lp.c:16973
SCIP_RETCODE SCIPboundchgUndo(SCIP_BOUNDCHG *boundchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:826
SCIP_RETCODE SCIPvarTransform(SCIP_VAR *origvar, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_OBJSENSE objsense, SCIP_VAR **transvar)
Definition: var.c:3462
void SCIPhistoryReset(SCIP_HISTORY *history)
Definition: history.c:78
SCIP_Real SCIPcolGetObj(SCIP_COL *col)
Definition: lp.c:16953
int nlocksup[NLOCKTYPES]
Definition: struct_var.h:264
static SCIP_RETCODE varEventVarUnlocked(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:3147
SCIP_Real constant
Definition: struct_var.h:203
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c: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:15013
#define TRUE
Definition: def.h:95
SCIP_Bool SCIPvarHasImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition: var.c:11101
static void varSetProbindex(SCIP_VAR *var, int probindex)
Definition: var.c:5997
SCIP_Real SCIPvarGetAvgConflictlength(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15350
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:17738
#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:18135
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:18598
int nlbchginfos
Definition: struct_var.h:267
static SCIP_BDCHGIDX presolvebdchgidx
Definition: var.c:16813
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:2075
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:17591
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:10902
#define SCIP_DECL_VARCOPY(x)
Definition: type_var.h:194
SCIP_RETCODE SCIPvarChgLbDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newbound)
Definition: var.c:8239
void SCIPvarSetNamePointer(SCIP_VAR *var, const char *name)
Definition: var.c:6031
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:8213
SCIP_Real SCIPvarGetAggrScalar(SCIP_VAR *var)
Definition: var.c:17645
void SCIPvarInitSolve(SCIP_VAR *var)
Definition: var.c:2932
SCIP_RETCODE SCIPvarChgUbGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Real newbound)
Definition: var.c:7318
public methods for problem variables
static GRAPHNODE ** active
SCIP_Real SCIPvarGetInferenceSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15969
void SCIPvarMarkDeletable(SCIP_VAR *var)
Definition: var.c:17475
static SCIP_RETCODE varCreate(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARCOPY((*varcopy)), SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_VARDATA *vardata)
Definition: var.c:1930
SCIP_RETCODE SCIPimplicsDel(SCIP_IMPLICS **implics, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition: implics.c:836
SCIP_Real SCIPvarGetAvgInferences(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:16057
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:11260
SCIP_VAR ** SCIPvarGetVlbVars(SCIP_VAR *var)
Definition: var.c:18105
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:11996
int SCIPbdchgidxGetPos(SCIP_BDCHGIDX *bdchgidx)
Definition: var.c:18433
SCIP_CLIQUE ** SCIPcliquelistGetCliques(SCIP_CLIQUELIST *cliquelist, SCIP_Bool value)
Definition: implics.c:3455
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:6168
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:17561
int SCIPvarGetConflictingBdchgDepth(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real bound)
Definition: var.c:16868
SCIP_RETCODE SCIPvarUpdatePseudocost(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition: var.c:14369
#define SCIPsetFreeBufferArray(set, ptr)
Definition: set.h:1741
SCIP_Longint SCIPvarGetNBranchingsCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15734
SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
Definition: var.c:17453
void SCIPvarAdjustLb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *lb)
Definition: var.c:6507
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:11808
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:17727
SCIP_RETCODE SCIProwIncCoef(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_COL *col, SCIP_Real incval)
Definition: lp.c:5528
SCIP_Real relaxsol
Definition: struct_var.h:216
SCIP_RETCODE SCIPvarRemoveCliquesImplicsVbs(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_CLIQUETABLE *cliquetable, SCIP_SET *set, SCIP_Bool irrelevantvar, SCIP_Bool onlyredundant, SCIP_Bool removefromvar)
Definition: var.c:1610
static SCIP_RETCODE boundchgCaptureData(SCIP_BOUNDCHG *boundchg)
Definition: var.c:971
SCIP_Real SCIPsetCeil(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6413
int conflictlbcount
Definition: struct_var.h:270
SCIP_Real SCIPvarGetRelaxSolTransVar(SCIP_VAR *var)
Definition: var.c:13985
#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:16816
int SCIPvarGetNCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18253
Definition: heur_padm.c:132
SCIP_PROB * origprob
Definition: struct_scip.h:80
SCIP_Real SCIPvarGetLPSol_rec(SCIP_VAR *var)
Definition: var.c:13059
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:16212
int * SCIPvarGetImplIds(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18241
SCIP_HOLELIST * SCIPvarGetHolelistOriginal(SCIP_VAR *var)
Definition: var.c:17887
SCIP_RETCODE SCIPeventCreateObjChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldobj, SCIP_Real newobj)
Definition: event.c:605
internal methods for collecting primal CIP solutions and primal informations
SCIP_Real SCIPsolGetVal(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var)
Definition: sol.c:1372
static SCIP_RETCODE varParse(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, const char *str, char *name, SCIP_Real *lb, SCIP_Real *ub, SCIP_Real *obj, SCIP_VARTYPE *vartype, SCIP_Real *lazylb, SCIP_Real *lazyub, SCIP_Bool local, char **endptr, SCIP_Bool *success)
Definition: var.c:2350
SCIP_RETCODE SCIPvboundsAdd(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_BOUNDTYPE vboundtype, SCIP_VAR *var, SCIP_Real coef, SCIP_Real constant, SCIP_Bool *added)
Definition: implics.c:206
SCIP_DECL_HASHKEYVAL(SCIPvarGetHashkeyVal)
Definition: var.c:11989
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:12992
int nrootboundchgs
Definition: struct_stat.h:222
#define SCIP_DECL_VARDELTRANS(x)
Definition: type_var.h:164
SCIP_Bool SCIPsetIsGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c: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:7536
SCIP_HISTORY * glbhistorycrun
Definition: struct_stat.h:182
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:17717
const char * SCIPgetProbName(SCIP *scip)
Definition: scip_prob.c:1067
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:15918
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:13132
int SCIPvarGetNBdchgInfosUb(SCIP_VAR *var)
Definition: var.c:18333
void SCIPcliquelistFree(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem)
Definition: implics.c:1441
SCIP_Real conflictrelaxedub
Definition: struct_var.h:222
SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
Definition: tree.c:7444
SCIP_Bool SCIPbdchginfoIsTighter(SCIP_BDCHGINFO *bdchginfo1, SCIP_BDCHGINFO *bdchginfo2)
Definition: var.c:18656
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:7960
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17911
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:12208
SCIP_Real SCIPvarGetObjLP(SCIP_VAR *var)
Definition: var.c:12876
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:13806
void SCIPvarSetHistory(SCIP_VAR *var, SCIP_HISTORY *history, SCIP_STAT *stat)
Definition: var.c:4525
public methods for managing constraints
static SCIP_RETCODE varProcessChgBranchFactor(SCIP_VAR *var, SCIP_SET *set, SCIP_Real branchfactor)
Definition: var.c:11486
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:13458
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:17283
enum SCIP_Confidencelevel SCIP_CONFIDENCELEVEL
Definition: type_misc.h:53
SCIP_RETCODE SCIPvarChgBranchPriority(SCIP_VAR *var, int branchpriority)
Definition: var.c:11677
SCIP_Real SCIPvarGetPseudocost(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition: var.c:14467
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:16996
static SCIP_RETCODE varEventUbChanged(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real oldbound, SCIP_Real newbound)
Definition: var.c:7574
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:4540
void SCIPvarSetDeltransData(SCIP_VAR *var, SCIP_DECL_VARDELTRANS((*vardeltrans)))
Definition: var.c:17307
SCIP_RETCODE SCIPvarChgUbLazy(SCIP_VAR *var, SCIP_SET *set, SCIP_Real lazyub)
Definition: var.c:7482
SCIP_Real SCIPvarGetBestBoundGlobal(SCIP_VAR *var)
Definition: var.c:17931
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:7794
void SCIPvarMergeHistories(SCIP_VAR *targetvar, SCIP_VAR *othervar, SCIP_STAT *stat)
Definition: var.c:4509
enum SCIP_LockType SCIP_LOCKTYPE
Definition: type_var.h:100
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:3340
SCIP_Bool SCIPvarDoNotAggr(SCIP_VAR *var)
Definition: var.c:5838
internal methods for storing and manipulating the main problem
#define MAX_CLIQUELENGTH
Definition: var.c:13454
#define SCIPerrorMessage
Definition: pub_message.h:64
SCIP_Bool SCIPboundchgIsRedundant(SCIP_BOUNDCHG *boundchg)
Definition: var.c:17179
void SCIPlpDecNLoosevars(SCIP_LP *lp)
Definition: lp.c:14330
SCIP_Real SCIPvarGetLbOriginal(SCIP_VAR *var)
Definition: var.c:17847
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:16810
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:14917
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:18443
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:6254
int SCIPvarCompareActiveAndNegated(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11894
int lbchginfossize
Definition: struct_var.h:266
SCIP_Real SCIPvarGetAvgBranchdepthCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15822
unsigned int varstatus
Definition: struct_var.h:281
SCIP_RETCODE SCIPvarRelease(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:2873
SCIP_Real SCIPvarGetUbOriginal(SCIP_VAR *var)
Definition: var.c:17867
SCIP_Bool SCIPvarIsTransformedOrigvar(SCIP_VAR *var)
Definition: var.c:12851
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:6444
SCIP_EVENTTYPE eventmask
Definition: struct_event.h:198
SCIP_DECL_SORTPTRCOMP(SCIPvarCompActiveAndNegated)
Definition: var.c:11924
SCIP_Real SCIPvarGetPseudocostCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition: var.c:14516
SCIP_Real SCIPvarGetUbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16652
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:11121
SCIP_RETCODE SCIPvarAddLocks(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LOCKTYPE locktype, int addnlocksdown, int addnlocksup)
Definition: var.c:3168
SCIP_RETCODE SCIPvarGetTransformed(SCIP_VAR *origvar, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **transvar)
Definition: var.c:3549
#define SCIPdebugCheckAggregation(set, var, aggrvars, scalars, constant, naggrvars)
Definition: debug.h:293
SCIP_HOLECHG * holechgs
Definition: struct_var.h:153
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8090
union SCIP_BoundChg::@20 data
SCIP_Real * SCIPvarGetVubConstants(SCIP_VAR *var)
Definition: var.c:18167
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:7001
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:1898
SCIP_Real SCIPvarGetAggrConstant(SCIP_VAR *var)
Definition: var.c:17657
SCIP_Real SCIPcolGetLb(SCIP_COL *col)
Definition: lp.c:16963
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:173
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17242
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:5044
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:11975
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:14188
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:7627
SCIP_RETCODE SCIPvarSetRelaxSol(SCIP_VAR *var, SCIP_SET *set, SCIP_RELAXATION *relaxation, SCIP_Real solval, SCIP_Bool updateobj)
Definition: var.c:13852
SCIP_HISTORY * glbhistory
Definition: struct_stat.h:181
SCIP_Real SCIPboundchgGetNewbound(SCIP_BOUNDCHG *boundchg)
Definition: var.c:17139
SCIP_Real * SCIPvboundsGetCoefs(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3306
#define REALABS(x)
Definition: def.h:210
int nparentvars
Definition: struct_var.h:261
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition: var.c:18275
SCIP_Real unchangedobj
Definition: struct_var.h:210
SCIP_HOLELIST * SCIPvarGetHolelistGlobal(SCIP_VAR *var)
Definition: var.c:17921
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:9991
SCIP_Longint SCIPvarGetNActiveConflicts(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15258
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:17771
SCIP_Real SCIPvarCalcPscostConfidenceBound(SCIP_VAR *var, SCIP_SET *set, SCIP_BRANCHDIR dir, SCIP_Bool onlycurrentrun, SCIP_CONFIDENCELEVEL clevel)
Definition: var.c:14736
#define SCIP_CALL(x)
Definition: def.h:394
SCIP main data structure.
SCIP_Bool SCIPbdchginfoHasInferenceReason(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18642
SCIP_VBOUNDS * vubs
Definition: struct_var.h:244
SCIP_Real SCIPvarGetLbLazy(SCIP_VAR *var)
Definition: var.c:18039
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:18125
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:15437
SCIP_Real SCIPvarGetMultaggrConstant(SCIP_VAR *var)
Definition: var.c:17705
SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
Definition: var.c:17529
int SCIPprobGetNContVars(SCIP_PROB *prob)
Definition: prob.c:2388
SCIP_Real SCIPvarGetPseudocostCount(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14563
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:9710
static SCIP_VAR * varGetActiveVar(SCIP_VAR *var)
Definition: var.c:5789
SCIP_Real * SCIPvboundsGetConstants(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3314
SCIP_Real SCIPvarGetCutoffSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:16169
SCIP_Real * SCIPvarGetVubCoefs(SCIP_VAR *var)
Definition: var.c:18157
SCIP_Bool SCIPbdchginfoIsRedundant(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18631
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:14651
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:11621
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:8087
#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:18553
SCIP_Longint SCIPvarGetNActiveConflictsCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15305
SCIP_RETCODE SCIPvarPrint(SCIP_VAR *var, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: var.c:3007
unsigned int branchdirection
Definition: struct_var.h:283
int ubchginfossize
Definition: struct_var.h:268
SCIP_Bool SCIPcliquelistsHaveCommonClique(SCIP_CLIQUELIST *cliquelist1, SCIP_Bool value1, SCIP_CLIQUELIST *cliquelist2, SCIP_Bool value2)
Definition: implics.c:1605
SCIP_Bool SCIPsetIsFeasLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c: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:13837
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:6541
#define BMSfreeBlockMemory(mem, ptr)
Definition: memory.h:467
internal methods for problem variables
SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
Definition: var.c:17371
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:6219
SCIP_RETCODE SCIPvarChgBranchFactor(SCIP_VAR *var, SCIP_SET *set, SCIP_Real branchfactor)
Definition: var.c:11550
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:5282
#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:18211
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:15605
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:6676
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:17219
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:8983
#define SCIP_Bool
Definition: def.h:93
void SCIPvarCapture(SCIP_VAR *var)
Definition: var.c:2848
#define BMSreallocBlockMemorySize(mem, ptr, oldsize, newsize)
Definition: memory.h:458
SCIP_BOUNDCHGTYPE SCIPboundchgGetBoundchgtype(SCIP_BOUNDCHG *boundchg)
Definition: var.c:17159
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:4731
int SCIPbdchginfoGetPos(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18543
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:16941
SCIP_Real SCIPvarGetInferenceSumCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:16014
SCIP_Bool SCIPvarIsInLP(SCIP_VAR *var)
Definition: var.c:17623
SCIP_RETCODE SCIPvarRemove(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_CLIQUETABLE *cliquetable, SCIP_SET *set, SCIP_Bool final)
Definition: var.c:6049
SCIP_RETCODE SCIPconsRelease(SCIP_CONS **cons, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: cons.c:6208
void SCIPvarMarkRelaxationOnly(SCIP_VAR *var)
Definition: var.c:17547
void SCIPvarStoreRootSol(SCIP_VAR *var, SCIP_Bool roothaslp)
Definition: var.c:13259
SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
Definition: var.c:18288
int SCIPvarGetBranchPriority(SCIP_VAR *var)
Definition: var.c:18073
int SCIPgetDepth(SCIP *scip)
Definition: scip_tree.c:670
SCIP_RETCODE SCIPvarFix(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: var.c:3750
SCIP_Real SCIPvarGetLbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16533
SCIP_Bool divingobjchg
Definition: struct_lp.h:381
int SCIPvarGetNImpls(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18179
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:8329
#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:3361
SCIP_VARDATA * SCIPvarGetData(SCIP_VAR *var)
Definition: var.c:17262
SCIP_RETCODE SCIPcolChgLb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newlb)
Definition: lp.c:3757
int SCIPvarGetNLocksUp(SCIP_VAR *var)
Definition: var.c:3430
#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:3322
SCIP_RETCODE SCIPboundchgApply(SCIP_BOUNDCHG *boundchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, int depth, int pos, SCIP_Bool *cutoff)
Definition: var.c:629
SCIP_VAR * SCIPboundchgGetVar(SCIP_BOUNDCHG *boundchg)
Definition: var.c:17149
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11932
SCIP_Bool * SCIPcliqueGetValues(SCIP_CLIQUE *clique)
Definition: implics.c:3392
SCIP_BOUNDCHG * SCIPdomchgGetBoundchg(SCIP_DOMCHG *domchg, int pos)
Definition: var.c:17197
SCIP_Real SCIPvarGetUnchangedObj(SCIP_VAR *var)
Definition: var.c:17759
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:2644
SCIP_Real SCIPvarGetMultaggrUbGlobal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8622
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:17749
SCIP_RETCODE SCIPvarAddCliqueToList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:11383
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18493
SCIP_Real SCIPvarGetBestRootRedcost(SCIP_VAR *var)
Definition: var.c:13772
SCIP_VAR * SCIPvarGetAggrVar(SCIP_VAR *var)
Definition: var.c:17633
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:4414
int nuses
Definition: struct_var.h:262
SCIP_Real SCIPvarGetAvgInferencesCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:16114
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:11172
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:11422
#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:17612
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:8735
SCIP_RETCODE SCIPvarCopy(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP *sourcescip, SCIP_VAR *sourcevar, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global)
Definition: var.c:2160
SCIP_Real SCIPvarGetRelaxSol(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:13913
datastructures for problem statistics
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:17669
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:18225
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12764
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:6329
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:15177
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:9502
SCIP_NODE * SCIPgetFocusNode(SCIP *scip)
Definition: scip_tree.c:72
SCIP_RETCODE SCIPcolChgUb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newub)
Definition: lp.c:3802
SCIP_RETCODE SCIPcolFree(SCIP_COL **col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: lp.c:3377
SCIP * scip
Definition: struct_var.h:288
SCIP_EVENTFILTER * eventfilter
Definition: struct_var.h:247
static SCIP_Real SCIPvarGetPseudoSol_rec(SCIP_VAR *var)
Definition: var.c:13180
SCIP_BDCHGINFO * SCIPvarGetLbchgInfo(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16400
SCIP_Bool SCIPprobIsTransformed(SCIP_PROB *prob)
Definition: prob.c:2287
SCIP_BOUNDTYPE SCIPbdchginfoGetInferBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18610
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:16456
int conflictubcount
Definition: struct_var.h:271
int SCIPvboundsGetNVbds(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3290
SCIP_RETCODE SCIPvarGetProbvarBound(SCIP_VAR **var, SCIP_Real *bound, SCIP_BOUNDTYPE *boundtype)
Definition: var.c:12459
static SCIP_RETCODE parseValue(SCIP_SET *set, const char *str, SCIP_Real *value, char **endptr)
Definition: var.c:2273
SCIP_DOM locdom
Definition: struct_var.h:226
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoUb(SCIP_VAR *var, int pos)
Definition: var.c:18321
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:9783
SCIP_BDCHGINFO * SCIPvarGetBdchgInfo(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16512
#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:2945
static SCIP_RETCODE varAddLbchginfo(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real oldbound, SCIP_Real newbound, int depth, int pos, SCIP_VAR *infervar, SCIP_CONS *infercons, SCIP_PROP *inferprop, int inferinfo, SCIP_BOUNDTYPE inferboundtype, SCIP_BOUNDCHGTYPE boundchgtype)
Definition: var.c:480
#define SCIP_DECL_VARDELORIG(x)
Definition: type_var.h:131
SCIP_Real SCIPhistoryGetCutoffSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c: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:14260
SCIP_RETCODE SCIPvarLoose(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *prob, SCIP_LP *lp)
Definition: var.c:3614
SCIP_Real newbound
Definition: struct_var.h:93
#define SCIP_REAL_MIN
Definition: def.h:188
static SCIP_RETCODE varEventVarFixed(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, int fixeventtype)
Definition: var.c:3655
methods for sorting joint arrays of various types
SCIP_VAR ** parentvars
Definition: struct_var.h:241
SCIP_BRANCHDIR SCIPbranchdirOpposite(SCIP_BRANCHDIR dir)
Definition: history.c:430
SCIP_VAR ** SCIPvarGetImplVars(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18196
static SCIP_RETCODE varFreeParents(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:2672
SCIP_Real SCIPsetFeasFloor(SCIP_SET *set, SCIP_Real val)
Definition: set.c: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:7508
#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:3417
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:5743
SCIP_RETCODE SCIPvarMultiaggregate(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, int naggvars, SCIP_VAR **aggvars, SCIP_Real *scalars, SCIP_Real constant, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition: var.c:5436
int lpipos
Definition: struct_lp.h:173
SCIP_NODE * SCIPtreeGetRootNode(SCIP_TREE *tree)
Definition: tree.c:8454
int SCIPdomchgGetNBoundchgs(SCIP_DOMCHG *domchg)
Definition: var.c:17189
SCIP_RETCODE SCIPvarColumn(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_LP *lp)
Definition: var.c:3580
SCIP_RETCODE 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:18533
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:3919
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:14851
SCIP_RETCODE SCIPvarMarkDoNotAggr(SCIP_VAR *var)
Definition: var.c:6096
SCIP_DECL_HASHKEYEQ(SCIPvarIsHashkeyEq)
Definition: var.c:11981
SCIP_Real SCIPvarGetBestRootSol(SCIP_VAR *var)
Definition: var.c:13705
SCIP_VAR * var
Definition: struct_var.h:119
public methods for message output
data structures for LP management
int nrootboundchgsrun
Definition: struct_stat.h:223
void SCIPcliquelistCheck(SCIP_CLIQUELIST *cliquelist, SCIP_VAR *var)
Definition: implics.c:3464
SCIP_VAR * a
Definition: circlepacking.c:66
void SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr,...)
Definition: message.c:618
void SCIPvarSetCopyData(SCIP_VAR *var, SCIP_DECL_VARCOPY((*varcopy)))
Definition: var.c:17318
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:9274
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:17209
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:17361
SCIP_RETCODE SCIPvarResetBounds(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat)
Definition: var.c:9221
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:9403
#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:2745
SCIP_RETCODE SCIPdomchgApply(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, int depth, SCIP_Bool *cutoff)
Definition: var.c:1300
SCIP_Longint SCIPvarGetNBranchings(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15689
SCIP_RETCODE SCIPvarsGetProbvarBinary(SCIP_VAR ***vars, SCIP_Bool **negatedarr, int nvars)
Definition: var.c:12268
SCIP_VAR * SCIPbdchginfoGetInferVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18563
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:17329
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:12552
SCIP_RETCODE SCIPlpUpdateVarLoose(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:14309
SCIP_Real SCIPvarGetVSIDS(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:18366
#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:17252
void SCIPvarsGetProbvar(SCIP_VAR **vars, int nvars)
Definition: var.c:12188
SCIP_RETCODE SCIPvarParseTransformed(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, const char *str, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARCOPY((*varcopy)), SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_VARDATA *vardata, char **endptr, SCIP_Bool *success)
Definition: var.c:2561
static SCIP_RETCODE parseBounds(SCIP_SET *set, const char *str, char *type, SCIP_Real *lb, SCIP_Real *ub, char **endptr)
Definition: var.c:2305
SCIP_VAR ** SCIPvarGetVubVars(SCIP_VAR *var)
Definition: var.c:18147
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:18013
SCIP_CONS * SCIPbdchginfoGetInferCons(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18575
SCIP_Bool SCIPsetIsDualfeasZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6934
SCIP_Real SCIPvarGetAvgSol(SCIP_VAR *var)
Definition: var.c:14052
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:17581
SCIP_Real nlpsol
Definition: struct_var.h:217
SCIP_VAR * lastbranchvar
Definition: struct_stat.h:183
static SCIP_RETCODE varEnsureParentvarsSize(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: var.c:2620
SCIP_Real SCIPvarGetAvgCutoffs(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:16255
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:9112
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:17407
SCIP_Real SCIPvarGetMultaggrUbLocal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8490
SCIP_RETCODE SCIPvarChgName(SCIP_VAR *var, BMS_BLKMEM *blkmem, const char *name)
Definition: var.c:2914
SCIP_DOM glbdom
Definition: struct_var.h:225
SCIP_Real SCIPsetEpsilon(SCIP_SET *set)
Definition: set.c: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:73
static SCIP_RETCODE varEventGubChanged(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real oldbound, SCIP_Real newbound)
Definition: var.c:6714
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:17509
SCIP_Bool SCIPcliqueIsCleanedUp(SCIP_CLIQUE *clique)
Definition: implics.c:3426
SCIP_Real newbound
Definition: struct_var.h:118
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17967
int SCIPcliqueGetNVars(SCIP_CLIQUE *clique)
Definition: implics.c:3370
SCIP_RETCODE SCIPvarAddHoleOriginal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real left, SCIP_Real right)
Definition: var.c:8683
void SCIPbdchginfoFree(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem)
Definition: var.c:16386
void SCIPvarAdjustUb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *ub)
Definition: var.c:6524
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:17384
static void varIncRootboundchgs(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat)
Definition: var.c:6784
#define BMSallocBlockMemory(mem, ptr)
Definition: memory.h:453
SCIP_HOLELIST * SCIPvarGetHolelistLocal(SCIP_VAR *var)
Definition: var.c:17977
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:18523
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:18408
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:14185
SCIP_HISTORY * history
Definition: struct_var.h:250
SCIP_RETCODE SCIPvarSetRemovable(SCIP_VAR *var, SCIP_Bool removable)
Definition: var.c:17345
SCIP_Real SCIPvarGetVSIDS_rec(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15867
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:12637
#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:18353
enum SCIP_BoundchgType SCIP_BOUNDCHGTYPE
Definition: type_var.h:91
SCIP_Real * SCIPimplicsGetBounds(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3349
SCIP_ORIGINAL original
Definition: struct_var.h:229
SCIP_Real SCIPcolGetRedcost(SCIP_COL *col, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:3952
SCIP_VAR * SCIPvarGetTransVar(SCIP_VAR *var)
Definition: var.c:17601
#define SCIP_ALLOC(x)
Definition: def.h:405
#define SCIPABORT()
Definition: def.h:366
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:17433
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:8424
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:17463
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:11345
void SCIPvarGetImplicVarBounds(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_Real *lb, SCIP_Real *ub)
Definition: var.c:11136
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:6085
void SCIPvarSetData(SCIP_VAR *var, SCIP_VARDATA *vardata)
Definition: var.c:17272
SCIP_Bool SCIPcolIsInLP(SCIP_COL *col)
Definition: lp.c:17115
SCIP_COL * col
Definition: struct_var.h:230
SCIP_RETCODE SCIPvarNegate(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **negvar)
Definition: var.c:5907
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:3452
#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:11741
SCIP_Bool SCIPvarMayRoundDown(SCIP_VAR *var)
Definition: var.c:3441
SCIP_RETCODE SCIPprobAddVar(SCIP_PROB *prob, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR *var)
Definition: prob.c: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:14682
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:17571
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:14986
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:17397
SCIP_RETCODE SCIProwAddConstant(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_Real addval)
Definition: lp.c:5640
SCIP_Real scalar
Definition: struct_var.h:185
uint64_t SCIP_EVENTTYPE
Definition: type_event.h:151
void SCIPvarMarkDeleteGlobalStructures(SCIP_VAR *var)
Definition: var.c:17499
SCIP_BOUNDCHGTYPE SCIPbdchginfoGetChgtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18513
SCIP_RETCODE SCIPvarDelCliqueFromList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:11405