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 2002-2022 Zuse Institute Berlin */
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 infered 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 infered 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 infered 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 infered bound change */
568  )
569 {
570  assert(var != NULL);
571  assert(SCIPsetIsGT(set, oldbound, newbound));
572  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, oldbound));
573  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
574  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, oldbound, 1.0));
575  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, 0.0));
576  assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
577  assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
578  assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
579 
580  SCIPsetDebugMsg(set, "adding upper bound change info to var <%s>[%g,%g]: depth=%d, pos=%d, infer%s=<%s>, inferinfo=%d, %g -> %g\n",
581  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, depth, pos, infercons != NULL ? "cons" : "prop",
582  infercons != NULL ? SCIPconsGetName(infercons) : (inferprop != NULL ? SCIPpropGetName(inferprop) : "-"), inferinfo,
583  oldbound, newbound);
584 
585  SCIP_CALL( varEnsureUbchginfosSize(var, blkmem, set, var->nubchginfos+1) );
586  var->ubchginfos[var->nubchginfos].oldbound = oldbound;
587  var->ubchginfos[var->nubchginfos].newbound = newbound;
588  var->ubchginfos[var->nubchginfos].var = var;
589  var->ubchginfos[var->nubchginfos].bdchgidx.depth = depth;
590  var->ubchginfos[var->nubchginfos].bdchgidx.pos = pos;
591  var->ubchginfos[var->nubchginfos].pos = var->nubchginfos; /*lint !e732*/
592  var->ubchginfos[var->nubchginfos].boundchgtype = boundchgtype; /*lint !e641*/
593  var->ubchginfos[var->nubchginfos].boundtype = SCIP_BOUNDTYPE_UPPER; /*lint !e641*/
594  var->ubchginfos[var->nubchginfos].redundant = FALSE;
595  var->ubchginfos[var->nubchginfos].inferboundtype = inferboundtype; /*lint !e641*/
596  var->ubchginfos[var->nubchginfos].inferencedata.var = infervar;
597  var->ubchginfos[var->nubchginfos].inferencedata.info = inferinfo;
598 
599  /**@note The "pos" data member of the bound change info has a size of 27 bits */
600  assert(var->nubchginfos < 1 << 27);
601 
602  switch( boundchgtype )
603  {
605  break;
607  assert(infercons != NULL);
608  var->ubchginfos[var->nubchginfos].inferencedata.reason.cons = infercons;
609  break;
611  var->ubchginfos[var->nubchginfos].inferencedata.reason.prop = inferprop;
612  break;
613  default:
614  SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
615  return SCIP_INVALIDDATA;
616  }
617 
618  var->nubchginfos++;
619 
620  assert(var->nubchginfos < 2
622  &var->ubchginfos[var->nubchginfos-1].bdchgidx));
623 
624  return SCIP_OKAY;
625 }
626 
627 /** applies single bound change */
629  SCIP_BOUNDCHG* boundchg, /**< bound change to apply */
630  BMS_BLKMEM* blkmem, /**< block memory */
631  SCIP_SET* set, /**< global SCIP settings */
632  SCIP_STAT* stat, /**< problem statistics */
633  SCIP_LP* lp, /**< current LP data */
634  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
635  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
636  int depth, /**< depth in the tree, where the bound change takes place */
637  int pos, /**< position of the bound change in its bound change array */
638  SCIP_Bool* cutoff /**< pointer to store whether an infeasible bound change was detected */
639  )
640 {
641  SCIP_VAR* var;
642 
643  assert(boundchg != NULL);
644  assert(stat != NULL);
645  assert(depth > 0);
646  assert(pos >= 0);
647  assert(cutoff != NULL);
648 
649  *cutoff = FALSE;
650 
651  /* ignore redundant bound changes */
652  if( boundchg->redundant )
653  return SCIP_OKAY;
654 
655  var = boundchg->var;
656  assert(var != NULL);
658  assert(!SCIPvarIsIntegral(var) || SCIPsetIsFeasIntegral(set, boundchg->newbound));
659 
660  /* apply bound change */
661  switch( boundchg->boundtype )
662  {
664  /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
665  if( SCIPsetIsGT(set, boundchg->newbound, var->locdom.lb) )
666  {
667  if( SCIPsetIsLE(set, boundchg->newbound, var->locdom.ub) )
668  {
669  /* add the bound change info to the variable's bound change info array */
670  switch( boundchg->boundchgtype )
671  {
673  SCIPsetDebugMsg(set, " -> branching: new lower bound of <%s>[%g,%g]: %g\n",
674  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
675  SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
677  stat->lastbranchvar = var;
679  stat->lastbranchvalue = boundchg->newbound;
680  break;
681 
683  assert(boundchg->data.inferencedata.reason.cons != NULL);
684  SCIPsetDebugMsg(set, " -> constraint <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
685  SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
686  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
687  SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
688  boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
689  boundchg->data.inferencedata.info,
691  break;
692 
694  SCIPsetDebugMsg(set, " -> propagator <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
695  boundchg->data.inferencedata.reason.prop != NULL
696  ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
697  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
698  SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
699  boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
700  boundchg->data.inferencedata.info,
702  break;
703 
704  default:
705  SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
706  return SCIP_INVALIDDATA;
707  }
708 
709  /* change local bound of variable */
710  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, boundchg->newbound) );
711  }
712  else
713  {
714  SCIPsetDebugMsg(set, " -> cutoff: new lower bound of <%s>[%g,%g]: %g\n",
715  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
716  *cutoff = TRUE;
717  boundchg->redundant = TRUE; /* bound change has not entered the lbchginfos array of the variable! */
718  }
719  }
720  else
721  {
722  /* mark bound change to be inactive */
723  SCIPsetDebugMsg(set, " -> inactive %s: new lower bound of <%s>[%g,%g]: %g\n",
724  (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
725  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
726  boundchg->redundant = TRUE;
727  }
728  break;
729 
731  /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
732  if( SCIPsetIsLT(set, boundchg->newbound, var->locdom.ub) )
733  {
734  if( SCIPsetIsGE(set, boundchg->newbound, var->locdom.lb) )
735  {
736  /* add the bound change info to the variable's bound change info array */
737  switch( boundchg->boundchgtype )
738  {
740  SCIPsetDebugMsg(set, " -> branching: new upper bound of <%s>[%g,%g]: %g\n",
741  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
742  SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
744  stat->lastbranchvar = var;
746  stat->lastbranchvalue = boundchg->newbound;
747  break;
748 
750  assert(boundchg->data.inferencedata.reason.cons != NULL);
751  SCIPsetDebugMsg(set, " -> constraint <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
752  SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
753  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
754  SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
755  boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
756  boundchg->data.inferencedata.info,
758  break;
759 
761  SCIPsetDebugMsg(set, " -> propagator <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
762  boundchg->data.inferencedata.reason.prop != NULL
763  ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
764  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
765  SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
766  boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
767  boundchg->data.inferencedata.info,
769  break;
770 
771  default:
772  SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
773  return SCIP_INVALIDDATA;
774  }
775 
776  /* change local bound of variable */
777  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, boundchg->newbound) );
778  }
779  else
780  {
781  SCIPsetDebugMsg(set, " -> cutoff: new upper bound of <%s>[%g,%g]: %g\n",
782  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
783  *cutoff = TRUE;
784  boundchg->redundant = TRUE; /* bound change has not entered the ubchginfos array of the variable! */
785  }
786  }
787  else
788  {
789  /* mark bound change to be inactive */
790  SCIPsetDebugMsg(set, " -> inactive %s: new upper bound of <%s>[%g,%g]: %g\n",
791  (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
792  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
793  boundchg->redundant = TRUE;
794  }
795  break;
796 
797  default:
798  SCIPerrorMessage("unknown bound type\n");
799  return SCIP_INVALIDDATA;
800  }
801 
802  /* update the branching and inference history */
803  if( !boundchg->applied && !boundchg->redundant )
804  {
805  assert(var == boundchg->var);
806 
808  {
809  SCIP_CALL( SCIPvarIncNBranchings(var, blkmem, set, stat,
812  }
813  else if( stat->lastbranchvar != NULL )
814  {
815  /**@todo if last branching variable is unknown, retrieve it from the nodes' boundchg arrays */
816  SCIP_CALL( SCIPvarIncInferenceSum(stat->lastbranchvar, blkmem, set, stat, stat->lastbranchdir, stat->lastbranchvalue, 1.0) );
817  }
818  boundchg->applied = TRUE;
819  }
820 
821  return SCIP_OKAY;
822 }
823 
824 /** undoes single bound change */
826  SCIP_BOUNDCHG* boundchg, /**< bound change to remove */
827  BMS_BLKMEM* blkmem, /**< block memory */
828  SCIP_SET* set, /**< global SCIP settings */
829  SCIP_STAT* stat, /**< problem statistics */
830  SCIP_LP* lp, /**< current LP data */
831  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
832  SCIP_EVENTQUEUE* eventqueue /**< event queue */
833  )
834 {
835  SCIP_VAR* var;
836 
837  assert(boundchg != NULL);
838  assert(stat != NULL);
839 
840  /* ignore redundant bound changes */
841  if( boundchg->redundant )
842  return SCIP_OKAY;
843 
844  var = boundchg->var;
845  assert(var != NULL);
847 
848  /* undo bound change: apply the previous bound change of variable */
849  switch( boundchg->boundtype )
850  {
852  var->nlbchginfos--;
853  assert(var->nlbchginfos >= 0);
854  assert(var->lbchginfos != NULL);
855  assert( SCIPsetIsFeasEQ(set, var->lbchginfos[var->nlbchginfos].newbound, var->locdom.lb) ); /*lint !e777*/
856  assert( SCIPsetIsFeasLE(set, boundchg->newbound, var->locdom.lb) ); /* current lb might be larger to intermediate global bound change */
857 
858  SCIPsetDebugMsg(set, "removed lower bound change info of var <%s>[%g,%g]: depth=%d, pos=%d, %g -> %g\n",
859  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub,
862 
863  /* reinstall the previous local bound */
864  SCIP_CALL( SCIPvarChgLbLocal(boundchg->var, blkmem, set, stat, lp, branchcand, eventqueue,
865  var->lbchginfos[var->nlbchginfos].oldbound) );
866 
867  /* in case all bound changes are removed the local bound should match the global bound */
868  assert(var->nlbchginfos > 0 || SCIPsetIsFeasEQ(set, var->locdom.lb, var->glbdom.lb));
869 
870  break;
871 
873  var->nubchginfos--;
874  assert(var->nubchginfos >= 0);
875  assert(var->ubchginfos != NULL);
876  assert( SCIPsetIsFeasEQ(set, var->ubchginfos[var->nubchginfos].newbound, var->locdom.ub) ); /*lint !e777*/
877  assert( SCIPsetIsFeasGE(set, boundchg->newbound, var->locdom.ub) ); /* current ub might be smaller to intermediate global bound change */
878 
879  SCIPsetDebugMsg(set, "removed upper bound change info of var <%s>[%g,%g]: depth=%d, pos=%d, %g -> %g\n",
880  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub,
883 
884  /* reinstall the previous local bound */
885  SCIP_CALL( SCIPvarChgUbLocal(boundchg->var, blkmem, set, stat, lp, branchcand, eventqueue,
886  var->ubchginfos[var->nubchginfos].oldbound) );
887 
888  /* in case all bound changes are removed the local bound should match the global bound */
889  assert(var->nubchginfos > 0 || SCIPsetIsFeasEQ(set, var->locdom.ub, var->glbdom.ub));
890 
891  break;
892 
893  default:
894  SCIPerrorMessage("unknown bound type\n");
895  return SCIP_INVALIDDATA;
896  }
897 
898  /* update last branching variable */
900  {
901  stat->lastbranchvar = NULL;
903  }
904 
905  return SCIP_OKAY;
906 }
907 
908 /** applies single bound change to the global problem by changing the global bound of the corresponding variable */
909 static
911  SCIP_BOUNDCHG* boundchg, /**< bound change to apply */
912  BMS_BLKMEM* blkmem, /**< block memory */
913  SCIP_SET* set, /**< global SCIP settings */
914  SCIP_STAT* stat, /**< problem statistics */
915  SCIP_LP* lp, /**< current LP data */
916  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
917  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
918  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
919  SCIP_Bool* cutoff /**< pointer to store whether an infeasible bound change was detected */
920  )
921 {
922  SCIP_VAR* var;
923  SCIP_Real newbound;
924  SCIP_BOUNDTYPE boundtype;
925 
926  assert(boundchg != NULL);
927  assert(cutoff != NULL);
928 
929  *cutoff = FALSE;
930 
931  /* ignore redundant bound changes */
932  if( boundchg->redundant )
933  return SCIP_OKAY;
934 
935  var = SCIPboundchgGetVar(boundchg);
936  newbound = SCIPboundchgGetNewbound(boundchg);
937  boundtype = SCIPboundchgGetBoundtype(boundchg);
938 
939  /* check if the bound change is redundant which can happen due to a (better) global bound change which was performed
940  * after that bound change was applied
941  *
942  * @note a global bound change is not captured by the redundant member of the bound change data structure
943  */
944  if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasLE(set, newbound, SCIPvarGetLbGlobal(var)))
945  || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasGE(set, newbound, SCIPvarGetUbGlobal(var))) )
946  {
947  return SCIP_OKAY;
948  }
949 
950  SCIPsetDebugMsg(set, "applying global bound change: <%s>[%g,%g] %s %g\n",
952  boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", newbound);
953 
954  /* check for cutoff */
955  if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGT(set, newbound, SCIPvarGetUbGlobal(var)))
956  || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLT(set, newbound, SCIPvarGetLbGlobal(var))) )
957  {
958  *cutoff = TRUE;
959  return SCIP_OKAY;
960  }
961 
962  /* apply bound change */
963  SCIP_CALL( SCIPvarChgBdGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound, boundtype) );
964 
965  return SCIP_OKAY;
966 }
967 
968 /** captures branching and inference data of bound change */
969 static
971  SCIP_BOUNDCHG* boundchg /**< bound change to remove */
972  )
973 {
974  assert(boundchg != NULL);
975 
976  /* capture variable associated with the bound change */
977  assert(boundchg->var != NULL);
978  SCIPvarCapture(boundchg->var);
979 
980  switch( boundchg->boundchgtype )
981  {
984  break;
985 
987  assert(boundchg->data.inferencedata.var != NULL);
988  assert(boundchg->data.inferencedata.reason.cons != NULL);
989  SCIPconsCapture(boundchg->data.inferencedata.reason.cons);
990  break;
991 
992  default:
993  SCIPerrorMessage("invalid bound change type\n");
994  return SCIP_INVALIDDATA;
995  }
996 
997  return SCIP_OKAY;
998 }
999 
1000 /** releases branching and inference data of bound change */
1001 static
1003  SCIP_BOUNDCHG* boundchg, /**< bound change to remove */
1004  BMS_BLKMEM* blkmem, /**< block memory */
1005  SCIP_SET* set, /**< global SCIP settings */
1006  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1007  SCIP_LP* lp /**< current LP data */
1008 
1009  )
1010 {
1011  assert(boundchg != NULL);
1012 
1013  switch( boundchg->boundchgtype )
1014  {
1017  break;
1018 
1020  assert(boundchg->data.inferencedata.var != NULL);
1021  assert(boundchg->data.inferencedata.reason.cons != NULL);
1022  SCIP_CALL( SCIPconsRelease(&boundchg->data.inferencedata.reason.cons, blkmem, set) );
1023  break;
1024 
1025  default:
1026  SCIPerrorMessage("invalid bound change type\n");
1027  return SCIP_INVALIDDATA;
1028  }
1029 
1030  /* release variable */
1031  assert(boundchg->var != NULL);
1032  SCIP_CALL( SCIPvarRelease(&boundchg->var, blkmem, set, eventqueue, lp) );
1033 
1034  return SCIP_OKAY;
1035 }
1036 
1037 /** creates empty domain change data with dynamic arrays */
1038 static
1040  SCIP_DOMCHG** domchg, /**< pointer to domain change data */
1041  BMS_BLKMEM* blkmem /**< block memory */
1042  )
1043 {
1044  assert(domchg != NULL);
1045  assert(blkmem != NULL);
1046 
1047  SCIP_ALLOC( BMSallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN)) );
1048  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1049  (*domchg)->domchgdyn.nboundchgs = 0;
1050  (*domchg)->domchgdyn.boundchgs = NULL;
1051  (*domchg)->domchgdyn.nholechgs = 0;
1052  (*domchg)->domchgdyn.holechgs = NULL;
1053  (*domchg)->domchgdyn.boundchgssize = 0;
1054  (*domchg)->domchgdyn.holechgssize = 0;
1055 
1056  return SCIP_OKAY;
1057 }
1058 
1059 /** frees domain change data */
1061  SCIP_DOMCHG** domchg, /**< pointer to domain change */
1062  BMS_BLKMEM* blkmem, /**< block memory */
1063  SCIP_SET* set, /**< global SCIP settings */
1064  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1065  SCIP_LP* lp /**< current LP data */
1066  )
1067 {
1068  assert(domchg != NULL);
1069  assert(blkmem != NULL);
1070 
1071  if( *domchg != NULL )
1072  {
1073  int i;
1074 
1075  /* release variables, branching and inference data associated with the bound changes */
1076  for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1077  {
1078  SCIP_CALL( boundchgReleaseData(&(*domchg)->domchgbound.boundchgs[i], blkmem, set, eventqueue, lp) );
1079  }
1080 
1081  /* free memory for bound and hole changes */
1082  switch( (*domchg)->domchgdyn.domchgtype )
1083  {
1084  case SCIP_DOMCHGTYPE_BOUND:
1085  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgbound.boundchgs, (*domchg)->domchgbound.nboundchgs);
1086  BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOUND));
1087  break;
1088  case SCIP_DOMCHGTYPE_BOTH:
1089  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgboth.boundchgs, (*domchg)->domchgboth.nboundchgs);
1090  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgboth.holechgs, (*domchg)->domchgboth.nholechgs);
1091  BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH));
1092  break;
1094  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.boundchgs, (*domchg)->domchgdyn.boundchgssize);
1095  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.holechgs, (*domchg)->domchgdyn.holechgssize);
1096  BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN));
1097  break;
1098  default:
1099  SCIPerrorMessage("invalid domain change type\n");
1100  return SCIP_INVALIDDATA;
1101  }
1102  }
1103 
1104  return SCIP_OKAY;
1105 }
1106 
1107 /** converts a static domain change data into a dynamic one */
1108 static
1110  SCIP_DOMCHG** domchg, /**< pointer to domain change data */
1111  BMS_BLKMEM* blkmem /**< block memory */
1112  )
1113 {
1114  assert(domchg != NULL);
1115  assert(blkmem != NULL);
1116 
1117  SCIPdebugMessage("making domain change data %p pointing to %p dynamic\n", (void*)domchg, (void*)*domchg);
1118 
1119  if( *domchg == NULL )
1120  {
1121  SCIP_CALL( domchgCreate(domchg, blkmem) );
1122  }
1123  else
1124  {
1125  switch( (*domchg)->domchgdyn.domchgtype )
1126  {
1127  case SCIP_DOMCHGTYPE_BOUND:
1128  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOUND), sizeof(SCIP_DOMCHGDYN)) );
1129  (*domchg)->domchgdyn.nholechgs = 0;
1130  (*domchg)->domchgdyn.holechgs = NULL;
1131  (*domchg)->domchgdyn.boundchgssize = (int) (*domchg)->domchgdyn.nboundchgs;
1132  (*domchg)->domchgdyn.holechgssize = 0;
1133  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1134  break;
1135  case SCIP_DOMCHGTYPE_BOTH:
1136  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH), sizeof(SCIP_DOMCHGDYN)) );
1137  (*domchg)->domchgdyn.boundchgssize = (int) (*domchg)->domchgdyn.nboundchgs;
1138  (*domchg)->domchgdyn.holechgssize = (*domchg)->domchgdyn.nholechgs;
1139  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1140  break;
1142  break;
1143  default:
1144  SCIPerrorMessage("invalid domain change type\n");
1145  return SCIP_INVALIDDATA;
1146  }
1147  }
1148 #ifndef NDEBUG
1149  {
1150  int i;
1151  for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1152  assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1153  || EPSISINT((*domchg)->domchgbound.boundchgs[i].newbound, 1e-06));
1154  }
1155 #endif
1156 
1157  return SCIP_OKAY;
1158 }
1159 
1160 /** converts a dynamic domain change data into a static one, using less memory than for a dynamic one */
1162  SCIP_DOMCHG** domchg, /**< pointer to domain change data */
1163  BMS_BLKMEM* blkmem, /**< block memory */
1164  SCIP_SET* set, /**< global SCIP settings */
1165  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1166  SCIP_LP* lp /**< current LP data */
1167  )
1168 {
1169  assert(domchg != NULL);
1170  assert(blkmem != NULL);
1171 
1172  SCIPsetDebugMsg(set, "making domain change data %p pointing to %p static\n", (void*)domchg, (void*)*domchg);
1173 
1174  if( *domchg != NULL )
1175  {
1176  switch( (*domchg)->domchgdyn.domchgtype )
1177  {
1178  case SCIP_DOMCHGTYPE_BOUND:
1179  if( (*domchg)->domchgbound.nboundchgs == 0 )
1180  {
1181  SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1182  }
1183  break;
1184  case SCIP_DOMCHGTYPE_BOTH:
1185  if( (*domchg)->domchgboth.nholechgs == 0 )
1186  {
1187  if( (*domchg)->domchgbound.nboundchgs == 0 )
1188  {
1189  SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1190  }
1191  else
1192  {
1193  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH), sizeof(SCIP_DOMCHGBOUND)) );
1194  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOUND; /*lint !e641*/
1195  }
1196  }
1197  break;
1199  if( (*domchg)->domchgboth.nholechgs == 0 )
1200  {
1201  if( (*domchg)->domchgbound.nboundchgs == 0 )
1202  {
1203  SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1204  }
1205  else
1206  {
1207  /* shrink dynamic size arrays to their minimal sizes */
1208  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.boundchgs, \
1209  (*domchg)->domchgdyn.boundchgssize, (*domchg)->domchgdyn.nboundchgs) ); /*lint !e571*/
1210  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.holechgs, (*domchg)->domchgdyn.holechgssize);
1211 
1212  /* convert into static domain change */
1213  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN), sizeof(SCIP_DOMCHGBOUND)) );
1214  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOUND; /*lint !e641*/
1215  }
1216  }
1217  else
1218  {
1219  /* shrink dynamic size arrays to their minimal sizes */
1220  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.boundchgs, \
1221  (*domchg)->domchgdyn.boundchgssize, (*domchg)->domchgdyn.nboundchgs) ); /*lint !e571*/
1222  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.holechgs, \
1223  (*domchg)->domchgdyn.holechgssize, (*domchg)->domchgdyn.nholechgs) );
1224 
1225  /* convert into static domain change */
1226  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN), sizeof(SCIP_DOMCHGBOTH)) );
1227  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOTH; /*lint !e641*/
1228  }
1229  break;
1230  default:
1231  SCIPerrorMessage("invalid domain change type\n");
1232  return SCIP_INVALIDDATA;
1233  }
1234 #ifndef NDEBUG
1235  if( *domchg != NULL )
1236  {
1237  int i;
1238  for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1239  assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1240  || SCIPsetIsFeasIntegral(set, (*domchg)->domchgbound.boundchgs[i].newbound));
1241  }
1242 #endif
1243  }
1244 
1245  return SCIP_OKAY;
1246 }
1247 
1248 /** ensures, that boundchgs array can store at least num entries */
1249 static
1251  SCIP_DOMCHG* domchg, /**< domain change data structure */
1252  BMS_BLKMEM* blkmem, /**< block memory */
1253  SCIP_SET* set, /**< global SCIP settings */
1254  int num /**< minimum number of entries to store */
1255  )
1256 {
1257  assert(domchg != NULL);
1258  assert(domchg->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1259 
1260  if( num > domchg->domchgdyn.boundchgssize )
1261  {
1262  int newsize;
1263 
1264  newsize = SCIPsetCalcMemGrowSize(set, num);
1265  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &domchg->domchgdyn.boundchgs, domchg->domchgdyn.boundchgssize, newsize) );
1266  domchg->domchgdyn.boundchgssize = newsize;
1267  }
1268  assert(num <= domchg->domchgdyn.boundchgssize);
1269 
1270  return SCIP_OKAY;
1271 }
1272 
1273 /** ensures, that holechgs array can store at least num additional entries */
1274 static
1276  SCIP_DOMCHG* domchg, /**< domain change data structure */
1277  BMS_BLKMEM* blkmem, /**< block memory */
1278  SCIP_SET* set, /**< global SCIP settings */
1279  int num /**< minimum number of additional entries to store */
1280  )
1281 {
1282  assert(domchg != NULL);
1283  assert(domchg->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1284 
1285  if( num > domchg->domchgdyn.holechgssize )
1286  {
1287  int newsize;
1288 
1289  newsize = SCIPsetCalcMemGrowSize(set, num);
1290  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &domchg->domchgdyn.holechgs, domchg->domchgdyn.holechgssize, newsize) );
1291  domchg->domchgdyn.holechgssize = newsize;
1292  }
1293  assert(num <= domchg->domchgdyn.holechgssize);
1294 
1295  return SCIP_OKAY;
1296 }
1297 
1298 /** applies domain change */
1300  SCIP_DOMCHG* domchg, /**< domain change to apply */
1301  BMS_BLKMEM* blkmem, /**< block memory */
1302  SCIP_SET* set, /**< global SCIP settings */
1303  SCIP_STAT* stat, /**< problem statistics */
1304  SCIP_LP* lp, /**< current LP data */
1305  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1306  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1307  int depth, /**< depth in the tree, where the domain change takes place */
1308  SCIP_Bool* cutoff /**< pointer to store whether an infeasible domain change was detected */
1309  )
1310 {
1311  int i;
1312 
1313  assert(cutoff != NULL);
1314 
1315  *cutoff = FALSE;
1316 
1317  SCIPsetDebugMsg(set, "applying domain changes at %p in depth %d\n", (void*)domchg, depth);
1318 
1319  if( domchg == NULL )
1320  return SCIP_OKAY;
1321 
1322  /* apply bound changes */
1323  for( i = 0; i < (int)domchg->domchgbound.nboundchgs; ++i )
1324  {
1325  SCIP_CALL( SCIPboundchgApply(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp,
1326  branchcand, eventqueue, depth, i, cutoff) );
1327  if( *cutoff )
1328  break;
1329  }
1330  SCIPsetDebugMsg(set, " -> %u bound changes (cutoff %u)\n", domchg->domchgbound.nboundchgs, *cutoff);
1331 
1332  /* mark all bound changes after a cutoff redundant */
1333  for( ; i < (int)domchg->domchgbound.nboundchgs; ++i )
1334  domchg->domchgbound.boundchgs[i].redundant = TRUE;
1335 
1336  /* apply holelist changes */
1337  if( domchg->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_BOUND ) /*lint !e641*/
1338  {
1339  for( i = 0; i < domchg->domchgboth.nholechgs; ++i )
1340  *(domchg->domchgboth.holechgs[i].ptr) = domchg->domchgboth.holechgs[i].newlist;
1341  SCIPsetDebugMsg(set, " -> %d hole changes\n", domchg->domchgboth.nholechgs);
1342  }
1343 
1344  return SCIP_OKAY;
1345 }
1346 
1347 /** undoes domain change */
1349  SCIP_DOMCHG* domchg, /**< domain change to remove */
1350  BMS_BLKMEM* blkmem, /**< block memory */
1351  SCIP_SET* set, /**< global SCIP settings */
1352  SCIP_STAT* stat, /**< problem statistics */
1353  SCIP_LP* lp, /**< current LP data */
1354  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1355  SCIP_EVENTQUEUE* eventqueue /**< event queue */
1356  )
1357 {
1358  int i;
1359 
1360  SCIPsetDebugMsg(set, "undoing domain changes at %p\n", (void*)domchg);
1361  if( domchg == NULL )
1362  return SCIP_OKAY;
1363 
1364  /* undo holelist changes */
1365  if( domchg->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_BOUND ) /*lint !e641*/
1366  {
1367  for( i = domchg->domchgboth.nholechgs-1; i >= 0; --i )
1368  *(domchg->domchgboth.holechgs[i].ptr) = domchg->domchgboth.holechgs[i].oldlist;
1369  SCIPsetDebugMsg(set, " -> %d hole changes\n", domchg->domchgboth.nholechgs);
1370  }
1371 
1372  /* undo bound changes */
1373  for( i = domchg->domchgbound.nboundchgs-1; i >= 0; --i )
1374  {
1375  SCIP_CALL( SCIPboundchgUndo(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp, branchcand, eventqueue) );
1376  }
1377  SCIPsetDebugMsg(set, " -> %u bound changes\n", domchg->domchgbound.nboundchgs);
1378 
1379  return SCIP_OKAY;
1380 }
1381 
1382 /** applies domain change to the global problem */
1384  SCIP_DOMCHG* domchg, /**< domain change to apply */
1385  BMS_BLKMEM* blkmem, /**< block memory */
1386  SCIP_SET* set, /**< global SCIP settings */
1387  SCIP_STAT* stat, /**< problem statistics */
1388  SCIP_LP* lp, /**< current LP data */
1389  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1390  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1391  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1392  SCIP_Bool* cutoff /**< pointer to store whether an infeasible domain change was detected */
1393  )
1394 {
1395  int i;
1396 
1397  assert(cutoff != NULL);
1398 
1399  *cutoff = FALSE;
1400 
1401  if( domchg == NULL )
1402  return SCIP_OKAY;
1403 
1404  SCIPsetDebugMsg(set, "applying domain changes at %p to the global problem\n", (void*)domchg);
1405 
1406  /* apply bound changes */
1407  for( i = 0; i < (int)domchg->domchgbound.nboundchgs; ++i )
1408  {
1409  SCIP_CALL( boundchgApplyGlobal(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp,
1410  branchcand, eventqueue, cliquetable, cutoff) );
1411  if( *cutoff )
1412  break;
1413  }
1414  SCIPsetDebugMsg(set, " -> %u global bound changes\n", domchg->domchgbound.nboundchgs);
1415 
1416  /**@todo globally apply holelist changes - how can this be done without confusing pointer updates? */
1417 
1418  return SCIP_OKAY;
1419 }
1420 
1421 /** adds bound change to domain changes */
1423  SCIP_DOMCHG** domchg, /**< pointer to domain change data structure */
1424  BMS_BLKMEM* blkmem, /**< block memory */
1425  SCIP_SET* set, /**< global SCIP settings */
1426  SCIP_VAR* var, /**< variable to change the bounds for */
1427  SCIP_Real newbound, /**< new value for bound */
1428  SCIP_BOUNDTYPE boundtype, /**< type of bound for var: lower or upper bound */
1429  SCIP_BOUNDCHGTYPE boundchgtype, /**< type of bound change: branching decision or inference */
1430  SCIP_Real lpsolval, /**< solval of variable in last LP on path to node, or SCIP_INVALID if unknown */
1431  SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself), or NULL */
1432  SCIP_CONS* infercons, /**< constraint that deduced the bound change, or NULL */
1433  SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
1434  int inferinfo, /**< user information for inference to help resolving the conflict */
1435  SCIP_BOUNDTYPE inferboundtype /**< type of bound for inference var: lower or upper bound */
1436  )
1437 {
1438  SCIP_BOUNDCHG* boundchg;
1439 
1440  assert(domchg != NULL);
1441  assert(var != NULL);
1443  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
1444  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, boundtype == SCIP_BOUNDTYPE_LOWER ? 1.0 : 0.0));
1445  assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
1446  assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
1447  assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
1448 
1449  SCIPsetDebugMsg(set, "adding %s bound change <%s: %g> of variable <%s> to domain change at %p pointing to %p\n",
1450  boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
1451  newbound, var->name, (void*)domchg, (void*)*domchg);
1452 
1453  /* if domain change data doesn't exist, create it;
1454  * if domain change is static, convert it into dynamic change
1455  */
1456  if( *domchg == NULL )
1457  {
1458  SCIP_CALL( domchgCreate(domchg, blkmem) );
1459  }
1460  else if( (*domchg)->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_DYNAMIC ) /*lint !e641*/
1461  {
1462  SCIP_CALL( domchgMakeDynamic(domchg, blkmem) );
1463  }
1464  assert(*domchg != NULL && (*domchg)->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1465 
1466  /* get memory for additional bound change */
1467  SCIP_CALL( domchgEnsureBoundchgsSize(*domchg, blkmem, set, (*domchg)->domchgdyn.nboundchgs+1) );
1468 
1469  /* fill in the bound change data */
1470  boundchg = &(*domchg)->domchgdyn.boundchgs[(*domchg)->domchgdyn.nboundchgs];
1471  boundchg->var = var;
1472  switch( boundchgtype )
1473  {
1475  boundchg->data.branchingdata.lpsolval = lpsolval;
1476  break;
1478  assert(infercons != NULL);
1479  boundchg->data.inferencedata.var = infervar;
1480  boundchg->data.inferencedata.reason.cons = infercons;
1481  boundchg->data.inferencedata.info = inferinfo;
1482  break;
1484  boundchg->data.inferencedata.var = infervar;
1485  boundchg->data.inferencedata.reason.prop = inferprop;
1486  boundchg->data.inferencedata.info = inferinfo;
1487  break;
1488  default:
1489  SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
1490  return SCIP_INVALIDDATA;
1491  }
1492 
1493  boundchg->newbound = newbound;
1494  boundchg->boundchgtype = boundchgtype; /*lint !e641*/
1495  boundchg->boundtype = boundtype; /*lint !e641*/
1496  boundchg->inferboundtype = inferboundtype; /*lint !e641*/
1497  boundchg->applied = FALSE;
1498  boundchg->redundant = FALSE;
1499  (*domchg)->domchgdyn.nboundchgs++;
1500 
1501  /* capture branching and inference data associated with the bound changes */
1502  SCIP_CALL( boundchgCaptureData(boundchg) );
1503 
1504 #ifdef SCIP_DISABLED_CODE /* expensive debug check */
1505 #ifdef SCIP_MORE_DEBUG
1506  {
1507  int i;
1508  for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1509  assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1510  || SCIPsetIsFeasIntegral(set, (*domchg)->domchgbound.boundchgs[i].newbound));
1511  }
1512 #endif
1513 #endif
1514 
1515  return SCIP_OKAY;
1516 }
1517 
1518 /** adds hole change to domain changes */
1520  SCIP_DOMCHG** domchg, /**< pointer to domain change data structure */
1521  BMS_BLKMEM* blkmem, /**< block memory */
1522  SCIP_SET* set, /**< global SCIP settings */
1523  SCIP_HOLELIST** ptr, /**< changed list pointer */
1524  SCIP_HOLELIST* newlist, /**< new value of list pointer */
1525  SCIP_HOLELIST* oldlist /**< old value of list pointer */
1526  )
1527 {
1528  SCIP_HOLECHG* holechg;
1529 
1530  assert(domchg != NULL);
1531  assert(ptr != NULL);
1532 
1533  /* if domain change data doesn't exist, create it;
1534  * if domain change is static, convert it into dynamic change
1535  */
1536  if( *domchg == NULL )
1537  {
1538  SCIP_CALL( domchgCreate(domchg, blkmem) );
1539  }
1540  else if( (*domchg)->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_DYNAMIC ) /*lint !e641*/
1541  {
1542  SCIP_CALL( domchgMakeDynamic(domchg, blkmem) );
1543  }
1544  assert(*domchg != NULL && (*domchg)->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1545 
1546  /* get memory for additional hole change */
1547  SCIP_CALL( domchgEnsureHolechgsSize(*domchg, blkmem, set, (*domchg)->domchgdyn.nholechgs+1) );
1548 
1549  /* fill in the hole change data */
1550  holechg = &(*domchg)->domchgdyn.holechgs[(*domchg)->domchgdyn.nholechgs];
1551  holechg->ptr = ptr;
1552  holechg->newlist = newlist;
1553  holechg->oldlist = oldlist;
1554  (*domchg)->domchgdyn.nholechgs++;
1555 
1556  return SCIP_OKAY;
1557 }
1558 
1559 
1560 
1561 
1562 /*
1563  * methods for variables
1564  */
1565 
1566 /** returns adjusted lower bound value, which is rounded for integral variable types */
1567 static
1569  SCIP_SET* set, /**< global SCIP settings */
1570  SCIP_VARTYPE vartype, /**< type of variable */
1571  SCIP_Real lb /**< lower bound to adjust */
1572  )
1573 {
1574  if( lb < 0.0 && SCIPsetIsInfinity(set, -lb) )
1575  return -SCIPsetInfinity(set);
1576  else if( lb > 0.0 && SCIPsetIsInfinity(set, lb) )
1577  return SCIPsetInfinity(set);
1578  else if( vartype != SCIP_VARTYPE_CONTINUOUS )
1579  return SCIPsetFeasCeil(set, lb);
1580  else if( lb > 0.0 && lb < SCIPsetEpsilon(set) )
1581  return 0.0;
1582  else
1583  return lb;
1584 }
1585 
1586 /** returns adjusted upper bound value, which is rounded for integral variable types */
1587 static
1589  SCIP_SET* set, /**< global SCIP settings */
1590  SCIP_VARTYPE vartype, /**< type of variable */
1591  SCIP_Real ub /**< upper bound to adjust */
1592  )
1593 {
1594  if( ub > 0.0 && SCIPsetIsInfinity(set, ub) )
1595  return SCIPsetInfinity(set);
1596  else if( ub < 0.0 && SCIPsetIsInfinity(set, -ub) )
1597  return -SCIPsetInfinity(set);
1598  else if( vartype != SCIP_VARTYPE_CONTINUOUS )
1599  return SCIPsetFeasFloor(set, ub);
1600  else if( ub < 0.0 && ub > -SCIPsetEpsilon(set) )
1601  return 0.0;
1602  else
1603  return ub;
1604 }
1605 
1606 /** removes (redundant) cliques, implications and variable bounds of variable from all other variables' implications and variable
1607  * bounds arrays, and optionally removes them also from the variable itself
1608  */
1610  SCIP_VAR* var, /**< problem variable */
1611  BMS_BLKMEM* blkmem, /**< block memory */
1612  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1613  SCIP_SET* set, /**< global SCIP settings */
1614  SCIP_Bool irrelevantvar, /**< has the variable become irrelevant? */
1615  SCIP_Bool onlyredundant, /**< should only the redundant implications and variable bounds be removed? */
1616  SCIP_Bool removefromvar /**< should the implications and variable bounds be removed from the var itself? */
1617  )
1618 {
1619  SCIP_Real lb;
1620  SCIP_Real ub;
1621 
1622  assert(var != NULL);
1624  assert(SCIPvarIsActive(var) || SCIPvarGetType(var) != SCIP_VARTYPE_BINARY);
1625 
1626  lb = SCIPvarGetLbGlobal(var);
1627  ub = SCIPvarGetUbGlobal(var);
1628 
1629  SCIPsetDebugMsg(set, "removing %s implications and vbounds of %s<%s>[%g,%g]\n",
1630  onlyredundant ? "redundant" : "all", irrelevantvar ? "irrelevant " : "", SCIPvarGetName(var), lb, ub);
1631 
1632  /* remove implications of (fixed) binary variable */
1633  if( var->implics != NULL && (!onlyredundant || lb > 0.5 || ub < 0.5) )
1634  {
1635  SCIP_Bool varfixing;
1636 
1637  assert(SCIPvarIsBinary(var));
1638 
1639  varfixing = FALSE;
1640  do
1641  {
1642  SCIP_VAR** implvars;
1643  SCIP_BOUNDTYPE* impltypes;
1644  int nimpls;
1645  int i;
1646 
1647  nimpls = SCIPimplicsGetNImpls(var->implics, varfixing);
1648  implvars = SCIPimplicsGetVars(var->implics, varfixing);
1649  impltypes = SCIPimplicsGetTypes(var->implics, varfixing);
1650 
1651  for( i = 0; i < nimpls; i++ )
1652  {
1653  SCIP_VAR* implvar;
1654  SCIP_BOUNDTYPE impltype;
1655 
1656  implvar = implvars[i];
1657  impltype = impltypes[i];
1658  assert(implvar != var);
1659 
1660  /* remove for all implications z == 0 / 1 ==> x <= p / x >= p (x not binary)
1661  * the following variable bound from x's variable bounds
1662  * x <= b*z+d (z in vubs of x) , for z == 0 / 1 ==> x <= p
1663  * x >= b*z+d (z in vlbs of x) , for z == 0 / 1 ==> x >= p
1664  */
1665  if( impltype == SCIP_BOUNDTYPE_UPPER )
1666  {
1667  if( implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1668  {
1669  SCIPsetDebugMsg(set, "deleting variable bound: <%s> == %u ==> <%s> <= %g\n",
1670  SCIPvarGetName(var), varfixing, SCIPvarGetName(implvar),
1671  SCIPimplicsGetBounds(var->implics, varfixing)[i]);
1672  SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, varfixing) );
1673  implvar->closestvblpcount = -1;
1674  var->closestvblpcount = -1;
1675  }
1676  }
1677  else
1678  {
1679  if( implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1680  {
1681  SCIPsetDebugMsg(set, "deleting variable bound: <%s> == %u ==> <%s> >= %g\n",
1682  SCIPvarGetName(var), varfixing, SCIPvarGetName(implvar),
1683  SCIPimplicsGetBounds(var->implics, varfixing)[i]);
1684  SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, !varfixing) );
1685  implvar->closestvblpcount = -1;
1686  var->closestvblpcount = -1;
1687  }
1688  }
1689  }
1690  varfixing = !varfixing;
1691  }
1692  while( varfixing == TRUE );
1693 
1694  if( removefromvar )
1695  {
1696  /* free the implications data structures */
1697  SCIPimplicsFree(&var->implics, blkmem);
1698  }
1699  }
1700 
1701  /* remove the (redundant) variable lower bounds */
1702  if( var->vlbs != NULL )
1703  {
1704  SCIP_VAR** vars;
1705  SCIP_Real* coefs;
1706  SCIP_Real* constants;
1707  int nvbds;
1708  int newnvbds;
1709  int i;
1710 
1711  nvbds = SCIPvboundsGetNVbds(var->vlbs);
1712  vars = SCIPvboundsGetVars(var->vlbs);
1713  coefs = SCIPvboundsGetCoefs(var->vlbs);
1714  constants = SCIPvboundsGetConstants(var->vlbs);
1715 
1716  /* remove for all variable bounds x >= b*z+d the following implication from z's implications
1717  * z == ub ==> x >= b*ub + d , if b > 0
1718  * z == lb ==> x >= b*lb + d , if b < 0
1719  */
1720  newnvbds = 0;
1721  for( i = 0; i < nvbds; i++ )
1722  {
1723  SCIP_VAR* implvar;
1724  SCIP_Real coef;
1725 
1726  assert(newnvbds <= i);
1727 
1728  implvar = vars[i];
1729  assert(implvar != NULL);
1730 
1731  coef = coefs[i];
1732  assert(!SCIPsetIsZero(set, coef));
1733 
1734  /* check, if we want to remove the variable bound */
1735  if( onlyredundant )
1736  {
1737  SCIP_Real vbound;
1738 
1739  vbound = MAX(coef * SCIPvarGetUbGlobal(implvar), coef * SCIPvarGetLbGlobal(implvar)) + constants[i]; /*lint !e666*/
1740  if( SCIPsetIsFeasGT(set, vbound, lb) )
1741  {
1742  /* the variable bound is not redundant: keep it */
1743  if( removefromvar )
1744  {
1745  if( newnvbds < i )
1746  {
1747  vars[newnvbds] = implvar;
1748  coefs[newnvbds] = coef;
1749  constants[newnvbds] = constants[i];
1750  }
1751  newnvbds++;
1752  }
1753  continue;
1754  }
1755  }
1756 
1757  /* remove the corresponding implication */
1758  if( implvar->implics != NULL ) /* variable may have been aggregated in the mean time */
1759  {
1760  SCIPsetDebugMsg(set, "deleting implication: <%s> == %d ==> <%s> >= %g\n",
1761  SCIPvarGetName(implvar), (coef > 0.0), SCIPvarGetName(var), MAX(coef, 0.0) + constants[i]);
1762  SCIP_CALL( SCIPimplicsDel(&implvar->implics, blkmem, set, (coef > 0.0), var, SCIP_BOUNDTYPE_LOWER) );
1763  }
1764  if( coef > 0.0 && implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1765  {
1766  SCIPsetDebugMsg(set, "deleting variable upper bound from <%s> involving variable %s\n",
1767  SCIPvarGetName(implvar), SCIPvarGetName(var));
1768  SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, FALSE) );
1769  implvar->closestvblpcount = -1;
1770  var->closestvblpcount = -1;
1771  }
1772  else if( coef < 0.0 && implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1773  {
1774  SCIPsetDebugMsg(set, "deleting variable lower bound from <%s> involving variable %s\n",
1775  SCIPvarGetName(implvar), SCIPvarGetName(var));
1776  SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, TRUE) );
1777  implvar->closestvblpcount = -1;
1778  var->closestvblpcount = -1;
1779  }
1780  }
1781 
1782  if( removefromvar )
1783  {
1784  /* update the number of variable bounds */
1785  SCIPvboundsShrink(&var->vlbs, blkmem, newnvbds);
1786  var->closestvblpcount = -1;
1787  }
1788  }
1789 
1790  /**@todo in general, variable bounds like x >= b*z + d corresponding to an implication like z = ub ==> x >= b*ub + d
1791  * might be missing because we only add variable bounds with reasonably small value of b. thus, we currently
1792  * cannot remove such variables x from z's implications.
1793  */
1794 
1795  /* remove the (redundant) variable upper bounds */
1796  if( var->vubs != NULL )
1797  {
1798  SCIP_VAR** vars;
1799  SCIP_Real* coefs;
1800  SCIP_Real* constants;
1801  int nvbds;
1802  int newnvbds;
1803  int i;
1804 
1805  nvbds = SCIPvboundsGetNVbds(var->vubs);
1806  vars = SCIPvboundsGetVars(var->vubs);
1807  coefs = SCIPvboundsGetCoefs(var->vubs);
1808  constants = SCIPvboundsGetConstants(var->vubs);
1809 
1810  /* remove for all variable bounds x <= b*z+d the following implication from z's implications
1811  * z == lb ==> x <= b*lb + d , if b > 0
1812  * z == ub ==> x <= b*ub + d , if b < 0
1813  */
1814  newnvbds = 0;
1815  for( i = 0; i < nvbds; i++ )
1816  {
1817  SCIP_VAR* implvar;
1818  SCIP_Real coef;
1819 
1820  assert(newnvbds <= i);
1821 
1822  implvar = vars[i];
1823  assert(implvar != NULL);
1824 
1825  coef = coefs[i];
1826  assert(!SCIPsetIsZero(set, coef));
1827 
1828  /* check, if we want to remove the variable bound */
1829  if( onlyredundant )
1830  {
1831  SCIP_Real vbound;
1832 
1833  vbound = MIN(coef * SCIPvarGetUbGlobal(implvar), coef * SCIPvarGetLbGlobal(implvar)) + constants[i]; /*lint !e666*/
1834  if( SCIPsetIsFeasLT(set, vbound, ub) )
1835  {
1836  /* the variable bound is not redundant: keep it */
1837  if( removefromvar )
1838  {
1839  if( newnvbds < i )
1840  {
1841  vars[newnvbds] = implvar;
1842  coefs[newnvbds] = coefs[i];
1843  constants[newnvbds] = constants[i];
1844  }
1845  newnvbds++;
1846  }
1847  continue;
1848  }
1849  }
1850 
1851  /* remove the corresponding implication */
1852  if( implvar->implics != NULL ) /* variable may have been aggregated in the mean time */
1853  {
1854  SCIPsetDebugMsg(set, "deleting implication: <%s> == %d ==> <%s> <= %g\n",
1855  SCIPvarGetName(implvar), (coef < 0.0), SCIPvarGetName(var), MIN(coef, 0.0) + constants[i]);
1856  SCIP_CALL( SCIPimplicsDel(&implvar->implics, blkmem, set, (coef < 0.0), var, SCIP_BOUNDTYPE_UPPER) );
1857  }
1858  if( coef < 0.0 && implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1859  {
1860  SCIPsetDebugMsg(set, "deleting variable upper bound from <%s> involving variable %s\n",
1861  SCIPvarGetName(implvar), SCIPvarGetName(var));
1862  SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, TRUE) );
1863  implvar->closestvblpcount = -1;
1864  var->closestvblpcount = -1;
1865  }
1866  else if( coef > 0.0 && implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1867  {
1868  SCIPsetDebugMsg(set, "deleting variable lower bound from <%s> involving variable %s\n",
1869  SCIPvarGetName(implvar), SCIPvarGetName(var));
1870  SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, FALSE) );
1871  implvar->closestvblpcount = -1;
1872  var->closestvblpcount = -1;
1873  }
1874  }
1875 
1876  if( removefromvar )
1877  {
1878  /* update the number of variable bounds */
1879  SCIPvboundsShrink(&var->vubs, blkmem, newnvbds);
1880  var->closestvblpcount = -1;
1881  }
1882  }
1883 
1884  /* remove the variable from all cliques */
1885  if( SCIPvarIsBinary(var) )
1886  {
1887  SCIPcliquelistRemoveFromCliques(var->cliquelist, cliquetable, var, irrelevantvar);
1888  SCIPcliquelistFree(&var->cliquelist, blkmem);
1889  }
1890 
1891  /**@todo variable bounds like x <= b*z + d with z general integer are not removed from x's vbd arrays, because
1892  * z has no link (like in the binary case) to x
1893  */
1894 
1895  return SCIP_OKAY;
1896 }
1897 
1898 /** sets the variable name */
1899 static
1901  SCIP_VAR* var, /**< problem variable */
1902  BMS_BLKMEM* blkmem, /**< block memory */
1903  SCIP_STAT* stat, /**< problem statistics, or NULL */
1904  const char* name /**< name of variable, or NULL for automatic name creation */
1905  )
1906 {
1907  assert(blkmem != NULL);
1908  assert(var != NULL);
1909 
1910  if( name == NULL )
1911  {
1912  char s[SCIP_MAXSTRLEN];
1913 
1914  assert(stat != NULL);
1915 
1916  (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "_var%d_", stat->nvaridx);
1917  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->name, s, strlen(s)+1) );
1918  }
1919  else
1920  {
1921  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->name, name, strlen(name)+1) );
1922  }
1923 
1924  return SCIP_OKAY;
1925 }
1926 
1927 
1928 /** creates variable; if variable is of integral type, fractional bounds are automatically rounded; an integer variable
1929  * with bounds zero and one is automatically converted into a binary variable
1930  */
1931 static
1933  SCIP_VAR** var, /**< pointer to variable data */
1934  BMS_BLKMEM* blkmem, /**< block memory */
1935  SCIP_SET* set, /**< global SCIP settings */
1936  SCIP_STAT* stat, /**< problem statistics */
1937  const char* name, /**< name of variable, or NULL for automatic name creation */
1938  SCIP_Real lb, /**< lower bound of variable */
1939  SCIP_Real ub, /**< upper bound of variable */
1940  SCIP_Real obj, /**< objective function value */
1941  SCIP_VARTYPE vartype, /**< type of variable */
1942  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
1943  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
1944  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
1945  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
1946  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
1947  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
1948  SCIP_VARDATA* vardata /**< user data for this specific variable */
1949  )
1950 {
1951  int i;
1952 
1953  assert(var != NULL);
1954  assert(blkmem != NULL);
1955  assert(stat != NULL);
1956 
1957  /* adjust bounds of variable */
1958  lb = adjustedLb(set, vartype, lb);
1959  ub = adjustedUb(set, vartype, ub);
1960 
1961  /* convert [0,1]-integers into binary variables and check that binary variables have correct bounds */
1962  if( (SCIPsetIsEQ(set, lb, 0.0) || SCIPsetIsEQ(set, lb, 1.0))
1963  && (SCIPsetIsEQ(set, ub, 0.0) || SCIPsetIsEQ(set, ub, 1.0)) )
1964  {
1965  if( vartype == SCIP_VARTYPE_INTEGER )
1966  vartype = SCIP_VARTYPE_BINARY;
1967  }
1968  else
1969  {
1970  if( vartype == SCIP_VARTYPE_BINARY )
1971  {
1972  SCIPerrorMessage("invalid bounds [%.2g,%.2g] for binary variable <%s>\n", lb, ub, name);
1973  return SCIP_INVALIDDATA;
1974  }
1975  }
1976 
1977  assert(vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, lb, 0.0) || SCIPsetIsEQ(set, lb, 1.0));
1978  assert(vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, ub, 0.0) || SCIPsetIsEQ(set, ub, 1.0));
1979 
1980  SCIP_ALLOC( BMSallocBlockMemory(blkmem, var) );
1981 
1982  /* set variable's name */
1983  SCIP_CALL( varSetName(*var, blkmem, stat, name) );
1984 
1985 #ifndef NDEBUG
1986  (*var)->scip = set->scip;
1987 #endif
1988  (*var)->obj = obj;
1989  (*var)->unchangedobj = obj;
1990  (*var)->branchfactor = 1.0;
1991  (*var)->rootsol = 0.0;
1992  (*var)->bestrootsol = 0.0;
1993  (*var)->bestrootredcost = 0.0;
1994  (*var)->bestrootlpobjval = SCIP_INVALID;
1995  (*var)->relaxsol = 0.0;
1996  (*var)->nlpsol = 0.0;
1997  (*var)->primsolavg = 0.5 * (lb + ub);
1998  (*var)->conflictlb = SCIP_REAL_MIN;
1999  (*var)->conflictub = SCIP_REAL_MAX;
2000  (*var)->conflictrelaxedlb = (*var)->conflictlb;
2001  (*var)->conflictrelaxedub = (*var)->conflictub;
2002  (*var)->lazylb = -SCIPsetInfinity(set);
2003  (*var)->lazyub = SCIPsetInfinity(set);
2004  (*var)->glbdom.holelist = NULL;
2005  (*var)->glbdom.lb = lb;
2006  (*var)->glbdom.ub = ub;
2007  (*var)->locdom.holelist = NULL;
2008  (*var)->locdom.lb = lb;
2009  (*var)->locdom.ub = ub;
2010  (*var)->varcopy = varcopy;
2011  (*var)->vardelorig = vardelorig;
2012  (*var)->vartrans = vartrans;
2013  (*var)->vardeltrans = vardeltrans;
2014  (*var)->vardata = vardata;
2015  (*var)->parentvars = NULL;
2016  (*var)->negatedvar = NULL;
2017  (*var)->vlbs = NULL;
2018  (*var)->vubs = NULL;
2019  (*var)->implics = NULL;
2020  (*var)->cliquelist = NULL;
2021  (*var)->eventfilter = NULL;
2022  (*var)->lbchginfos = NULL;
2023  (*var)->ubchginfos = NULL;
2024  (*var)->index = stat->nvaridx;
2025  (*var)->probindex = -1;
2026  (*var)->pseudocandindex = -1;
2027  (*var)->eventqueueindexobj = -1;
2028  (*var)->eventqueueindexlb = -1;
2029  (*var)->eventqueueindexub = -1;
2030  (*var)->parentvarssize = 0;
2031  (*var)->nparentvars = 0;
2032  (*var)->nuses = 0;
2033  (*var)->branchpriority = 0;
2034  (*var)->branchdirection = SCIP_BRANCHDIR_AUTO; /*lint !e641*/
2035  (*var)->lbchginfossize = 0;
2036  (*var)->nlbchginfos = 0;
2037  (*var)->ubchginfossize = 0;
2038  (*var)->nubchginfos = 0;
2039  (*var)->conflictlbcount = 0;
2040  (*var)->conflictubcount = 0;
2041  (*var)->closestvlbidx = -1;
2042  (*var)->closestvubidx = -1;
2043  (*var)->closestvblpcount = -1;
2044  (*var)->initial = initial;
2045  (*var)->removable = removable;
2046  (*var)->deleted = FALSE;
2047  (*var)->donotaggr = FALSE;
2048  (*var)->donotmultaggr = FALSE;
2049  (*var)->vartype = vartype; /*lint !e641*/
2050  (*var)->pseudocostflag = FALSE;
2051  (*var)->eventqueueimpl = FALSE;
2052  (*var)->deletable = FALSE;
2053  (*var)->delglobalstructs = FALSE;
2054  (*var)->relaxationonly = FALSE;
2055 
2056  for( i = 0; i < NLOCKTYPES; i++ )
2057  {
2058  (*var)->nlocksdown[i] = 0;
2059  (*var)->nlocksup[i] = 0;
2060  }
2061 
2062  stat->nvaridx++;
2063 
2064  /* create branching and inference history entries */
2065  SCIP_CALL( SCIPhistoryCreate(&(*var)->history, blkmem) );
2066  SCIP_CALL( SCIPhistoryCreate(&(*var)->historycrun, blkmem) );
2067 
2068  /* the value based history is only created on demand */
2069  (*var)->valuehistory = NULL;
2070 
2071  return SCIP_OKAY;
2072 }
2073 
2074 /** creates and captures an original problem variable; an integer variable with bounds
2075  * zero and one is automatically converted into a binary variable
2076  */
2078  SCIP_VAR** var, /**< pointer to variable data */
2079  BMS_BLKMEM* blkmem, /**< block memory */
2080  SCIP_SET* set, /**< global SCIP settings */
2081  SCIP_STAT* stat, /**< problem statistics */
2082  const char* name, /**< name of variable, or NULL for automatic name creation */
2083  SCIP_Real lb, /**< lower bound of variable */
2084  SCIP_Real ub, /**< upper bound of variable */
2085  SCIP_Real obj, /**< objective function value */
2086  SCIP_VARTYPE vartype, /**< type of variable */
2087  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2088  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2089  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2090  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2091  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2092  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2093  SCIP_VARDATA* vardata /**< user data for this specific variable */
2094  )
2095 {
2096  assert(var != NULL);
2097  assert(blkmem != NULL);
2098  assert(stat != NULL);
2099 
2100  /* create variable */
2101  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2102  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2103 
2104  /* set variable status and data */
2105  (*var)->varstatus = SCIP_VARSTATUS_ORIGINAL; /*lint !e641*/
2106  (*var)->data.original.origdom.holelist = NULL;
2107  (*var)->data.original.origdom.lb = lb;
2108  (*var)->data.original.origdom.ub = ub;
2109  (*var)->data.original.transvar = NULL;
2110 
2111  /* capture variable */
2112  SCIPvarCapture(*var);
2113 
2114  return SCIP_OKAY;
2115 }
2116 
2117 /** creates and captures a loose variable belonging to the transformed problem; an integer variable with bounds
2118  * zero and one is automatically converted into a binary variable
2119  */
2121  SCIP_VAR** var, /**< pointer to variable data */
2122  BMS_BLKMEM* blkmem, /**< block memory */
2123  SCIP_SET* set, /**< global SCIP settings */
2124  SCIP_STAT* stat, /**< problem statistics */
2125  const char* name, /**< name of variable, or NULL for automatic name creation */
2126  SCIP_Real lb, /**< lower bound of variable */
2127  SCIP_Real ub, /**< upper bound of variable */
2128  SCIP_Real obj, /**< objective function value */
2129  SCIP_VARTYPE vartype, /**< type of variable */
2130  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2131  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2132  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2133  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2134  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2135  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2136  SCIP_VARDATA* vardata /**< user data for this specific variable */
2137  )
2138 {
2139  assert(var != NULL);
2140  assert(blkmem != NULL);
2141 
2142  /* create variable */
2143  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2144  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2145 
2146  /* create event filter for transformed variable */
2147  SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
2148 
2149  /* set variable status and data */
2150  (*var)->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
2151 
2152  /* capture variable */
2153  SCIPvarCapture(*var);
2154 
2155  return SCIP_OKAY;
2156 }
2157 
2158 /** copies and captures a variable from source to target SCIP; an integer variable with bounds zero and one is
2159  * automatically converted into a binary variable; in case the variable data cannot be copied the variable is not
2160  * copied at all
2161  */
2163  SCIP_VAR** var, /**< pointer to store the target variable */
2164  BMS_BLKMEM* blkmem, /**< block memory */
2165  SCIP_SET* set, /**< global SCIP settings */
2166  SCIP_STAT* stat, /**< problem statistics */
2167  SCIP* sourcescip, /**< source SCIP data structure */
2168  SCIP_VAR* sourcevar, /**< source variable */
2169  SCIP_HASHMAP* varmap, /**< a hashmap to store the mapping of source variables corresponding
2170  * target variables */
2171  SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
2172  * target constraints */
2173  SCIP_Bool global /**< should global or local bounds be used? */
2174  )
2175 {
2176  SCIP_VARDATA* targetdata;
2177  SCIP_RESULT result;
2178  SCIP_Real lb;
2179  SCIP_Real ub;
2180 
2181  assert(set != NULL);
2182  assert(blkmem != NULL);
2183  assert(stat != NULL);
2184  assert(sourcescip != NULL);
2185  assert(sourcevar != NULL);
2186  assert(var != NULL);
2187  assert(set->stage == SCIP_STAGE_PROBLEM);
2188  assert(varmap != NULL);
2189  assert(consmap != NULL);
2190 
2191  /** @todo copy hole lists */
2192  assert(global || SCIPvarGetHolelistLocal(sourcevar) == NULL);
2193  assert(!global || SCIPvarGetHolelistGlobal(sourcevar) == NULL);
2194 
2195  result = SCIP_DIDNOTRUN;
2196  targetdata = NULL;
2197 
2198  if( SCIPvarGetStatus(sourcevar) == SCIP_VARSTATUS_ORIGINAL )
2199  {
2200  lb = SCIPvarGetLbOriginal(sourcevar);
2201  ub = SCIPvarGetUbOriginal(sourcevar);
2202  }
2203  else
2204  {
2205  lb = global ? SCIPvarGetLbGlobal(sourcevar) : SCIPvarGetLbLocal(sourcevar);
2206  ub = global ? SCIPvarGetUbGlobal(sourcevar) : SCIPvarGetUbLocal(sourcevar);
2207  }
2208 
2209  /* creates and captures the variable in the target SCIP and initialize callback methods and variable data to NULL */
2210  SCIP_CALL( SCIPvarCreateOriginal(var, blkmem, set, stat, SCIPvarGetName(sourcevar),
2211  lb, ub, SCIPvarGetObj(sourcevar), SCIPvarGetType(sourcevar),
2212  SCIPvarIsInitial(sourcevar), SCIPvarIsRemovable(sourcevar),
2213  NULL, NULL, NULL, NULL, NULL) );
2214  assert(*var != NULL);
2215 
2216  /* directly copy donot(mult)aggr flag */
2217  (*var)->donotaggr = sourcevar->donotaggr;
2218  (*var)->donotmultaggr = sourcevar->donotmultaggr;
2219 
2220  /* insert variable into mapping between source SCIP and the target SCIP */
2221  assert(!SCIPhashmapExists(varmap, sourcevar));
2222  SCIP_CALL( SCIPhashmapInsert(varmap, sourcevar, *var) );
2223 
2224  /* in case there exists variable data and the variable data copy callback, try to copy variable data */
2225  if( sourcevar->vardata != NULL && sourcevar->varcopy != NULL )
2226  {
2227  SCIP_CALL( sourcevar->varcopy(set->scip, sourcescip, sourcevar, sourcevar->vardata,
2228  varmap, consmap, (*var), &targetdata, &result) );
2229 
2230  /* evaluate result */
2231  if( result != SCIP_DIDNOTRUN && result != SCIP_SUCCESS )
2232  {
2233  SCIPerrorMessage("variable data copying method returned invalid result <%d>\n", result);
2234  return SCIP_INVALIDRESULT;
2235  }
2236 
2237  assert(targetdata == NULL || result == SCIP_SUCCESS);
2238 
2239  /* if copying was successful, add the created variable data to the variable as well as all callback methods */
2240  if( result == SCIP_SUCCESS )
2241  {
2242  (*var)->varcopy = sourcevar->varcopy;
2243  (*var)->vardelorig = sourcevar->vardelorig;
2244  (*var)->vartrans = sourcevar->vartrans;
2245  (*var)->vardeltrans = sourcevar->vardeltrans;
2246  (*var)->vardata = targetdata;
2247  }
2248  }
2249 
2250  /* we initialize histories of the variables by copying the source variable-information */
2251  if( set->history_allowtransfer )
2252  {
2253  SCIPvarMergeHistories((*var), sourcevar, stat);
2254  }
2255 
2256  /* in case the copying was successfully, add the created variable data to the variable as well as all callback
2257  * methods
2258  */
2259  if( result == SCIP_SUCCESS )
2260  {
2261  (*var)->varcopy = sourcevar->varcopy;
2262  (*var)->vardelorig = sourcevar->vardelorig;
2263  (*var)->vartrans = sourcevar->vartrans;
2264  (*var)->vardeltrans = sourcevar->vardeltrans;
2265  (*var)->vardata = targetdata;
2266  }
2267 
2268  SCIPsetDebugMsg(set, "created copy <%s> of variable <%s>\n", SCIPvarGetName(*var), SCIPvarGetName(sourcevar));
2269 
2270  return SCIP_OKAY;
2271 }
2272 
2273 /** parse given string for a SCIP_Real bound */
2274 static
2276  SCIP_SET* set, /**< global SCIP settings */
2277  const char* str, /**< string to parse */
2278  SCIP_Real* value, /**< pointer to store the parsed value */
2279  char** endptr /**< pointer to store the final string position if successfully parsed */
2280  )
2281 {
2282  /* first check for infinity value */
2283  if( strncmp(str, "+inf", 4) == 0 )
2284  {
2285  *value = SCIPsetInfinity(set);
2286  (*endptr) = (char*)str + 4;
2287  }
2288  else if( strncmp(str, "-inf", 4) == 0 )
2289  {
2290  *value = -SCIPsetInfinity(set);
2291  (*endptr) = (char*)str + 4;
2292  }
2293  else
2294  {
2295  if( !SCIPstrToRealValue(str, value, endptr) )
2296  {
2297  SCIPerrorMessage("expected value: %s.\n", str);
2298  return SCIP_READERROR;
2299  }
2300  }
2301 
2302  return SCIP_OKAY;
2303 }
2304 
2305 /** parse the characters as bounds */
2306 static
2308  SCIP_SET* set, /**< global SCIP settings */
2309  const char* str, /**< string to parse */
2310  char* type, /**< bound type (global, local, or lazy) */
2311  SCIP_Real* lb, /**< pointer to store the lower bound */
2312  SCIP_Real* ub, /**< pointer to store the upper bound */
2313  char** endptr /**< pointer to store the final string position if successfully parsed (or NULL if an error occured) */
2314  )
2315 {
2316  char token[SCIP_MAXSTRLEN];
2317  char* tmpend;
2318 
2319  SCIPsetDebugMsg(set, "parsing bounds: '%s'\n", str);
2320 
2321  /* get bound type */
2322  SCIPstrCopySection(str, ' ', ' ', type, SCIP_MAXSTRLEN, endptr);
2323  if ( strncmp(type, "original", 8) != 0 && strncmp(type, "global", 6) != 0 && strncmp(type, "local", 5) != 0 && strncmp(type, "lazy", 4) != 0 )
2324  {
2325  SCIPsetDebugMsg(set, "unkown bound type <%s>\n", type);
2326  *endptr = NULL;
2327  return SCIP_OKAY;
2328  }
2329 
2330  SCIPsetDebugMsg(set, "parsed bound type <%s>\n", type);
2331 
2332  /* get lower bound */
2333  SCIPstrCopySection(str, '[', ',', token, SCIP_MAXSTRLEN, endptr);
2334  str = *endptr;
2335  SCIP_CALL( parseValue(set, token, lb, &tmpend) );
2336 
2337  /* get upper bound */
2338  SCIP_CALL( parseValue(set, str, ub, endptr) );
2339 
2340  SCIPsetDebugMsg(set, "parsed bounds: [%g,%g]\n", *lb, *ub);
2341 
2342  /* skip end of bounds */
2343  while ( **endptr != '\0' && (**endptr == ']' || **endptr == ',') )
2344  ++(*endptr);
2345 
2346  return SCIP_OKAY;
2347 }
2348 
2349 /** parses a given string for a variable informations */
2350 static
2352  SCIP_SET* set, /**< global SCIP settings */
2353  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2354  const char* str, /**< string to parse */
2355  char* name, /**< pointer to store the variable name */
2356  SCIP_Real* lb, /**< pointer to store the lower bound */
2357  SCIP_Real* ub, /**< pointer to store the upper bound */
2358  SCIP_Real* obj, /**< pointer to store the objective coefficient */
2359  SCIP_VARTYPE* vartype, /**< pointer to store the variable type */
2360  SCIP_Real* lazylb, /**< pointer to store if the lower bound is lazy */
2361  SCIP_Real* lazyub, /**< pointer to store if the upper bound is lazy */
2362  SCIP_Bool local, /**< should the local bound be applied */
2363  char** endptr, /**< pointer to store the final string position if successfully */
2364  SCIP_Bool* success /**< pointer store if the paring process was successful */
2365  )
2366 {
2367  SCIP_Real parsedlb;
2368  SCIP_Real parsedub;
2369  char token[SCIP_MAXSTRLEN];
2370  char* strptr;
2371  int i;
2372 
2373  assert(lb != NULL);
2374  assert(ub != NULL);
2375  assert(obj != NULL);
2376  assert(vartype != NULL);
2377  assert(lazylb != NULL);
2378  assert(lazyub != NULL);
2379  assert(success != NULL);
2380 
2381  (*success) = TRUE;
2382 
2383  /* copy variable type */
2384  SCIPstrCopySection(str, '[', ']', token, SCIP_MAXSTRLEN, endptr);
2385  assert(str != *endptr);
2386  SCIPsetDebugMsg(set, "parsed variable type <%s>\n", token);
2387 
2388  /* get variable type */
2389  if( strncmp(token, "binary", 3) == 0 )
2390  (*vartype) = SCIP_VARTYPE_BINARY;
2391  else if( strncmp(token, "integer", 3) == 0 )
2392  (*vartype) = SCIP_VARTYPE_INTEGER;
2393  else if( strncmp(token, "implicit", 3) == 0 )
2394  (*vartype) = SCIP_VARTYPE_IMPLINT;
2395  else if( strncmp(token, "continuous", 3) == 0 )
2396  (*vartype) = SCIP_VARTYPE_CONTINUOUS;
2397  else
2398  {
2399  SCIPmessagePrintWarning(messagehdlr, "unknown variable type\n");
2400  (*success) = FALSE;
2401  return SCIP_OKAY;
2402  }
2403 
2404  /* move string pointer behind variable type */
2405  str = *endptr;
2406 
2407  /* get variable name */
2408  SCIPstrCopySection(str, '<', '>', name, SCIP_MAXSTRLEN, endptr);
2409  assert(endptr != NULL);
2410  SCIPsetDebugMsg(set, "parsed variable name <%s>\n", name);
2411 
2412  /* move string pointer behind variable name */
2413  str = *endptr;
2414 
2415  /* cut out objective coefficient */
2416  SCIPstrCopySection(str, '=', ',', token, SCIP_MAXSTRLEN, endptr);
2417 
2418  /* move string pointer behind objective coefficient */
2419  str = *endptr;
2420 
2421  /* get objective coefficient */
2422  if( !SCIPstrToRealValue(token, obj, endptr) )
2423  {
2424  *endptr = NULL;
2425  return SCIP_READERROR;
2426  }
2427 
2428  SCIPsetDebugMsg(set, "parsed objective coefficient <%g>\n", *obj);
2429 
2430  /* parse global/original bounds */
2431  SCIP_CALL( parseBounds(set, str, token, lb, ub, endptr) );
2432  if ( *endptr == NULL )
2433  {
2434  SCIPerrorMessage("Expected bound type: %s.\n", token);
2435  return SCIP_READERROR;
2436  }
2437  assert(strncmp(token, "global", 6) == 0 || strncmp(token, "original", 8) == 0);
2438 
2439  /* initialize the lazy bound */
2440  *lazylb = -SCIPsetInfinity(set);
2441  *lazyub = SCIPsetInfinity(set);
2442 
2443  /* store pointer */
2444  strptr = *endptr;
2445 
2446  /* possibly parse optional local and lazy bounds */
2447  for( i = 0; i < 2 && *endptr != NULL && **endptr != '\0'; ++i )
2448  {
2449  /* start after previous bounds */
2450  strptr = *endptr;
2451 
2452  /* parse global bounds */
2453  SCIP_CALL( parseBounds(set, strptr, token, &parsedlb, &parsedub, endptr) );
2454 
2455  /* stop if parsing of bounds failed */
2456  if( *endptr == NULL )
2457  break;
2458 
2459  if( strncmp(token, "local", 5) == 0 && local )
2460  {
2461  *lb = parsedlb;
2462  *ub = parsedub;
2463  }
2464  else if( strncmp(token, "lazy", 4) == 0 )
2465  {
2466  *lazylb = parsedlb;
2467  *lazyub = parsedub;
2468  }
2469  }
2470 
2471  /* restore pointer */
2472  if ( *endptr == NULL )
2473  *endptr = strptr;
2474 
2475  /* check bounds for binary variables */
2476  if ( (*vartype) == SCIP_VARTYPE_BINARY )
2477  {
2478  if ( SCIPsetIsLT(set, *lb, 0.0) || SCIPsetIsGT(set, *ub, 1.0) )
2479  {
2480  SCIPerrorMessage("Parsed invalid bounds for binary variable <%s>: [%f, %f].\n", name, *lb, *ub);
2481  return SCIP_READERROR;
2482  }
2483  if ( !SCIPsetIsInfinity(set, -(*lazylb)) && !SCIPsetIsInfinity(set, *lazyub) &&
2484  ( SCIPsetIsLT(set, *lazylb, 0.0) || SCIPsetIsGT(set, *lazyub, 1.0) ) )
2485  {
2486  SCIPerrorMessage("Parsed invalid lazy bounds for binary variable <%s>: [%f, %f].\n", name, *lazylb, *lazyub);
2487  return SCIP_READERROR;
2488  }
2489  }
2490 
2491  return SCIP_OKAY;
2492 }
2493 
2494 /** parses variable information (in cip format) out of a string; if the parsing process was successful an original
2495  * variable is created and captured; if variable is of integral type, fractional bounds are automatically rounded; an
2496  * integer variable with bounds zero and one is automatically converted into a binary variable
2497  */
2499  SCIP_VAR** var, /**< pointer to variable data */
2500  BMS_BLKMEM* blkmem, /**< block memory */
2501  SCIP_SET* set, /**< global SCIP settings */
2502  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2503  SCIP_STAT* stat, /**< problem statistics */
2504  const char* str, /**< string to parse */
2505  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2506  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2507  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2508  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable */
2509  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data */
2510  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable */
2511  SCIP_VARDATA* vardata, /**< user data for this specific variable */
2512  char** endptr, /**< pointer to store the final string position if successfully */
2513  SCIP_Bool* success /**< pointer store if the paring process was successful */
2514  )
2515 {
2516  char name[SCIP_MAXSTRLEN];
2517  SCIP_Real lb;
2518  SCIP_Real ub;
2519  SCIP_Real obj;
2520  SCIP_VARTYPE vartype;
2521  SCIP_Real lazylb;
2522  SCIP_Real lazyub;
2523 
2524  assert(var != NULL);
2525  assert(blkmem != NULL);
2526  assert(stat != NULL);
2527  assert(endptr != NULL);
2528  assert(success != NULL);
2529 
2530  /* parse string in cip format for variable information */
2531  SCIP_CALL( varParse(set, messagehdlr, str, name, &lb, &ub, &obj, &vartype, &lazylb, &lazyub, FALSE, endptr, success) );
2532 
2533  if( *success ) /*lint !e774*/
2534  {
2535  /* create variable */
2536  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2537  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2538 
2539  /* set variable status and data */
2540  (*var)->varstatus = SCIP_VARSTATUS_ORIGINAL; /*lint !e641*/
2541  (*var)->data.original.origdom.holelist = NULL;
2542  (*var)->data.original.origdom.lb = lb;
2543  (*var)->data.original.origdom.ub = ub;
2544  (*var)->data.original.transvar = NULL;
2545 
2546  /* set lazy status of variable bounds */
2547  (*var)->lazylb = lazylb;
2548  (*var)->lazyub = lazyub;
2549 
2550  /* capture variable */
2551  SCIPvarCapture(*var);
2552  }
2553 
2554  return SCIP_OKAY;
2555 }
2556 
2557 /** parses variable information (in cip format) out of a string; if the parsing process was successful a loose variable
2558  * belonging to the transformed problem is created and captured; if variable is of integral type, fractional bounds are
2559  * automatically rounded; an integer variable with bounds zero and one is automatically converted into a binary
2560  * variable
2561  */
2563  SCIP_VAR** var, /**< pointer to variable data */
2564  BMS_BLKMEM* blkmem, /**< block memory */
2565  SCIP_SET* set, /**< global SCIP settings */
2566  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2567  SCIP_STAT* stat, /**< problem statistics */
2568  const char* str, /**< string to parse */
2569  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2570  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2571  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2572  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable */
2573  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data */
2574  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable */
2575  SCIP_VARDATA* vardata, /**< user data for this specific variable */
2576  char** endptr, /**< pointer to store the final string position if successfully */
2577  SCIP_Bool* success /**< pointer store if the paring process was successful */
2578  )
2579 {
2580  char name[SCIP_MAXSTRLEN];
2581  SCIP_Real lb;
2582  SCIP_Real ub;
2583  SCIP_Real obj;
2584  SCIP_VARTYPE vartype;
2585  SCIP_Real lazylb;
2586  SCIP_Real lazyub;
2587 
2588  assert(var != NULL);
2589  assert(blkmem != NULL);
2590  assert(endptr != NULL);
2591  assert(success != NULL);
2592 
2593  /* parse string in cip format for variable information */
2594  SCIP_CALL( varParse(set, messagehdlr, str, name, &lb, &ub, &obj, &vartype, &lazylb, &lazyub, TRUE, endptr, success) );
2595 
2596  if( *success ) /*lint !e774*/
2597  {
2598  /* create variable */
2599  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2600  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2601 
2602  /* create event filter for transformed variable */
2603  SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
2604 
2605  /* set variable status and data */
2606  (*var)->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
2607 
2608  /* set lazy status of variable bounds */
2609  (*var)->lazylb = lazylb;
2610  (*var)->lazyub = lazyub;
2611 
2612  /* capture variable */
2613  SCIPvarCapture(*var);
2614  }
2615 
2616  return SCIP_OKAY;
2617 }
2618 
2619 /** ensures, that parentvars array of var can store at least num entries */
2620 static
2622  SCIP_VAR* var, /**< problem variable */
2623  BMS_BLKMEM* blkmem, /**< block memory */
2624  SCIP_SET* set, /**< global SCIP settings */
2625  int num /**< minimum number of entries to store */
2626  )
2627 {
2628  assert(var->nparentvars <= var->parentvarssize);
2629 
2630  if( num > var->parentvarssize )
2631  {
2632  int newsize;
2633 
2634  newsize = SCIPsetCalcMemGrowSize(set, num);
2635  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->parentvars, var->parentvarssize, newsize) );
2636  var->parentvarssize = newsize;
2637  }
2638  assert(num <= var->parentvarssize);
2639 
2640  return SCIP_OKAY;
2641 }
2642 
2643 /** adds variable to parent list of a variable and captures parent variable */
2644 static
2646  SCIP_VAR* var, /**< variable to add parent to */
2647  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
2648  SCIP_SET* set, /**< global SCIP settings */
2649  SCIP_VAR* parentvar /**< parent variable to add */
2650  )
2651 {
2652  assert(var != NULL);
2653  assert(parentvar != NULL);
2654 
2655  /* the direct original counterpart must be stored as first parent */
2656  assert(var->nparentvars == 0 || SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL);
2657 
2658  SCIPsetDebugMsg(set, "adding parent <%s>[%p] to variable <%s>[%p] in slot %d\n",
2659  parentvar->name, (void*)parentvar, var->name, (void*)var, var->nparentvars);
2660 
2661  SCIP_CALL( varEnsureParentvarsSize(var, blkmem, set, var->nparentvars+1) );
2662 
2663  var->parentvars[var->nparentvars] = parentvar;
2664  var->nparentvars++;
2665 
2666  SCIPvarCapture(parentvar);
2667 
2668  return SCIP_OKAY;
2669 }
2670 
2671 /** deletes and releases all variables from the parent list of a variable, frees the memory of parents array */
2672 static
2674  SCIP_VAR** var, /**< pointer to variable */
2675  BMS_BLKMEM* blkmem, /**< block memory */
2676  SCIP_SET* set, /**< global SCIP settings */
2677  SCIP_EVENTQUEUE* eventqueue, /**< event queue (or NULL, if it's an original variable) */
2678  SCIP_LP* lp /**< current LP data (or NULL, if it's an original variable) */
2679  )
2680 {
2681  SCIP_VAR* parentvar;
2682  int i;
2683 
2684  SCIPsetDebugMsg(set, "free parents of <%s>\n", (*var)->name);
2685 
2686  /* release the parent variables and remove the link from the parent variable to the child */
2687  for( i = 0; i < (*var)->nparentvars; ++i )
2688  {
2689  assert((*var)->parentvars != NULL);
2690  parentvar = (*var)->parentvars[i];
2691  assert(parentvar != NULL);
2692 
2693  switch( SCIPvarGetStatus(parentvar) )
2694  {
2696  assert(parentvar->data.original.transvar == *var);
2697  assert(&parentvar->data.original.transvar != var);
2698  parentvar->data.original.transvar = NULL;
2699  break;
2700 
2702  assert(parentvar->data.aggregate.var == *var);
2703  assert(&parentvar->data.aggregate.var != var);
2704  parentvar->data.aggregate.var = NULL;
2705  break;
2706 
2707 #if 0
2708  /* The following code is unclear: should the current variable be removed from its parents? */
2710  assert(parentvar->data.multaggr.vars != NULL);
2711  for( v = 0; v < parentvar->data.multaggr.nvars && parentvar->data.multaggr.vars[v] != *var; ++v )
2712  {}
2713  assert(v < parentvar->data.multaggr.nvars && parentvar->data.multaggr.vars[v] == *var);
2714  if( v < parentvar->data.multaggr.nvars-1 )
2715  {
2716  parentvar->data.multaggr.vars[v] = parentvar->data.multaggr.vars[parentvar->data.multaggr.nvars-1];
2717  parentvar->data.multaggr.scalars[v] = parentvar->data.multaggr.scalars[parentvar->data.multaggr.nvars-1];
2718  }
2719  parentvar->data.multaggr.nvars--;
2720  break;
2721 #endif
2722 
2724  assert(parentvar->negatedvar == *var);
2725  assert((*var)->negatedvar == parentvar);
2726  parentvar->negatedvar = NULL;
2727  (*var)->negatedvar = NULL;
2728  break;
2729 
2730  default:
2731  SCIPerrorMessage("parent variable is neither ORIGINAL, AGGREGATED nor NEGATED\n");
2732  return SCIP_INVALIDDATA;
2733  } /*lint !e788*/
2734 
2735  SCIP_CALL( SCIPvarRelease(&(*var)->parentvars[i], blkmem, set, eventqueue, lp) );
2736  }
2737 
2738  /* free parentvars array */
2739  BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->parentvars, (*var)->parentvarssize);
2740 
2741  return SCIP_OKAY;
2742 }
2743 
2744 /** frees a variable */
2745 static
2747  SCIP_VAR** var, /**< pointer to variable */
2748  BMS_BLKMEM* blkmem, /**< block memory */
2749  SCIP_SET* set, /**< global SCIP settings */
2750  SCIP_EVENTQUEUE* eventqueue, /**< event queue (may be NULL, if it's not a column variable) */
2751  SCIP_LP* lp /**< current LP data (may be NULL, if it's not a column variable) */
2752  )
2753 {
2754  assert(var != NULL);
2755  assert(*var != NULL);
2756  assert(SCIPvarGetStatus(*var) != SCIP_VARSTATUS_COLUMN || &(*var)->data.col->var != var);
2757  assert((*var)->nuses == 0);
2758  assert((*var)->probindex == -1);
2759  assert((*var)->nlocksup[SCIP_LOCKTYPE_MODEL] == 0);
2760  assert((*var)->nlocksdown[SCIP_LOCKTYPE_MODEL] == 0);
2761 
2762  SCIPsetDebugMsg(set, "free variable <%s> with status=%d\n", (*var)->name, SCIPvarGetStatus(*var));
2763 
2764  switch( SCIPvarGetStatus(*var) )
2765  {
2767  assert((*var)->data.original.transvar == NULL); /* cannot free variable, if transformed variable is still existing */
2768  holelistFree(&(*var)->data.original.origdom.holelist, blkmem);
2769  assert((*var)->data.original.origdom.holelist == NULL);
2770  break;
2771  case SCIP_VARSTATUS_LOOSE:
2772  break;
2773  case SCIP_VARSTATUS_COLUMN:
2774  SCIP_CALL( SCIPcolFree(&(*var)->data.col, blkmem, set, eventqueue, lp) ); /* free corresponding LP column */
2775  break;
2776  case SCIP_VARSTATUS_FIXED:
2778  break;
2780  BMSfreeBlockMemoryArray(blkmem, &(*var)->data.multaggr.vars, (*var)->data.multaggr.varssize);
2781  BMSfreeBlockMemoryArray(blkmem, &(*var)->data.multaggr.scalars, (*var)->data.multaggr.varssize);
2782  break;
2784  break;
2785  default:
2786  SCIPerrorMessage("unknown variable status\n");
2787  return SCIP_INVALIDDATA;
2788  }
2789 
2790  /* release all parent variables and free the parentvars array */
2791  SCIP_CALL( varFreeParents(var, blkmem, set, eventqueue, lp) );
2792 
2793  /* free user data */
2795  {
2796  if( (*var)->vardelorig != NULL )
2797  {
2798  SCIP_CALL( (*var)->vardelorig(set->scip, *var, &(*var)->vardata) );
2799  }
2800  }
2801  else
2802  {
2803  if( (*var)->vardeltrans != NULL )
2804  {
2805  SCIP_CALL( (*var)->vardeltrans(set->scip, *var, &(*var)->vardata) );
2806  }
2807  }
2808 
2809  /* free event filter */
2810  if( (*var)->eventfilter != NULL )
2811  {
2812  SCIP_CALL( SCIPeventfilterFree(&(*var)->eventfilter, blkmem, set) );
2813  }
2814  assert((*var)->eventfilter == NULL);
2815 
2816  /* free hole lists */
2817  holelistFree(&(*var)->glbdom.holelist, blkmem);
2818  holelistFree(&(*var)->locdom.holelist, blkmem);
2819  assert((*var)->glbdom.holelist == NULL);
2820  assert((*var)->locdom.holelist == NULL);
2821 
2822  /* free variable bounds data structures */
2823  SCIPvboundsFree(&(*var)->vlbs, blkmem);
2824  SCIPvboundsFree(&(*var)->vubs, blkmem);
2825 
2826  /* free implications data structures */
2827  SCIPimplicsFree(&(*var)->implics, blkmem);
2828 
2829  /* free clique list data structures */
2830  SCIPcliquelistFree(&(*var)->cliquelist, blkmem);
2831 
2832  /* free bound change information arrays */
2833  BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->lbchginfos, (*var)->lbchginfossize);
2834  BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->ubchginfos, (*var)->ubchginfossize);
2835 
2836  /* free branching and inference history entries */
2837  SCIPhistoryFree(&(*var)->history, blkmem);
2838  SCIPhistoryFree(&(*var)->historycrun, blkmem);
2839  SCIPvaluehistoryFree(&(*var)->valuehistory, blkmem);
2840 
2841  /* free variable data structure */
2842  BMSfreeBlockMemoryArray(blkmem, &(*var)->name, strlen((*var)->name)+1);
2843  BMSfreeBlockMemory(blkmem, var);
2844 
2845  return SCIP_OKAY;
2846 }
2847 
2848 /** increases usage counter of variable */
2849 void SCIPvarCapture(
2850  SCIP_VAR* var /**< variable */
2851  )
2852 {
2853  assert(var != NULL);
2854  assert(var->nuses >= 0);
2855 
2856  SCIPdebugMessage("capture variable <%s> with nuses=%d\n", var->name, var->nuses);
2857  var->nuses++;
2858 
2859 #ifdef DEBUGUSES_VARNAME
2860  if( strcmp(var->name, DEBUGUSES_VARNAME) == 0
2861 #ifdef DEBUGUSES_PROBNAME
2862  && ((var->scip->transprob != NULL && strcmp(SCIPprobGetName(var->scip->transprob), DEBUGUSES_PROBNAME) == 0) ||
2863  strcmp(SCIPprobGetName(var->scip->origprob), DEBUGUSES_PROBNAME) == 0)
2864 #endif
2865  )
2866  {
2867  printf("Captured variable " DEBUGUSES_VARNAME " in SCIP %p, now %d uses; captured at\n", (void*)var->scip, var->nuses);
2868  print_backtrace();
2869  }
2870 #endif
2871 }
2872 
2873 /** decreases usage counter of variable, and frees memory if necessary */
2875  SCIP_VAR** var, /**< pointer to variable */
2876  BMS_BLKMEM* blkmem, /**< block memory */
2877  SCIP_SET* set, /**< global SCIP settings */
2878  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2879  SCIP_LP* lp /**< current LP data (or NULL, if it's an original variable) */
2880  )
2881 {
2882  assert(var != NULL);
2883  assert(*var != NULL);
2884  assert((*var)->nuses >= 1);
2885  assert(blkmem != NULL);
2886  assert((*var)->scip == set->scip);
2887 
2888  SCIPsetDebugMsg(set, "release variable <%s> with nuses=%d\n", (*var)->name, (*var)->nuses);
2889  (*var)->nuses--;
2890 
2891 #ifdef DEBUGUSES_VARNAME
2892  if( strcmp((*var)->name, DEBUGUSES_VARNAME) == 0
2893 #ifdef DEBUGUSES_PROBNAME
2894  && (((*var)->scip->transprob != NULL && strcmp(SCIPprobGetName((*var)->scip->transprob), DEBUGUSES_PROBNAME) == 0) ||
2895  strcmp(SCIPprobGetName((*var)->scip->origprob), DEBUGUSES_PROBNAME) == 0)
2896 #endif
2897  )
2898  {
2899  printf("Released variable " DEBUGUSES_VARNAME " in SCIP %p, now %d uses; released at\n", (void*)(*var)->scip, (*var)->nuses);
2900  print_backtrace();
2901  }
2902 #endif
2903 
2904  if( (*var)->nuses == 0 )
2905  {
2906  SCIP_CALL( varFree(var, blkmem, set, eventqueue, lp) );
2907  }
2908 
2909  *var = NULL;
2910 
2911  return SCIP_OKAY;
2912 }
2913 
2914 /** change variable name */
2916  SCIP_VAR* var, /**< problem variable */
2917  BMS_BLKMEM* blkmem, /**< block memory */
2918  const char* name /**< name of variable */
2919  )
2920 {
2921  assert(name != NULL);
2922 
2923  /* remove old variable name */
2924  BMSfreeBlockMemoryArray(blkmem, &var->name, strlen(var->name)+1);
2925 
2926  /* set new variable name */
2927  SCIP_CALL( varSetName(var, blkmem, NULL, name) );
2928 
2929  return SCIP_OKAY;
2930 }
2931 
2932 /** initializes variable data structure for solving */
2933 void SCIPvarInitSolve(
2934  SCIP_VAR* var /**< problem variable */
2935  )
2936 {
2937  assert(var != NULL);
2938 
2940  var->conflictlbcount = 0;
2941  var->conflictubcount = 0;
2942 }
2943 
2944 /** outputs the given bounds into the file stream */
2945 static
2946 void printBounds(
2947  SCIP_SET* set, /**< global SCIP settings */
2948  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2949  FILE* file, /**< output file (or NULL for standard output) */
2950  SCIP_Real lb, /**< lower bound */
2951  SCIP_Real ub, /**< upper bound */
2952  const char* name /**< bound type name */
2953  )
2954 {
2955  assert(set != NULL);
2956 
2957  SCIPmessageFPrintInfo(messagehdlr, file, ", %s=", name);
2958  if( SCIPsetIsInfinity(set, lb) )
2959  SCIPmessageFPrintInfo(messagehdlr, file, "[+inf,");
2960  else if( SCIPsetIsInfinity(set, -lb) )
2961  SCIPmessageFPrintInfo(messagehdlr, file, "[-inf,");
2962  else
2963  SCIPmessageFPrintInfo(messagehdlr, file, "[%.15g,", lb);
2964  if( SCIPsetIsInfinity(set, ub) )
2965  SCIPmessageFPrintInfo(messagehdlr, file, "+inf]");
2966  else if( SCIPsetIsInfinity(set, -ub) )
2967  SCIPmessageFPrintInfo(messagehdlr, file, "-inf]");
2968  else
2969  SCIPmessageFPrintInfo(messagehdlr, file, "%.15g]", ub);
2970 }
2971 
2972 /** prints hole list to file stream */
2973 static
2974 void printHolelist(
2975  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2976  FILE* file, /**< output file (or NULL for standard output) */
2977  SCIP_HOLELIST* holelist, /**< hole list pointer to hole of interest */
2978  const char* name /**< hole type name */
2979  )
2980 { /*lint --e{715}*/
2981  SCIP_Real left;
2982  SCIP_Real right;
2983 
2984  if( holelist == NULL )
2985  return;
2986 
2987  left = SCIPholelistGetLeft(holelist);
2988  right = SCIPholelistGetRight(holelist);
2989 
2990  /* display first hole */
2991  SCIPmessageFPrintInfo(messagehdlr, file, ", %s=(%g,%g)", name, left, right);
2992  holelist = SCIPholelistGetNext(holelist);
2993 
2994  while(holelist != NULL )
2995  {
2996  left = SCIPholelistGetLeft(holelist);
2997  right = SCIPholelistGetRight(holelist);
2998 
2999  /* display hole */
3000  SCIPmessageFPrintInfo(messagehdlr, file, "(%g,%g)", left, right);
3001 
3002  /* get next hole */
3003  holelist = SCIPholelistGetNext(holelist);
3004  }
3005 }
3006 
3007 /** outputs variable information into file stream */
3009  SCIP_VAR* var, /**< problem variable */
3010  SCIP_SET* set, /**< global SCIP settings */
3011  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3012  FILE* file /**< output file (or NULL for standard output) */
3013  )
3014 {
3015  SCIP_HOLELIST* holelist;
3016  SCIP_Real lb;
3017  SCIP_Real ub;
3018  int i;
3019 
3020  assert(var != NULL);
3021  assert(var->scip == set->scip);
3022 
3023  /* type of variable */
3024  switch( SCIPvarGetType(var) )
3025  {
3026  case SCIP_VARTYPE_BINARY:
3027  SCIPmessageFPrintInfo(messagehdlr, file, " [binary]");
3028  break;
3029  case SCIP_VARTYPE_INTEGER:
3030  SCIPmessageFPrintInfo(messagehdlr, file, " [integer]");
3031  break;
3032  case SCIP_VARTYPE_IMPLINT:
3033  SCIPmessageFPrintInfo(messagehdlr, file, " [implicit]");
3034  break;
3036  SCIPmessageFPrintInfo(messagehdlr, file, " [continuous]");
3037  break;
3038  default:
3039  SCIPerrorMessage("unknown variable type\n");
3040  SCIPABORT();
3041  return SCIP_ERROR; /*lint !e527*/
3042  }
3043 
3044  /* name */
3045  SCIPmessageFPrintInfo(messagehdlr, file, " <%s>:", var->name);
3046 
3047  /* objective value */
3048  SCIPmessageFPrintInfo(messagehdlr, file, " obj=%.15g", var->obj);
3049 
3050  /* bounds (global bounds for transformed variables, original bounds for original variables) */
3051  if( !SCIPvarIsTransformed(var) )
3052  {
3053  /* output original bound */
3054  lb = SCIPvarGetLbOriginal(var);
3055  ub = SCIPvarGetUbOriginal(var);
3056  printBounds(set, messagehdlr, file, lb, ub, "original bounds");
3057 
3058  /* output lazy bound */
3059  lb = SCIPvarGetLbLazy(var);
3060  ub = SCIPvarGetUbLazy(var);
3061 
3062  /* only display the lazy bounds if they are different from [-infinity,infinity] */
3063  if( !SCIPsetIsInfinity(set, -lb) || !SCIPsetIsInfinity(set, ub) )
3064  printBounds(set, messagehdlr, file, lb, ub, "lazy bounds");
3065 
3066  holelist = SCIPvarGetHolelistOriginal(var);
3067  printHolelist(messagehdlr, file, holelist, "original holes");
3068  }
3069  else
3070  {
3071  /* output global bound */
3072  lb = SCIPvarGetLbGlobal(var);
3073  ub = SCIPvarGetUbGlobal(var);
3074  printBounds(set, messagehdlr, file, lb, ub, "global bounds");
3075 
3076  /* output local bound */
3077  lb = SCIPvarGetLbLocal(var);
3078  ub = SCIPvarGetUbLocal(var);
3079  printBounds(set, messagehdlr, file, lb, ub, "local bounds");
3080 
3081  /* output lazy bound */
3082  lb = SCIPvarGetLbLazy(var);
3083  ub = SCIPvarGetUbLazy(var);
3084 
3085  /* only display the lazy bounds if they are different from [-infinity,infinity] */
3086  if( !SCIPsetIsInfinity(set, -lb) || !SCIPsetIsInfinity(set, ub) )
3087  printBounds(set, messagehdlr, file, lb, ub, "lazy bounds");
3088 
3089  /* global hole list */
3090  holelist = SCIPvarGetHolelistGlobal(var);
3091  printHolelist(messagehdlr, file, holelist, "global holes");
3092 
3093  /* local hole list */
3094  holelist = SCIPvarGetHolelistLocal(var);
3095  printHolelist(messagehdlr, file, holelist, "local holes");
3096  }
3097 
3098  /* fixings and aggregations */
3099  switch( SCIPvarGetStatus(var) )
3100  {
3102  case SCIP_VARSTATUS_LOOSE:
3103  case SCIP_VARSTATUS_COLUMN:
3104  break;
3105 
3106  case SCIP_VARSTATUS_FIXED:
3107  SCIPmessageFPrintInfo(messagehdlr, file, ", fixed:");
3108  if( SCIPsetIsInfinity(set, var->glbdom.lb) )
3109  SCIPmessageFPrintInfo(messagehdlr, file, "+inf");
3110  else if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
3111  SCIPmessageFPrintInfo(messagehdlr, file, "-inf");
3112  else
3113  SCIPmessageFPrintInfo(messagehdlr, file, "%.15g", var->glbdom.lb);
3114  break;
3115 
3117  SCIPmessageFPrintInfo(messagehdlr, file, ", aggregated:");
3118  if( !SCIPsetIsZero(set, var->data.aggregate.constant) )
3119  SCIPmessageFPrintInfo(messagehdlr, file, " %.15g", var->data.aggregate.constant);
3120  SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g<%s>", var->data.aggregate.scalar, SCIPvarGetName(var->data.aggregate.var));
3121  break;
3122 
3124  SCIPmessageFPrintInfo(messagehdlr, file, ", aggregated:");
3125  if( var->data.multaggr.nvars == 0 || !SCIPsetIsZero(set, var->data.multaggr.constant) )
3126  SCIPmessageFPrintInfo(messagehdlr, file, " %.15g", var->data.multaggr.constant);
3127  for( i = 0; i < var->data.multaggr.nvars; ++i )
3128  SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g<%s>", var->data.multaggr.scalars[i], SCIPvarGetName(var->data.multaggr.vars[i]));
3129  break;
3130 
3132  SCIPmessageFPrintInfo(messagehdlr, file, ", negated: %.15g - <%s>", var->data.negate.constant, SCIPvarGetName(var->negatedvar));
3133  break;
3134 
3135  default:
3136  SCIPerrorMessage("unknown variable status\n");
3137  SCIPABORT();
3138  return SCIP_ERROR; /*lint !e527*/
3139  }
3140 
3141  SCIPmessageFPrintInfo(messagehdlr, file, "\n");
3142 
3143  return SCIP_OKAY;
3144 }
3145 
3146 /** issues a VARUNLOCKED event on the given variable */
3147 static
3149  SCIP_VAR* var, /**< problem variable to change */
3150  BMS_BLKMEM* blkmem, /**< block memory */
3151  SCIP_SET* set, /**< global SCIP settings */
3152  SCIP_EVENTQUEUE* eventqueue /**< event queue */
3153  )
3154 {
3155  SCIP_EVENT* event;
3156 
3157  assert(var != NULL);
3158  assert(var->nlocksdown[SCIP_LOCKTYPE_MODEL] <= 1 && var->nlocksup[SCIP_LOCKTYPE_MODEL] <= 1);
3159  assert(var->scip == set->scip);
3160 
3161  /* issue VARUNLOCKED event on variable */
3162  SCIP_CALL( SCIPeventCreateVarUnlocked(&event, blkmem, var) );
3163  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
3164 
3165  return SCIP_OKAY;
3166 }
3167 
3168 /** modifies lock numbers for rounding */
3170  SCIP_VAR* var, /**< problem variable */
3171  BMS_BLKMEM* blkmem, /**< block memory */
3172  SCIP_SET* set, /**< global SCIP settings */
3173  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3174  SCIP_LOCKTYPE locktype, /**< type of the variable locks */
3175  int addnlocksdown, /**< increase in number of rounding down locks */
3176  int addnlocksup /**< increase in number of rounding up locks */
3177  )
3178 {
3179  SCIP_VAR* lockvar;
3180 
3181  assert(var != NULL);
3182  assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
3183  assert(var->nlocksup[locktype] >= 0);
3184  assert(var->nlocksdown[locktype] >= 0);
3185  assert(var->scip == set->scip);
3186 
3187  if( addnlocksdown == 0 && addnlocksup == 0 )
3188  return SCIP_OKAY;
3189 
3190 #ifdef SCIP_DEBUG
3191  SCIPsetDebugMsg(set, "add rounding locks %d/%d to variable <%s> (locks=%d/%d, type=%u)\n",
3192  addnlocksdown, addnlocksup, var->name, var->nlocksdown[locktype], var->nlocksup[locktype], locktype);
3193 #endif
3194 
3195  lockvar = var;
3196 
3197  while( TRUE ) /*lint !e716 */
3198  {
3199  assert(lockvar != NULL);
3200 
3201  switch( SCIPvarGetStatus(lockvar) )
3202  {
3204  if( lockvar->data.original.transvar != NULL )
3205  {
3206  lockvar = lockvar->data.original.transvar;
3207  break;
3208  }
3209  else
3210  {
3211  lockvar->nlocksdown[locktype] += addnlocksdown;
3212  lockvar->nlocksup[locktype] += addnlocksup;
3213 
3214  assert(lockvar->nlocksdown[locktype] >= 0);
3215  assert(lockvar->nlocksup[locktype] >= 0);
3216 
3217  return SCIP_OKAY;
3218  }
3219  case SCIP_VARSTATUS_LOOSE:
3220  case SCIP_VARSTATUS_COLUMN:
3221  case SCIP_VARSTATUS_FIXED:
3222  lockvar->nlocksdown[locktype] += addnlocksdown;
3223  lockvar->nlocksup[locktype] += addnlocksup;
3224 
3225  assert(lockvar->nlocksdown[locktype] >= 0);
3226  assert(lockvar->nlocksup[locktype] >= 0);
3227 
3228  if( locktype == SCIP_LOCKTYPE_MODEL && lockvar->nlocksdown[locktype] <= 1
3229  && lockvar->nlocksup[locktype] <= 1 )
3230  {
3231  SCIP_CALL( varEventVarUnlocked(lockvar, blkmem, set, eventqueue) );
3232  }
3233 
3234  return SCIP_OKAY;
3236  assert(!lockvar->donotaggr);
3237 
3238  if( lockvar->data.aggregate.scalar < 0.0 )
3239  {
3240  int tmp = addnlocksup;
3241 
3242  addnlocksup = addnlocksdown;
3243  addnlocksdown = tmp;
3244  }
3245 
3246  lockvar = lockvar->data.aggregate.var;
3247  break;
3249  {
3250  int v;
3251 
3252  assert(!lockvar->donotmultaggr);
3253 
3254  lockvar->nlocksdown[locktype] += addnlocksdown;
3255  lockvar->nlocksup[locktype] += addnlocksup;
3256 
3257  assert(lockvar->nlocksdown[locktype] >= 0);
3258  assert(lockvar->nlocksup[locktype] >= 0);
3259 
3260  for( v = lockvar->data.multaggr.nvars - 1; v >= 0; --v )
3261  {
3262  if( lockvar->data.multaggr.scalars[v] > 0.0 )
3263  {
3264  SCIP_CALL( SCIPvarAddLocks(lockvar->data.multaggr.vars[v], blkmem, set, eventqueue, locktype, addnlocksdown,
3265  addnlocksup) );
3266  }
3267  else
3268  {
3269  SCIP_CALL( SCIPvarAddLocks(lockvar->data.multaggr.vars[v], blkmem, set, eventqueue, locktype, addnlocksup,
3270  addnlocksdown) );
3271  }
3272  }
3273  return SCIP_OKAY;
3274  }
3276  {
3277  int tmp = addnlocksup;
3278 
3279  assert(lockvar->negatedvar != NULL);
3280  assert(SCIPvarGetStatus(lockvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
3281  assert(lockvar->negatedvar->negatedvar == lockvar);
3282 
3283  addnlocksup = addnlocksdown;
3284  addnlocksdown = tmp;
3285 
3286  lockvar = lockvar->negatedvar;
3287  break;
3288  }
3289  default:
3290  SCIPerrorMessage("unknown variable status\n");
3291  return SCIP_INVALIDDATA;
3292  }
3293  }
3294 }
3295 
3296 /** gets number of locks for rounding down of a special type */
3298  SCIP_VAR* var, /**< problem variable */
3299  SCIP_LOCKTYPE locktype /**< type of variable locks */
3300  )
3301 {
3302  int nlocks;
3303  int i;
3304 
3305  assert(var != NULL);
3306  assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
3307  assert(var->nlocksdown[locktype] >= 0);
3308 
3309  switch( SCIPvarGetStatus(var) )
3310  {
3312  if( var->data.original.transvar != NULL )
3313  return SCIPvarGetNLocksDownType(var->data.original.transvar, locktype);
3314  else
3315  return var->nlocksdown[locktype];
3316 
3317  case SCIP_VARSTATUS_LOOSE:
3318  case SCIP_VARSTATUS_COLUMN:
3319  case SCIP_VARSTATUS_FIXED:
3320  return var->nlocksdown[locktype];
3321 
3323  assert(!var->donotaggr);
3324  if( var->data.aggregate.scalar > 0.0 )
3325  return SCIPvarGetNLocksDownType(var->data.aggregate.var, locktype);
3326  else
3327  return SCIPvarGetNLocksUpType(var->data.aggregate.var, locktype);
3328 
3330  assert(!var->donotmultaggr);
3331  nlocks = 0;
3332  for( i = 0; i < var->data.multaggr.nvars; ++i )
3333  {
3334  if( var->data.multaggr.scalars[i] > 0.0 )
3335  nlocks += SCIPvarGetNLocksDownType(var->data.multaggr.vars[i], locktype);
3336  else
3337  nlocks += SCIPvarGetNLocksUpType(var->data.multaggr.vars[i], locktype);
3338  }
3339  return nlocks;
3340 
3342  assert(var->negatedvar != NULL);
3344  assert(var->negatedvar->negatedvar == var);
3345  return SCIPvarGetNLocksUpType(var->negatedvar, locktype);
3346 
3347  default:
3348  SCIPerrorMessage("unknown variable status\n");
3349  SCIPABORT();
3350  return INT_MAX; /*lint !e527*/
3351  }
3352 }
3353 
3354 /** gets number of locks for rounding up of a special type */
3356  SCIP_VAR* var, /**< problem variable */
3357  SCIP_LOCKTYPE locktype /**< type of variable locks */
3358  )
3359 {
3360  int nlocks;
3361  int i;
3362 
3363  assert(var != NULL);
3364  assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
3365  assert(var->nlocksup[locktype] >= 0);
3366 
3367  switch( SCIPvarGetStatus(var) )
3368  {
3370  if( var->data.original.transvar != NULL )
3371  return SCIPvarGetNLocksUpType(var->data.original.transvar, locktype);
3372  else
3373  return var->nlocksup[locktype];
3374 
3375  case SCIP_VARSTATUS_LOOSE:
3376  case SCIP_VARSTATUS_COLUMN:
3377  case SCIP_VARSTATUS_FIXED:
3378  return var->nlocksup[locktype];
3379 
3381  assert(!var->donotaggr);
3382  if( var->data.aggregate.scalar > 0.0 )
3383  return SCIPvarGetNLocksUpType(var->data.aggregate.var, locktype);
3384  else
3385  return SCIPvarGetNLocksDownType(var->data.aggregate.var, locktype);
3386 
3388  assert(!var->donotmultaggr);
3389  nlocks = 0;
3390  for( i = 0; i < var->data.multaggr.nvars; ++i )
3391  {
3392  if( var->data.multaggr.scalars[i] > 0.0 )
3393  nlocks += SCIPvarGetNLocksUpType(var->data.multaggr.vars[i], locktype);
3394  else
3395  nlocks += SCIPvarGetNLocksDownType(var->data.multaggr.vars[i], locktype);
3396  }
3397  return nlocks;
3398 
3400  assert(var->negatedvar != NULL);
3402  assert(var->negatedvar->negatedvar == var);
3403  return SCIPvarGetNLocksDownType(var->negatedvar, locktype);
3404 
3405  default:
3406  SCIPerrorMessage("unknown variable status\n");
3407  SCIPABORT();
3408  return INT_MAX; /*lint !e527*/
3409  }
3410 }
3411 
3412 /** gets number of locks for rounding down
3413  *
3414  * @note This method will always return variable locks of type model
3415  *
3416  * @note It is recommented to use SCIPvarGetNLocksDownType()
3417  */
3419  SCIP_VAR* var /**< problem variable */
3420  )
3421 {
3423 }
3424 
3425 /** gets number of locks for rounding up
3426  *
3427  * @note This method will always return variable locks of type model
3428  *
3429  * @note It is recommented to use SCIPvarGetNLocksUpType()
3430  */
3431 int SCIPvarGetNLocksUp(
3432  SCIP_VAR* var /**< problem variable */
3433  )
3434 {
3436 }
3437 
3438 /** is it possible, to round variable down and stay feasible?
3439  *
3440  * @note This method will always check w.r.t variable locks of type model
3441  */
3443  SCIP_VAR* var /**< problem variable */
3444  )
3445 {
3446  return (SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 0);
3447 }
3448 
3449 /** is it possible, to round variable up and stay feasible?
3450  *
3451  * @note This method will always check w.r.t. variable locks of type model
3452  */
3454  SCIP_VAR* var /**< problem variable */
3455  )
3456 {
3457  return (SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 0);
3458 }
3459 
3460 /** gets and captures transformed variable of a given variable; if the variable is not yet transformed,
3461  * a new transformed variable for this variable is created
3462  */
3464  SCIP_VAR* origvar, /**< original problem variable */
3465  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3466  SCIP_SET* set, /**< global SCIP settings */
3467  SCIP_STAT* stat, /**< problem statistics */
3468  SCIP_OBJSENSE objsense, /**< objective sense of original problem; transformed is always MINIMIZE */
3469  SCIP_VAR** transvar /**< pointer to store the transformed variable */
3470  )
3471 {
3472  char name[SCIP_MAXSTRLEN];
3473 
3474  assert(origvar != NULL);
3475  assert(origvar->scip == set->scip);
3476  assert(SCIPvarGetStatus(origvar) == SCIP_VARSTATUS_ORIGINAL);
3477  assert(SCIPsetIsEQ(set, origvar->glbdom.lb, origvar->locdom.lb));
3478  assert(SCIPsetIsEQ(set, origvar->glbdom.ub, origvar->locdom.ub));
3479  assert(origvar->vlbs == NULL);
3480  assert(origvar->vubs == NULL);
3481  assert(transvar != NULL);
3482 
3483  /* check if variable is already transformed */
3484  if( origvar->data.original.transvar != NULL )
3485  {
3486  *transvar = origvar->data.original.transvar;
3487  SCIPvarCapture(*transvar);
3488  }
3489  else
3490  {
3491  int i;
3492 
3493  /* create transformed variable */
3494  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "t_%s", origvar->name);
3495  SCIP_CALL( SCIPvarCreateTransformed(transvar, blkmem, set, stat, name,
3496  origvar->glbdom.lb, origvar->glbdom.ub, (SCIP_Real)objsense * origvar->obj,
3497  SCIPvarGetType(origvar), origvar->initial, origvar->removable,
3498  origvar->vardelorig, origvar->vartrans, origvar->vardeltrans, origvar->varcopy, NULL) );
3499 
3500  /* copy the branch factor and priority */
3501  (*transvar)->branchfactor = origvar->branchfactor;
3502  (*transvar)->branchpriority = origvar->branchpriority;
3503  (*transvar)->branchdirection = origvar->branchdirection; /*lint !e732*/
3504 
3505  /* duplicate hole lists */
3506  SCIP_CALL( holelistDuplicate(&(*transvar)->glbdom.holelist, blkmem, set, origvar->glbdom.holelist) );
3507  SCIP_CALL( holelistDuplicate(&(*transvar)->locdom.holelist, blkmem, set, origvar->locdom.holelist) );
3508 
3509  /* link original and transformed variable */
3510  origvar->data.original.transvar = *transvar;
3511  SCIP_CALL( varAddParent(*transvar, blkmem, set, origvar) );
3512 
3513  /* copy rounding locks */
3514  for( i = 0; i < NLOCKTYPES; i++ )
3515  {
3516  (*transvar)->nlocksdown[i] = origvar->nlocksdown[i];
3517  (*transvar)->nlocksup[i] = origvar->nlocksup[i];
3518  assert((*transvar)->nlocksdown[i] >= 0);
3519  assert((*transvar)->nlocksup[i] >= 0);
3520  }
3521 
3522  /* copy donot(mult)aggr status */
3523  (*transvar)->donotaggr = origvar->donotaggr;
3524  (*transvar)->donotmultaggr = origvar->donotmultaggr;
3525 
3526  /* copy lazy bounds */
3527  (*transvar)->lazylb = origvar->lazylb;
3528  (*transvar)->lazyub = origvar->lazyub;
3529 
3530  /* transfer eventual variable statistics; do not update global statistics, because this has been done
3531  * when original variable was created
3532  */
3533  SCIPhistoryUnite((*transvar)->history, origvar->history, FALSE);
3534 
3535  /* transform user data */
3536  if( origvar->vartrans != NULL )
3537  {
3538  SCIP_CALL( origvar->vartrans(set->scip, origvar, origvar->vardata, *transvar, &(*transvar)->vardata) );
3539  }
3540  else
3541  (*transvar)->vardata = origvar->vardata;
3542  }
3543 
3544  SCIPsetDebugMsg(set, "transformed variable: <%s>[%p] -> <%s>[%p]\n", origvar->name, (void*)origvar, (*transvar)->name, (void*)*transvar);
3545 
3546  return SCIP_OKAY;
3547 }
3548 
3549 /** gets corresponding transformed variable of an original or negated original variable */
3551  SCIP_VAR* origvar, /**< original problem variable */
3552  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3553  SCIP_SET* set, /**< global SCIP settings */
3554  SCIP_STAT* stat, /**< problem statistics */
3555  SCIP_VAR** transvar /**< pointer to store the transformed variable, or NULL if not existing yet */
3556  )
3557 {
3558  assert(origvar != NULL);
3560  assert(origvar->scip == set->scip);
3561 
3562  if( SCIPvarGetStatus(origvar) == SCIP_VARSTATUS_NEGATED )
3563  {
3564  assert(origvar->negatedvar != NULL);
3566 
3567  if( origvar->negatedvar->data.original.transvar == NULL )
3568  *transvar = NULL;
3569  else
3570  {
3571  SCIP_CALL( SCIPvarNegate(origvar->negatedvar->data.original.transvar, blkmem, set, stat, transvar) );
3572  }
3573  }
3574  else
3575  *transvar = origvar->data.original.transvar;
3576 
3577  return SCIP_OKAY;
3578 }
3579 
3580 /** converts loose transformed variable into column variable, creates LP column */
3582  SCIP_VAR* var, /**< problem variable */
3583  BMS_BLKMEM* blkmem, /**< block memory */
3584  SCIP_SET* set, /**< global SCIP settings */
3585  SCIP_STAT* stat, /**< problem statistics */
3586  SCIP_PROB* prob, /**< problem data */
3587  SCIP_LP* lp /**< current LP data */
3588  )
3589 {
3590  assert(var != NULL);
3591  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
3592  assert(var->scip == set->scip);
3593 
3594  SCIPsetDebugMsg(set, "creating column for variable <%s>\n", var->name);
3595 
3596  /* switch variable status */
3597  var->varstatus = SCIP_VARSTATUS_COLUMN; /*lint !e641*/
3598 
3599  /* create column of variable */
3600  SCIP_CALL( SCIPcolCreate(&var->data.col, blkmem, set, stat, var, 0, NULL, NULL, var->removable) );
3601 
3602  if( var->probindex != -1 )
3603  {
3604  /* inform problem about the variable's status change */
3605  SCIP_CALL( SCIPprobVarChangedStatus(prob, blkmem, set, NULL, NULL, var) );
3606 
3607  /* inform LP, that problem variable is now a column variable and no longer loose */
3608  SCIP_CALL( SCIPlpUpdateVarColumn(lp, set, var) );
3609  }
3610 
3611  return SCIP_OKAY;
3612 }
3613 
3614 /** converts column transformed variable back into loose variable, frees LP column */
3616  SCIP_VAR* var, /**< problem variable */
3617  BMS_BLKMEM* blkmem, /**< block memory */
3618  SCIP_SET* set, /**< global SCIP settings */
3619  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3620  SCIP_PROB* prob, /**< problem data */
3621  SCIP_LP* lp /**< current LP data */
3622  )
3623 {
3624  assert(var != NULL);
3625  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
3626  assert(var->scip == set->scip);
3627  assert(var->data.col != NULL);
3628  assert(var->data.col->lppos == -1);
3629  assert(var->data.col->lpipos == -1);
3630 
3631  SCIPsetDebugMsg(set, "deleting column for variable <%s>\n", var->name);
3632 
3633  /* free column of variable */
3634  SCIP_CALL( SCIPcolFree(&var->data.col, blkmem, set, eventqueue, lp) );
3635 
3636  /* switch variable status */
3637  var->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
3638 
3639  if( var->probindex != -1 )
3640  {
3641  /* inform problem about the variable's status change */
3642  SCIP_CALL( SCIPprobVarChangedStatus(prob, blkmem, set, NULL, NULL, var) );
3643 
3644  /* inform LP, that problem variable is now a loose variable and no longer a column */
3645  SCIP_CALL( SCIPlpUpdateVarLoose(lp, set, var) );
3646  }
3647 
3648  return SCIP_OKAY;
3649 }
3650 
3651 /** issues a VARFIXED event on the given variable and all its parents (except ORIGINAL parents);
3652  * the event issuing on the parents is necessary, because unlike with bound changes, the parent variables
3653  * are not informed about a fixing of an active variable they are pointing to
3654  */
3655 static
3657  SCIP_VAR* var, /**< problem variable to change */
3658  BMS_BLKMEM* blkmem, /**< block memory */
3659  SCIP_SET* set, /**< global SCIP settings */
3660  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3661  int fixeventtype /**< is this event a fixation(0), an aggregation(1), or a
3662  * multi-aggregation(2)
3663  */
3664  )
3665 {
3666  SCIP_EVENT* event;
3667  SCIP_VARSTATUS varstatus;
3668  int i;
3669 
3670  assert(var != NULL);
3671  assert(var->scip == set->scip);
3672  assert(0 <= fixeventtype && fixeventtype <= 2);
3673 
3674  /* issue VARFIXED event on variable */
3675  SCIP_CALL( SCIPeventCreateVarFixed(&event, blkmem, var) );
3676  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
3677 
3678 #ifndef NDEBUG
3679  for( i = var->nparentvars -1; i >= 0; --i )
3680  {
3682  }
3683 #endif
3684 
3685  switch( fixeventtype )
3686  {
3687  case 0:
3688  /* process all parents of a fixed variable */
3689  for( i = var->nparentvars - 1; i >= 0; --i )
3690  {
3691  varstatus = SCIPvarGetStatus(var->parentvars[i]);
3692 
3693  assert(varstatus != SCIP_VARSTATUS_FIXED);
3694 
3695  /* issue event on all not yet fixed parent variables, (that should already issued this event) except the original
3696  * one
3697  */
3698  if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3699  {
3700  SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3701  }
3702  }
3703  break;
3704  case 1:
3705  /* process all parents of a aggregated variable */
3706  for( i = var->nparentvars - 1; i >= 0; --i )
3707  {
3708  varstatus = SCIPvarGetStatus(var->parentvars[i]);
3709 
3710  assert(varstatus != SCIP_VARSTATUS_FIXED);
3711 
3712  /* issue event for not aggregated parent variable, because for these and its parents the var event was already
3713  * issued(, except the original one)
3714  *
3715  * @note that even before an aggregated parent variable, there might be variables, for which the vent was not
3716  * yet issued
3717  */
3718  if( varstatus == SCIP_VARSTATUS_AGGREGATED )
3719  continue;
3720 
3721  if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3722  {
3723  SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3724  }
3725  }
3726  break;
3727  case 2:
3728  /* process all parents of a aggregated variable */
3729  for( i = var->nparentvars - 1; i >= 0; --i )
3730  {
3731  varstatus = SCIPvarGetStatus(var->parentvars[i]);
3732 
3733  assert(varstatus != SCIP_VARSTATUS_FIXED);
3734 
3735  /* issue event on all parent variables except the original one */
3736  if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3737  {
3738  SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3739  }
3740  }
3741  break;
3742  default:
3743  SCIPerrorMessage("unknown variable fixation event origin\n");
3744  return SCIP_INVALIDDATA;
3745  }
3746 
3747  return SCIP_OKAY;
3748 }
3749 
3750 /** converts variable into fixed variable */
3752  SCIP_VAR* var, /**< problem variable */
3753  BMS_BLKMEM* blkmem, /**< block memory */
3754  SCIP_SET* set, /**< global SCIP settings */
3755  SCIP_STAT* stat, /**< problem statistics */
3756  SCIP_PROB* transprob, /**< tranformed problem data */
3757  SCIP_PROB* origprob, /**< original problem data */
3758  SCIP_PRIMAL* primal, /**< primal data */
3759  SCIP_TREE* tree, /**< branch and bound tree */
3760  SCIP_REOPT* reopt, /**< reoptimization data structure */
3761  SCIP_LP* lp, /**< current LP data */
3762  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3763  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
3764  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3765  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
3766  SCIP_Real fixedval, /**< value to fix variable at */
3767  SCIP_Bool* infeasible, /**< pointer to store whether the fixing is infeasible */
3768  SCIP_Bool* fixed /**< pointer to store whether the fixing was performed (variable was unfixed) */
3769  )
3770 {
3771  SCIP_Real obj;
3772  SCIP_Real childfixedval;
3773 
3774  assert(var != NULL);
3775  assert(var->scip == set->scip);
3776  assert(SCIPsetIsEQ(set, var->glbdom.lb, var->locdom.lb));
3777  assert(SCIPsetIsEQ(set, var->glbdom.ub, var->locdom.ub));
3778  assert(infeasible != NULL);
3779  assert(fixed != NULL);
3780 
3781  SCIPsetDebugMsg(set, "fix variable <%s>[%g,%g] to %g\n", var->name, var->glbdom.lb, var->glbdom.ub, fixedval);
3782 
3783  *infeasible = FALSE;
3784  *fixed = FALSE;
3785 
3787  {
3788  *infeasible = !SCIPsetIsFeasEQ(set, fixedval, var->locdom.lb);
3789  SCIPsetDebugMsg(set, " -> variable already fixed to %g (fixedval=%g): infeasible=%u\n", var->locdom.lb, fixedval, *infeasible);
3790  return SCIP_OKAY;
3791  }
3792  else if( (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPsetIsFeasIntegral(set, fixedval))
3793  || SCIPsetIsFeasLT(set, fixedval, var->locdom.lb)
3794  || SCIPsetIsFeasGT(set, fixedval, var->locdom.ub) )
3795  {
3796  SCIPsetDebugMsg(set, " -> fixing infeasible: locdom=[%g,%g], fixedval=%g\n", var->locdom.lb, var->locdom.ub, fixedval);
3797  *infeasible = TRUE;
3798  return SCIP_OKAY;
3799  }
3800 
3801  switch( SCIPvarGetStatus(var) )
3802  {
3804  if( var->data.original.transvar == NULL )
3805  {
3806  SCIPerrorMessage("cannot fix an untransformed original variable\n");
3807  return SCIP_INVALIDDATA;
3808  }
3809  SCIP_CALL( SCIPvarFix(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
3810  lp, branchcand, eventfilter, eventqueue, cliquetable, fixedval, infeasible, fixed) );
3811  break;
3812 
3813  case SCIP_VARSTATUS_LOOSE:
3814  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
3815 
3816  /* set the fixed variable's objective value to 0.0 */
3817  obj = var->obj;
3818  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
3819 
3820  /* since we change the variable type form loose to fixed, we have to adjust the number of loose
3821  * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
3822  * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
3823  * objective of this variable is set to zero
3824  */
3825  SCIPlpDecNLoosevars(lp);
3826 
3827  /* change variable's bounds to fixed value (thereby removing redundant implications and variable bounds) */
3828  holelistFree(&var->glbdom.holelist, blkmem);
3829  holelistFree(&var->locdom.holelist, blkmem);
3830  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, fixedval) );
3831  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, fixedval) );
3832 
3833  /* explicitly set variable's bounds, even if the fixed value is in epsilon range of the old bound */
3834  var->glbdom.lb = fixedval;
3835  var->glbdom.ub = fixedval;
3836  var->locdom.lb = fixedval;
3837  var->locdom.ub = fixedval;
3838 
3839  /* delete implications and variable bounds information */
3840  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
3841  assert(var->vlbs == NULL);
3842  assert(var->vubs == NULL);
3843  assert(var->implics == NULL);
3844  assert(var->cliquelist == NULL);
3845 
3846  /* clear the history of the variable */
3847  SCIPhistoryReset(var->history);
3849 
3850  /* convert variable into fixed variable */
3851  var->varstatus = SCIP_VARSTATUS_FIXED; /*lint !e641*/
3852 
3853  /* inform problem about the variable's status change */
3854  if( var->probindex != -1 )
3855  {
3856  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
3857  }
3858 
3859  /* reset the objective value of the fixed variable, thus adjusting the problem's objective offset */
3860  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventfilter, eventqueue, obj) );
3861 
3862  /* issue VARFIXED event */
3863  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 0) );
3864 
3865  *fixed = TRUE;
3866  break;
3867 
3868  case SCIP_VARSTATUS_COLUMN:
3869  SCIPerrorMessage("cannot fix a column variable\n");
3870  return SCIP_INVALIDDATA;
3871 
3872  case SCIP_VARSTATUS_FIXED:
3873  SCIPerrorMessage("cannot fix a fixed variable again\n"); /*lint !e527*/
3874  SCIPABORT(); /* case is already handled in earlier if condition */
3875  return SCIP_INVALIDDATA; /*lint !e527*/
3876 
3878  /* fix aggregation variable y in x = a*y + c, instead of fixing x directly */
3879  assert(SCIPsetIsZero(set, var->obj));
3880  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
3881  if( SCIPsetIsInfinity(set, fixedval) || SCIPsetIsInfinity(set, -fixedval) )
3882  childfixedval = (var->data.aggregate.scalar < 0.0 ? -fixedval : fixedval);
3883  else
3884  childfixedval = (fixedval - var->data.aggregate.constant)/var->data.aggregate.scalar;
3885  SCIP_CALL( SCIPvarFix(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
3886  branchcand, eventfilter, eventqueue, cliquetable, childfixedval, infeasible, fixed) );
3887  break;
3888 
3890  SCIPerrorMessage("cannot fix a multiple aggregated variable\n");
3891  SCIPABORT();
3892  return SCIP_INVALIDDATA; /*lint !e527*/
3893 
3895  /* fix negation variable x in x' = offset - x, instead of fixing x' directly */
3896  assert(SCIPsetIsZero(set, var->obj));
3897  assert(var->negatedvar != NULL);
3899  assert(var->negatedvar->negatedvar == var);
3900  SCIP_CALL( SCIPvarFix(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
3901  branchcand, eventfilter, eventqueue, cliquetable, var->data.negate.constant - fixedval, infeasible, fixed) );
3902  break;
3903 
3904  default:
3905  SCIPerrorMessage("unknown variable status\n");
3906  return SCIP_INVALIDDATA;
3907  }
3908 
3909  return SCIP_OKAY;
3910 }
3911 
3912 /** transforms given variables, scalars and constant to the corresponding active variables, scalars and constant
3913  *
3914  * If the number of needed active variables is greater than the available slots in the variable array, nothing happens except
3915  * that the required size is stored in the corresponding variable; hence, if afterwards the required size is greater than the
3916  * available slots (varssize), nothing happens; otherwise, the active variable representation is stored in the arrays.
3917  *
3918  * The reason for this approach is that we cannot reallocate memory, since we do not know how the
3919  * memory has been allocated (e.g., by a C++ 'new' or SCIP functions).
3920  */
3922  SCIP_SET* set, /**< global SCIP settings */
3923  SCIP_VAR** vars, /**< variable array to get active variables */
3924  SCIP_Real* scalars, /**< scalars a_1, ..., a_n in linear sum a_1*x_1 + ... + a_n*x_n + c */
3925  int* nvars, /**< pointer to number of variables and values in vars and scalars array */
3926  int varssize, /**< available slots in vars and scalars array */
3927  SCIP_Real* constant, /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c */
3928  int* requiredsize, /**< pointer to store the required array size for the active variables */
3929  SCIP_Bool mergemultiples /**< should multiple occurrences of a var be replaced by a single coeff? */
3930  )
3931 {
3932  SCIP_VAR** activevars;
3933  SCIP_Real* activescalars;
3934  int nactivevars;
3935  SCIP_Real activeconstant;
3936  SCIP_Bool activeconstantinf;
3937  int activevarssize;
3938 
3939  SCIP_VAR* var;
3940  SCIP_Real scalar;
3941  int v;
3942  int k;
3943 
3944  SCIP_VAR** tmpvars;
3945  SCIP_VAR** multvars;
3946  SCIP_Real* tmpscalars;
3947  SCIP_Real* multscalars;
3948  int tmpvarssize;
3949  int ntmpvars;
3950  int nmultvars;
3951 
3952  SCIP_VAR* multvar;
3953  SCIP_Real multscalar;
3954  SCIP_Real multconstant;
3955  int pos;
3956 
3957  int noldtmpvars;
3958 
3959  SCIP_VAR** tmpvars2;
3960  SCIP_Real* tmpscalars2;
3961  int tmpvarssize2;
3962  int ntmpvars2;
3963 
3964  SCIP_Bool sortagain = FALSE;
3965 
3966  assert(set != NULL);
3967  assert(nvars != NULL);
3968  assert(scalars != NULL || *nvars == 0);
3969  assert(constant != NULL);
3970  assert(requiredsize != NULL);
3971  assert(*nvars <= varssize);
3972 
3973  *requiredsize = 0;
3974 
3975  if( *nvars == 0 )
3976  return SCIP_OKAY;
3977 
3978  assert(vars != NULL);
3979 
3980  /* handle the "easy" case of just one variable and avoid memory allocation if the variable is already active */
3981  if( *nvars == 1 && (vars[0]->varstatus == ((int) SCIP_VARSTATUS_COLUMN) || vars[0]->varstatus == ((int) SCIP_VARSTATUS_LOOSE)) )
3982  {
3983  *requiredsize = 1;
3984 
3985  return SCIP_OKAY;
3986  }
3987 
3988  nactivevars = 0;
3989  activeconstant = 0.0;
3990  activeconstantinf = FALSE;
3991  activevarssize = (*nvars) * 2;
3992  ntmpvars = *nvars;
3993  tmpvarssize = *nvars;
3994 
3995  tmpvarssize2 = 1;
3996 
3997  /* allocate temporary memory */
3998  SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpvars2, tmpvarssize2) );
3999  SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpscalars2, tmpvarssize2) );
4000  SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
4001  SCIP_CALL( SCIPsetAllocBufferArray(set, &activescalars, activevarssize) );
4002  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
4003  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpscalars, scalars, ntmpvars) );
4004 
4005  /* to avoid unnecessary expanding of variable arrays while disaggregating several variables multiple times combine same variables
4006  * first, first get all corresponding variables with status loose, column, multaggr or fixed
4007  */
4008  for( v = ntmpvars - 1; v >= 0; --v )
4009  {
4010  var = tmpvars[v];
4011  scalar = tmpscalars[v];
4012 
4013  assert(var != NULL);
4014  /* transforms given variable, scalar and constant to the corresponding active, fixed, or
4015  * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed
4016  * variable, "scalar" will be 0.0 and the value of the sum will be stored in "constant".
4017  */
4018  SCIP_CALL( SCIPvarGetProbvarSum(&var, set, &scalar, &activeconstant) );
4019  assert(var != NULL);
4020 
4021  assert(SCIPsetIsInfinity(set, activeconstant) == (activeconstant == SCIPsetInfinity(set))); /*lint !e777*/
4022  assert(SCIPsetIsInfinity(set, -activeconstant) == (activeconstant == -SCIPsetInfinity(set))); /*lint !e777*/
4023 
4024  activeconstantinf = SCIPsetIsInfinity(set, activeconstant) || SCIPsetIsInfinity(set, -activeconstant);
4025 
4026  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
4027  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
4030 
4031  tmpvars[v] = var;
4032  tmpscalars[v] = scalar;
4033  }
4034  noldtmpvars = ntmpvars;
4035 
4036  /* sort all variables to combine equal variables easily */
4037  SCIPsortPtrReal((void**)tmpvars, tmpscalars, SCIPvarComp, noldtmpvars);
4038  ntmpvars = 0;
4039  for( v = 1; v < noldtmpvars; ++v )
4040  {
4041  /* combine same variables */
4042  if( SCIPvarCompare(tmpvars[v], tmpvars[ntmpvars]) == 0 )
4043  {
4044  tmpscalars[ntmpvars] += tmpscalars[v];
4045  }
4046  else
4047  {
4048  ++ntmpvars;
4049  if( v > ntmpvars )
4050  {
4051  tmpscalars[ntmpvars] = tmpscalars[v];
4052  tmpvars[ntmpvars] = tmpvars[v];
4053  }
4054  }
4055  }
4056  ++ntmpvars;
4057 
4058 #ifdef SCIP_MORE_DEBUG
4059  for( v = 1; v < ntmpvars; ++v )
4060  assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
4061 #endif
4062 
4063  /* collect for each variable the representation in active variables */
4064  while( ntmpvars >= 1 )
4065  {
4066  --ntmpvars;
4067  ntmpvars2 = 0;
4068  var = tmpvars[ntmpvars];
4069  scalar = tmpscalars[ntmpvars];
4070 
4071  assert(var != NULL);
4072 
4073  /* TODO: maybe we should test here on SCIPsetIsZero() instead of 0.0 */
4074  if( scalar == 0.0 )
4075  continue;
4076 
4077  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
4078  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
4081 
4082  switch( SCIPvarGetStatus(var) )
4083  {
4084  case SCIP_VARSTATUS_LOOSE:
4085  case SCIP_VARSTATUS_COLUMN:
4086  /* x = a*y + c */
4087  if( nactivevars >= activevarssize )
4088  {
4089  activevarssize *= 2;
4090  SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
4091  SCIP_CALL( SCIPsetReallocBufferArray(set, &activescalars, activevarssize) );
4092  assert(nactivevars < activevarssize);
4093  }
4094  activevars[nactivevars] = var;
4095  activescalars[nactivevars] = scalar;
4096  nactivevars++;
4097  break;
4098 
4100  /* x = a_1*y_1 + ... + a_n*y_n + c */
4101  nmultvars = var->data.multaggr.nvars;
4102  multvars = var->data.multaggr.vars;
4103  multscalars = var->data.multaggr.scalars;
4104  sortagain = TRUE;
4105 
4106  if( nmultvars + ntmpvars > tmpvarssize )
4107  {
4108  while( nmultvars + ntmpvars > tmpvarssize )
4109  tmpvarssize *= 2;
4110  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
4111  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpscalars, tmpvarssize) );
4112  assert(nmultvars + ntmpvars <= tmpvarssize);
4113  }
4114 
4115  if( nmultvars > tmpvarssize2 )
4116  {
4117  while( nmultvars > tmpvarssize2 )
4118  tmpvarssize2 *= 2;
4119  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars2, tmpvarssize2) );
4120  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpscalars2, tmpvarssize2) );
4121  assert(nmultvars <= tmpvarssize2);
4122  }
4123 
4124  --nmultvars;
4125 
4126  for( ; nmultvars >= 0; --nmultvars )
4127  {
4128  multvar = multvars[nmultvars];
4129  multscalar = multscalars[nmultvars];
4130  multconstant = 0;
4131 
4132  assert(multvar != NULL);
4133  SCIP_CALL( SCIPvarGetProbvarSum(&multvar, set, &multscalar, &multconstant) );
4134  assert(multvar != NULL);
4135 
4136  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
4137  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
4140 
4141  if( !activeconstantinf )
4142  {
4143  assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
4144 
4145  if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) )
4146  {
4147  assert(scalar != 0.0);
4148  if( scalar * multconstant > 0.0 )
4149  {
4150  activeconstant = SCIPsetInfinity(set);
4151  activeconstantinf = TRUE;
4152  }
4153  else
4154  {
4155  activeconstant = -SCIPsetInfinity(set);
4156  activeconstantinf = TRUE;
4157  }
4158  }
4159  else
4160  activeconstant += scalar * multconstant;
4161  }
4162 #ifndef NDEBUG
4163  else
4164  {
4165  assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
4166  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4167  assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
4168  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4169  }
4170 #endif
4171 
4172  if( SCIPsortedvecFindPtr((void**)tmpvars, SCIPvarComp, multvar, ntmpvars, &pos) )
4173  {
4174  assert(SCIPvarCompare(tmpvars[pos], multvar) == 0);
4175  tmpscalars[pos] += scalar * multscalar;
4176  }
4177  else
4178  {
4179  tmpvars2[ntmpvars2] = multvar;
4180  tmpscalars2[ntmpvars2] = scalar * multscalar;
4181  ++(ntmpvars2);
4182  assert(ntmpvars2 <= tmpvarssize2);
4183  }
4184  }
4185 
4186  if( ntmpvars2 > 0 )
4187  {
4188  /* sort all variables to combine equal variables easily */
4189  SCIPsortPtrReal((void**)tmpvars2, tmpscalars2, SCIPvarComp, ntmpvars2);
4190  pos = 0;
4191  for( v = 1; v < ntmpvars2; ++v )
4192  {
4193  /* combine same variables */
4194  if( SCIPvarCompare(tmpvars2[v], tmpvars2[pos]) == 0 )
4195  {
4196  tmpscalars2[pos] += tmpscalars2[v];
4197  }
4198  else
4199  {
4200  ++pos;
4201  if( v > pos )
4202  {
4203  tmpscalars2[pos] = tmpscalars2[v];
4204  tmpvars2[pos] = tmpvars2[v];
4205  }
4206  }
4207  }
4208  ntmpvars2 = pos + 1;
4209 #ifdef SCIP_MORE_DEBUG
4210  for( v = 1; v < ntmpvars2; ++v )
4211  {
4212  assert(SCIPvarCompare(tmpvars2[v], tmpvars2[v-1]) > 0);
4213  }
4214  for( v = 1; v < ntmpvars; ++v )
4215  {
4216  assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
4217  }
4218 #endif
4219  v = ntmpvars - 1;
4220  k = ntmpvars2 - 1;
4221  pos = ntmpvars + ntmpvars2 - 1;
4222  ntmpvars += ntmpvars2;
4223 
4224  while( v >= 0 && k >= 0 )
4225  {
4226  assert(pos >= 0);
4227  assert(SCIPvarCompare(tmpvars[v], tmpvars2[k]) != 0);
4228  if( SCIPvarCompare(tmpvars[v], tmpvars2[k]) >= 0 )
4229  {
4230  tmpvars[pos] = tmpvars[v];
4231  tmpscalars[pos] = tmpscalars[v];
4232  --v;
4233  }
4234  else
4235  {
4236  tmpvars[pos] = tmpvars2[k];
4237  tmpscalars[pos] = tmpscalars2[k];
4238  --k;
4239  }
4240  --pos;
4241  assert(pos >= 0);
4242  }
4243  while( v >= 0 )
4244  {
4245  assert(pos >= 0);
4246  tmpvars[pos] = tmpvars[v];
4247  tmpscalars[pos] = tmpscalars[v];
4248  --v;
4249  --pos;
4250  }
4251  while( k >= 0 )
4252  {
4253  assert(pos >= 0);
4254  tmpvars[pos] = tmpvars2[k];
4255  tmpscalars[pos] = tmpscalars2[k];
4256  --k;
4257  --pos;
4258  }
4259  }
4260 #ifdef SCIP_MORE_DEBUG
4261  for( v = 1; v < ntmpvars; ++v )
4262  {
4263  assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
4264  }
4265 #endif
4266 
4267  if( !activeconstantinf )
4268  {
4269  assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
4270 
4271  multconstant = SCIPvarGetMultaggrConstant(var);
4272 
4273  if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) )
4274  {
4275  assert(scalar != 0.0);
4276  if( scalar * multconstant > 0.0 )
4277  {
4278  activeconstant = SCIPsetInfinity(set);
4279  activeconstantinf = TRUE;
4280  }
4281  else
4282  {
4283  activeconstant = -SCIPsetInfinity(set);
4284  activeconstantinf = TRUE;
4285  }
4286  }
4287  else
4288  activeconstant += scalar * multconstant;
4289  }
4290 #ifndef NDEBUG
4291  else
4292  {
4293  multconstant = SCIPvarGetMultaggrConstant(var);
4294  assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
4295  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4296  assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
4297  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4298  }
4299 #endif
4300  break;
4301 
4302  case SCIP_VARSTATUS_FIXED:
4306  default:
4307  /* case x = c, but actually we should not be here, since SCIPvarGetProbvarSum() returns a scalar of 0.0 for
4308  * fixed variables and is handled already
4309  */
4310  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED);
4311  assert(SCIPsetIsZero(set, var->glbdom.lb) && SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub));
4312  }
4313  }
4314 
4315  if( mergemultiples )
4316  {
4317  if( sortagain )
4318  {
4319  /* sort variable and scalar array by variable index */
4320  SCIPsortPtrReal((void**)activevars, activescalars, SCIPvarComp, nactivevars);
4321 
4322  /* eliminate duplicates and count required size */
4323  v = nactivevars - 1;
4324  while( v > 0 )
4325  {
4326  /* combine both variable since they are the same */
4327  if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
4328  {
4329  if( activescalars[v - 1] + activescalars[v] != 0.0 )
4330  {
4331  activescalars[v - 1] += activescalars[v];
4332  --nactivevars;
4333  activevars[v] = activevars[nactivevars];
4334  activescalars[v] = activescalars[nactivevars];
4335  }
4336  else
4337  {
4338  --nactivevars;
4339  activevars[v] = activevars[nactivevars];
4340  activescalars[v] = activescalars[nactivevars];
4341  --nactivevars;
4342  --v;
4343  activevars[v] = activevars[nactivevars];
4344  activescalars[v] = activescalars[nactivevars];
4345  }
4346  }
4347  --v;
4348  }
4349  }
4350  /* the variables were added in reverse order, we revert the order now;
4351  * this should not be necessary, but not doing this changes the behavior sometimes
4352  */
4353  else
4354  {
4355  SCIP_VAR* tmpvar;
4356  SCIP_Real tmpscalar;
4357 
4358  for( v = 0; v < nactivevars / 2; ++v )
4359  {
4360  tmpvar = activevars[v];
4361  tmpscalar = activescalars[v];
4362  activevars[v] = activevars[nactivevars - 1 - v];
4363  activescalars[v] = activescalars[nactivevars - 1 - v];
4364  activevars[nactivevars - 1 - v] = tmpvar;
4365  activescalars[nactivevars - 1 - v] = tmpscalar;
4366  }
4367  }
4368  }
4369  *requiredsize = nactivevars;
4370 
4371  if( varssize >= *requiredsize )
4372  {
4373  assert(vars != NULL);
4374 
4375  *nvars = *requiredsize;
4376 
4377  if( !SCIPsetIsInfinity(set, *constant) && !SCIPsetIsInfinity(set, -(*constant)) )
4378  {
4379  /* if the activeconstant is infinite, the constant pointer gets the same value, otherwise add the value */
4380  if( activeconstantinf )
4381  (*constant) = activeconstant;
4382  else
4383  (*constant) += activeconstant;
4384  }
4385 #ifndef NDEBUG
4386  else
4387  {
4388  assert(!SCIPsetIsInfinity(set, (*constant)) || !SCIPsetIsInfinity(set, -activeconstant));
4389  assert(!SCIPsetIsInfinity(set, -(*constant)) || !SCIPsetIsInfinity(set, activeconstant));
4390  }
4391 #endif
4392 
4393  /* copy active variable and scalar array to the given arrays */
4394  for( v = 0; v < *nvars; ++v )
4395  {
4396  vars[v] = activevars[v];
4397  scalars[v] = activescalars[v]; /*lint !e613*/
4398  }
4399  }
4400 
4401  assert(SCIPsetIsInfinity(set, *constant) == ((*constant) == SCIPsetInfinity(set))); /*lint !e777*/
4402  assert(SCIPsetIsInfinity(set, -(*constant)) == ((*constant) == -SCIPsetInfinity(set))); /*lint !e777*/
4403 
4404  SCIPsetFreeBufferArray(set, &tmpscalars);
4405  SCIPsetFreeBufferArray(set, &tmpvars);
4406  SCIPsetFreeBufferArray(set, &activescalars);
4407  SCIPsetFreeBufferArray(set, &activevars);
4408  SCIPsetFreeBufferArray(set, &tmpscalars2);
4409  SCIPsetFreeBufferArray(set, &tmpvars2);
4410 
4411  return SCIP_OKAY;
4412 }
4413 
4414 
4415 /** flattens aggregation graph of multi-aggregated variable in order to avoid exponential recursion later on */
4417  SCIP_VAR* var, /**< problem variable */
4418  BMS_BLKMEM* blkmem, /**< block memory */
4419  SCIP_SET* set, /**< global SCIP settings */
4420  SCIP_EVENTQUEUE* eventqueue /**< event queue */
4421  )
4422 {
4423  int nlocksup[NLOCKTYPES];
4424  int nlocksdown[NLOCKTYPES];
4425  SCIP_Real multconstant;
4426  int multvarssize;
4427  int nmultvars;
4428  int multrequiredsize;
4429  int i;
4430 
4431  assert( var != NULL );
4432  assert( SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR );
4433  assert(var->scip == set->scip);
4434 
4435  /* in order to update the locks on the active representation of the multi-aggregated variable, we remove all locks
4436  * on the current representation now and re-add the locks once the variable graph has been flattened, which
4437  * may lead to duplicate occurences of the same variable being merged
4438  *
4439  * Here is an example. Assume we have the multi-aggregation z = x + y.
4440  * z occures with positive coefficient in a <= constraint c1, so it has an uplock from there.
4441  * When the multi-aggregation is performed, all locks are added to the active representation,
4442  * so x and y both get an uplock from c1. However, z was not yet replaced by x + y in c1.
4443  * Next, a negation y = 1 - x is identified. Again, locks are moved, so that the uplock of y originating
4444  * from c1 is added to x as a downlock. Thus, x has both an up- and downlock from c1.
4445  * The multi-aggregation changes to z = x + 1 - x, which corresponds to the locks.
4446  * However, before z is replaced by that sum, SCIPvarFlattenAggregationGraph() is called
4447  * which changes z = x + y = x + 1 - x = 1, since it merges multiple occurences of the same variable.
4448  * The up- and downlock of x, however, is not removed when replacing z in c1 by its active representation,
4449  * because it is just 1 now. Therefore, we need to update locks when flattening the aggregation graph.
4450  * For this, the multi-aggregated variable knows its locks in addition to adding them to the active
4451  * representation, which corresponds to the locks from constraints where the variable was not replaced yet.
4452  * By removing the locks here, based on the old representation and adding them again after flattening,
4453  * we ensure that the locks are correct afterwards if coefficients were merged.
4454  */
4455  for( i = 0; i < NLOCKTYPES; ++i )
4456  {
4457  nlocksup[i] = var->nlocksup[i];
4458  nlocksdown[i] = var->nlocksdown[i];
4459 
4460  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, -nlocksdown[i], -nlocksup[i]) );
4461  }
4462 
4463  multconstant = var->data.multaggr.constant;
4464  nmultvars = var->data.multaggr.nvars;
4465  multvarssize = var->data.multaggr.varssize;
4466 
4467  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize, TRUE) );
4468 
4469  if( multrequiredsize > multvarssize )
4470  {
4471  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.vars), multvarssize, multrequiredsize) );
4472  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.scalars), multvarssize, multrequiredsize) );
4473  multvarssize = multrequiredsize;
4474  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize, TRUE) );
4475  assert( multrequiredsize <= multvarssize );
4476  }
4477  /**@note After the flattening the multi aggregation might resolve to be in fact an aggregation (or even a fixing?).
4478  * This issue is not resolved right now, since var->data.multaggr.nvars < 2 should not cause troubles. However, one
4479  * may loose performance hereby, since aggregated variables are easier to handle.
4480  *
4481  * Note, that there are two cases where SCIPvarFlattenAggregationGraph() is called: The easier one is that it is
4482  * called while installing the multi-aggregation. in principle, the described issue could be handled straightforward
4483  * in this case by aggregating or fixing the variable instead. The more complicated case is the one, when the
4484  * multi-aggregation is used, e.g., in linear presolving (and the variable is already declared to be multi-aggregated).
4485  *
4486  * By now, it is not allowed to fix or aggregate multi-aggregated variables which would be necessary in this case.
4487  *
4488  * The same issue appears in the SCIPvarGetProbvar...() methods.
4489  */
4490 
4491  var->data.multaggr.constant = multconstant;
4492  var->data.multaggr.nvars = nmultvars;
4493  var->data.multaggr.varssize = multvarssize;
4494 
4495  for( i = 0; i < NLOCKTYPES; ++i )
4496  {
4497  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
4498  }
4499 
4500  return SCIP_OKAY;
4501 }
4502 
4503 /** merge two variable histories together; a typical use case is that \p othervar is an image of the target variable
4504  * in a SCIP copy. Method should be applied with care, especially because no internal checks are performed whether
4505  * the history merge is reasonable
4506  *
4507  * @note Do not use this method if the two variables originate from two SCIP's with different objective functions, since
4508  * this corrupts the variable pseudo costs
4509  * @note Apply with care; no internal checks are performed if the two variables should be merged
4510  */
4512  SCIP_VAR* targetvar, /**< the variable that should contain both histories afterwards */
4513  SCIP_VAR* othervar, /**< the variable whose history is to be merged with that of the target variable */
4514  SCIP_STAT* stat /**< problem statistics */
4515  )
4516 {
4517  /* merge only the history of the current run into the target history */
4518  SCIPhistoryUnite(targetvar->history, othervar->historycrun, FALSE);
4519 
4520  /* apply the changes also to the global history */
4521  SCIPhistoryUnite(stat->glbhistory, othervar->historycrun, FALSE);
4522 }
4523 
4524 /** sets the history of a variable; this method is typically used within reoptimization to keep and update the variable
4525  * history over several iterations
4526  */
4527 void SCIPvarSetHistory(
4528  SCIP_VAR* var, /**< variable */
4529  SCIP_HISTORY* history, /**< the history which is to set */
4530  SCIP_STAT* stat /**< problem statistics */
4531  )
4532 {
4533  /* merge only the history of the current run into the target history */
4534  SCIPhistoryUnite(var->history, history, FALSE);
4535 
4536  /* apply the changes also to the global history */
4537  SCIPhistoryUnite(stat->glbhistory, history, FALSE);
4538 }
4539 
4540 /** tightens the bounds of both variables in aggregation x = a*y + c */
4541 static
4543  SCIP_VAR* var, /**< problem variable */
4544  BMS_BLKMEM* blkmem, /**< block memory */
4545  SCIP_SET* set, /**< global SCIP settings */
4546  SCIP_STAT* stat, /**< problem statistics */
4547  SCIP_PROB* transprob, /**< tranformed problem data */
4548  SCIP_PROB* origprob, /**< original problem data */
4549  SCIP_PRIMAL* primal, /**< primal data */
4550  SCIP_TREE* tree, /**< branch and bound tree */
4551  SCIP_REOPT* reopt, /**< reoptimization data structure */
4552  SCIP_LP* lp, /**< current LP data */
4553  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4554  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4555  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4556  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4557  SCIP_VAR* aggvar, /**< variable y in aggregation x = a*y + c */
4558  SCIP_Real scalar, /**< multiplier a in aggregation x = a*y + c */
4559  SCIP_Real constant, /**< constant shift c in aggregation x = a*y + c */
4560  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4561  SCIP_Bool* fixed /**< pointer to store whether the variables were fixed */
4562  )
4563 {
4564  SCIP_Real varlb;
4565  SCIP_Real varub;
4566  SCIP_Real aggvarlb;
4567  SCIP_Real aggvarub;
4568  SCIP_Bool aggvarbdschanged;
4569 
4570  assert(var != NULL);
4571  assert(var->scip == set->scip);
4572  assert(aggvar != NULL);
4573  assert(!SCIPsetIsZero(set, scalar));
4574  assert(infeasible != NULL);
4575  assert(fixed != NULL);
4576 
4577  *infeasible = FALSE;
4578  *fixed = FALSE;
4579 
4580  SCIPsetDebugMsg(set, "updating bounds of variables in aggregation <%s> == %g*<%s> %+g\n", var->name, scalar, aggvar->name, constant);
4581  SCIPsetDebugMsg(set, " old bounds: <%s> [%g,%g] <%s> [%g,%g]\n",
4582  var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
4583 
4584  /* loop as long additional changes may be found */
4585  do
4586  {
4587  aggvarbdschanged = FALSE;
4588 
4589  /* update the bounds of the aggregated variable x in x = a*y + c */
4590  if( scalar > 0.0 )
4591  {
4592  if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
4593  varlb = -SCIPsetInfinity(set);
4594  else
4595  varlb = aggvar->glbdom.lb * scalar + constant;
4596  if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
4597  varub = SCIPsetInfinity(set);
4598  else
4599  varub = aggvar->glbdom.ub * scalar + constant;
4600  }
4601  else
4602  {
4603  if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
4604  varub = SCIPsetInfinity(set);
4605  else
4606  varub = aggvar->glbdom.lb * scalar + constant;
4607  if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
4608  varlb = -SCIPsetInfinity(set);
4609  else
4610  varlb = aggvar->glbdom.ub * scalar + constant;
4611  }
4612  varlb = MAX(varlb, var->glbdom.lb);
4613  varub = MIN(varub, var->glbdom.ub);
4614  SCIPvarAdjustLb(var, set, &varlb);
4615  SCIPvarAdjustUb(var, set, &varub);
4616 
4617  /* check the new bounds */
4618  if( SCIPsetIsGT(set, varlb, varub) )
4619  {
4620  /* the aggregation is infeasible */
4621  *infeasible = TRUE;
4622  return SCIP_OKAY;
4623  }
4624  else if( SCIPsetIsEQ(set, varlb, varub) )
4625  {
4626  /* the aggregated variable is fixed -> fix both variables */
4627  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4628  eventfilter, eventqueue, cliquetable, varlb, infeasible, fixed) );
4629  if( !(*infeasible) )
4630  {
4631  SCIP_Bool aggfixed;
4632 
4633  SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4634  eventfilter, eventqueue, cliquetable, (varlb-constant)/scalar, infeasible, &aggfixed) );
4635  assert(*fixed == aggfixed);
4636  }
4637  return SCIP_OKAY;
4638  }
4639  else
4640  {
4641  if( SCIPsetIsGT(set, varlb, var->glbdom.lb) )
4642  {
4643  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, varlb) );
4644  }
4645  if( SCIPsetIsLT(set, varub, var->glbdom.ub) )
4646  {
4647  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, varub) );
4648  }
4649 
4650  /* update the hole list of the aggregation variable */
4651  /**@todo update hole list of aggregation variable */
4652  }
4653 
4654  /* update the bounds of the aggregation variable y in x = a*y + c -> y = (x-c)/a */
4655  if( scalar > 0.0 )
4656  {
4657  if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
4658  aggvarlb = -SCIPsetInfinity(set);
4659  else
4660  aggvarlb = (var->glbdom.lb - constant) / scalar;
4661  if( SCIPsetIsInfinity(set, var->glbdom.ub) )
4662  aggvarub = SCIPsetInfinity(set);
4663  else
4664  aggvarub = (var->glbdom.ub - constant) / scalar;
4665  }
4666  else
4667  {
4668  if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
4669  aggvarub = SCIPsetInfinity(set);
4670  else
4671  aggvarub = (var->glbdom.lb - constant) / scalar;
4672  if( SCIPsetIsInfinity(set, var->glbdom.ub) )
4673  aggvarlb = -SCIPsetInfinity(set);
4674  else
4675  aggvarlb = (var->glbdom.ub - constant) / scalar;
4676  }
4677  aggvarlb = MAX(aggvarlb, aggvar->glbdom.lb);
4678  aggvarub = MIN(aggvarub, aggvar->glbdom.ub);
4679  SCIPvarAdjustLb(aggvar, set, &aggvarlb);
4680  SCIPvarAdjustUb(aggvar, set, &aggvarub);
4681 
4682  /* check the new bounds */
4683  if( SCIPsetIsGT(set, aggvarlb, aggvarub) )
4684  {
4685  /* the aggregation is infeasible */
4686  *infeasible = TRUE;
4687  return SCIP_OKAY;
4688  }
4689  else if( SCIPsetIsEQ(set, aggvarlb, aggvarub) )
4690  {
4691  /* the aggregation variable is fixed -> fix both variables */
4692  SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4693  eventfilter, eventqueue, cliquetable, aggvarlb, infeasible, fixed) );
4694  if( !(*infeasible) )
4695  {
4696  SCIP_Bool varfixed;
4697 
4698  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4699  eventfilter, eventqueue, cliquetable, aggvarlb * scalar + constant, infeasible, &varfixed) );
4700  assert(*fixed == varfixed);
4701  }
4702  return SCIP_OKAY;
4703  }
4704  else
4705  {
4706  SCIP_Real oldbd;
4707  if( SCIPsetIsGT(set, aggvarlb, aggvar->glbdom.lb) )
4708  {
4709  oldbd = aggvar->glbdom.lb;
4710  SCIP_CALL( SCIPvarChgLbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, aggvarlb) );
4711  aggvarbdschanged = !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.lb);
4712  }
4713  if( SCIPsetIsLT(set, aggvarub, aggvar->glbdom.ub) )
4714  {
4715  oldbd = aggvar->glbdom.ub;
4716  SCIP_CALL( SCIPvarChgUbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, aggvarub) );
4717  aggvarbdschanged = aggvarbdschanged || !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.ub);
4718  }
4719 
4720  /* update the hole list of the aggregation variable */
4721  /**@todo update hole list of aggregation variable */
4722  }
4723  }
4724  while( aggvarbdschanged );
4725 
4726  SCIPsetDebugMsg(set, " new bounds: <%s> [%g,%g] <%s> [%g,%g]\n",
4727  var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
4728 
4729  return SCIP_OKAY;
4730 }
4731 
4732 /** converts loose variable into aggregated variable */
4734  SCIP_VAR* var, /**< loose problem variable */
4735  BMS_BLKMEM* blkmem, /**< block memory */
4736  SCIP_SET* set, /**< global SCIP settings */
4737  SCIP_STAT* stat, /**< problem statistics */
4738  SCIP_PROB* transprob, /**< tranformed problem data */
4739  SCIP_PROB* origprob, /**< original problem data */
4740  SCIP_PRIMAL* primal, /**< primal data */
4741  SCIP_TREE* tree, /**< branch and bound tree */
4742  SCIP_REOPT* reopt, /**< reoptimization data structure */
4743  SCIP_LP* lp, /**< current LP data */
4744  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4745  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4746  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4747  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4748  SCIP_VAR* aggvar, /**< loose variable y in aggregation x = a*y + c */
4749  SCIP_Real scalar, /**< multiplier a in aggregation x = a*y + c */
4750  SCIP_Real constant, /**< constant shift c in aggregation x = a*y + c */
4751  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4752  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
4753  )
4754 {
4755  SCIP_VAR** vars;
4756  SCIP_Real* coefs;
4757  SCIP_Real* constants;
4758  SCIP_Real obj;
4759  SCIP_Real branchfactor;
4760  SCIP_Bool fixed;
4761  int branchpriority;
4762  int nlocksdown[NLOCKTYPES];
4763  int nlocksup[NLOCKTYPES];
4764  int nvbds;
4765  int i;
4766  int j;
4767 
4768  assert(var != NULL);
4769  assert(aggvar != NULL);
4770  assert(var->scip == set->scip);
4771  assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
4772  assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
4773  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
4774  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
4775  assert(infeasible != NULL);
4776  assert(aggregated != NULL);
4777 
4778  /* check aggregation on debugging solution */
4779  SCIP_CALL( SCIPdebugCheckAggregation(set, var, &aggvar, &scalar, constant, 1) ); /*lint !e506 !e774*/
4780 
4781  *infeasible = FALSE;
4782  *aggregated = FALSE;
4783 
4784  /* get active problem variable of aggregation variable */
4785  SCIP_CALL( SCIPvarGetProbvarSum(&aggvar, set, &scalar, &constant) );
4786 
4787  /* aggregation is a fixing, if the scalar is zero */
4788  if( SCIPsetIsZero(set, scalar) )
4789  {
4790  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventfilter,
4791  eventqueue, cliquetable, constant, infeasible, aggregated) );
4792  return SCIP_OKAY;
4793  }
4794 
4795  /* don't perform the aggregation if the aggregation variable is multi-aggregated itself */
4796  if( SCIPvarGetStatus(aggvar) == SCIP_VARSTATUS_MULTAGGR )
4797  return SCIP_OKAY;
4798 
4799  /**@todo currently we don't perform the aggregation if the aggregation variable has a non-empty hole list; this
4800  * should be changed in the future
4801  */
4802  if( SCIPvarGetHolelistGlobal(var) != NULL )
4803  return SCIP_OKAY;
4804 
4805  /* if the variable is not allowed to be aggregated */
4806  if( SCIPvarDoNotAggr(var) )
4807  {
4808  SCIPsetDebugMsg(set, "variable is not allowed to be aggregated.\n");
4809  return SCIP_OKAY;
4810  }
4811 
4812  assert(aggvar->glbdom.lb == aggvar->locdom.lb); /*lint !e777*/
4813  assert(aggvar->glbdom.ub == aggvar->locdom.ub); /*lint !e777*/
4814  assert(SCIPvarGetStatus(aggvar) == SCIP_VARSTATUS_LOOSE);
4815 
4816  SCIPsetDebugMsg(set, "aggregate variable <%s>[%g,%g] == %g*<%s>[%g,%g] %+g\n", var->name, var->glbdom.lb, var->glbdom.ub,
4817  scalar, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub, constant);
4818 
4819  /* if variable and aggregation variable are equal, the variable can be fixed: x == a*x + c => x == c/(1-a) */
4820  if( var == aggvar )
4821  {
4822  if( SCIPsetIsEQ(set, scalar, 1.0) )
4823  *infeasible = !SCIPsetIsZero(set, constant);
4824  else
4825  {
4826  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4827  eventfilter, eventqueue, cliquetable, constant/(1.0-scalar), infeasible, aggregated) );
4828  }
4829  return SCIP_OKAY;
4830  }
4831 
4832  /* tighten the bounds of aggregated and aggregation variable */
4833  SCIP_CALL( varUpdateAggregationBounds(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
4834  branchcand, eventfilter, eventqueue, cliquetable, aggvar, scalar, constant, infeasible, &fixed) );
4835  if( *infeasible || fixed )
4836  {
4837  *aggregated = fixed;
4838  return SCIP_OKAY;
4839  }
4840 
4841  /* delete implications and variable bounds of the aggregated variable from other variables, but keep them in the
4842  * aggregated variable
4843  */
4844  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, FALSE) );
4845  assert(var->cliquelist == NULL);
4846 
4847  /* set the aggregated variable's objective value to 0.0 */
4848  obj = var->obj;
4849  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
4850 
4851  /* unlock all locks */
4852  for( i = 0; i < NLOCKTYPES; i++ )
4853  {
4854  nlocksdown[i] = var->nlocksdown[i];
4855  nlocksup[i] = var->nlocksup[i];
4856 
4857  var->nlocksdown[i] = 0;
4858  var->nlocksup[i] = 0;
4859  }
4860 
4861  /* check, if variable should be used as NEGATED variable of the aggregation variable */
4862  if( SCIPvarIsBinary(var) && SCIPvarIsBinary(aggvar)
4863  && var->negatedvar == NULL && aggvar->negatedvar == NULL
4864  && SCIPsetIsEQ(set, scalar, -1.0) && SCIPsetIsEQ(set, constant, 1.0) )
4865  {
4866  /* link both variables as negation pair */
4867  var->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
4868  var->data.negate.constant = 1.0;
4869  var->negatedvar = aggvar;
4870  aggvar->negatedvar = var;
4871 
4872  /* copy donot(mult)aggr status */
4873  aggvar->donotaggr |= var->donotaggr;
4874  aggvar->donotmultaggr |= var->donotmultaggr;
4875 
4876  /* mark both variables to be non-deletable */
4878  SCIPvarMarkNotDeletable(aggvar);
4879  }
4880  else
4881  {
4882  /* convert variable into aggregated variable */
4883  var->varstatus = SCIP_VARSTATUS_AGGREGATED; /*lint !e641*/
4884  var->data.aggregate.var = aggvar;
4885  var->data.aggregate.scalar = scalar;
4886  var->data.aggregate.constant = constant;
4887 
4888  /* copy donot(mult)aggr status */
4889  aggvar->donotaggr |= var->donotaggr;
4890  aggvar->donotmultaggr |= var->donotmultaggr;
4891 
4892  /* mark both variables to be non-deletable */
4894  SCIPvarMarkNotDeletable(aggvar);
4895  }
4896 
4897  /* make aggregated variable a parent of the aggregation variable */
4898  SCIP_CALL( varAddParent(aggvar, blkmem, set, var) );
4899 
4900  /* relock the variable, thus increasing the locks of the aggregation variable */
4901  for( i = 0; i < NLOCKTYPES; i++ )
4902  {
4903  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
4904  }
4905 
4906  /* move the variable bounds to the aggregation variable:
4907  * - add all variable bounds again to the variable, thus adding it to the aggregation variable
4908  * - free the variable bounds data structures
4909  */
4910  if( var->vlbs != NULL )
4911  {
4912  nvbds = SCIPvboundsGetNVbds(var->vlbs);
4913  vars = SCIPvboundsGetVars(var->vlbs);
4914  coefs = SCIPvboundsGetCoefs(var->vlbs);
4915  constants = SCIPvboundsGetConstants(var->vlbs);
4916  for( i = 0; i < nvbds && !(*infeasible); ++i )
4917  {
4918  SCIP_CALL( SCIPvarAddVlb(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
4919  eventqueue, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
4920  }
4921  }
4922  if( var->vubs != NULL )
4923  {
4924  nvbds = SCIPvboundsGetNVbds(var->vubs);
4925  vars = SCIPvboundsGetVars(var->vubs);
4926  coefs = SCIPvboundsGetCoefs(var->vubs);
4927  constants = SCIPvboundsGetConstants(var->vubs);
4928  for( i = 0; i < nvbds && !(*infeasible); ++i )
4929  {
4930  SCIP_CALL( SCIPvarAddVub(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
4931  eventqueue, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
4932  }
4933  }
4934  SCIPvboundsFree(&var->vlbs, blkmem);
4935  SCIPvboundsFree(&var->vubs, blkmem);
4936 
4937  /* move the implications to the aggregation variable:
4938  * - add all implications again to the variable, thus adding it to the aggregation variable
4939  * - free the implications data structures
4940  */
4941  if( var->implics != NULL && SCIPvarGetType(aggvar) == SCIP_VARTYPE_BINARY )
4942  {
4943  assert(SCIPvarIsBinary(var));
4944  for( i = 0; i < 2; ++i )
4945  {
4946  SCIP_VAR** implvars;
4947  SCIP_BOUNDTYPE* impltypes;
4948  SCIP_Real* implbounds;
4949  int nimpls;
4950 
4951  nimpls = SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i);
4952  implvars = SCIPimplicsGetVars(var->implics, (SCIP_Bool)i);
4953  impltypes = SCIPimplicsGetTypes(var->implics, (SCIP_Bool)i);
4954  implbounds = SCIPimplicsGetBounds(var->implics, (SCIP_Bool)i);
4955 
4956  for( j = 0; j < nimpls && !(*infeasible); ++j )
4957  {
4958  /* @todo can't we omit transitive closure, because it should already have been done when adding the
4959  * implication to the aggregated variable?
4960  */
4961  SCIP_CALL( SCIPvarAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
4962  branchcand, eventqueue, (SCIP_Bool)i, implvars[j], impltypes[j], implbounds[j], FALSE, infeasible,
4963  NULL) );
4964  assert(nimpls == SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i));
4965  }
4966  }
4967  }
4968  SCIPimplicsFree(&var->implics, blkmem);
4969 
4970  /* add the history entries to the aggregation variable and clear the history of the aggregated variable */
4971  SCIPhistoryUnite(aggvar->history, var->history, scalar < 0.0);
4972  SCIPhistoryUnite(aggvar->historycrun, var->historycrun, scalar < 0.0);
4973  SCIPhistoryReset(var->history);
4975 
4976  /* update flags of aggregation variable */
4977  aggvar->removable &= var->removable;
4978 
4979  /* update branching factors and priorities of both variables to be the maximum of both variables */
4980  branchfactor = MAX(aggvar->branchfactor, var->branchfactor);
4981  branchpriority = MAX(aggvar->branchpriority, var->branchpriority);
4982  SCIP_CALL( SCIPvarChgBranchFactor(aggvar, set, branchfactor) );
4983  SCIP_CALL( SCIPvarChgBranchPriority(aggvar, branchpriority) );
4984  SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
4985  SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
4986 
4987  /* update branching direction of both variables to agree to a single direction */
4988  if( scalar >= 0.0 )
4989  {
4991  {
4993  }
4994  else if( (SCIP_BRANCHDIR)aggvar->branchdirection == SCIP_BRANCHDIR_AUTO )
4995  {
4997  }
4998  else if( var->branchdirection != aggvar->branchdirection )
4999  {
5001  }
5002  }
5003  else
5004  {
5006  {
5008  }
5009  else if( (SCIP_BRANCHDIR)aggvar->branchdirection == SCIP_BRANCHDIR_AUTO )
5010  {
5012  }
5013  else if( var->branchdirection != aggvar->branchdirection )
5014  {
5016  }
5017  }
5018 
5019  if( var->probindex != -1 )
5020  {
5021  /* inform problem about the variable's status change */
5022  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
5023  }
5024 
5025  /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
5026  * variable and the problem's objective offset
5027  */
5028  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventfilter, eventqueue, obj) );
5029 
5030  /* issue VARFIXED event */
5031  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 1) );
5032 
5033  *aggregated = TRUE;
5034 
5035  return SCIP_OKAY;
5036 }
5037 
5038 /** Tries to aggregate an equality a*x + b*y == c consisting of two (implicit) integral active problem variables x and
5039  * y. An integer aggregation (i.e. integral coefficients a' and b', such that a'*x + b'*y == c') is searched.
5040  *
5041  * This can lead to the detection of infeasibility (e.g. if c' is fractional), or to a rejection of the aggregation
5042  * (denoted by aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
5043  */
5044 static
5046  SCIP_SET* set, /**< global SCIP settings */
5047  BMS_BLKMEM* blkmem, /**< block memory */
5048  SCIP_STAT* stat, /**< problem statistics */
5049  SCIP_PROB* transprob, /**< tranformed problem data */
5050  SCIP_PROB* origprob, /**< original problem data */
5051  SCIP_PRIMAL* primal, /**< primal data */
5052  SCIP_TREE* tree, /**< branch and bound tree */
5053  SCIP_REOPT* reopt, /**< reoptimization data structure */
5054  SCIP_LP* lp, /**< current LP data */
5055  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5056  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5057  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
5058  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5059  SCIP_VAR* varx, /**< integral variable x in equality a*x + b*y == c */
5060  SCIP_VAR* vary, /**< integral variable y in equality a*x + b*y == c */
5061  SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
5062  SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
5063  SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
5064  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
5065  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
5066  )
5067 {
5068  SCIP_VAR* aggvar;
5069  char aggvarname[SCIP_MAXSTRLEN];
5070  SCIP_Longint scalarxn = 0;
5071  SCIP_Longint scalarxd = 0;
5072  SCIP_Longint scalaryn = 0;
5073  SCIP_Longint scalaryd = 0;
5074  SCIP_Longint a;
5075  SCIP_Longint b;
5076  SCIP_Longint c;
5077  SCIP_Longint scm;
5078  SCIP_Longint gcd;
5079  SCIP_Longint currentclass;
5080  SCIP_Longint classstep;
5081  SCIP_Longint xsol;
5082  SCIP_Longint ysol;
5083  SCIP_Bool success;
5084  SCIP_VARTYPE vartype;
5085 
5086 #define MAXDNOM 1000000LL
5087 
5088  assert(set != NULL);
5089  assert(blkmem != NULL);
5090  assert(stat != NULL);
5091  assert(transprob != NULL);
5092  assert(origprob != NULL);
5093  assert(tree != NULL);
5094  assert(lp != NULL);
5095  assert(cliquetable != NULL);
5096  assert(branchcand != NULL);
5097  assert(eventqueue != NULL);
5098  assert(varx != NULL);
5099  assert(vary != NULL);
5100  assert(varx != vary);
5101  assert(infeasible != NULL);
5102  assert(aggregated != NULL);
5103  assert(SCIPsetGetStage(set) == SCIP_STAGE_PRESOLVING);
5104  assert(SCIPvarGetStatus(varx) == SCIP_VARSTATUS_LOOSE);
5106  assert(SCIPvarGetStatus(vary) == SCIP_VARSTATUS_LOOSE);
5108  assert(!SCIPsetIsZero(set, scalarx));
5109  assert(!SCIPsetIsZero(set, scalary));
5110 
5111  *infeasible = FALSE;
5112  *aggregated = FALSE;
5113 
5114  /* if the variable is not allowed to be aggregated */
5115  if( SCIPvarDoNotAggr(varx) )
5116  {
5117  SCIPsetDebugMsg(set, "variable is not allowed to be aggregated.\n");
5118  return SCIP_OKAY;
5119  }
5120 
5121  /* get rational representation of coefficients */
5122  success = SCIPrealToRational(scalarx, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalarxn, &scalarxd);
5123  if( success )
5124  success = SCIPrealToRational(scalary, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalaryn, &scalaryd);
5125  if( !success )
5126  return SCIP_OKAY;
5127  assert(scalarxd >= 1);
5128  assert(scalaryd >= 1);
5129 
5130  /* multiply equality with smallest common denominator */
5131  scm = SCIPcalcSmaComMul(scalarxd, scalaryd);
5132  a = (scm/scalarxd)*scalarxn;
5133  b = (scm/scalaryd)*scalaryn;
5134  rhs *= scm;
5135 
5136  /* divide equality by the greatest common divisor of a and b */
5137  gcd = SCIPcalcGreComDiv(ABS(a), ABS(b));
5138  a /= gcd;
5139  b /= gcd;
5140  rhs /= gcd;
5141  assert(a != 0);
5142  assert(b != 0);
5143 
5144  /* check, if right hand side is integral */
5145  if( !SCIPsetIsFeasIntegral(set, rhs) )
5146  {
5147  *infeasible = TRUE;
5148  return SCIP_OKAY;
5149  }
5150  c = (SCIP_Longint)(SCIPsetFeasFloor(set, rhs));
5151 
5152  /* check that the scalar and constant in the aggregation are not too large to avoid numerical problems */
5153  if( REALABS((SCIP_Real)(c/a)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) /*lint !e653*/
5154  || REALABS((SCIP_Real)(b)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) /*lint !e653*/
5155  || REALABS((SCIP_Real)(a)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
5156  {
5157  return SCIP_OKAY;
5158  }
5159 
5160  /* check, if we are in an easy case with either |a| = 1 or |b| = 1 */
5161  if( (a == 1 || a == -1) && SCIPvarGetType(vary) == SCIP_VARTYPE_INTEGER )
5162  {
5163  /* aggregate x = - b/a*y + c/a */
5164  /*lint --e{653}*/
5165  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5166  branchcand, eventfilter, eventqueue, vary, (SCIP_Real)(-b/a), (SCIP_Real)(c/a), infeasible, aggregated) );
5167  assert(*aggregated);
5168  return SCIP_OKAY;
5169  }
5170  if( (b == 1 || b == -1) && SCIPvarGetType(varx) == SCIP_VARTYPE_INTEGER )
5171  {
5172  /* aggregate y = - a/b*x + c/b */
5173  /*lint --e{653}*/
5174  SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5175  branchcand, eventfilter, eventqueue, varx, (SCIP_Real)(-a/b), (SCIP_Real)(c/b), infeasible, aggregated) );
5176  assert(*aggregated);
5177  return SCIP_OKAY;
5178  }
5179 
5180  /* Both variables are integers, their coefficients are not multiples of each other, and they don't have any
5181  * common divisor. Let (x',y') be a solution of the equality
5182  * a*x + b*y == c -> a*x == c - b*y
5183  * Then x = -b*z + x', y = a*z + y' with z integral gives all solutions to the equality.
5184  */
5185 
5186  /* find initial solution (x',y'):
5187  * - find y' such that c - b*y' is a multiple of a
5188  * - start in equivalence class c%a
5189  * - step through classes, where each step increases class number by (-b)%a, until class 0 is visited
5190  * - if equivalence class 0 is visited, we are done: y' equals the number of steps taken
5191  * - 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
5192  * - calculate x' with x' = (c - b*y')/a (which must be integral)
5193  *
5194  * Algorithm works for a > 0 only.
5195  */
5196  if( a < 0 )
5197  {
5198  a = -a;
5199  b = -b;
5200  c = -c;
5201  }
5202  assert(a > 0);
5203 
5204  /* search upwards from ysol = 0 */
5205  ysol = 0;
5206  currentclass = c % a;
5207  if( currentclass < 0 )
5208  currentclass += a;
5209  assert(0 <= currentclass && currentclass < a);
5210 
5211  classstep = (-b) % a;
5212 
5213  if( classstep < 0 )
5214  classstep += a;
5215  assert(0 <= classstep && classstep < a);
5216 
5217  while( currentclass != 0 )
5218  {
5219  assert(0 <= currentclass && currentclass < a);
5220  currentclass += classstep;
5221  if( currentclass >= a )
5222  currentclass -= a;
5223  ysol++;
5224  }
5225  assert(ysol < a);
5226  assert(((c - b*ysol) % a) == 0);
5227 
5228  xsol = (c - b*ysol)/a;
5229 
5230  /* determine variable type for new artificial variable:
5231  *
5232  * if both variables are implicit integer the new variable can be implicit too, because the integer implication on
5233  * these both variables should be enforced by some other variables, otherwise the new variable needs to be of
5234  * integral type
5235  */
5238 
5239  /* feasible solutions are (x,y) = (x',y') + z*(-b,a)
5240  * - create new integer variable z with infinite bounds
5241  * - aggregate variable x = -b*z + x'
5242  * - aggregate variable y = a*z + y'
5243  * - the bounds of z are calculated automatically during aggregation
5244  */
5245  (void) SCIPsnprintf(aggvarname, SCIP_MAXSTRLEN, "agg%d", stat->nvaridx);
5246  SCIP_CALL( SCIPvarCreateTransformed(&aggvar, blkmem, set, stat,
5247  aggvarname, -SCIPsetInfinity(set), SCIPsetInfinity(set), 0.0, vartype,
5249  NULL, NULL, NULL, NULL, NULL) );
5250 
5251  SCIP_CALL( SCIPprobAddVar(transprob, blkmem, set, lp, branchcand, eventfilter, eventqueue, aggvar) );
5252 
5253  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5254  branchcand, eventfilter, eventqueue, aggvar, (SCIP_Real)(-b), (SCIP_Real)xsol, infeasible, aggregated) );
5255  assert(*aggregated || *infeasible);
5256 
5257  if( !(*infeasible) )
5258  {
5259  SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5260  branchcand, eventfilter, eventqueue, aggvar, (SCIP_Real)a, (SCIP_Real)ysol, infeasible, aggregated) );
5261  assert(*aggregated || *infeasible);
5262  }
5263 
5264  /* release z */
5265  SCIP_CALL( SCIPvarRelease(&aggvar, blkmem, set, eventqueue, lp) );
5266 
5267  return SCIP_OKAY; /*lint !e438*/
5268 }
5269 
5270 /** performs second step of SCIPaggregateVars():
5271  * the variable to be aggregated is chosen among active problem variables x' and y', preferring a less strict variable
5272  * type as aggregation variable (i.e. continuous variables are preferred over implicit integers, implicit integers
5273  * or integers over binaries). If none of the variables is continuous, it is tried to find an integer
5274  * aggregation (i.e. integral coefficients a'' and b'', such that a''*x' + b''*y' == c''). This can lead to
5275  * the detection of infeasibility (e.g. if c'' is fractional), or to a rejection of the aggregation (denoted by
5276  * aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
5277  *
5278  * @todo check for fixings, infeasibility, bound changes, or domain holes:
5279  * a) if there is no easy aggregation and we have one binary variable and another integer/implicit/binary variable
5280  * b) for implicit integer variables with fractional aggregation scalar (we cannot (for technical reasons) and do
5281  * not want to aggregate implicit integer variables, since we loose the corresponding divisibility property)
5282  */
5284  SCIP_SET* set, /**< global SCIP settings */
5285  BMS_BLKMEM* blkmem, /**< block memory */
5286  SCIP_STAT* stat, /**< problem statistics */
5287  SCIP_PROB* transprob, /**< tranformed problem data */
5288  SCIP_PROB* origprob, /**< original problem data */
5289  SCIP_PRIMAL* primal, /**< primal data */
5290  SCIP_TREE* tree, /**< branch and bound tree */
5291  SCIP_REOPT* reopt, /**< reoptimization data structure */
5292  SCIP_LP* lp, /**< current LP data */
5293  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5294  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5295  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
5296  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5297  SCIP_VAR* varx, /**< variable x in equality a*x + b*y == c */
5298  SCIP_VAR* vary, /**< variable y in equality a*x + b*y == c */
5299  SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
5300  SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
5301  SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
5302  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
5303  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
5304  )
5305 {
5306  SCIP_Bool easyaggr;
5307  SCIP_Real maxscalar;
5308  SCIP_Real absquot;
5309 
5310  assert(set != NULL);
5311  assert(blkmem != NULL);
5312  assert(stat != NULL);
5313  assert(transprob != NULL);
5314  assert(origprob != NULL);
5315  assert(tree != NULL);
5316  assert(lp != NULL);
5317  assert(cliquetable != NULL);
5318  assert(branchcand != NULL);
5319  assert(eventqueue != NULL);
5320  assert(varx != NULL);
5321  assert(vary != NULL);
5322  assert(varx != vary);
5323  assert(infeasible != NULL);
5324  assert(aggregated != NULL);
5325  assert(SCIPsetGetStage(set) == SCIP_STAGE_PRESOLVING);
5326  assert(SCIPvarGetStatus(varx) == SCIP_VARSTATUS_LOOSE);
5327  assert(SCIPvarGetStatus(vary) == SCIP_VARSTATUS_LOOSE);
5328  assert(!SCIPsetIsZero(set, scalarx));
5329  assert(!SCIPsetIsZero(set, scalary));
5330 
5331  *infeasible = FALSE;
5332  *aggregated = FALSE;
5333 
5334  absquot = REALABS(scalarx / scalary);
5335  maxscalar = SCIPsetFeastol(set) / SCIPsetEpsilon(set);
5336  maxscalar = MAX(maxscalar, 1.0);
5337 
5338  if( absquot > maxscalar || absquot < 1 / maxscalar )
5339  return SCIP_OKAY;
5340 
5341  /* prefer aggregating the variable of more general type (preferred aggregation variable is varx) */
5342  if( SCIPvarGetType(vary) > SCIPvarGetType(varx) ||
5343  (SCIPvarGetType(vary) == SCIPvarGetType(varx) && !SCIPvarIsBinary(vary) && SCIPvarIsBinary(varx)) )
5344  {
5345  SCIP_VAR* var;
5346  SCIP_Real scalar;
5347 
5348  /* switch the variables, such that varx is the variable of more general type (cont > implint > int > bin) */
5349  var = vary;
5350  vary = varx;
5351  varx = var;
5352  scalar = scalary;
5353  scalary = scalarx;
5354  scalarx = scalar;
5355  }
5356 
5357  /* don't aggregate if the aggregation would lead to a binary variable aggregated to a non-binary variable */
5358  if( SCIPvarIsBinary(varx) && !SCIPvarIsBinary(vary) )
5359  return SCIP_OKAY;
5360 
5361  assert(SCIPvarGetType(varx) >= SCIPvarGetType(vary));
5362 
5363  /* figure out, which variable should be aggregated */
5364  easyaggr = FALSE;
5365 
5366  /* check if it is an easy aggregation that means:
5367  *
5368  * a*x + b*y == c -> x == -b/a * y + c/a iff |b/a| > feastol and |a/b| > feastol
5369  */
5370  if( !SCIPsetIsFeasZero(set, scalary/scalarx) && !SCIPsetIsFeasZero(set, scalarx/scalary) )
5371  {
5373  {
5374  easyaggr = TRUE;
5375  }
5376  else if( SCIPsetIsFeasIntegral(set, scalary/scalarx) )
5377  {
5378  easyaggr = TRUE;
5379  }
5380  else if( SCIPsetIsFeasIntegral(set, scalarx/scalary) && SCIPvarGetType(vary) == SCIPvarGetType(varx) )
5381  {
5382  /* we have an easy aggregation if we flip the variables x and y */
5383  SCIP_VAR* var;
5384  SCIP_Real scalar;
5385 
5386  /* switch the variables, such that varx is the aggregated variable */
5387  var = vary;
5388  vary = varx;
5389  varx = var;
5390  scalar = scalary;
5391  scalary = scalarx;
5392  scalarx = scalar;
5393  easyaggr = TRUE;
5394  }
5395  else if( SCIPvarGetType(varx) == SCIP_VARTYPE_CONTINUOUS )
5396  {
5397  /* the aggregation is still easy if both variables are continuous */
5398  assert(SCIPvarGetType(vary) == SCIP_VARTYPE_CONTINUOUS); /* otherwise we are in the first case */
5399  easyaggr = TRUE;
5400  }
5401  }
5402 
5403  /* did we find an "easy" aggregation? */
5404  if( easyaggr )
5405  {
5406  SCIP_Real scalar;
5407  SCIP_Real constant;
5408 
5409  assert(SCIPvarGetType(varx) >= SCIPvarGetType(vary));
5410 
5411  /* calculate aggregation scalar and constant: a*x + b*y == c => x == -b/a * y + c/a */
5412  scalar = -scalary/scalarx;
5413  constant = rhs/scalarx;
5414 
5415  if( REALABS(constant) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
5416  return SCIP_OKAY;
5417 
5418  /* check aggregation for integer feasibility */
5421  && SCIPsetIsFeasIntegral(set, scalar) && !SCIPsetIsFeasIntegral(set, constant) )
5422  {
5423  *infeasible = TRUE;
5424  return SCIP_OKAY;
5425  }
5426 
5427  /* if the aggregation scalar is fractional, we cannot (for technical reasons) and do not want to aggregate implicit integer variables,
5428  * since then we would loose the corresponding divisibility property
5429  */
5430  assert(SCIPvarGetType(varx) != SCIP_VARTYPE_IMPLINT || SCIPsetIsFeasIntegral(set, scalar));
5431 
5432  /* aggregate the variable */
5433  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5434  branchcand, eventfilter, eventqueue, vary, scalar, constant, infeasible, aggregated) );
5435  assert(*aggregated || *infeasible || SCIPvarDoNotAggr(varx));
5436  }
5439  {
5440  /* the variables are both integral: we have to try to find an integer aggregation */
5441  SCIP_CALL( tryAggregateIntVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5442  branchcand, eventfilter, eventqueue, varx, vary, scalarx, scalary, rhs, infeasible, aggregated) );
5443  }
5444 
5445  return SCIP_OKAY;
5446 }
5447 
5448 /** converts variable into multi-aggregated variable */
5450  SCIP_VAR* var, /**< problem variable */
5451  BMS_BLKMEM* blkmem, /**< block memory */
5452  SCIP_SET* set, /**< global SCIP settings */
5453  SCIP_STAT* stat, /**< problem statistics */
5454  SCIP_PROB* transprob, /**< tranformed problem data */
5455  SCIP_PROB* origprob, /**< original problem data */
5456  SCIP_PRIMAL* primal, /**< primal data */
5457  SCIP_TREE* tree, /**< branch and bound tree */
5458  SCIP_REOPT* reopt, /**< reoptimization data structure */
5459  SCIP_LP* lp, /**< current LP data */
5460  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5461  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5462  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
5463  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5464  int naggvars, /**< number n of variables in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5465  SCIP_VAR** aggvars, /**< variables y_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5466  SCIP_Real* scalars, /**< multipliers a_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5467  SCIP_Real constant, /**< constant shift c in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5468  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
5469  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
5470  )
5471 {
5472  SCIP_VAR** tmpvars;
5473  SCIP_Real* tmpscalars;
5474  SCIP_Real obj;
5475  SCIP_Real branchfactor;
5476  int branchpriority;
5477  SCIP_BRANCHDIR branchdirection;
5478  int nlocksdown[NLOCKTYPES];
5479  int nlocksup[NLOCKTYPES];
5480  int v;
5481  SCIP_Real tmpconstant;
5482  SCIP_Real tmpscalar;
5483  int ntmpvars;
5484  int tmpvarssize;
5485  int tmprequiredsize;
5486  int i;
5487 
5488  assert(var != NULL);
5489  assert(var->scip == set->scip);
5490  assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
5491  assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
5492  assert(naggvars == 0 || aggvars != NULL);
5493  assert(naggvars == 0 || scalars != NULL);
5494  assert(infeasible != NULL);
5495  assert(aggregated != NULL);
5496 
5497  SCIPsetDebugMsg(set, "trying multi-aggregating variable <%s> == ...%d vars... %+g\n", var->name, naggvars, constant);
5498 
5499  /* check multi-aggregation on debugging solution */
5500  SCIP_CALL( SCIPdebugCheckAggregation(set, var, aggvars, scalars, constant, naggvars) ); /*lint !e506 !e774*/
5501 
5502  *infeasible = FALSE;
5503  *aggregated = FALSE;
5504 
5505  switch( SCIPvarGetStatus(var) )
5506  {
5508  if( var->data.original.transvar == NULL )
5509  {
5510  SCIPerrorMessage("cannot multi-aggregate an untransformed original variable\n");
5511  return SCIP_INVALIDDATA;
5512  }
5513  SCIP_CALL( SCIPvarMultiaggregate(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
5514  reopt, lp, cliquetable, branchcand, eventfilter, eventqueue, naggvars, aggvars, scalars, constant, infeasible, aggregated) );
5515  break;
5516 
5517  case SCIP_VARSTATUS_LOOSE:
5518  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
5519 
5520  /* check if we would create a self-reference */
5521  ntmpvars = naggvars;
5522  tmpvarssize = naggvars;
5523  tmpconstant = constant;
5524  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpvars, aggvars, ntmpvars) );
5525  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpscalars, scalars, ntmpvars) );
5526 
5527  /* get all active variables for multi-aggregation */
5528  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize, FALSE) );
5529  if( tmprequiredsize > tmpvarssize )
5530  {
5531  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpvars, tmpvarssize, tmprequiredsize) );
5532  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize, tmprequiredsize) );
5533  tmpvarssize = tmprequiredsize;
5534  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize, FALSE) );
5535  assert( tmprequiredsize <= tmpvarssize );
5536  }
5537 
5538  tmpscalar = 0.0;
5539 
5540  /* iterate over all active variables of the multi-aggregation and filter all variables which are equal to the
5541  * possible multi-aggregated variable
5542  */
5543  for( v = ntmpvars - 1; v >= 0; --v )
5544  {
5545  assert(tmpvars[v] != NULL);
5546  assert(SCIPvarGetStatus(tmpvars[v]) == SCIP_VARSTATUS_LOOSE);
5547 
5548  if( tmpvars[v]->index == var->index )
5549  {
5550  tmpscalar += tmpscalars[v];
5551  tmpvars[v] = tmpvars[ntmpvars - 1];
5552  tmpscalars[v] = tmpscalars[ntmpvars - 1];
5553  --ntmpvars;
5554  }
5555  }
5556 
5557  /* this means that x = x + a_1*y_1 + ... + a_n*y_n + c */
5558  if( SCIPsetIsEQ(set, tmpscalar, 1.0) )
5559  {
5560  if( ntmpvars == 0 )
5561  {
5562  if( SCIPsetIsZero(set, tmpconstant) ) /* x = x */
5563  {
5564  SCIPsetDebugMsg(set, "Possible multi-aggregation was completely resolved and detected to be redundant.\n");
5565  goto TERMINATE;
5566  }
5567  else /* 0 = c and c != 0 */
5568  {
5569  SCIPsetDebugMsg(set, "Multi-aggregation was completely resolved and led to infeasibility.\n");
5570  *infeasible = TRUE;
5571  goto TERMINATE;
5572  }
5573  }
5574  else if( ntmpvars == 1 ) /* 0 = a*y + c => y = -c/a */
5575  {
5576  assert(tmpscalars[0] != 0.0);
5577  assert(tmpvars[0] != NULL);
5578 
5579  SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(tmpvars[0]), -constant/tmpscalars[0]);
5580  SCIP_CALL( SCIPvarFix(tmpvars[0], blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5581  branchcand, eventfilter, eventqueue, cliquetable, -constant/tmpscalars[0], infeasible, aggregated) );
5582  goto TERMINATE;
5583  }
5584  else if( ntmpvars == 2 ) /* 0 = a_1*y_1 + a_2*y_2 + c => y_1 = -a_2/a_1 * y_2 - c/a_1 */
5585  {
5586  /* both variables are different active problem variables, and both scalars are non-zero: try to aggregate them */
5587  SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
5588  SCIPvarGetName(tmpvars[0]), SCIPvarGetName(tmpvars[1]), tmpscalars[0], tmpscalars[1], -tmpconstant);
5589 
5590  SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
5591  cliquetable, branchcand, eventfilter, eventqueue, tmpvars[0], tmpvars[1], tmpscalars[0],
5592  tmpscalars[1], -tmpconstant, infeasible, aggregated) );
5593 
5594  goto TERMINATE;
5595  }
5596  else
5597  /* @todo: it is possible to multi-aggregate another variable, does it make sense?,
5598  * rest looks like 0 = a_1*y_1 + ... + a_n*y_n + c and has at least three variables
5599  */
5600  goto TERMINATE;
5601  }
5602  /* this means that x = b*x + a_1*y_1 + ... + a_n*y_n + c */
5603  else if( !SCIPsetIsZero(set, tmpscalar) )
5604  {
5605  tmpscalar = 1 - tmpscalar;
5606  tmpconstant /= tmpscalar;
5607  for( v = ntmpvars - 1; v >= 0; --v )
5608  tmpscalars[v] /= tmpscalar;
5609  }
5610 
5611  /* check, if we are in one of the simple cases */
5612  if( ntmpvars == 0 )
5613  {
5614  SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(var), tmpconstant);
5615  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
5616  eventfilter, eventqueue, cliquetable, tmpconstant, infeasible, aggregated) );
5617  goto TERMINATE;
5618  }
5619 
5620  /* if only one aggregation variable is left, we perform a normal aggregation instead of a multi-aggregation */
5621  if( ntmpvars == 1 )
5622  {
5623  SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
5624  SCIPvarGetName(var), SCIPvarGetName(tmpvars[0]), 1.0, -tmpscalars[0], tmpconstant);
5625 
5626  SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
5627  cliquetable, branchcand, eventfilter, eventqueue, var, tmpvars[0], 1.0, -tmpscalars[0], tmpconstant,
5628  infeasible, aggregated) );
5629 
5630  goto TERMINATE;
5631  }
5632 
5633  /**@todo currently we don't perform the multi aggregation if the multi aggregation variable has a non
5634  * empty hole list; this should be changed in the future */
5635  if( SCIPvarGetHolelistGlobal(var) != NULL )
5636  goto TERMINATE;
5637 
5638  /* if the variable is not allowed to be multi-aggregated */
5639  if( SCIPvarDoNotMultaggr(var) )
5640  {
5641  SCIPsetDebugMsg(set, "variable is not allowed to be multi-aggregated.\n");
5642  goto TERMINATE;
5643  }
5644 
5645  /* if the variable to be multi-aggregated has implications or variable bounds (i.e. is the implied variable or
5646  * variable bound variable of another variable), we have to remove it from the other variables implications or
5647  * variable bounds
5648  */
5649  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
5650  assert(var->vlbs == NULL);
5651  assert(var->vubs == NULL);
5652  assert(var->implics == NULL);
5653  assert(var->cliquelist == NULL);
5654 
5655  /* set the aggregated variable's objective value to 0.0 */
5656  obj = var->obj;
5657  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
5658 
5659  /* since we change the variable type form loose to multi aggregated, we have to adjust the number of loose
5660  * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
5661  * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
5662  * objective of this variable is set to zero
5663  */
5664  SCIPlpDecNLoosevars(lp);
5665 
5666  /* unlock all rounding locks */
5667  for( i = 0; i < NLOCKTYPES; i++ )
5668  {
5669  nlocksdown[i] = var->nlocksdown[i];
5670  nlocksup[i] = var->nlocksup[i];
5671 
5672  var->nlocksdown[i] = 0;
5673  var->nlocksup[i] = 0;
5674  }
5675 
5676  /* convert variable into multi-aggregated variable */
5677  var->varstatus = SCIP_VARSTATUS_MULTAGGR; /*lint !e641*/
5678  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.vars, tmpvars, ntmpvars) );
5679  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.scalars, tmpscalars, ntmpvars) );
5680  var->data.multaggr.constant = tmpconstant;
5681  var->data.multaggr.nvars = ntmpvars;
5682  var->data.multaggr.varssize = ntmpvars;
5683 
5684  /* mark variable to be non-deletable */
5686 
5687  /* relock the variable, thus increasing the locks of the aggregation variables */
5688  for( i = 0; i < NLOCKTYPES; i++ )
5689  {
5690  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
5691  }
5692 
5693  /* update flags and branching factors and priorities of aggregation variables;
5694  * update preferred branching direction of all aggregation variables that don't have a preferred direction yet
5695  */
5696  branchfactor = var->branchfactor;
5697  branchpriority = var->branchpriority;
5698  branchdirection = (SCIP_BRANCHDIR)var->branchdirection;
5699 
5700  for( v = 0; v < ntmpvars; ++v )
5701  {
5702  assert(tmpvars[v] != NULL);
5703  tmpvars[v]->removable &= var->removable;
5704  branchfactor = MAX(tmpvars[v]->branchfactor, branchfactor);
5705  branchpriority = MAX(tmpvars[v]->branchpriority, branchpriority);
5706 
5707  /* mark variable to be non-deletable */
5708  SCIPvarMarkNotDeletable(tmpvars[v]);
5709  }
5710  for( v = 0; v < ntmpvars; ++v )
5711  {
5712  SCIP_CALL( SCIPvarChgBranchFactor(tmpvars[v], set, branchfactor) );
5713  SCIP_CALL( SCIPvarChgBranchPriority(tmpvars[v], branchpriority) );
5714  if( (SCIP_BRANCHDIR)tmpvars[v]->branchdirection == SCIP_BRANCHDIR_AUTO )
5715  {
5716  if( tmpscalars[v] >= 0.0 )
5717  {
5718  SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], branchdirection) );
5719  }
5720  else
5721  {
5722  SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], SCIPbranchdirOpposite(branchdirection)) );
5723  }
5724  }
5725  }
5726  SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
5727  SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
5728 
5729  if( var->probindex != -1 )
5730  {
5731  /* inform problem about the variable's status change */
5732  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
5733  }
5734 
5735  /* issue VARFIXED event */
5736  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 2) );
5737 
5738  /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
5739  * variables and the problem's objective offset
5740  */
5741  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventfilter, eventqueue, obj) );
5742 
5743  *aggregated = TRUE;
5744 
5745  TERMINATE:
5746  BMSfreeBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize);
5747  BMSfreeBlockMemoryArray(blkmem, &tmpvars, tmpvarssize);
5748 
5749  break;
5750 
5751  case SCIP_VARSTATUS_COLUMN:
5752  SCIPerrorMessage("cannot multi-aggregate a column variable\n");
5753  return SCIP_INVALIDDATA;
5754 
5755  case SCIP_VARSTATUS_FIXED:
5756  SCIPerrorMessage("cannot multi-aggregate a fixed variable\n");
5757  return SCIP_INVALIDDATA;
5758 
5760  SCIPerrorMessage("cannot multi-aggregate an aggregated variable\n");
5761  return SCIP_INVALIDDATA;
5762 
5764  SCIPerrorMessage("cannot multi-aggregate a multiple aggregated variable again\n");
5765  return SCIP_INVALIDDATA;
5766 
5768  /* aggregate negation variable x in x' = offset - x, instead of aggregating x' directly:
5769  * x' = a_1*y_1 + ... + a_n*y_n + c -> x = offset - x' = offset - a_1*y_1 - ... - a_n*y_n - c
5770  */
5771  assert(SCIPsetIsZero(set, var->obj));
5772  assert(var->negatedvar != NULL);
5774  assert(var->negatedvar->negatedvar == var);
5775 
5776  /* switch the signs of the aggregation scalars */
5777  for( v = 0; v < naggvars; ++v )
5778  scalars[v] *= -1.0;
5779 
5780  /* perform the multi aggregation on the negation variable */
5781  SCIP_CALL( SCIPvarMultiaggregate(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5782  cliquetable, branchcand, eventfilter, eventqueue, naggvars, aggvars, scalars,
5783  var->data.negate.constant - constant, infeasible, aggregated) );
5784 
5785  /* switch the signs of the aggregation scalars again, to reset them to their original values */
5786  for( v = 0; v < naggvars; ++v )
5787  scalars[v] *= -1.0;
5788  break;
5789 
5790  default:
5791  SCIPerrorMessage("unknown variable status\n");
5792  return SCIP_INVALIDDATA;
5793  }
5794 
5795  return SCIP_OKAY;
5796 }
5797 
5798 /** transformed variables are resolved to their active, fixed, or multi-aggregated problem variable of a variable,
5799  * or for original variables the same variable is returned
5800  */
5801 static
5803  SCIP_VAR* var /**< problem variable */
5804  )
5805 {
5806  SCIP_VAR* retvar;
5807 
5808  assert(var != NULL);
5809 
5810  retvar = var;
5811 
5812  SCIPdebugMessage("get active variable of <%s>\n", var->name);
5813 
5814  while( TRUE ) /*lint !e716 */
5815  {
5816  assert(retvar != NULL);
5817 
5818  switch( SCIPvarGetStatus(retvar) )
5819  {
5821  case SCIP_VARSTATUS_LOOSE:
5822  case SCIP_VARSTATUS_COLUMN:
5823  case SCIP_VARSTATUS_FIXED:
5824  return retvar;
5825 
5827  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
5828  if ( retvar->data.multaggr.nvars == 1 )
5829  retvar = retvar->data.multaggr.vars[0];
5830  else
5831  return retvar;
5832  break;
5833 
5835  retvar = retvar->data.aggregate.var;
5836  break;
5837 
5839  retvar = retvar->negatedvar;
5840  break;
5841 
5842  default:
5843  SCIPerrorMessage("unknown variable status\n");
5844  SCIPABORT();
5845  return NULL; /*lint !e527*/
5846  }
5847  }
5848 }
5849 
5850 /** returns whether variable is not allowed to be aggregated */
5852  SCIP_VAR* var /**< problem variable */
5853  )
5854 {
5855  SCIP_VAR* retvar;
5856 
5857  assert(var != NULL);
5858 
5859  retvar = varGetActiveVar(var);
5860  assert(retvar != NULL);
5861 
5862  switch( SCIPvarGetStatus(retvar) )
5863  {
5865  case SCIP_VARSTATUS_LOOSE:
5866  case SCIP_VARSTATUS_COLUMN:
5867  case SCIP_VARSTATUS_FIXED:
5868  return retvar->donotaggr;
5869 
5871  return FALSE;
5872 
5875  default:
5876  /* aggregated and negated variables should be resolved by varGetActiveVar() */
5877  SCIPerrorMessage("wrong variable status\n");
5878  SCIPABORT();
5879  return FALSE; /*lint !e527 */
5880  }
5881 }
5882 
5883 /** returns whether variable is not allowed to be multi-aggregated */
5885  SCIP_VAR* var /**< problem variable */
5886  )
5887 {
5888  SCIP_VAR* retvar;
5889 
5890  assert(var != NULL);
5891 
5892  retvar = varGetActiveVar(var);
5893  assert(retvar != NULL);
5894 
5895  switch( SCIPvarGetStatus(retvar) )
5896  {
5898  case SCIP_VARSTATUS_LOOSE:
5899  case SCIP_VARSTATUS_COLUMN:
5900  case SCIP_VARSTATUS_FIXED:
5901  return retvar->donotmultaggr;
5902 
5904  return FALSE;
5905 
5908  default:
5909  /* aggregated and negated variables should be resolved by varGetActiveVar() */
5910  SCIPerrorMessage("wrong variable status\n");
5911  SCIPABORT();
5912  return FALSE; /*lint !e527 */
5913  }
5914 }
5915 
5916 /** gets negated variable x' = offset - x of problem variable x; the negated variable is created if not yet existing;
5917  * the negation offset of binary variables is always 1, the offset of other variables is fixed to lb + ub when the
5918  * negated variable is created
5919  */
5921  SCIP_VAR* var, /**< problem variable to negate */
5922  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
5923  SCIP_SET* set, /**< global SCIP settings */
5924  SCIP_STAT* stat, /**< problem statistics */
5925  SCIP_VAR** negvar /**< pointer to store the negated variable */
5926  )
5927 {
5928  assert(var != NULL);
5929  assert(var->scip == set->scip);
5930  assert(negvar != NULL);
5931 
5932  /* check, if we already created the negated variable */
5933  if( var->negatedvar == NULL )
5934  {
5935  char negvarname[SCIP_MAXSTRLEN];
5936 
5937  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED);
5938 
5939  SCIPsetDebugMsg(set, "creating negated variable of <%s>\n", var->name);
5940 
5941  /* negation is only possible for bounded variables */
5942  if( SCIPsetIsInfinity(set, -var->glbdom.lb) || SCIPsetIsInfinity(set, var->glbdom.ub) )
5943  {
5944  SCIPerrorMessage("cannot negate unbounded variable\n");
5945  return SCIP_INVALIDDATA;
5946  }
5947 
5948  (void) SCIPsnprintf(negvarname, SCIP_MAXSTRLEN, "%s_neg", var->name);
5949 
5950  /* create negated variable */
5951  SCIP_CALL( varCreate(negvar, blkmem, set, stat, negvarname, var->glbdom.lb, var->glbdom.ub, 0.0,
5952  SCIPvarGetType(var), var->initial, var->removable, NULL, NULL, NULL, NULL, NULL) );
5953  (*negvar)->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
5954  if( SCIPvarIsBinary(var) )
5955  (*negvar)->data.negate.constant = 1.0;
5956  else
5957  (*negvar)->data.negate.constant = var->glbdom.lb + var->glbdom.ub;
5958 
5959  /* create event filter for transformed variable */
5960  if( SCIPvarIsTransformed(var) )
5961  {
5962  SCIP_CALL( SCIPeventfilterCreate(&(*negvar)->eventfilter, blkmem) );
5963  }
5964 
5965  /* set the bounds corresponding to the negation variable */
5966  (*negvar)->glbdom.lb = (*negvar)->data.negate.constant - var->glbdom.ub;
5967  (*negvar)->glbdom.ub = (*negvar)->data.negate.constant - var->glbdom.lb;
5968  (*negvar)->locdom.lb = (*negvar)->data.negate.constant - var->locdom.ub;
5969  (*negvar)->locdom.ub = (*negvar)->data.negate.constant - var->locdom.lb;
5970  /**@todo create holes in the negated variable corresponding to the holes of the negation variable */
5971 
5972  /* link the variables together */
5973  var->negatedvar = *negvar;
5974  (*negvar)->negatedvar = var;
5975 
5976  /* mark both variables to be non-deletable */
5978  SCIPvarMarkNotDeletable(*negvar);
5979 
5980  /* copy the branch factor and priority, and use the negative preferred branching direction */
5981  (*negvar)->branchfactor = var->branchfactor;
5982  (*negvar)->branchpriority = var->branchpriority;
5983  (*negvar)->branchdirection = SCIPbranchdirOpposite((SCIP_BRANCHDIR)var->branchdirection); /*lint !e641*/
5984 
5985  /* copy donot(mult)aggr status */
5986  (*negvar)->donotaggr = var->donotaggr;
5987  (*negvar)->donotmultaggr = var->donotmultaggr;
5988 
5989  /* copy lazy bounds (they have to be flipped) */
5990  (*negvar)->lazylb = (*negvar)->data.negate.constant - var->lazyub;
5991  (*negvar)->lazyub = (*negvar)->data.negate.constant - var->lazylb;
5992 
5993  /* make negated variable a parent of the negation variable (negated variable is captured as a parent) */
5994  SCIP_CALL( varAddParent(var, blkmem, set, *negvar) );
5995  assert((*negvar)->nuses == 1);
5996  }
5997  assert(var->negatedvar != NULL);
5998 
5999  /* return the negated variable */
6000  *negvar = var->negatedvar;
6001 
6002  /* exactly one variable of the negation pair has to be marked as negated variable */
6004 
6005  return SCIP_OKAY;
6006 }
6007 
6008 /** informs variable that its position in problem's vars array changed */
6009 static
6010 void varSetProbindex(
6011  SCIP_VAR* var, /**< problem variable */
6012  int probindex /**< new problem index of variable (-1 for removal) */
6013  )
6014 {
6015  assert(var != NULL);
6016  assert(probindex >= 0 || var->vlbs == NULL);
6017  assert(probindex >= 0 || var->vubs == NULL);
6018  assert(probindex >= 0 || var->implics == NULL);
6019 
6020  var->probindex = probindex;
6022  {
6023  assert(var->data.col != NULL);
6024  var->data.col->var_probindex = probindex;
6025  }
6026 }
6027 
6028 /** informs variable that its position in problem's vars array changed */
6029 void SCIPvarSetProbindex(
6030  SCIP_VAR* var, /**< problem variable */
6031  int probindex /**< new problem index of variable */
6032  )
6033 {
6034  assert(var != NULL);
6035  assert(probindex >= 0);
6036 
6037  varSetProbindex(var, probindex);
6038 }
6039 
6040 /** gives the variable a new name
6041  *
6042  * @note the old pointer is overwritten, which might result in a memory leakage
6043  */
6045  SCIP_VAR* var, /**< problem variable */
6046  const char* name /**< new name of variable */
6047  )
6048 {
6049  assert(var != NULL);
6050  assert(name != NULL);
6051 
6052  var->name = (char*)name;
6053 }
6054 
6055 /** informs variable that it will be removed from the problem; adjusts probindex and removes variable from the
6056  * implication graph;
6057  * If 'final' is TRUE, the thorough implication graph removal is not performed. Instead, only the
6058  * variable bounds and implication data structures of the variable are freed. Since in the final removal
6059  * of all variables from the transformed problem, this deletes the implication graph completely and is faster
6060  * than removing the variables one by one, each time updating all lists of the other variables.
6061  */
6063  SCIP_VAR* var, /**< problem variable */
6064  BMS_BLKMEM* blkmem, /**< block memory buffer */
6065  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6066  SCIP_SET* set, /**< global SCIP settings */
6067  SCIP_Bool final /**< is this the final removal of all problem variables? */
6068  )
6069 {
6070  assert(SCIPvarGetProbindex(var) >= 0);
6071  assert(var->scip == set->scip);
6072 
6073  /* if the variable is active in the transformed problem, remove it from the implication graph */
6074  if( SCIPvarIsTransformed(var)
6076  {
6077  if( final )
6078  {
6079  /* just destroy the data structures */
6080  SCIPvboundsFree(&var->vlbs, blkmem);
6081  SCIPvboundsFree(&var->vubs, blkmem);
6082  SCIPimplicsFree(&var->implics, blkmem);
6083  }
6084  else
6085  {
6086  /* unlink the variable from all other variables' lists and free the data structures */
6087  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
6088  }
6089  }
6090 
6091  /* mark the variable to be no longer a member of the problem */
6092  varSetProbindex(var, -1);
6093 
6094  return SCIP_OKAY;
6095 }
6096 
6097 /** marks the variable to be deleted from the problem */
6098 void SCIPvarMarkDeleted(
6099  SCIP_VAR* var /**< problem variable */
6100  )
6101 {
6102  assert(var != NULL);
6103  assert(var->probindex != -1);
6104 
6105  var->deleted = TRUE;
6106 }
6107 
6108 /** marks the variable to not to be aggregated */
6110  SCIP_VAR* var /**< problem variable */
6111  )
6112 {
6113  SCIP_VAR* retvar;
6114 
6115  assert(var != NULL);
6116 
6117  retvar = varGetActiveVar(var);
6118  assert(retvar != NULL);
6119 
6120  switch( SCIPvarGetStatus(retvar) )
6121  {
6123  case SCIP_VARSTATUS_LOOSE:
6124  case SCIP_VARSTATUS_COLUMN:
6125  case SCIP_VARSTATUS_FIXED:
6126  retvar->donotaggr = TRUE;
6127  break;
6128 
6130  SCIPerrorMessage("cannot mark a multi-aggregated variable to not be aggregated.\n");
6131  return SCIP_INVALIDDATA;
6132 
6135  default:
6136  /* aggregated and negated variables should be resolved by varGetActiveVar() */
6137  SCIPerrorMessage("wrong variable status\n");
6138  return SCIP_INVALIDDATA;
6139  }
6140 
6141  return SCIP_OKAY;
6142 }
6143 
6144 /** marks the variable to not to be multi-aggregated */
6146  SCIP_VAR* var /**< problem variable */
6147  )
6148 {
6149  SCIP_VAR* retvar;
6150 
6151  assert(var != NULL);
6152 
6153  retvar = varGetActiveVar(var);
6154  assert(retvar != NULL);
6155 
6156  switch( SCIPvarGetStatus(retvar) )
6157  {
6159  case SCIP_VARSTATUS_LOOSE:
6160  case SCIP_VARSTATUS_COLUMN:
6161  case SCIP_VARSTATUS_FIXED:
6162  retvar->donotmultaggr = TRUE;
6163  break;
6164 
6166  SCIPerrorMessage("cannot mark a multi-aggregated variable to not be multi-aggregated.\n");
6167  return SCIP_INVALIDDATA;
6168 
6171  default:
6172  /* aggregated and negated variables should be resolved by varGetActiveVar() */
6173  SCIPerrorMessage("wrong variable status\n");
6174  return SCIP_INVALIDDATA;
6175  }
6176 
6177  return SCIP_OKAY;
6178 }
6179 
6180 /** changes type of variable; cannot be called, if var belongs to a problem */
6182  SCIP_VAR* var, /**< problem variable to change */
6183  BMS_BLKMEM* blkmem, /**< block memory */
6184  SCIP_SET* set, /**< global SCIP settings */
6185  SCIP_PRIMAL* primal, /**< primal data */
6186  SCIP_LP* lp, /**< current LP data */
6187  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6188  SCIP_VARTYPE vartype /**< new type of variable */
6189  )
6190 {
6191  SCIP_EVENT* event;
6192  SCIP_VARTYPE oldtype;
6193 
6194  assert(var != NULL);
6195 
6196  SCIPdebugMessage("change type of <%s> from %d to %d\n", var->name, SCIPvarGetType(var), vartype);
6197 
6198  if( var->probindex >= 0 )
6199  {
6200  SCIPerrorMessage("cannot change type of variable already in the problem\n");
6201  return SCIP_INVALIDDATA;
6202  }
6203 
6204  oldtype = (SCIP_VARTYPE)var->vartype;
6205  var->vartype = vartype; /*lint !e641*/
6206 
6208  {
6209  SCIP_CALL( SCIPeventCreateTypeChanged(&event, blkmem, var, oldtype, vartype) );
6210  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
6211  }
6212 
6213  if( var->negatedvar != NULL )
6214  {
6215  assert(oldtype == (SCIP_VARTYPE)var->negatedvar->vartype
6216  || SCIPvarIsBinary(var) == SCIPvarIsBinary(var->negatedvar));
6217 
6218 
6219  var->negatedvar->vartype = vartype; /*lint !e641*/
6220 
6222  {
6223  SCIP_CALL( SCIPeventCreateTypeChanged(&event, blkmem, var->negatedvar, oldtype, vartype) );
6224  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
6225  }
6226  }
6227 
6228  return SCIP_OKAY;
6229 }
6230 
6231 /** appends OBJCHANGED event to the event queue */
6232 static
6234  SCIP_VAR* var, /**< problem variable to change */
6235  BMS_BLKMEM* blkmem, /**< block memory */
6236  SCIP_SET* set, /**< global SCIP settings */
6237  SCIP_PRIMAL* primal, /**< primal data */
6238  SCIP_LP* lp, /**< current LP data */
6239  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6240  SCIP_Real oldobj, /**< old objective value for variable */
6241  SCIP_Real newobj /**< new objective value for variable */
6242  )
6243 {
6244  SCIP_EVENT* event;
6245 
6246  assert(var != NULL);
6247  assert(var->scip == set->scip);
6248  assert(var->eventfilter != NULL);
6250  assert(SCIPvarIsTransformed(var));
6251 
6252  /* In the case where the objcetive value of a variable is very close to epsilon, and it is aggregated
6253  * into a variable with a big objective value, round-off errors might make the assert oldobj != newobj fail.
6254  * Hence, we relax it by letting it pass if the variables are percieved the same and we use very large values
6255  * that make comparison with values close to epsilon inaccurate.
6256  */
6257  assert(!SCIPsetIsEQ(set, oldobj, newobj) ||
6258  (SCIPsetIsEQ(set, oldobj, newobj) && REALABS(newobj) > 1e+15 * SCIPsetEpsilon(set))
6259  );
6260 
6261  SCIP_CALL( SCIPeventCreateObjChanged(&event, blkmem, var, oldobj, newobj) );
6262  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
6263 
6264  return SCIP_OKAY;
6265 }
6266 
6267 /** changes objective value of variable */
6269  SCIP_VAR* var, /**< variable to change */
6270  BMS_BLKMEM* blkmem, /**< block memory */
6271  SCIP_SET* set, /**< global SCIP settings */
6272  SCIP_PROB* prob, /**< problem data */
6273  SCIP_PRIMAL* primal, /**< primal data */
6274  SCIP_LP* lp, /**< current LP data */
6275  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6276  SCIP_Real newobj /**< new objective value for variable */
6277  )
6278 {
6279  SCIP_Real oldobj;
6280 
6281  assert(var != NULL);
6282  assert(set != NULL);
6283  assert(var->scip == set->scip);
6284 
6285  SCIPsetDebugMsg(set, "changing objective value of <%s> from %g to %g\n", var->name, var->obj, newobj);
6286 
6287  if( !SCIPsetIsEQ(set, var->obj, newobj) )
6288  {
6289  switch( SCIPvarGetStatus(var) )
6290  {
6292  if( var->data.original.transvar != NULL )
6293  {
6294  assert(SCIPprobIsTransformed(prob));
6295 
6296  SCIP_CALL( SCIPvarChgObj(var->data.original.transvar, blkmem, set, prob, primal, lp, eventqueue,
6297  (SCIP_Real) prob->objsense * newobj/prob->objscale) );
6298  }
6299  else
6300  assert(set->stage == SCIP_STAGE_PROBLEM);
6301 
6302  var->obj = newobj;
6303  var->unchangedobj = newobj;
6304 
6305  break;
6306 
6307  case SCIP_VARSTATUS_LOOSE:
6308  case SCIP_VARSTATUS_COLUMN:
6309  oldobj = var->obj;
6310  var->obj = newobj;
6311 
6312  /* update unchanged objective value of variable */
6313  if( !lp->divingobjchg )
6314  var->unchangedobj = newobj;
6315 
6316  /* update the number of variables with non-zero objective coefficient;
6317  * we only want to do the update, if the variable is added to the problem;
6318  * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
6319  */
6320  if( SCIPvarIsActive(var) )
6321  SCIPprobUpdateNObjVars(prob, set, oldobj, var->obj);
6322 
6323  SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
6324  break;
6325 
6326  case SCIP_VARSTATUS_FIXED:
6330  SCIPerrorMessage("cannot change objective value of a fixed, aggregated, multi-aggregated, or negated variable\n");
6331  return SCIP_INVALIDDATA;
6332 
6333  default:
6334  SCIPerrorMessage("unknown variable status\n");
6335  return SCIP_INVALIDDATA;
6336  }
6337  }
6338 
6339  return SCIP_OKAY;
6340 }
6341 
6342 /** adds value to objective value of variable */
6344  SCIP_VAR* var, /**< variable to change */
6345  BMS_BLKMEM* blkmem, /**< block memory */
6346  SCIP_SET* set, /**< global SCIP settings */
6347  SCIP_STAT* stat, /**< problem statistics */
6348  SCIP_PROB* transprob, /**< transformed problem data */
6349  SCIP_PROB* origprob, /**< original problem data */
6350  SCIP_PRIMAL* primal, /**< primal data */
6351  SCIP_TREE* tree, /**< branch and bound tree */
6352  SCIP_REOPT* reopt, /**< reoptimization data structure */
6353  SCIP_LP* lp, /**< current LP data */
6354  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
6355  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6356  SCIP_Real addobj /**< additional objective value for variable */
6357  )
6358 {
6359  assert(var != NULL);
6360  assert(set != NULL);
6361  assert(var->scip == set->scip);
6362  assert(set->stage < SCIP_STAGE_INITSOLVE);
6363 
6364  SCIPsetDebugMsg(set, "adding %g to objective value %g of <%s>\n", addobj, var->obj, var->name);
6365 
6366  if( !SCIPsetIsZero(set, addobj) )
6367  {
6368  SCIP_Real oldobj;
6369  int i;
6370 
6371  switch( SCIPvarGetStatus(var) )
6372  {
6374  if( var->data.original.transvar != NULL )
6375  {
6376  SCIP_CALL( SCIPvarAddObj(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
6377  reopt, lp, eventfilter, eventqueue, (SCIP_Real) transprob->objsense * addobj/transprob->objscale) );
6378  }
6379  else
6380  assert(set->stage == SCIP_STAGE_PROBLEM);
6381 
6382  var->obj += addobj;
6383  var->unchangedobj += addobj;
6384  assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
6385 
6386  break;
6387 
6388  case SCIP_VARSTATUS_LOOSE:
6389  case SCIP_VARSTATUS_COLUMN:
6390  oldobj = var->obj;
6391  var->obj += addobj;
6392 
6393  /* update unchanged objective value of variable */
6394  if( !lp->divingobjchg )
6395  {
6396  var->unchangedobj += addobj;
6397  assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
6398  }
6399 
6400  /* update the number of variables with non-zero objective coefficient;
6401  * we only want to do the update, if the variable is added to the problem;
6402  * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
6403  */
6404  if( SCIPvarIsActive(var) )
6405  SCIPprobUpdateNObjVars(transprob, set, oldobj, var->obj);
6406 
6407  SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
6408  break;
6409 
6410  case SCIP_VARSTATUS_FIXED:
6411  assert(SCIPsetIsEQ(set, var->locdom.lb, var->locdom.ub));
6412  SCIPprobAddObjoffset(transprob, var->locdom.lb * addobj);
6413  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6414  break;
6415 
6417  assert(!var->donotaggr);
6418  /* x = a*y + c -> add a*addobj to obj. val. of y, and c*addobj to obj. offset of problem */
6419  SCIPprobAddObjoffset(transprob, var->data.aggregate.constant * addobj);
6420  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6421  SCIP_CALL( SCIPvarAddObj(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
6422  lp, eventfilter, eventqueue, var->data.aggregate.scalar * addobj) );
6423  break;
6424 
6426  assert(!var->donotmultaggr);
6427  /* 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 */
6428  SCIPprobAddObjoffset(transprob, var->data.multaggr.constant * addobj);
6429  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6430  for( i = 0; i < var->data.multaggr.nvars; ++i )
6431  {
6432  SCIP_CALL( SCIPvarAddObj(var->data.multaggr.vars[i], blkmem, set, stat, transprob, origprob, primal, tree,
6433  reopt, lp, eventfilter, eventqueue, var->data.multaggr.scalars[i] * addobj) );
6434  }
6435  break;
6436 
6438  /* x' = offset - x -> add -addobj to obj. val. of x and offset*addobj to obj. offset of problem */
6439  assert(var->negatedvar != NULL);
6441  assert(var->negatedvar->negatedvar == var);
6442  SCIPprobAddObjoffset(transprob, var->data.negate.constant * addobj);
6443  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6444  SCIP_CALL( SCIPvarAddObj(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
6445  eventfilter, eventqueue, -addobj) );
6446  break;
6447 
6448  default:
6449  SCIPerrorMessage("unknown variable status\n");
6450  return SCIP_INVALIDDATA;
6451  }
6452  }
6453 
6454  return SCIP_OKAY;
6455 }
6456 
6457 /** changes objective value of variable in current dive */
6459  SCIP_VAR* var, /**< problem variable to change */
6460  SCIP_SET* set, /**< global SCIP settings */
6461  SCIP_LP* lp, /**< current LP data */
6462  SCIP_Real newobj /**< new objective value for variable */
6463  )
6464 {
6465  assert(var != NULL);
6466  assert(set != NULL);
6467  assert(var->scip == set->scip);
6468  assert(lp != NULL);
6469 
6470  SCIPsetDebugMsg(set, "changing objective of <%s> to %g in current dive\n", var->name, newobj);
6471 
6472  if( SCIPsetIsZero(set, newobj) )
6473  newobj = 0.0;
6474 
6475  /* change objective value of attached variables */
6476  switch( SCIPvarGetStatus(var) )
6477  {
6479  assert(var->data.original.transvar != NULL);
6480  SCIP_CALL( SCIPvarChgObjDive(var->data.original.transvar, set, lp, newobj) );
6481  break;
6482 
6483  case SCIP_VARSTATUS_COLUMN:
6484  assert(var->data.col != NULL);
6485  SCIP_CALL( SCIPcolChgObj(var->data.col, set, lp, newobj) );
6486  break;
6487 
6488  case SCIP_VARSTATUS_LOOSE:
6489  case SCIP_VARSTATUS_FIXED:
6490  /* nothing to do here: only the constant shift in objective function would change */
6491  break;
6492 
6493  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6494  assert(var->data.aggregate.var != NULL);
6495  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
6496  SCIP_CALL( SCIPvarChgObjDive(var->data.aggregate.var, set, lp, newobj / var->data.aggregate.scalar) );
6497  /* the constant can be ignored, because it would only affect the objective shift */
6498  break;
6499 
6501  SCIPerrorMessage("cannot change diving objective value of a multi-aggregated variable\n");
6502  return SCIP_INVALIDDATA;
6503 
6504  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6505  assert(var->negatedvar != NULL);
6507  assert(var->negatedvar->negatedvar == var);
6508  SCIP_CALL( SCIPvarChgObjDive(var->negatedvar, set, lp, -newobj) );
6509  /* the offset can be ignored, because it would only affect the objective shift */
6510  break;
6511 
6512  default:
6513  SCIPerrorMessage("unknown variable status\n");
6514  return SCIP_INVALIDDATA;
6515  }
6516 
6517  return SCIP_OKAY;
6518 }
6519 
6520 /** adjust lower bound to integral value, if variable is integral */
6521 void SCIPvarAdjustLb(
6522  SCIP_VAR* var, /**< problem variable */
6523  SCIP_SET* set, /**< global SCIP settings */
6524  SCIP_Real* lb /**< pointer to lower bound to adjust */
6525  )
6526 {
6527  assert(var != NULL);
6528  assert(set != NULL);
6529  assert(var->scip == set->scip);
6530  assert(lb != NULL);
6531 
6532  SCIPsetDebugMsg(set, "adjust lower bound %g of <%s>\n", *lb, var->name);
6533 
6534  *lb = adjustedLb(set, SCIPvarGetType(var), *lb);
6535 }
6536 
6537 /** adjust upper bound to integral value, if variable is integral */
6538 void SCIPvarAdjustUb(
6539  SCIP_VAR* var, /**< problem variable */
6540  SCIP_SET* set, /**< global SCIP settings */
6541  SCIP_Real* ub /**< pointer to upper bound to adjust */
6542  )
6543 {
6544  assert(var != NULL);
6545  assert(set != NULL);
6546  assert(var->scip == set->scip);
6547  assert(ub != NULL);
6548 
6549  SCIPsetDebugMsg(set, "adjust upper bound %g of <%s>\n", *ub, var->name);
6550 
6551  *ub = adjustedUb(set, SCIPvarGetType(var), *ub);
6552 }
6553 
6554 /** adjust lower or upper bound to integral value, if variable is integral */
6555 void SCIPvarAdjustBd(
6556  SCIP_VAR* var, /**< problem variable */
6557  SCIP_SET* set, /**< global SCIP settings */
6558  SCIP_BOUNDTYPE boundtype, /**< type of bound to adjust */
6559  SCIP_Real* bd /**< pointer to bound to adjust */
6560  )
6561 {
6562  assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
6563 
6564  if( boundtype == SCIP_BOUNDTYPE_LOWER )
6565  SCIPvarAdjustLb(var, set, bd);
6566  else
6567  SCIPvarAdjustUb(var, set, bd);
6568 }
6569 
6570 /** changes lower bound of original variable in original problem */
6572  SCIP_VAR* var, /**< problem variable to change */
6573  SCIP_SET* set, /**< global SCIP settings */
6574  SCIP_Real newbound /**< new bound for variable */
6575  )
6576 {
6577  int i;
6578 
6579  assert(var != NULL);
6580  assert(!SCIPvarIsTransformed(var));
6582  assert(set != NULL);
6583  assert(var->scip == set->scip);
6584  assert(set->stage == SCIP_STAGE_PROBLEM);
6585 
6586  /* check that the bound is feasible */
6587  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsLE(set, newbound, SCIPvarGetUbOriginal(var)));
6588  /* adjust bound to integral value if variable is of integral type */
6589  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6590 
6591  if( SCIPsetIsZero(set, newbound) )
6592  newbound = 0.0;
6593 
6594  /* original domains are only stored for ORIGINAL variables, not for NEGATED */
6596  {
6597  SCIPsetDebugMsg(set, "changing original lower bound of <%s> from %g to %g\n",
6598  var->name, var->data.original.origdom.lb, newbound);
6599 
6600  if( SCIPsetIsEQ(set, var->data.original.origdom.lb, newbound) )
6601  return SCIP_OKAY;
6602 
6603  /* change the bound */
6604  var->data.original.origdom.lb = newbound;
6605  }
6606  else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
6607  {
6608  assert( var->negatedvar != NULL );
6609  SCIP_CALL( SCIPvarChgUbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
6610  }
6611 
6612  /* process parent variables */
6613  for( i = 0; i < var->nparentvars; ++i )
6614  {
6615  SCIP_VAR* parentvar;
6616 
6617  parentvar = var->parentvars[i];
6618  assert(parentvar != NULL);
6619  assert(SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_NEGATED);
6620  assert(parentvar->negatedvar == var);
6621  assert(var->negatedvar == parentvar);
6622 
6623  SCIP_CALL( SCIPvarChgUbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
6624  }
6625 
6626  return SCIP_OKAY;
6627 }
6628 
6629 /** changes upper bound of original variable in original problem */
6631  SCIP_VAR* var, /**< problem variable to change */
6632  SCIP_SET* set, /**< global SCIP settings */
6633  SCIP_Real newbound /**< new bound for variable */
6634  )
6635 {
6636  int i;
6637 
6638  assert(var != NULL);
6639  assert(!SCIPvarIsTransformed(var));
6641  assert(set != NULL);
6642  assert(var->scip == set->scip);
6643  assert(set->stage == SCIP_STAGE_PROBLEM);
6644 
6645  /* check that the bound is feasible */
6646  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsGE(set, newbound, SCIPvarGetLbOriginal(var)));
6647  /* adjust bound to integral value if variable is of integral type */
6648  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
6649 
6650  if( SCIPsetIsZero(set, newbound) )
6651  newbound = 0.0;
6652 
6653  /* original domains are only stored for ORIGINAL variables, not for NEGATED */
6655  {
6656  SCIPsetDebugMsg(set, "changing original upper bound of <%s> from %g to %g\n",
6657  var->name, var->data.original.origdom.ub, newbound);
6658 
6659  if( SCIPsetIsEQ(set, var->data.original.origdom.ub, newbound) )
6660  return SCIP_OKAY;
6661 
6662  /* change the bound */
6663  var->data.original.origdom.ub = newbound;
6664  }
6665  else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
6666  {
6667  assert( var->negatedvar != NULL );
6668  SCIP_CALL( SCIPvarChgLbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
6669  }
6670 
6671  /* process parent variables */
6672  for( i = 0; i < var->nparentvars; ++i )
6673  {
6674  SCIP_VAR* parentvar;
6675 
6676  parentvar = var->parentvars[i];
6677  assert(parentvar != NULL);
6678  assert(SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_NEGATED);
6679  assert(parentvar->negatedvar == var);
6680  assert(var->negatedvar == parentvar);
6681 
6682  SCIP_CALL( SCIPvarChgLbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
6683  }
6684 
6685  return SCIP_OKAY;
6686 }
6687 
6688 /** appends GLBCHANGED event to the event queue */
6689 static
6691  SCIP_VAR* var, /**< problem variable to change */
6692  BMS_BLKMEM* blkmem, /**< block memory */
6693  SCIP_SET* set, /**< global SCIP settings */
6694  SCIP_LP* lp, /**< current LP data */
6695  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6696  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6697  SCIP_Real oldbound, /**< old lower bound for variable */
6698  SCIP_Real newbound /**< new lower bound for variable */
6699  )
6700 {
6701  assert(var != NULL);
6702  assert(var->eventfilter != NULL);
6703  assert(SCIPvarIsTransformed(var));
6704  assert(!SCIPsetIsEQ(set, oldbound, newbound) || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
6705  assert(set != NULL);
6706  assert(var->scip == set->scip);
6707 
6708  /* check, if the variable is being tracked for bound changes
6709  * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
6710  */
6711  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GLBCHANGED) != 0)
6714  {
6715  SCIP_EVENT* event;
6716 
6717  SCIPsetDebugMsg(set, "issue GLBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
6718 
6719  SCIP_CALL( SCIPeventCreateGlbChanged(&event, blkmem, var, oldbound, newbound) );
6720  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
6721  }
6722 
6723  return SCIP_OKAY;
6724 }
6725 
6726 /** appends GUBCHANGED event to the event queue */
6727 static
6729  SCIP_VAR* var, /**< problem variable to change */
6730  BMS_BLKMEM* blkmem, /**< block memory */
6731  SCIP_SET* set, /**< global SCIP settings */
6732  SCIP_LP* lp, /**< current LP data */
6733  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6734  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6735  SCIP_Real oldbound, /**< old lower bound for variable */
6736  SCIP_Real newbound /**< new lower bound for variable */
6737  )
6738 {
6739  assert(var != NULL);
6740  assert(var->eventfilter != NULL);
6741  assert(SCIPvarIsTransformed(var));
6742  assert(!SCIPsetIsEQ(set, oldbound, newbound) || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
6743  assert(set != NULL);
6744  assert(var->scip == set->scip);
6745 
6746  /* check, if the variable is being tracked for bound changes
6747  * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
6748  */
6749  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GUBCHANGED) != 0)
6752  {
6753  SCIP_EVENT* event;
6754 
6755  SCIPsetDebugMsg(set, "issue GUBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
6756 
6757  SCIP_CALL( SCIPeventCreateGubChanged(&event, blkmem, var, oldbound, newbound) );
6758  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
6759  }
6760 
6761  return SCIP_OKAY;
6762 }
6763 
6764 /** appends GHOLEADDED event to the event queue */
6765 static
6767  SCIP_VAR* var, /**< problem variable to change */
6768  BMS_BLKMEM* blkmem, /**< block memory */
6769  SCIP_SET* set, /**< global SCIP settings */
6770  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6771  SCIP_Real left, /**< left bound of open interval in new hole */
6772  SCIP_Real right /**< right bound of open interval in new hole */
6773  )
6774 {
6775  assert(var != NULL);
6776  assert(var->eventfilter != NULL);
6777  assert(SCIPvarIsTransformed(var));
6778  assert(set != NULL);
6779  assert(var->scip == set->scip);
6780  assert(SCIPsetIsLT(set, left, right));
6781 
6782  /* check, if the variable is being tracked for bound changes */
6783  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GHOLEADDED) != 0) )
6784  {
6785  SCIP_EVENT* event;
6786 
6787  SCIPsetDebugMsg(set, "issue GHOLEADDED event for variable <%s>: (%.15g,%.15g)\n", var->name, left, right);
6788 
6789  SCIP_CALL( SCIPeventCreateGholeAdded(&event, blkmem, var, left, right) );
6790  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
6791  }
6792 
6793  return SCIP_OKAY;
6794 }
6795 
6796 /** increases root bound change statistics after a global bound change */
6797 static
6798 void varIncRootboundchgs(
6799  SCIP_VAR* var, /**< problem variable to change */
6800  SCIP_SET* set, /**< global SCIP settings */
6801  SCIP_STAT* stat /**< problem statistics */
6802  )
6803 {
6804  assert(var != NULL);
6805  assert(set != NULL);
6806  assert(var->scip == set->scip);
6807  assert(stat != NULL);
6808 
6809  if( SCIPvarIsActive(var) && SCIPvarIsTransformed(var) && set->stage == SCIP_STAGE_SOLVING )
6810  {
6811  stat->nrootboundchgs++;
6812  stat->nrootboundchgsrun++;
6813  if( SCIPvarIsIntegral(var) && SCIPvarGetLbGlobal(var) + 0.5 > SCIPvarGetUbGlobal(var) )
6814  {
6815  stat->nrootintfixings++;
6816  stat->nrootintfixingsrun++;
6817  }
6818  }
6819 }
6820 
6821 /* forward declaration, because both methods call each other recursively */
6822 
6823 /* performs the current change in upper bound, changes all parents accordingly */
6824 static
6826  SCIP_VAR* var, /**< problem variable to change */
6827  BMS_BLKMEM* blkmem, /**< block memory */
6828  SCIP_SET* set, /**< global SCIP settings */
6829  SCIP_STAT* stat, /**< problem statistics */
6830  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6831  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6832  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6833  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6834  SCIP_Real newbound /**< new bound for variable */
6835  );
6836 
6837 /** performs the current change in lower bound, changes all parents accordingly */
6838 static
6840  SCIP_VAR* var, /**< problem variable to change */
6841  BMS_BLKMEM* blkmem, /**< block memory */
6842  SCIP_SET* set, /**< global SCIP settings */
6843  SCIP_STAT* stat, /**< problem statistics */
6844  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6845  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6846  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6847  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6848  SCIP_Real newbound /**< new bound for variable */
6849  )
6850 {
6851  SCIP_VAR* parentvar;
6852  SCIP_Real oldbound;
6853  int i;
6854 
6855  assert(var != NULL);
6856  /* local domains can violate global bounds but not more than feasibility epsilon */
6857  assert(SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb));
6858  assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
6859  assert(blkmem != NULL);
6860  assert(set != NULL);
6861  assert(var->scip == set->scip);
6862  assert(stat != NULL);
6863 
6864  /* adjust bound to integral value if variable is of integral type */
6865  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6866 
6867  /* check that the bound is feasible */
6868  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound > var->glbdom.ub )
6869  {
6870  /* due to numerics we only want to be feasible in feasibility tolerance */
6871  assert(SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
6872  newbound = var->glbdom.ub;
6873  }
6874  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6875 
6876  assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
6877 
6878  SCIPsetDebugMsg(set, "process changing global lower bound of <%s> from %f to %f\n", var->name, var->glbdom.lb, newbound);
6879 
6880  if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) && !(newbound != var->glbdom.lb && newbound * var->glbdom.lb <= 0.0) ) /*lint !e777*/
6881  return SCIP_OKAY;
6882 
6883  /* check bound on debugging solution */
6884  SCIP_CALL( SCIPdebugCheckLbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
6885 
6886  /* change the bound */
6887  oldbound = var->glbdom.lb;
6888  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
6889  var->glbdom.lb = newbound;
6890  assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
6891  assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
6892 
6893  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6894  {
6895  /* merges overlapping holes into single holes, moves bounds respectively */
6896  domMerge(&var->glbdom, blkmem, set, &newbound, NULL);
6897  }
6898 
6899  /* update the root bound changes counters */
6900  varIncRootboundchgs(var, set, stat);
6901 
6902  /* update the lbchginfos array by replacing worse local bounds with the new global bound and changing the
6903  * redundant bound changes to be branching decisions
6904  */
6905  for( i = 0; i < var->nlbchginfos; ++i )
6906  {
6907  assert(var->lbchginfos[i].var == var);
6908 
6909  if( var->lbchginfos[i].oldbound < var->glbdom.lb )
6910  {
6911  SCIPsetDebugMsg(set, " -> adjust lower bound change <%s>: %g -> %g due to new global lower bound %g\n",
6912  SCIPvarGetName(var), var->lbchginfos[i].oldbound, var->lbchginfos[i].newbound, var->glbdom.lb);
6913  var->lbchginfos[i].oldbound = var->glbdom.lb;
6914  if( SCIPsetIsLE(set, var->lbchginfos[i].newbound, var->glbdom.lb) )
6915  {
6916  /* this bound change is redundant due to the new global bound */
6917  var->lbchginfos[i].newbound = var->glbdom.lb;
6918  var->lbchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
6919  var->lbchginfos[i].redundant = TRUE;
6920  }
6921  else
6922  break; /* from now on, the remaining local bound changes are not redundant */
6923  }
6924  else
6925  break; /* from now on, the remaining local bound changes are not redundant */
6926  }
6927 
6928  /* remove redundant implications and variable bounds */
6930  && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
6931  {
6932  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
6933  }
6934 
6935  /* issue bound change event */
6936  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
6937  if( var->eventfilter != NULL )
6938  {
6939  SCIP_CALL( varEventGlbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
6940  }
6941 
6942  /* process parent variables */
6943  for( i = 0; i < var->nparentvars; ++i )
6944  {
6945  parentvar = var->parentvars[i];
6946  assert(parentvar != NULL);
6947 
6948  switch( SCIPvarGetStatus(parentvar) )
6949  {
6951  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6952  break;
6953 
6954  case SCIP_VARSTATUS_COLUMN:
6955  case SCIP_VARSTATUS_LOOSE:
6956  case SCIP_VARSTATUS_FIXED:
6958  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
6959  return SCIP_INVALIDDATA;
6960 
6961  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6962  assert(parentvar->data.aggregate.var == var);
6963  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
6964  {
6965  SCIP_Real parentnewbound;
6966 
6967  /* a > 0 -> change lower bound of y */
6968  assert(SCIPsetIsInfinity(set, -parentvar->glbdom.lb) || SCIPsetIsInfinity(set, -oldbound)
6969  || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
6970  || (SCIPsetIsZero(set, parentvar->glbdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
6971 
6972  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6973  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6974  else
6975  parentnewbound = newbound;
6976  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6977  }
6978  else
6979  {
6980  SCIP_Real parentnewbound;
6981 
6982  /* a < 0 -> change upper bound of y */
6983  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
6984  assert(SCIPsetIsInfinity(set, parentvar->glbdom.ub) || SCIPsetIsInfinity(set, -oldbound)
6985  || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
6986  || (SCIPsetIsZero(set, parentvar->glbdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
6987 
6988  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6989  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6990  else
6991  parentnewbound = -newbound;
6992  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6993  }
6994  break;
6995 
6996  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6997  assert(parentvar->negatedvar != NULL);
6998  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
6999  assert(parentvar->negatedvar->negatedvar == parentvar);
7000  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7001  parentvar->data.negate.constant - newbound) );
7002  break;
7003 
7004  default:
7005  SCIPerrorMessage("unknown variable status\n");
7006  return SCIP_INVALIDDATA;
7007  }
7008  }
7009 
7010  return SCIP_OKAY;
7011 }
7012 
7013 /** performs the current change in upper bound, changes all parents accordingly */
7014 static
7016  SCIP_VAR* var, /**< problem variable to change */
7017  BMS_BLKMEM* blkmem, /**< block memory */
7018  SCIP_SET* set, /**< global SCIP settings */
7019  SCIP_STAT* stat, /**< problem statistics */
7020  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7021  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7022  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7023  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7024  SCIP_Real newbound /**< new bound for variable */
7025  )
7026 {
7027  SCIP_VAR* parentvar;
7028  SCIP_Real oldbound;
7029  int i;
7030 
7031  assert(var != NULL);
7032  /* local domains can violate global bounds but not more than feasibility epsilon */
7033  assert(SCIPsetIsFeasLE(set, var->glbdom.lb , var->locdom.lb));
7034  assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
7035  assert(blkmem != NULL);
7036  assert(set != NULL);
7037  assert(var->scip == set->scip);
7038  assert(stat != NULL);
7039 
7040  /* adjust bound to integral value if variable is of integral type */
7041  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7042 
7043  /* check that the bound is feasible */
7044  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound < var->glbdom.lb )
7045  {
7046  /* due to numerics we only want to be feasible in feasibility tolerance */
7047  assert(SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
7048  newbound = var->glbdom.lb;
7049  }
7050  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7051 
7052  assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
7053 
7054  SCIPsetDebugMsg(set, "process changing global upper bound of <%s> from %f to %f\n", var->name, var->glbdom.ub, newbound);
7055 
7056  if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) && !(newbound != var->glbdom.ub && newbound * var->glbdom.ub <= 0.0) ) /*lint !e777*/
7057  return SCIP_OKAY;
7058 
7059  /* check bound on debugging solution */
7060  SCIP_CALL( SCIPdebugCheckUbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
7061 
7062  /* change the bound */
7063  oldbound = var->glbdom.ub;
7064  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
7065  var->glbdom.ub = newbound;
7066  assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
7067  assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
7068 
7069  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7070  {
7071  /* merges overlapping holes into single holes, moves bounds respectively */
7072  domMerge(&var->glbdom, blkmem, set, NULL, &newbound);
7073  }
7074 
7075  /* update the root bound changes counters */
7076  varIncRootboundchgs(var, set, stat);
7077 
7078  /* update the ubchginfos array by replacing worse local bounds with the new global bound and changing the
7079  * redundant bound changes to be branching decisions
7080  */
7081  for( i = 0; i < var->nubchginfos; ++i )
7082  {
7083  assert(var->ubchginfos[i].var == var);
7084  if( var->ubchginfos[i].oldbound > var->glbdom.ub )
7085  {
7086  SCIPsetDebugMsg(set, " -> adjust upper bound change <%s>: %g -> %g due to new global upper bound %g\n",
7087  SCIPvarGetName(var), var->ubchginfos[i].oldbound, var->ubchginfos[i].newbound, var->glbdom.ub);
7088  var->ubchginfos[i].oldbound = var->glbdom.ub;
7089  if( SCIPsetIsGE(set, var->ubchginfos[i].newbound, var->glbdom.ub) )
7090  {
7091  /* this bound change is redundant due to the new global bound */
7092  var->ubchginfos[i].newbound = var->glbdom.ub;
7093  var->ubchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
7094  var->ubchginfos[i].redundant = TRUE;
7095  }
7096  else
7097  break; /* from now on, the remaining local bound changes are not redundant */
7098  }
7099  else
7100  break; /* from now on, the remaining local bound changes are not redundant */
7101  }
7102 
7103  /* remove redundant implications and variable bounds */
7105  && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
7106  {
7107  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
7108  }
7109 
7110  /* issue bound change event */
7111  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7112  if( var->eventfilter != NULL )
7113  {
7114  SCIP_CALL( varEventGubChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7115  }
7116 
7117  /* process parent variables */
7118  for( i = 0; i < var->nparentvars; ++i )
7119  {
7120  parentvar = var->parentvars[i];
7121  assert(parentvar != NULL);
7122 
7123  switch( SCIPvarGetStatus(parentvar) )
7124  {
7126  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7127  break;
7128 
7129  case SCIP_VARSTATUS_COLUMN:
7130  case SCIP_VARSTATUS_LOOSE:
7131  case SCIP_VARSTATUS_FIXED:
7133  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7134  return SCIP_INVALIDDATA;
7135 
7136  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7137  assert(parentvar->data.aggregate.var == var);
7138  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7139  {
7140  SCIP_Real parentnewbound;
7141 
7142  /* a > 0 -> change upper bound of y */
7143  assert(SCIPsetIsInfinity(set, parentvar->glbdom.ub) || SCIPsetIsInfinity(set, oldbound)
7144  || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub,
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( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
7151  }
7152  else
7153  {
7154  SCIP_Real parentnewbound;
7155 
7156  /* a < 0 -> change lower bound of y */
7157  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7158  assert(SCIPsetIsInfinity(set, -parentvar->glbdom.lb) || SCIPsetIsInfinity(set, oldbound)
7159  || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb,
7160  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7161  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7162  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7163  else
7164  parentnewbound = -newbound;
7165  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
7166  }
7167  break;
7168 
7169  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7170  assert(parentvar->negatedvar != NULL);
7171  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7172  assert(parentvar->negatedvar->negatedvar == parentvar);
7173  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7174  parentvar->data.negate.constant - newbound) );
7175  break;
7176 
7177  default:
7178  SCIPerrorMessage("unknown variable status\n");
7179  return SCIP_INVALIDDATA;
7180  }
7181  }
7182 
7183  return SCIP_OKAY;
7184 }
7185 
7186 /** changes global lower bound of variable; if possible, adjusts bound to integral value;
7187  * updates local lower bound if the global bound is tighter
7188  */
7190  SCIP_VAR* var, /**< problem variable to change */
7191  BMS_BLKMEM* blkmem, /**< block memory */
7192  SCIP_SET* set, /**< global SCIP settings */
7193  SCIP_STAT* stat, /**< problem statistics */
7194  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7195  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7196  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7197  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7198  SCIP_Real newbound /**< new bound for variable */
7199  )
7200 {
7201  assert(var != NULL);
7202  assert(blkmem != NULL);
7203  assert(set != NULL);
7204  assert(var->scip == set->scip);
7205 
7206  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7207  * of the domain within feastol
7208  */
7209  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
7210 
7211  /* adjust bound to integral value if variable is of integral type */
7212  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7213 
7214  /* check that the adjusted bound is feasible
7215  * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
7216  * here because we reset bounds to their original value!
7217  */
7218  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
7219 
7220  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7221  {
7222  /* we do not want to exceed the upperbound, which could have happened due to numerics */
7223  newbound = MIN(newbound, var->glbdom.ub);
7224  }
7225  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7226 
7227  /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
7228  * SCIPvarFix() allows fixings that are outside of the domain within feastol
7229  */
7230  assert(lp == NULL || SCIPsetIsFeasLE(set, var->glbdom.lb, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
7231 
7232  SCIPsetDebugMsg(set, "changing global lower bound of <%s> from %g to %g\n", var->name, var->glbdom.lb, newbound);
7233 
7234  if( SCIPsetIsEQ(set, var->glbdom.lb, newbound) && !(newbound != var->glbdom.lb && newbound * var->glbdom.lb <= 0.0) ) /*lint !e777*/
7235  return SCIP_OKAY;
7236 
7237  /* change bounds of attached variables */
7238  switch( SCIPvarGetStatus(var) )
7239  {
7241  if( var->data.original.transvar != NULL )
7242  {
7243  SCIP_CALL( SCIPvarChgLbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
7244  cliquetable, newbound) );
7245  }
7246  else
7247  {
7248  assert(set->stage == SCIP_STAGE_PROBLEM);
7249  if( newbound > SCIPvarGetLbLocal(var) )
7250  {
7251  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7252  }
7253  SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7254  }
7255  break;
7256 
7257  case SCIP_VARSTATUS_COLUMN:
7258  case SCIP_VARSTATUS_LOOSE:
7259  if( newbound > SCIPvarGetLbLocal(var) )
7260  {
7261  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7262  }
7263  SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7264  break;
7265 
7266  case SCIP_VARSTATUS_FIXED:
7267  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7268  return SCIP_INVALIDDATA;
7269 
7270  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7271  assert(var->data.aggregate.var != NULL);
7272  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7273  {
7274  SCIP_Real childnewbound;
7275 
7276  /* a > 0 -> change lower bound of y */
7277  assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, -var->data.aggregate.var->glbdom.lb))
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( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7285  childnewbound) );
7286  }
7287  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7288  {
7289  SCIP_Real childnewbound;
7290 
7291  /* a < 0 -> change upper bound of y */
7292  assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
7293  || SCIPsetIsFeasEQ(set, var->glbdom.lb,
7295  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7296  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7297  else
7298  childnewbound = -newbound;
7299  SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7300  childnewbound) );
7301  }
7302  else
7303  {
7304  SCIPerrorMessage("scalar is zero in aggregation\n");
7305  return SCIP_INVALIDDATA;
7306  }
7307  break;
7308 
7310  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7311  return SCIP_INVALIDDATA;
7312 
7313  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7314  assert(var->negatedvar != NULL);
7316  assert(var->negatedvar->negatedvar == var);
7317  SCIP_CALL( SCIPvarChgUbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7318  var->data.negate.constant - newbound) );
7319  break;
7320 
7321  default:
7322  SCIPerrorMessage("unknown variable status\n");
7323  return SCIP_INVALIDDATA;
7324  }
7325 
7326  return SCIP_OKAY;
7327 }
7328 
7329 /** changes global upper bound of variable; if possible, adjusts bound to integral value;
7330  * updates local upper bound if the global bound is tighter
7331  */
7333  SCIP_VAR* var, /**< problem variable to change */
7334  BMS_BLKMEM* blkmem, /**< block memory */
7335  SCIP_SET* set, /**< global SCIP settings */
7336  SCIP_STAT* stat, /**< problem statistics */
7337  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7338  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7339  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7340  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7341  SCIP_Real newbound /**< new bound for variable */
7342  )
7343 {
7344  assert(var != NULL);
7345  assert(blkmem != NULL);
7346  assert(set != NULL);
7347  assert(var->scip == set->scip);
7348 
7349  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7350  * of the domain within feastol
7351  */
7352  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
7353 
7354  /* adjust bound to integral value if variable is of integral type */
7355  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7356 
7357  /* check that the adjusted bound is feasible
7358  * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
7359  * here because we reset bounds to their original value!
7360  */
7361  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
7362 
7363  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7364  {
7365  /* we do not want to undercut the lowerbound, which could have happened due to numerics */
7366  newbound = MAX(newbound, var->glbdom.lb);
7367  }
7368  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7369 
7370  /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
7371  * SCIPvarFix() allows fixings that are outside of the domain within feastol
7372  */
7373  assert(lp == NULL || SCIPsetIsFeasGE(set, var->glbdom.ub, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
7374 
7375  SCIPsetDebugMsg(set, "changing global upper bound of <%s> from %g to %g\n", var->name, var->glbdom.ub, newbound);
7376 
7377  if( SCIPsetIsEQ(set, var->glbdom.ub, newbound) && !(newbound != var->glbdom.ub && newbound * var->glbdom.ub <= 0.0) ) /*lint !e777*/
7378  return SCIP_OKAY;
7379 
7380  /* change bounds of attached variables */
7381  switch( SCIPvarGetStatus(var) )
7382  {
7384  if( var->data.original.transvar != NULL )
7385  {
7386  SCIP_CALL( SCIPvarChgUbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7387  newbound) );
7388  }
7389  else
7390  {
7391  assert(set->stage == SCIP_STAGE_PROBLEM);
7392  if( newbound < SCIPvarGetUbLocal(var) )
7393  {
7394  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7395  }
7396  SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7397  }
7398  break;
7399 
7400  case SCIP_VARSTATUS_COLUMN:
7401  case SCIP_VARSTATUS_LOOSE:
7402  if( newbound < SCIPvarGetUbLocal(var) )
7403  {
7404  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7405  }
7406  SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7407  break;
7408 
7409  case SCIP_VARSTATUS_FIXED:
7410  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7411  return SCIP_INVALIDDATA;
7412 
7413  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7414  assert(var->data.aggregate.var != NULL);
7415  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7416  {
7417  SCIP_Real childnewbound;
7418 
7419  /* a > 0 -> change lower bound of y */
7420  assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
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( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7428  childnewbound) );
7429  }
7430  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7431  {
7432  SCIP_Real childnewbound;
7433 
7434  /* a < 0 -> change upper bound of y */
7435  assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, -var->data.aggregate.var->glbdom.lb))
7436  || SCIPsetIsFeasEQ(set, var->glbdom.ub,
7438  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7439  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7440  else
7441  childnewbound = -newbound;
7442  SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7443  childnewbound) );
7444  }
7445  else
7446  {
7447  SCIPerrorMessage("scalar is zero in aggregation\n");
7448  return SCIP_INVALIDDATA;
7449  }
7450  break;
7451 
7453  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7454  return SCIP_INVALIDDATA;
7455 
7456  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7457  assert(var->negatedvar != NULL);
7459  assert(var->negatedvar->negatedvar == var);
7460  SCIP_CALL( SCIPvarChgLbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7461  var->data.negate.constant - newbound) );
7462  break;
7463 
7464  default:
7465  SCIPerrorMessage("unknown variable status\n");
7466  return SCIP_INVALIDDATA;
7467  }
7468 
7469  return SCIP_OKAY;
7470 }
7471 
7472 /** changes lazy lower bound of the variable, this is only possible if the variable is not in the LP yet */
7474  SCIP_VAR* var, /**< problem variable */
7475  SCIP_SET* set, /**< global SCIP settings */
7476  SCIP_Real lazylb /**< the lazy lower bound to be set */
7477  )
7478 {
7479  assert(var != NULL);
7480  assert(var->probindex != -1);
7481  assert(SCIPsetIsFeasGE(set, var->glbdom.ub, lazylb));
7482  assert(SCIPsetIsFeasGE(set, var->lazyub, lazylb));
7483  assert(set != NULL);
7484  assert(var->scip == set->scip);
7485 
7486  /* variable should not be in the LP */
7488  return SCIP_INVALIDCALL;
7489 
7490  var->lazylb = lazylb;
7491 
7492  return SCIP_OKAY;
7493 }
7494 
7495 /** changes lazy upper bound of the variable, this is only possible if the variable is not in the LP yet */
7497  SCIP_VAR* var, /**< problem variable */
7498  SCIP_SET* set, /**< global SCIP settings */
7499  SCIP_Real lazyub /**< the lazy lower bound to be set */
7500  )
7501 {
7502  assert(var != NULL);
7503  assert(var->probindex != -1);
7504  assert(SCIPsetIsFeasGE(set, lazyub, var->glbdom.lb));
7505  assert(SCIPsetIsFeasGE(set, lazyub, var->lazylb));
7506  assert(set != NULL);
7507  assert(var->scip == set->scip);
7508 
7509  /* variable should not be in the LP */
7511  return SCIP_INVALIDCALL;
7512 
7513  var->lazyub = lazyub;
7514 
7515  return SCIP_OKAY;
7516 }
7517 
7518 
7519 /** changes global bound of variable; if possible, adjusts bound to integral value;
7520  * updates local bound if the global bound is tighter
7521  */
7523  SCIP_VAR* var, /**< problem variable to change */
7524  BMS_BLKMEM* blkmem, /**< block memory */
7525  SCIP_SET* set, /**< global SCIP settings */
7526  SCIP_STAT* stat, /**< problem statistics */
7527  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7528  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7529  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7530  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7531  SCIP_Real newbound, /**< new bound for variable */
7532  SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
7533  )
7534 {
7535  /* apply bound change to the LP data */
7536  switch( boundtype )
7537  {
7538  case SCIP_BOUNDTYPE_LOWER:
7539  return SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
7540  case SCIP_BOUNDTYPE_UPPER:
7541  return SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
7542  default:
7543  SCIPerrorMessage("unknown bound type\n");
7544  return SCIP_INVALIDDATA;
7545  }
7546 }
7547 
7548 /** appends LBTIGHTENED or LBRELAXED event to the event queue */
7549 static
7551  SCIP_VAR* var, /**< problem variable to change */
7552  BMS_BLKMEM* blkmem, /**< block memory */
7553  SCIP_SET* set, /**< global SCIP settings */
7554  SCIP_LP* lp, /**< current LP data */
7555  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7556  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7557  SCIP_Real oldbound, /**< old lower bound for variable */
7558  SCIP_Real newbound /**< new lower bound for variable */
7559  )
7560 {
7561  assert(var != NULL);
7562  assert(var->eventfilter != NULL);
7563  assert(SCIPvarIsTransformed(var));
7564  assert(!SCIPsetIsEQ(set, oldbound, newbound) || newbound == var->glbdom.lb || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
7565  assert(set != NULL);
7566  assert(var->scip == set->scip);
7567 
7568  /* check, if the variable is being tracked for bound changes
7569  * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
7570  */
7571  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_LBCHANGED) != 0)
7574  {
7575  SCIP_EVENT* event;
7576 
7577  SCIPsetDebugMsg(set, "issue LBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
7578 
7579  SCIP_CALL( SCIPeventCreateLbChanged(&event, blkmem, var, oldbound, newbound) );
7580  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
7581  }
7582 
7583  return SCIP_OKAY;
7584 }
7585 
7586 /** appends UBTIGHTENED or UBRELAXED event to the event queue */
7587 static
7589  SCIP_VAR* var, /**< problem variable to change */
7590  BMS_BLKMEM* blkmem, /**< block memory */
7591  SCIP_SET* set, /**< global SCIP settings */
7592  SCIP_LP* lp, /**< current LP data */
7593  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7594  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7595  SCIP_Real oldbound, /**< old upper bound for variable */
7596  SCIP_Real newbound /**< new upper bound for variable */
7597  )
7598 {
7599  assert(var != NULL);
7600  assert(var->eventfilter != NULL);
7601  assert(SCIPvarIsTransformed(var));
7602  assert(!SCIPsetIsEQ(set, oldbound, newbound) || newbound == var->glbdom.ub || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
7603  assert(set != NULL);
7604  assert(var->scip == set->scip);
7605 
7606  /* check, if the variable is being tracked for bound changes
7607  * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
7608  */
7609  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_UBCHANGED) != 0)
7612  {
7613  SCIP_EVENT* event;
7614 
7615  SCIPsetDebugMsg(set, "issue UBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
7616 
7617  SCIP_CALL( SCIPeventCreateUbChanged(&event, blkmem, var, oldbound, newbound) );
7618  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
7619  }
7620 
7621  return SCIP_OKAY;
7622 }
7623 
7624 /* forward declaration, because both methods call each other recursively */
7625 
7626 /* performs the current change in upper bound, changes all parents accordingly */
7627 static
7629  SCIP_VAR* var, /**< problem variable to change */
7630  BMS_BLKMEM* blkmem, /**< block memory */
7631  SCIP_SET* set, /**< global SCIP settings */
7632  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7633  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7634  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7635  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7636  SCIP_Real newbound /**< new bound for variable */
7637  );
7638 
7639 /** performs the current change in lower bound, changes all parents accordingly */
7640 static
7642  SCIP_VAR* var, /**< problem variable to change */
7643  BMS_BLKMEM* blkmem, /**< block memory */
7644  SCIP_SET* set, /**< global SCIP settings */
7645  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7646  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7647  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7648  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7649  SCIP_Real newbound /**< new bound for variable */
7650  )
7651 {
7652  SCIP_VAR* parentvar;
7653  SCIP_Real oldbound;
7654  int i;
7655 
7656  assert(var != NULL);
7657  assert(set != NULL);
7658  assert(var->scip == set->scip);
7659  assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)
7660  || SCIPsetIsEQ(set, newbound, var->locdom.ub)))
7661  || (SCIPvarGetType(var) < SCIP_VARTYPE_CONTINUOUS && (SCIPsetIsIntegral(set, newbound)
7662  || SCIPsetIsEQ(set, newbound, var->locdom.ub)))
7664 
7665  /* check that the bound is feasible */
7666  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsLE(set, newbound, var->glbdom.ub));
7667  /* adjust bound to integral value if variable is of integral type */
7668  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7669 
7670  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7671  {
7672  /* we do not want to exceed the upper bound, which could have happened due to numerics */
7673  newbound = MIN(newbound, var->locdom.ub);
7674 
7675  /* we do not want to undercut the global lower bound, which could have happened due to numerics */
7676  newbound = MAX(newbound, var->glbdom.lb);
7677  }
7678  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7679 
7680  SCIPsetDebugMsg(set, "process changing lower bound of <%s> from %g to %g\n", var->name, var->locdom.lb, newbound);
7681 
7682  if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) && var->glbdom.lb != var->locdom.lb ) /*lint !e777*/
7683  newbound = var->glbdom.lb;
7684  else if( SCIPsetIsEQ(set, newbound, var->locdom.lb) && !(newbound != var->locdom.lb && newbound * var->locdom.lb <= 0.0) ) /*lint !e777*/
7685  return SCIP_OKAY;
7686 
7687  /* change the bound */
7688  oldbound = var->locdom.lb;
7689  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->locdom.ub));
7690  var->locdom.lb = newbound;
7691 
7692  /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
7693  * once update the statistic
7694  */
7695  if( stat != NULL )
7696  SCIPstatIncrement(stat, set, domchgcount);
7697 
7698  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7699  {
7700  /* merges overlapping holes into single holes, moves bounds respectively */
7701  domMerge(&var->locdom, blkmem, set, &newbound, NULL);
7702  }
7703 
7704  /* issue bound change event */
7705  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7706  if( var->eventfilter != NULL )
7707  {
7708  SCIP_CALL( varEventLbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7709  }
7710 
7711  /* process parent variables */
7712  for( i = 0; i < var->nparentvars; ++i )
7713  {
7714  parentvar = var->parentvars[i];
7715  assert(parentvar != NULL);
7716 
7717  switch( SCIPvarGetStatus(parentvar) )
7718  {
7720  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
7721  break;
7722 
7723  case SCIP_VARSTATUS_COLUMN:
7724  case SCIP_VARSTATUS_LOOSE:
7725  case SCIP_VARSTATUS_FIXED:
7727  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7728  return SCIP_INVALIDDATA;
7729 
7730  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7731  assert(parentvar->data.aggregate.var == var);
7732  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7733  {
7734  SCIP_Real parentnewbound;
7735 
7736  /* a > 0 -> change lower bound of y */
7737  assert(SCIPsetIsInfinity(set, -parentvar->locdom.lb) || SCIPsetIsInfinity(set, -oldbound)
7738  || SCIPsetIsFeasEQ(set, parentvar->locdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
7739  || (SCIPsetIsZero(set, parentvar->locdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
7740 
7741  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7742  {
7743  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7744  /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
7745  * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
7746  * as a result, the parent's lower bound is set to it's upper bound, and not above
7747  */
7748  if( parentnewbound > parentvar->glbdom.ub )
7749  {
7750  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7751  assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
7752  parentnewbound = parentvar->glbdom.ub;
7753  }
7754  }
7755  else
7756  parentnewbound = newbound;
7757  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7758  }
7759  else
7760  {
7761  SCIP_Real parentnewbound;
7762 
7763  /* a < 0 -> change upper bound of y */
7764  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7765  assert(SCIPsetIsInfinity(set, parentvar->locdom.ub) || SCIPsetIsInfinity(set, -oldbound)
7766  || SCIPsetIsFeasEQ(set, parentvar->locdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
7767  || (SCIPsetIsZero(set, parentvar->locdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
7768 
7769  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7770  {
7771  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7772  /* 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
7773  * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
7774  * as a result, the parent's upper bound is set to it's lower bound, and not below
7775  */
7776  if( parentnewbound < parentvar->glbdom.lb )
7777  {
7778  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7779  assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
7780  parentnewbound = parentvar->glbdom.lb;
7781  }
7782  }
7783  else
7784  parentnewbound = -newbound;
7785  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7786  }
7787  break;
7788 
7789  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
7790  assert(parentvar->negatedvar != NULL);
7791  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7792  assert(parentvar->negatedvar->negatedvar == parentvar);
7793  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
7794  parentvar->data.negate.constant - newbound) );
7795  break;
7796 
7797  default:
7798  SCIPerrorMessage("unknown variable status\n");
7799  return SCIP_INVALIDDATA;
7800  }
7801  }
7802 
7803  return SCIP_OKAY;
7804 }
7805 
7806 /** performs the current change in upper bound, changes all parents accordingly */
7807 static
7809  SCIP_VAR* var, /**< problem variable to change */
7810  BMS_BLKMEM* blkmem, /**< block memory */
7811  SCIP_SET* set, /**< global SCIP settings */
7812  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7813  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7814  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7815  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7816  SCIP_Real newbound /**< new bound for variable */
7817  )
7818 {
7819  SCIP_VAR* parentvar;
7820  SCIP_Real oldbound;
7821  int i;
7822 
7823  assert(var != NULL);
7824  assert(set != NULL);
7825  assert(var->scip == set->scip);
7826  assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)
7827  || SCIPsetIsEQ(set, newbound, var->locdom.lb)))
7828  || (SCIPvarGetType(var) < SCIP_VARTYPE_CONTINUOUS && (SCIPsetIsIntegral(set, newbound)
7829  || SCIPsetIsEQ(set, newbound, var->locdom.lb)))
7831 
7832  /* check that the bound is feasible */
7833  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsGE(set, newbound, var->glbdom.lb));
7834  /* adjust bound to integral value if variable is of integral type */
7835  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7836 
7837  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7838  {
7839  /* we do not want to undercut the lower bound, which could have happened due to numerics */
7840  newbound = MAX(newbound, var->locdom.lb);
7841 
7842  /* we do not want to exceed the global upper bound, which could have happened due to numerics */
7843  newbound = MIN(newbound, var->glbdom.ub);
7844  }
7845  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7846 
7847  SCIPsetDebugMsg(set, "process changing upper bound of <%s> from %g to %g\n", var->name, var->locdom.ub, newbound);
7848 
7849  if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) && var->glbdom.ub != var->locdom.ub ) /*lint !e777*/
7850  newbound = var->glbdom.ub;
7851  else if( SCIPsetIsEQ(set, newbound, var->locdom.ub) && !(newbound != var->locdom.ub && newbound * var->locdom.ub <= 0.0) ) /*lint !e777*/
7852  return SCIP_OKAY;
7853 
7854  /* change the bound */
7855  oldbound = var->locdom.ub;
7856  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->locdom.lb));
7857  var->locdom.ub = newbound;
7858 
7859  /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
7860  * once update the statistic
7861  */
7862  if( stat != NULL )
7863  SCIPstatIncrement(stat, set, domchgcount);
7864 
7865  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7866  {
7867  /* merges overlapping holes into single holes, moves bounds respectively */
7868  domMerge(&var->locdom, blkmem, set, NULL, &newbound);
7869  }
7870 
7871  /* issue bound change event */
7872  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7873  if( var->eventfilter != NULL )
7874  {
7875  SCIP_CALL( varEventUbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7876  }
7877 
7878  /* process parent variables */
7879  for( i = 0; i < var->nparentvars; ++i )
7880  {
7881  parentvar = var->parentvars[i];
7882  assert(parentvar != NULL);
7883 
7884  switch( SCIPvarGetStatus(parentvar) )
7885  {
7887  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
7888  break;
7889 
7890  case SCIP_VARSTATUS_COLUMN:
7891  case SCIP_VARSTATUS_LOOSE:
7892  case SCIP_VARSTATUS_FIXED:
7894  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7895  return SCIP_INVALIDDATA;
7896 
7897  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7898  assert(parentvar->data.aggregate.var == var);
7899  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7900  {
7901  SCIP_Real parentnewbound;
7902 
7903  /* a > 0 -> change upper bound of x */
7904  assert(SCIPsetIsInfinity(set, parentvar->locdom.ub) || SCIPsetIsInfinity(set, oldbound)
7905  || SCIPsetIsFeasEQ(set, parentvar->locdom.ub,
7906  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7907  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7908  {
7909  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7910  /* 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
7911  * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
7912  * as a result, the parent's upper bound is set to it's lower bound, and not below
7913  */
7914  if( parentnewbound < parentvar->glbdom.lb )
7915  {
7916  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7917  assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
7918  parentnewbound = parentvar->glbdom.lb;
7919  }
7920  }
7921  else
7922  parentnewbound = newbound;
7923  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7924  }
7925  else
7926  {
7927  SCIP_Real parentnewbound;
7928 
7929  /* a < 0 -> change lower bound of x */
7930  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7931  assert(SCIPsetIsInfinity(set, -parentvar->locdom.lb) || SCIPsetIsInfinity(set, oldbound)
7932  || SCIPsetIsFeasEQ(set, parentvar->locdom.lb,
7933  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7934  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7935  {
7936  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7937  /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
7938  * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
7939  * as a result, the parent's lower bound is set to it's upper bound, and not above
7940  */
7941  if( parentnewbound > parentvar->glbdom.ub )
7942  {
7943  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7944  assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
7945  parentnewbound = parentvar->glbdom.ub;
7946  }
7947  }
7948  else
7949  parentnewbound = -newbound;
7950  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7951  }
7952  break;
7953 
7954  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
7955  assert(parentvar->negatedvar != NULL);
7956  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7957  assert(parentvar->negatedvar->negatedvar == parentvar);
7958  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
7959  parentvar->data.negate.constant - newbound) );
7960  break;
7961 
7962  default:
7963  SCIPerrorMessage("unknown variable status\n");
7964  return SCIP_INVALIDDATA;
7965  }
7966  }
7967 
7968  return SCIP_OKAY;
7969 }
7970 
7971 /** changes current local lower bound of variable; if possible, adjusts bound to integral value; stores inference
7972  * information in variable
7973  */
7975  SCIP_VAR* var, /**< problem variable to change */
7976  BMS_BLKMEM* blkmem, /**< block memory */
7977  SCIP_SET* set, /**< global SCIP settings */
7978  SCIP_STAT* stat, /**< problem statistics */
7979  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7980  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7981  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7982  SCIP_Real newbound /**< new bound for variable */
7983  )
7984 {
7985  assert(var != NULL);
7986  assert(blkmem != NULL);
7987  assert(set != NULL);
7988  assert(var->scip == set->scip);
7989 
7990  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7991  * of the domain within feastol
7992  */
7993  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
7994 
7995  /* adjust bound to integral value if variable is of integral type */
7996  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7997 
7998  /* check that the adjusted bound is feasible */
7999  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
8000 
8001  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
8002  {
8003  /* we do not want to exceed the upperbound, which could have happened due to numerics */
8004  newbound = MIN(newbound, var->locdom.ub);
8005  }
8006  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
8007 
8008  SCIPsetDebugMsg(set, "changing lower bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
8009 
8010  if( SCIPsetIsEQ(set, var->locdom.lb, newbound) && (!SCIPsetIsEQ(set, var->glbdom.lb, newbound) || var->locdom.lb == newbound) /*lint !e777*/
8011  && !(newbound != var->locdom.lb && newbound * var->locdom.lb <= 0.0) ) /*lint !e777*/
8012  return SCIP_OKAY;
8013 
8014  /* change bounds of attached variables */
8015  switch( SCIPvarGetStatus(var) )
8016  {
8018  if( var->data.original.transvar != NULL )
8019  {
8020  SCIP_CALL( SCIPvarChgLbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
8021  newbound) );
8022  }
8023  else
8024  {
8025  assert(set->stage == SCIP_STAGE_PROBLEM);
8026  SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8027  }
8028  break;
8029 
8030  case SCIP_VARSTATUS_COLUMN:
8031  case SCIP_VARSTATUS_LOOSE:
8032  SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8033  break;
8034 
8035  case SCIP_VARSTATUS_FIXED:
8036  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8037  return SCIP_INVALIDDATA;
8038 
8039  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8040  assert(var->data.aggregate.var != NULL);
8041  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8042  {
8043  SCIP_Real childnewbound;
8044 
8045  /* a > 0 -> change lower bound of y */
8046  assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, -var->data.aggregate.var->locdom.lb))
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( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
8054  childnewbound) );
8055  }
8056  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8057  {
8058  SCIP_Real childnewbound;
8059 
8060  /* a < 0 -> change upper bound of y */
8061  assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->locdom.ub))
8062  || SCIPsetIsFeasEQ(set, var->locdom.lb,
8064  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8065  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8066  else
8067  childnewbound = -newbound;
8068  SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
8069  childnewbound) );
8070  }
8071  else
8072  {
8073  SCIPerrorMessage("scalar is zero in aggregation\n");
8074  return SCIP_INVALIDDATA;
8075  }
8076  break;
8077 
8079  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8080  return SCIP_INVALIDDATA;
8081 
8082  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8083  assert(var->negatedvar != NULL);
8085  assert(var->negatedvar->negatedvar == var);
8086  SCIP_CALL( SCIPvarChgUbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
8087  var->data.negate.constant - newbound) );
8088  break;
8089 
8090  default:
8091  SCIPerrorMessage("unknown variable status\n");
8092  return SCIP_INVALIDDATA;
8093  }
8094 
8095  return SCIP_OKAY;
8096 }
8097 
8098 /** changes current local upper bound of variable; if possible, adjusts bound to integral value; stores inference
8099  * information in variable
8100  */
8102  SCIP_VAR* var, /**< problem variable to change */
8103  BMS_BLKMEM* blkmem, /**< block memory */
8104  SCIP_SET* set, /**< global SCIP settings */
8105  SCIP_STAT* stat, /**< problem statistics */
8106  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
8107  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
8108  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8109  SCIP_Real newbound /**< new bound for variable */
8110  )
8111 {
8112  assert(var != NULL);
8113  assert(blkmem != NULL);
8114  assert(set != NULL);
8115  assert(var->scip == set->scip);
8116 
8117  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
8118  * of the domain within feastol
8119  */
8120  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
8121 
8122  /* adjust bound to integral value if variable is of integral type */
8123  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
8124 
8125  /* check that the adjusted bound is feasible */
8126  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
8127 
8128  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
8129  {
8130  /* we do not want to undercut the lowerbound, which could have happened due to numerics */
8131  newbound = MAX(newbound, var->locdom.lb);
8132  }
8133  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
8134 
8135  SCIPsetDebugMsg(set, "changing upper bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
8136 
8137  if( SCIPsetIsEQ(set, var->locdom.ub, newbound) && (!SCIPsetIsEQ(set, var->glbdom.ub, newbound) || var->locdom.ub == newbound) /*lint !e777*/
8138  && !(newbound != var->locdom.ub && newbound * var->locdom.ub <= 0.0) ) /*lint !e777*/
8139  return SCIP_OKAY;
8140 
8141  /* change bounds of attached variables */
8142  switch( SCIPvarGetStatus(var) )
8143  {
8145  if( var->data.original.transvar != NULL )
8146  {
8147  SCIP_CALL( SCIPvarChgUbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8148  }
8149  else
8150  {
8151  assert(set->stage == SCIP_STAGE_PROBLEM);
8152  SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8153  }
8154  break;
8155 
8156  case SCIP_VARSTATUS_COLUMN:
8157  case SCIP_VARSTATUS_LOOSE:
8158  SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8159  break;
8160 
8161  case SCIP_VARSTATUS_FIXED:
8162  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8163  return SCIP_INVALIDDATA;
8164 
8165  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8166  assert(var->data.aggregate.var != NULL);
8167  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8168  {
8169  SCIP_Real childnewbound;
8170 
8171  /* a > 0 -> change upper bound of y */
8172  assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, var->data.aggregate.var->locdom.ub))
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( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
8180  childnewbound) );
8181  }
8182  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8183  {
8184  SCIP_Real childnewbound;
8185 
8186  /* a < 0 -> change lower bound of y */
8187  assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, -var->data.aggregate.var->locdom.lb))
8188  || SCIPsetIsFeasEQ(set, var->locdom.ub,
8190  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8191  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8192  else
8193  childnewbound = -newbound;
8194  SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
8195  childnewbound) );
8196  }
8197  else
8198  {
8199  SCIPerrorMessage("scalar is zero in aggregation\n");
8200  return SCIP_INVALIDDATA;
8201  }
8202  break;
8203 
8205  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8206  return SCIP_INVALIDDATA;
8207 
8208  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8209  assert(var->negatedvar != NULL);
8211  assert(var->negatedvar->negatedvar == var);
8212  SCIP_CALL( SCIPvarChgLbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
8213  var->data.negate.constant - newbound) );
8214  break;
8215 
8216  default:
8217  SCIPerrorMessage("unknown variable status\n");
8218  return SCIP_INVALIDDATA;
8219  }
8220 
8221  return SCIP_OKAY;
8222 }
8223 
8224 /** changes current local bound of variable; if possible, adjusts bound to integral value; stores inference
8225  * information in variable
8226  */
8228  SCIP_VAR* var, /**< problem variable to change */
8229  BMS_BLKMEM* blkmem, /**< block memory */
8230  SCIP_SET* set, /**< global SCIP settings */
8231  SCIP_STAT* stat, /**< problem statistics */
8232  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
8233  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
8234  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8235  SCIP_Real newbound, /**< new bound for variable */
8236  SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
8237  )
8238 {
8239  /* apply bound change to the LP data */
8240  switch( boundtype )
8241  {
8242  case SCIP_BOUNDTYPE_LOWER:
8243  return SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
8244  case SCIP_BOUNDTYPE_UPPER:
8245  return SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
8246  default:
8247  SCIPerrorMessage("unknown bound type\n");
8248  return SCIP_INVALIDDATA;
8249  }
8250 }
8251 
8252 /** changes lower bound of variable in current dive; if possible, adjusts bound to integral value */
8254  SCIP_VAR* var, /**< problem variable to change */
8255  SCIP_SET* set, /**< global SCIP settings */
8256  SCIP_LP* lp, /**< current LP data */
8257  SCIP_Real newbound /**< new bound for variable */
8258  )
8259 {
8260  assert(var != NULL);
8261  assert(set != NULL);
8262  assert(var->scip == set->scip);
8263  assert(lp != NULL);
8264  assert(SCIPlpDiving(lp));
8265 
8266  /* adjust bound for integral variables */
8267  SCIPvarAdjustLb(var, set, &newbound);
8268 
8269  SCIPsetDebugMsg(set, "changing lower bound of <%s> to %g in current dive\n", var->name, newbound);
8270 
8271  /* change bounds of attached variables */
8272  switch( SCIPvarGetStatus(var) )
8273  {
8275  assert(var->data.original.transvar != NULL);
8276  SCIP_CALL( SCIPvarChgLbDive(var->data.original.transvar, set, lp, newbound) );
8277  break;
8278 
8279  case SCIP_VARSTATUS_COLUMN:
8280  assert(var->data.col != NULL);
8281  SCIP_CALL( SCIPcolChgLb(var->data.col, set, lp, newbound) );
8282  break;
8283 
8284  case SCIP_VARSTATUS_LOOSE:
8285  SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
8286  return SCIP_INVALIDDATA;
8287 
8288  case SCIP_VARSTATUS_FIXED:
8289  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8290  return SCIP_INVALIDDATA;
8291 
8292  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8293  assert(var->data.aggregate.var != NULL);
8294  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8295  {
8296  SCIP_Real childnewbound;
8297 
8298  /* a > 0 -> change lower bound of y */
8299  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8300  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8301  else
8302  childnewbound = newbound;
8303  SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
8304  }
8305  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8306  {
8307  SCIP_Real childnewbound;
8308 
8309  /* a < 0 -> change upper bound of y */
8310  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8311  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8312  else
8313  childnewbound = -newbound;
8314  SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
8315  }
8316  else
8317  {
8318  SCIPerrorMessage("scalar is zero in aggregation\n");
8319  return SCIP_INVALIDDATA;
8320  }
8321  break;
8322 
8324  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8325  return SCIP_INVALIDDATA;
8326 
8327  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8328  assert(var->negatedvar != NULL);
8330  assert(var->negatedvar->negatedvar == var);
8331  SCIP_CALL( SCIPvarChgUbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
8332  break;
8333 
8334  default:
8335  SCIPerrorMessage("unknown variable status\n");
8336  return SCIP_INVALIDDATA;
8337  }
8338 
8339  return SCIP_OKAY;
8340 }
8341 
8342 /** changes upper bound of variable in current dive; if possible, adjusts bound to integral value */
8344  SCIP_VAR* var, /**< problem variable to change */
8345  SCIP_SET* set, /**< global SCIP settings */
8346  SCIP_LP* lp, /**< current LP data */
8347  SCIP_Real newbound /**< new bound for variable */
8348  )
8349 {
8350  assert(var != NULL);
8351  assert(set != NULL);
8352  assert(var->scip == set->scip);
8353  assert(lp != NULL);
8354  assert(SCIPlpDiving(lp));
8355 
8356  /* adjust bound for integral variables */
8357  SCIPvarAdjustUb(var, set, &newbound);
8358 
8359  SCIPsetDebugMsg(set, "changing upper bound of <%s> to %g in current dive\n", var->name, newbound);
8360 
8361  /* change bounds of attached variables */
8362  switch( SCIPvarGetStatus(var) )
8363  {
8365  assert(var->data.original.transvar != NULL);
8366  SCIP_CALL( SCIPvarChgUbDive(var->data.original.transvar, set, lp, newbound) );
8367  break;
8368 
8369  case SCIP_VARSTATUS_COLUMN:
8370  assert(var->data.col != NULL);
8371  SCIP_CALL( SCIPcolChgUb(var->data.col, set, lp, newbound) );
8372  break;
8373 
8374  case SCIP_VARSTATUS_LOOSE:
8375  SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
8376  return SCIP_INVALIDDATA;
8377 
8378  case SCIP_VARSTATUS_FIXED:
8379  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8380  return SCIP_INVALIDDATA;
8381 
8382  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8383  assert(var->data.aggregate.var != NULL);
8384  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8385  {
8386  SCIP_Real childnewbound;
8387 
8388  /* a > 0 -> change upper bound of y */
8389  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8390  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8391  else
8392  childnewbound = newbound;
8393  SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
8394  }
8395  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8396  {
8397  SCIP_Real childnewbound;
8398 
8399  /* a < 0 -> change lower bound of y */
8400  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8401  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8402  else
8403  childnewbound = -newbound;
8404  SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
8405  }
8406  else
8407  {
8408  SCIPerrorMessage("scalar is zero in aggregation\n");
8409  return SCIP_INVALIDDATA;
8410  }
8411  break;
8412 
8414  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8415  return SCIP_INVALIDDATA;
8416 
8417  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8418  assert(var->negatedvar != NULL);
8420  assert(var->negatedvar->negatedvar == var);
8421  SCIP_CALL( SCIPvarChgLbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
8422  break;
8423 
8424  default:
8425  SCIPerrorMessage("unknown variable status\n");
8426  return SCIP_INVALIDDATA;
8427  }
8428 
8429  return SCIP_OKAY;
8430 }
8431 
8432 /** for a multi-aggregated variable, gives the local lower bound computed by adding the local bounds from all
8433  * aggregation variables, this lower bound may be tighter than the one given by SCIPvarGetLbLocal, since the latter is
8434  * not updated if bounds of aggregation variables are changing
8435  *
8436  * calling this function for a non-multi-aggregated variable is not allowed
8437  */
8439  SCIP_VAR* var, /**< problem variable */
8440  SCIP_SET* set /**< global SCIP settings */
8441  )
8442 {
8443  int i;
8444  SCIP_Real lb;
8445  SCIP_Real bnd;
8446  SCIP_VAR* aggrvar;
8447  SCIP_Bool posinf;
8448  SCIP_Bool neginf;
8449 
8450  assert(var != NULL);
8451  assert(set != NULL);
8452  assert(var->scip == set->scip);
8454 
8455  posinf = FALSE;
8456  neginf = FALSE;
8457  lb = var->data.multaggr.constant;
8458  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8459  {
8460  aggrvar = var->data.multaggr.vars[i];
8461  if( var->data.multaggr.scalars[i] > 0.0 )
8462  {
8463  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbLocal(aggrvar, set) : SCIPvarGetLbLocal(aggrvar);
8464 
8465  if( SCIPsetIsInfinity(set, bnd) )
8466  posinf = TRUE;
8467  else if( SCIPsetIsInfinity(set, -bnd) )
8468  neginf = TRUE;
8469  else
8470  lb += var->data.multaggr.scalars[i] * bnd;
8471  }
8472  else
8473  {
8474  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbLocal(aggrvar, set) : SCIPvarGetUbLocal(aggrvar);
8475 
8476  if( SCIPsetIsInfinity(set, -bnd) )
8477  posinf = TRUE;
8478  else if( SCIPsetIsInfinity(set, bnd) )
8479  neginf = TRUE;
8480  else
8481  lb += var->data.multaggr.scalars[i] * bnd;
8482  }
8483 
8484  /* stop if two diffrent infinities (or a -infinity) were found and return local lower bound of multi aggregated
8485  * variable
8486  */
8487  if( neginf )
8488  return SCIPvarGetLbLocal(var);
8489  }
8490 
8491  /* if positive infinity flag was set to true return infinity */
8492  if( posinf )
8493  return SCIPsetInfinity(set);
8494 
8495  return (MAX(lb, SCIPvarGetLbLocal(var))); /*lint !e666*/
8496 }
8497 
8498 /** for a multi-aggregated variable, gives the local upper bound computed by adding the local bounds from all
8499  * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbLocal, since the latter is
8500  * not updated if bounds of aggregation variables are changing
8501  *
8502  * calling this function for a non-multi-aggregated variable is not allowed
8503  */
8505  SCIP_VAR* var, /**< problem variable */
8506  SCIP_SET* set /**< global SCIP settings */
8507  )
8508 {
8509  int i;
8510  SCIP_Real ub;
8511  SCIP_Real bnd;
8512  SCIP_VAR* aggrvar;
8513  SCIP_Bool posinf;
8514  SCIP_Bool neginf;
8515 
8516  assert(var != NULL);
8517  assert(set != NULL);
8518  assert(var->scip == set->scip);
8520 
8521  posinf = FALSE;
8522  neginf = FALSE;
8523  ub = var->data.multaggr.constant;
8524  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8525  {
8526  aggrvar = var->data.multaggr.vars[i];
8527  if( var->data.multaggr.scalars[i] > 0.0 )
8528  {
8529  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbLocal(aggrvar, set) : SCIPvarGetUbLocal(aggrvar);
8530 
8531  if( SCIPsetIsInfinity(set, bnd) )
8532  posinf = TRUE;
8533  else if( SCIPsetIsInfinity(set, -bnd) )
8534  neginf = TRUE;
8535  else
8536  ub += var->data.multaggr.scalars[i] * bnd;
8537  }
8538  else
8539  {
8540  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbLocal(aggrvar, set) : SCIPvarGetLbLocal(aggrvar);
8541 
8542  if( SCIPsetIsInfinity(set, -bnd) )
8543  posinf = TRUE;
8544  else if( SCIPsetIsInfinity(set, bnd) )
8545  neginf = TRUE;
8546  else
8547  ub += var->data.multaggr.scalars[i] * bnd;
8548  }
8549 
8550  /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
8551  * variable
8552  */
8553  if( posinf )
8554  return SCIPvarGetUbLocal(var);
8555  }
8556 
8557  /* if negative infinity flag was set to true return -infinity */
8558  if( neginf )
8559  return -SCIPsetInfinity(set);
8560 
8561  return (MIN(ub, SCIPvarGetUbLocal(var))); /*lint !e666*/
8562 }
8563 
8564 /** for a multi-aggregated variable, gives the global lower bound computed by adding the global bounds from all
8565  * aggregation variables, this global bound may be tighter than the one given by SCIPvarGetLbGlobal, since the latter is
8566  * not updated if bounds of aggregation variables are changing
8567  *
8568  * calling this function for a non-multi-aggregated variable is not allowed
8569  */
8571  SCIP_VAR* var, /**< problem variable */
8572  SCIP_SET* set /**< global SCIP settings */
8573  )
8574 {
8575  int i;
8576  SCIP_Real lb;
8577  SCIP_Real bnd;
8578  SCIP_VAR* aggrvar;
8579  SCIP_Bool posinf;
8580  SCIP_Bool neginf;
8581 
8582  assert(var != NULL);
8583  assert(set != NULL);
8584  assert(var->scip == set->scip);
8586 
8587  posinf = FALSE;
8588  neginf = FALSE;
8589  lb = var->data.multaggr.constant;
8590  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8591  {
8592  aggrvar = var->data.multaggr.vars[i];
8593  if( var->data.multaggr.scalars[i] > 0.0 )
8594  {
8595  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbGlobal(aggrvar, set) : SCIPvarGetLbGlobal(aggrvar);
8596 
8597  if( SCIPsetIsInfinity(set, bnd) )
8598  posinf = TRUE;
8599  else if( SCIPsetIsInfinity(set, -bnd) )
8600  neginf = TRUE;
8601  else
8602  lb += var->data.multaggr.scalars[i] * bnd;
8603  }
8604  else
8605  {
8606  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbGlobal(aggrvar, set) : SCIPvarGetUbGlobal(aggrvar);
8607 
8608  if( SCIPsetIsInfinity(set, -bnd) )
8609  posinf = TRUE;
8610  else if( SCIPsetIsInfinity(set, bnd) )
8611  neginf = TRUE;
8612  else
8613  lb += var->data.multaggr.scalars[i] * bnd;
8614  }
8615 
8616  /* stop if two diffrent infinities (or a -infinity) were found and return global lower bound of multi aggregated
8617  * variable
8618  */
8619  if( neginf )
8620  return SCIPvarGetLbGlobal(var);
8621  }
8622 
8623  /* if positive infinity flag was set to true return infinity */
8624  if( posinf )
8625  return SCIPsetInfinity(set);
8626 
8627  return (MAX(lb, SCIPvarGetLbGlobal(var))); /*lint !e666*/
8628 }
8629 
8630 /** for a multi-aggregated variable, gives the global upper bound computed by adding the global bounds from all
8631  * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbGlobal, since the latter is
8632  * not updated if bounds of aggregation variables are changing
8633  *
8634  * calling this function for a non-multi-aggregated variable is not allowed
8635  */
8637  SCIP_VAR* var, /**< problem variable */
8638  SCIP_SET* set /**< global SCIP settings */
8639  )
8640 {
8641  int i;
8642  SCIP_Real ub;
8643  SCIP_Real bnd;
8644  SCIP_VAR* aggrvar;
8645  SCIP_Bool posinf;
8646  SCIP_Bool neginf;
8647 
8648  assert(var != NULL);
8649  assert(set != NULL);
8650  assert(var->scip == set->scip);
8652 
8653  posinf = FALSE;
8654  neginf = FALSE;
8655  ub = var->data.multaggr.constant;
8656  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8657  {
8658  aggrvar = var->data.multaggr.vars[i];
8659  if( var->data.multaggr.scalars[i] > 0.0 )
8660  {
8661  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbGlobal(aggrvar, set) : SCIPvarGetUbGlobal(aggrvar);
8662 
8663  if( SCIPsetIsInfinity(set, bnd) )
8664  posinf = TRUE;
8665  else if( SCIPsetIsInfinity(set, -bnd) )
8666  neginf = TRUE;
8667  else
8668  ub += var->data.multaggr.scalars[i] * bnd;
8669  }
8670  else
8671  {
8672  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbGlobal(aggrvar, set) : SCIPvarGetLbGlobal(aggrvar);
8673 
8674  if( SCIPsetIsInfinity(set, -bnd) )
8675  posinf = TRUE;
8676  else if( SCIPsetIsInfinity(set, bnd) )
8677  neginf = TRUE;
8678  else
8679  ub += var->data.multaggr.scalars[i] * bnd;
8680  }
8681 
8682  /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
8683  * variable
8684  */
8685  if( posinf )
8686  return SCIPvarGetUbGlobal(var);
8687  }
8688 
8689  /* if negative infinity flag was set to true return -infinity */
8690  if( neginf )
8691  return -SCIPsetInfinity(set);
8692 
8693  return (MIN(ub, SCIPvarGetUbGlobal(var))); /*lint !e666*/
8694 }
8695 
8696 /** adds a hole to the original domain of the variable */
8698  SCIP_VAR* var, /**< problem variable */
8699  BMS_BLKMEM* blkmem, /**< block memory */
8700  SCIP_SET* set, /**< global SCIP settings */
8701  SCIP_Real left, /**< left bound of open interval in new hole */
8702  SCIP_Real right /**< right bound of open interval in new hole */
8703  )
8704 {
8705  SCIP_Bool added;
8706 
8707  assert(var != NULL);
8708  assert(!SCIPvarIsTransformed(var));
8710  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8711  assert(set != NULL);
8712  assert(var->scip == set->scip);
8713  assert(set->stage == SCIP_STAGE_PROBLEM);
8714 
8715  SCIPsetDebugMsg(set, "adding original hole (%g,%g) to <%s>\n", left, right, var->name);
8716 
8717  if( SCIPsetIsEQ(set, left, right) )
8718  return SCIP_OKAY;
8719 
8720  /* the interval should not be empty */
8721  assert(SCIPsetIsLT(set, left, right));
8722 
8723  /* the the interval bound should already be adjusted */
8724  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8725  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8726 
8727  /* the the interval should lay between the lower and upper bound */
8728  assert(SCIPsetIsGE(set, left, SCIPvarGetLbOriginal(var)));
8729  assert(SCIPsetIsLE(set, right, SCIPvarGetUbOriginal(var)));
8730 
8731  /* add domain hole */
8732  SCIP_CALL( domAddHole(&var->data.original.origdom, blkmem, set, left, right, &added) );
8733 
8734  /* merges overlapping holes into single holes, moves bounds respectively if hole was added */
8735  if( added )
8736  {
8737  domMerge(&var->data.original.origdom, blkmem, set, NULL, NULL);
8738  }
8739 
8740  /**@todo add hole in parent and child variables (just like with bound changes);
8741  * warning! original vars' holes are in original blkmem, transformed vars' holes in transformed blkmem
8742  */
8743 
8744  return SCIP_OKAY;
8745 }
8746 
8747 /** performs the current add of domain, changes all parents accordingly */
8748 static
8750  SCIP_VAR* var, /**< problem variable */
8751  BMS_BLKMEM* blkmem, /**< block memory */
8752  SCIP_SET* set, /**< global SCIP settings */
8753  SCIP_STAT* stat, /**< problem statistics */
8754  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8755  SCIP_Real left, /**< left bound of open interval in new hole */
8756  SCIP_Real right, /**< right bound of open interval in new hole */
8757  SCIP_Bool* added /**< pointer to store whether the hole was added */
8758  )
8759 {
8760  SCIP_VAR* parentvar;
8761  SCIP_Real newlb;
8762  SCIP_Real newub;
8763  int i;
8764 
8765  assert(var != NULL);
8766  assert(added != NULL);
8767  assert(blkmem != NULL);
8768 
8769  /* the interval should not be empty */
8770  assert(SCIPsetIsLT(set, left, right));
8771 
8772  /* the interval bound should already be adjusted */
8773  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8774  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8775 
8776  /* the interval should lay between the lower and upper bound */
8777  assert(SCIPsetIsGE(set, left, SCIPvarGetLbGlobal(var)));
8778  assert(SCIPsetIsLE(set, right, SCIPvarGetUbGlobal(var)));
8779 
8780  /* @todo add debugging mechanism for holes when using a debugging solution */
8781 
8782  /* add hole to hole list */
8783  SCIP_CALL( domAddHole(&var->glbdom, blkmem, set, left, right, added) );
8784 
8785  /* check if the hole is redundant */
8786  if( !(*added) )
8787  return SCIP_OKAY;
8788 
8789  /* current bounds */
8790  newlb = var->glbdom.lb;
8791  newub = var->glbdom.ub;
8792 
8793  /* merge domain holes */
8794  domMerge(&var->glbdom, blkmem, set, &newlb, &newub);
8795 
8796  /* the bound should not be changed */
8797  assert(SCIPsetIsEQ(set, newlb, var->glbdom.lb));
8798  assert(SCIPsetIsEQ(set, newub, var->glbdom.ub));
8799 
8800  /* issue bound change event */
8801  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
8802  if( var->eventfilter != NULL )
8803  {
8804  SCIP_CALL( varEventGholeAdded(var, blkmem, set, eventqueue, left, right) );
8805  }
8806 
8807  /* process parent variables */
8808  for( i = 0; i < var->nparentvars; ++i )
8809  {
8810  SCIP_Real parentnewleft;
8811  SCIP_Real parentnewright;
8812  SCIP_Bool localadded;
8813 
8814  parentvar = var->parentvars[i];
8815  assert(parentvar != NULL);
8816 
8817  switch( SCIPvarGetStatus(parentvar) )
8818  {
8820  parentnewleft = left;
8821  parentnewright = right;
8822  break;
8823 
8824  case SCIP_VARSTATUS_COLUMN:
8825  case SCIP_VARSTATUS_LOOSE:
8826  case SCIP_VARSTATUS_FIXED:
8828  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
8829  return SCIP_INVALIDDATA;
8830 
8831  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8832  assert(parentvar->data.aggregate.var == var);
8833 
8834  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
8835  {
8836  /* a > 0 -> change upper bound of x */
8837  parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8838  parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8839  }
8840  else
8841  {
8842  /* a < 0 -> change lower bound of x */
8843  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
8844 
8845  parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8846  parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8847  }
8848  break;
8849 
8850  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
8851  assert(parentvar->negatedvar != NULL);
8852  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
8853  assert(parentvar->negatedvar->negatedvar == parentvar);
8854 
8855  parentnewright = -left + parentvar->data.negate.constant;
8856  parentnewleft = -right + parentvar->data.negate.constant;
8857  break;
8858 
8859  default:
8860  SCIPerrorMessage("unknown variable status\n");
8861  return SCIP_INVALIDDATA;
8862  }
8863 
8864  SCIPsetDebugMsg(set, "add global hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
8865 
8866  /* perform hole added for parent variable */
8867  assert(blkmem != NULL);
8868  assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
8869  SCIP_CALL( varProcessAddHoleGlobal(parentvar, blkmem, set, stat, eventqueue,
8870  parentnewleft, parentnewright, &localadded) );
8871  assert(localadded);
8872  }
8873 
8874  return SCIP_OKAY;
8875 }
8876 
8877 /** adds a hole to the variable's global and local domain */
8879  SCIP_VAR* var, /**< problem variable */
8880  BMS_BLKMEM* blkmem, /**< block memory */
8881  SCIP_SET* set, /**< global SCIP settings */
8882  SCIP_STAT* stat, /**< problem statistics */
8883  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8884  SCIP_Real left, /**< left bound of open interval in new hole */
8885  SCIP_Real right, /**< right bound of open interval in new hole */
8886  SCIP_Bool* added /**< pointer to store whether the hole was added */
8887  )
8888 {
8889  SCIP_Real childnewleft;
8890  SCIP_Real childnewright;
8891 
8892  assert(var != NULL);
8893  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8894  assert(blkmem != NULL);
8895  assert(added != NULL);
8896 
8897  SCIPsetDebugMsg(set, "adding global hole (%g,%g) to <%s>\n", left, right, var->name);
8898 
8899  /* the interval should not be empty */
8900  assert(SCIPsetIsLT(set, left, right));
8901 
8902  /* the the interval bound should already be adjusted */
8903  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8904  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8905 
8906  /* the the interval should lay between the lower and upper bound */
8907  assert(SCIPsetIsGE(set, left, SCIPvarGetLbGlobal(var)));
8908  assert(SCIPsetIsLE(set, right, SCIPvarGetUbGlobal(var)));
8909 
8910  /* change bounds of attached variables */
8911  switch( SCIPvarGetStatus(var) )
8912  {
8914  if( var->data.original.transvar != NULL )
8915  {
8916  SCIP_CALL( SCIPvarAddHoleGlobal(var->data.original.transvar, blkmem, set, stat, eventqueue,
8917  left, right, added) );
8918  }
8919  else
8920  {
8921  assert(set->stage == SCIP_STAGE_PROBLEM);
8922 
8923  SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
8924  if( *added )
8925  {
8926  SCIP_Bool localadded;
8927 
8928  SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
8929  }
8930  }
8931  break;
8932 
8933  case SCIP_VARSTATUS_COLUMN:
8934  case SCIP_VARSTATUS_LOOSE:
8935  SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
8936  if( *added )
8937  {
8938  SCIP_Bool localadded;
8939 
8940  SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
8941  }
8942  break;
8943 
8944  case SCIP_VARSTATUS_FIXED:
8945  SCIPerrorMessage("cannot add hole of a fixed variable\n");
8946  return SCIP_INVALIDDATA;
8947 
8948  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8949  assert(var->data.aggregate.var != NULL);
8950 
8951  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8952  {
8953  /* a > 0 -> change lower bound of y */
8954  childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8955  childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8956  }
8957  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8958  {
8959  childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8960  childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8961  }
8962  else
8963  {
8964  SCIPerrorMessage("scalar is zero in aggregation\n");
8965  return SCIP_INVALIDDATA;
8966  }
8967  SCIP_CALL( SCIPvarAddHoleGlobal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
8968  childnewleft, childnewright, added) );
8969  break;
8970 
8972  SCIPerrorMessage("cannot add a hole of a multi-aggregated variable.\n");
8973  return SCIP_INVALIDDATA;
8974 
8975  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8976  assert(var->negatedvar != NULL);
8978  assert(var->negatedvar->negatedvar == var);
8979 
8980  childnewright = -left + var->data.negate.constant;
8981  childnewleft = -right + var->data.negate.constant;
8982 
8983  SCIP_CALL( SCIPvarAddHoleGlobal(var->negatedvar, blkmem, set, stat, eventqueue,
8984  childnewleft, childnewright, added) );
8985  break;
8986 
8987  default:
8988  SCIPerrorMessage("unknown variable status\n");
8989  return SCIP_INVALIDDATA;
8990  }
8991 
8992  return SCIP_OKAY;
8993 }
8994 
8995 /** performs the current add of domain, changes all parents accordingly */
8996 static
8998  SCIP_VAR* var, /**< problem variable */
8999  BMS_BLKMEM* blkmem, /**< block memory */
9000  SCIP_SET* set, /**< global SCIP settings */
9001  SCIP_STAT* stat, /**< problem statistics */
9002  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
9003  SCIP_Real left, /**< left bound of open interval in new hole */
9004  SCIP_Real right, /**< right bound of open interval in new hole */
9005  SCIP_Bool* added /**< pointer to store whether the hole was added, or NULL */
9006  )
9007 {
9008  SCIP_VAR* parentvar;
9009  SCIP_Real newlb;
9010  SCIP_Real newub;
9011  int i;
9012 
9013  assert(var != NULL);
9014  assert(added != NULL);
9015  assert(blkmem != NULL);
9016 
9017  /* the interval should not be empty */
9018  assert(SCIPsetIsLT(set, left, right));
9019 
9020  /* the the interval bound should already be adjusted */
9021  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
9022  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
9023 
9024  /* the the interval should lay between the lower and upper bound */
9025  assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
9026  assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
9027 
9028  /* add hole to hole list */
9029  SCIP_CALL( domAddHole(&var->locdom, blkmem, set, left, right, added) );
9030 
9031  /* check if the hole is redundant */
9032  if( !(*added) )
9033  return SCIP_OKAY;
9034 
9035  /* current bounds */
9036  newlb = var->locdom.lb;
9037  newub = var->locdom.ub;
9038 
9039  /* merge domain holes */
9040  domMerge(&var->locdom, blkmem, set, &newlb, &newub);
9041 
9042  /* the bound should not be changed */
9043  assert(SCIPsetIsEQ(set, newlb, var->locdom.lb));
9044  assert(SCIPsetIsEQ(set, newub, var->locdom.ub));
9045 
9046 #if 0
9047  /* issue bound change event */
9048  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
9049  if( var->eventfilter != NULL )
9050  {
9051  SCIP_CALL( varEventLholeAdded(var, blkmem, set, lp, branchcand, eventqueue, left, right) );
9052  }
9053 #endif
9054 
9055  /* process parent variables */
9056  for( i = 0; i < var->nparentvars; ++i )
9057  {
9058  SCIP_Real parentnewleft;
9059  SCIP_Real parentnewright;
9060  SCIP_Bool localadded;
9061 
9062  parentvar = var->parentvars[i];
9063  assert(parentvar != NULL);
9064 
9065  switch( SCIPvarGetStatus(parentvar) )
9066  {
9068  parentnewleft = left;
9069  parentnewright = right;
9070  break;
9071 
9072  case SCIP_VARSTATUS_COLUMN:
9073  case SCIP_VARSTATUS_LOOSE:
9074  case SCIP_VARSTATUS_FIXED:
9076  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
9077  return SCIP_INVALIDDATA;
9078 
9079  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
9080  assert(parentvar->data.aggregate.var == var);
9081 
9082  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
9083  {
9084  /* a > 0 -> change upper bound of x */
9085  parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
9086  parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
9087  }
9088  else
9089  {
9090  /* a < 0 -> change lower bound of x */
9091  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
9092 
9093  parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
9094  parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
9095  }
9096  break;
9097 
9098  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
9099  assert(parentvar->negatedvar != NULL);
9100  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
9101  assert(parentvar->negatedvar->negatedvar == parentvar);
9102 
9103  parentnewright = -left + parentvar->data.negate.constant;
9104  parentnewleft = -right + parentvar->data.negate.constant;
9105  break;
9106 
9107  default:
9108  SCIPerrorMessage("unknown variable status\n");
9109  return SCIP_INVALIDDATA;
9110  }
9111 
9112  SCIPsetDebugMsg(set, "add local hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
9113 
9114  /* perform hole added for parent variable */
9115  assert(blkmem != NULL);
9116  assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
9117  SCIP_CALL( varProcessAddHoleLocal(parentvar, blkmem, set, stat, eventqueue,
9118  parentnewleft, parentnewright, &localadded) );
9119  assert(localadded);
9120  }
9121 
9122  return SCIP_OKAY;
9123 }
9124 
9125 /** adds a hole to the variable's current local domain */
9127  SCIP_VAR* var, /**< problem variable */
9128  BMS_BLKMEM* blkmem, /**< block memory */
9129  SCIP_SET* set, /**< global SCIP settings */
9130  SCIP_STAT* stat, /**< problem statistics */
9131  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
9132  SCIP_Real left, /**< left bound of open interval in new hole */
9133  SCIP_Real right, /**< right bound of open interval in new hole */
9134  SCIP_Bool* added /**< pointer to store whether the hole was added */
9135  )
9136 {
9137  SCIP_Real childnewleft;
9138  SCIP_Real childnewright;
9139 
9140  assert(var != NULL);
9141 
9142  SCIPsetDebugMsg(set, "adding local hole (%g,%g) to <%s>\n", left, right, var->name);
9143 
9144  assert(set != NULL);
9145  assert(var->scip == set->scip);
9146  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
9147  assert(blkmem != NULL);
9148  assert(added != NULL);
9149 
9150  /* the interval should not be empty */
9151  assert(SCIPsetIsLT(set, left, right));
9152 
9153  /* the the interval bound should already be adjusted */
9154  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
9155  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
9156 
9157  /* the the interval should lay between the lower and upper bound */
9158  assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
9159  assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
9160 
9161  /* change bounds of attached variables */
9162  switch( SCIPvarGetStatus(var) )
9163  {
9165  if( var->data.original.transvar != NULL )
9166  {
9167  SCIP_CALL( SCIPvarAddHoleLocal(var->data.original.transvar, blkmem, set, stat, eventqueue,
9168  left, right, added) );
9169  }
9170  else
9171  {
9172  assert(set->stage == SCIP_STAGE_PROBLEM);
9173  SCIPstatIncrement(stat, set, domchgcount);
9174  SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
9175  }
9176  break;
9177 
9178  case SCIP_VARSTATUS_COLUMN:
9179  case SCIP_VARSTATUS_LOOSE:
9180  SCIPstatIncrement(stat, set, domchgcount);
9181  SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
9182  break;
9183 
9184  case SCIP_VARSTATUS_FIXED:
9185  SCIPerrorMessage("cannot add domain hole to a fixed variable\n");
9186  return SCIP_INVALIDDATA;
9187 
9188  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
9189  assert(var->data.aggregate.var != NULL);
9190 
9191  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
9192  {
9193  /* a > 0 -> change lower bound of y */
9194  childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
9195  childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
9196  }
9197  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
9198  {
9199  childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
9200  childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
9201  }
9202  else
9203  {
9204  SCIPerrorMessage("scalar is zero in aggregation\n");
9205  return SCIP_INVALIDDATA;
9206  }
9207  SCIP_CALL( SCIPvarAddHoleLocal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
9208  childnewleft, childnewright, added) );
9209  break;
9210 
9212  SCIPerrorMessage("cannot add domain hole to a multi-aggregated variable.\n");
9213  return SCIP_INVALIDDATA;
9214 
9215  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
9216  assert(var->negatedvar != NULL);
9218  assert(var->negatedvar->negatedvar == var);
9219 
9220  childnewright = -left + var->data.negate.constant;
9221  childnewleft = -right + var->data.negate.constant;
9222 
9223  SCIP_CALL( SCIPvarAddHoleLocal(var->negatedvar, blkmem, set, stat, eventqueue, childnewleft, childnewright, added) );
9224  break;
9225 
9226  default:
9227  SCIPerrorMessage("unknown variable status\n");
9228  return SCIP_INVALIDDATA;
9229  }
9230 
9231  return SCIP_OKAY;
9232 }
9233 
9234 /** resets the global and local bounds of original variable to their original values */
9236  SCIP_VAR* var, /**< problem variable */
9237  BMS_BLKMEM* blkmem, /**< block memory */
9238  SCIP_SET* set, /**< global SCIP settings */
9239  SCIP_STAT* stat /**< problem statistics */
9240  )
9241 {
9242  assert(var != NULL);
9243  assert(set != NULL);
9244  assert(var->scip == set->scip);
9245  assert(SCIPvarIsOriginal(var));
9246  /* resetting of bounds on original variables which have a transformed counterpart easily fails if, e.g.,
9247  * the transformed variable has been fixed */
9248  assert(SCIPvarGetTransVar(var) == NULL);
9249 
9250  /* copy the original bounds back to the global and local bounds */
9251  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.lb) );
9252  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.ub) );
9253  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.lb) );
9254  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.ub) );
9255 
9256  /* free the global and local holelists and duplicate the original ones */
9257  /**@todo this has also to be called recursively with methods similar to SCIPvarChgLbGlobal() */
9258  holelistFree(&var->glbdom.holelist, blkmem);
9259  holelistFree(&var->locdom.holelist, blkmem);
9260  SCIP_CALL( holelistDuplicate(&var->glbdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
9261  SCIP_CALL( holelistDuplicate(&var->locdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
9262 
9263  return SCIP_OKAY;
9264 }
9265 
9266 /** issues a IMPLADDED event on the given variable */
9267 static
9269  SCIP_VAR* var, /**< problem variable to change */
9270  BMS_BLKMEM* blkmem, /**< block memory */
9271  SCIP_SET* set, /**< global SCIP settings */
9272  SCIP_EVENTQUEUE* eventqueue /**< event queue */
9273  )
9274 {
9275  SCIP_EVENT* event;
9276 
9277  assert(var != NULL);
9278 
9279  /* issue IMPLADDED event on variable */
9280  SCIP_CALL( SCIPeventCreateImplAdded(&event, blkmem, var) );
9281  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
9282 
9283  return SCIP_OKAY;
9284 }
9285 
9286 /** actually performs the addition of a variable bound to the variable's vbound arrays */
9287 static
9289  SCIP_VAR* var, /**< problem variable x in x <= b*z + d or x >= b*z + d */
9290  BMS_BLKMEM* blkmem, /**< block memory */
9291  SCIP_SET* set, /**< global SCIP settings */
9292  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9293  SCIP_BOUNDTYPE vbtype, /**< type of variable bound (LOWER or UPPER) */
9294  SCIP_VAR* vbvar, /**< variable z in x <= b*z + d or x >= b*z + d */
9295  SCIP_Real vbcoef, /**< coefficient b in x <= b*z + d or x >= b*z + d */
9296  SCIP_Real vbconstant /**< constant d in x <= b*z + d or x >= b*z + d */
9297  )
9298 {
9299  SCIP_Bool added;
9300 
9301  /* It can happen that the variable "var" and the variable "vbvar" are the same variable. For example if a variable
9302  * gets aggregated, the variable bounds (vbound) of that variable are copied to the other variable. A variable bound
9303  * variable of the aggregated variable might be the same as the one its gets aggregated too.
9304  *
9305  * If the variable "var" and the variable "vbvar" are the same, the variable bound which should be added here has to
9306  * be redundant. This is the case since an infeasibility should have be detected in the previous methods. As well as
9307  * the bounds of the variable which should be also already be tightened in the previous methods. Therefore, the
9308  * variable bound can be ignored.
9309  *
9310  * From the way the the variable bound system is implemented (detecting infeasibility, tighten bounds), the
9311  * equivalence of the variables should be checked here.
9312  */
9313  if( var == vbvar )
9314  {
9315  /* in this case the variable bound has to be redundant, this means for possible assignments to this variable; this
9316  * can be checked via the global bounds of the variable */
9317 #ifndef NDEBUG
9318  SCIP_Real lb;
9319  SCIP_Real ub;
9320 
9321  lb = SCIPvarGetLbGlobal(var);
9322  ub = SCIPvarGetUbGlobal(var);
9323 
9324  if(vbtype == SCIP_BOUNDTYPE_LOWER)
9325  {
9326  if( vbcoef > 0.0 )
9327  {
9328  assert(SCIPsetIsGE(set, lb, lb * vbcoef + vbconstant) );
9329  assert(SCIPsetIsGE(set, ub, ub * vbcoef + vbconstant) );
9330  }
9331  else
9332  {
9333  assert(SCIPsetIsGE(set, lb, ub * vbcoef + vbconstant) );
9334  assert(SCIPsetIsGE(set, ub, lb * vbcoef + vbconstant) );
9335  }
9336  }
9337  else
9338  {
9339  assert(vbtype == SCIP_BOUNDTYPE_UPPER);
9340  if( vbcoef > 0.0 )
9341  {
9342  assert(SCIPsetIsLE(set, lb, lb * vbcoef + vbconstant) );
9343  assert(SCIPsetIsLE(set, ub, ub * vbcoef + vbconstant) );
9344  }
9345  else
9346  {
9347  assert(SCIPsetIsLE(set, lb, ub * vbcoef + vbconstant) );
9348  assert(SCIPsetIsLE(set, ub, lb * vbcoef + vbconstant) );
9349  }
9350  }
9351 #endif
9352  SCIPsetDebugMsg(set, "redundant variable bound: <%s> %s %g<%s> %+g\n",
9353  SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
9354 
9355  return SCIP_OKAY;
9356  }
9357 
9358  SCIPsetDebugMsg(set, "adding variable bound: <%s> %s %g<%s> %+g\n",
9359  SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
9360 
9361  /* check variable bound on debugging solution */
9362  SCIP_CALL( SCIPdebugCheckVbound(set, var, vbtype, vbvar, vbcoef, vbconstant) ); /*lint !e506 !e774*/
9363 
9364  /* perform the addition */
9365  if( vbtype == SCIP_BOUNDTYPE_LOWER )
9366  {
9367  SCIP_CALL( SCIPvboundsAdd(&var->vlbs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
9368  }
9369  else
9370  {
9371  SCIP_CALL( SCIPvboundsAdd(&var->vubs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
9372  }
9373  var->closestvblpcount = -1;
9374 
9375  if( added )
9376  {
9377  /* issue IMPLADDED event */
9378  SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
9379  }
9380 
9381  return SCIP_OKAY;
9382 }
9383 
9384 /** checks whether the given implication is redundant or infeasible w.r.t. the implied variables global bounds */
9385 static
9386 void checkImplic(
9387  SCIP_SET* set, /**< global SCIP settings */
9388  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9389  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9390  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9391  SCIP_Bool* redundant, /**< pointer to store whether the implication is redundant */
9392  SCIP_Bool* infeasible /**< pointer to store whether the implication is infeasible */
9393  )
9394 {
9395  SCIP_Real impllb;
9396  SCIP_Real implub;
9397 
9398  assert(redundant != NULL);
9399  assert(infeasible != NULL);
9400 
9401  impllb = SCIPvarGetLbGlobal(implvar);
9402  implub = SCIPvarGetUbGlobal(implvar);
9403  if( impltype == SCIP_BOUNDTYPE_LOWER )
9404  {
9405  *infeasible = SCIPsetIsFeasGT(set, implbound, implub);
9406  *redundant = SCIPsetIsFeasLE(set, implbound, impllb);
9407  }
9408  else
9409  {
9410  *infeasible = SCIPsetIsFeasLT(set, implbound, impllb);
9411  *redundant = SCIPsetIsFeasGE(set, implbound, implub);
9412  }
9413 }
9414 
9415 /** applies the given implication, if it is not redundant */
9416 static
9418  BMS_BLKMEM* blkmem, /**< block memory */
9419  SCIP_SET* set, /**< global SCIP settings */
9420  SCIP_STAT* stat, /**< problem statistics */
9421  SCIP_PROB* transprob, /**< transformed problem */
9422  SCIP_PROB* origprob, /**< original problem */
9423  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9424  SCIP_REOPT* reopt, /**< reoptimization data structure */
9425  SCIP_LP* lp, /**< current LP data */
9426  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9427  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9428  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9429  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9430  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9431  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9432  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9433  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9434  )
9435 {
9436  SCIP_Real implub;
9437  SCIP_Real impllb;
9438 
9439  assert(infeasible != NULL);
9440 
9441  *infeasible = FALSE;
9442 
9443  implub = SCIPvarGetUbGlobal(implvar);
9444  impllb = SCIPvarGetLbGlobal(implvar);
9445  if( impltype == SCIP_BOUNDTYPE_LOWER )
9446  {
9447  if( SCIPsetIsFeasGT(set, implbound, implub) )
9448  {
9449  /* the implication produces a conflict: the problem is infeasible */
9450  *infeasible = TRUE;
9451  }
9452  else if( SCIPsetIsFeasGT(set, implbound, impllb) )
9453  {
9454  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9455  * with the local bound, in this case we need to store the bound change as pending bound change
9456  */
9457  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9458  {
9459  assert(tree != NULL);
9460  assert(transprob != NULL);
9461  assert(SCIPprobIsTransformed(transprob));
9462 
9463  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9464  tree, reopt, lp, branchcand, eventqueue, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
9465  }
9466  else
9467  {
9468  SCIP_CALL( SCIPvarChgLbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
9469  }
9470 
9471  if( nbdchgs != NULL )
9472  (*nbdchgs)++;
9473  }
9474  }
9475  else
9476  {
9477  if( SCIPsetIsFeasLT(set, implbound, impllb) )
9478  {
9479  /* the implication produces a conflict: the problem is infeasible */
9480  *infeasible = TRUE;
9481  }
9482  else if( SCIPsetIsFeasLT(set, implbound, implub) )
9483  {
9484  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9485  * with the local bound, in this case we need to store the bound change as pending bound change
9486  */
9487  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9488  {
9489  assert(tree != NULL);
9490  assert(transprob != NULL);
9491  assert(SCIPprobIsTransformed(transprob));
9492 
9493  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9494  tree, reopt, lp, branchcand, eventqueue, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
9495  }
9496  else
9497  {
9498  SCIP_CALL( SCIPvarChgUbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
9499  }
9500 
9501  if( nbdchgs != NULL )
9502  (*nbdchgs)++;
9503  }
9504  }
9505 
9506  return SCIP_OKAY;
9507 }
9508 
9509 /** actually performs the addition of an implication to the variable's implication arrays,
9510  * and adds the corresponding implication or variable bound to the implied variable;
9511  * if the implication is conflicting, the variable is fixed to the opposite value;
9512  * if the variable is already fixed to the given value, the implication is performed immediately;
9513  * if the implication is redundant with respect to the variables' global bounds, it is ignored
9514  */
9515 static
9517  SCIP_VAR* var, /**< problem variable */
9518  BMS_BLKMEM* blkmem, /**< block memory */
9519  SCIP_SET* set, /**< global SCIP settings */
9520  SCIP_STAT* stat, /**< problem statistics */
9521  SCIP_PROB* transprob, /**< transformed problem */
9522  SCIP_PROB* origprob, /**< original problem */
9523  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9524  SCIP_REOPT* reopt, /**< reoptimization data structure */
9525  SCIP_LP* lp, /**< current LP data */
9526  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9527  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9528  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9529  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9530  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9531  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9532  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9533  SCIP_Bool isshortcut, /**< is the implication a shortcut, i.e., added as part of the transitive closure of another implication? */
9534  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9535  int* nbdchgs, /**< pointer to count the number of performed bound changes, or NULL */
9536  SCIP_Bool* added /**< pointer to store whether an implication was added */
9537  )
9538 {
9539  SCIP_Bool redundant;
9540  SCIP_Bool conflict;
9541 
9542  assert(var != NULL);
9543  assert(SCIPvarIsActive(var));
9545  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
9546  assert(SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED);
9547  assert(infeasible != NULL);
9548  assert(added != NULL);
9549 
9550  /* check implication on debugging solution */
9551  SCIP_CALL( SCIPdebugCheckImplic(set, var, varfixing, implvar, impltype, implbound) ); /*lint !e506 !e774*/
9552 
9553  *infeasible = FALSE;
9554  *added = FALSE;
9555 
9556  /* check, if the implication is redundant or infeasible */
9557  checkImplic(set, implvar, impltype, implbound, &redundant, &conflict);
9558  assert(!redundant || !conflict);
9559  if( redundant )
9560  return SCIP_OKAY;
9561 
9562  if( var == implvar )
9563  {
9564  /* special cases appear were a bound to a variable implies itself to be outside the bounds:
9565  * x == varfixing => x < 0 or x > 1
9566  */
9567  if( SCIPsetIsLT(set, implbound, 0.0) || SCIPsetIsGT(set, implbound, 1.0) )
9568  conflict = TRUE;
9569  else
9570  {
9571  /* variable implies itself: x == varfixing => x == (impltype == SCIP_BOUNDTYPE_LOWER) */
9572  assert(SCIPsetIsZero(set, implbound) || SCIPsetIsEQ(set, implbound, 1.0));
9573  assert(SCIPsetIsZero(set, implbound) == (impltype == SCIP_BOUNDTYPE_UPPER));
9574  assert(SCIPsetIsEQ(set, implbound, 1.0) == (impltype == SCIP_BOUNDTYPE_LOWER));
9575  conflict = conflict || ((varfixing == TRUE) == (impltype == SCIP_BOUNDTYPE_UPPER));
9576  if( !conflict )
9577  return SCIP_OKAY;
9578  }
9579  }
9580 
9581  /* check, if the variable is already fixed */
9582  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
9583  {
9584  /* if the variable is fixed to the given value, perform the implication; otherwise, ignore the implication */
9585  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
9586  {
9587  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
9588  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
9589  }
9590  return SCIP_OKAY;
9591  }
9592 
9593  assert((impltype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, implbound, SCIPvarGetLbGlobal(implvar)))
9594  || (impltype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, implbound, SCIPvarGetUbGlobal(implvar))));
9595 
9596  if( !conflict )
9597  {
9598  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9599 
9600  if( SCIPvarIsBinary(implvar) )
9601  {
9602  SCIP_VAR* vars[2];
9603  SCIP_Bool vals[2];
9604 
9605  assert(SCIPsetIsFeasEQ(set, implbound, 1.0) || SCIPsetIsFeasZero(set, implbound));
9606  assert((impltype == SCIP_BOUNDTYPE_UPPER) == SCIPsetIsFeasZero(set, implbound));
9607 
9608  vars[0] = var;
9609  vars[1] = implvar;
9610  vals[0] = varfixing;
9611  vals[1] = (impltype == SCIP_BOUNDTYPE_UPPER);
9612 
9613  /* add the clique to the clique table */
9614  SCIP_CALL( SCIPcliquetableAdd(cliquetable, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
9615  eventqueue, vars, vals, 2, FALSE, &conflict, nbdchgs) );
9616 
9617  if( !conflict )
9618  return SCIP_OKAY;
9619  }
9620  else
9621  {
9622  /* add implication x == 0/1 -> y <= b / y >= b to the implications list of x */
9623  SCIPsetDebugMsg(set, "adding implication: <%s> == %u ==> <%s> %s %g\n",
9624  SCIPvarGetName(var), varfixing,
9625  SCIPvarGetName(implvar), impltype == SCIP_BOUNDTYPE_UPPER ? "<=" : ">=", implbound);
9626  SCIP_CALL( SCIPimplicsAdd(&var->implics, blkmem, set, stat, varfixing, implvar, impltype, implbound,
9627  isshortcut, &conflict, added) );
9628  }
9629  }
9630  assert(!conflict || !(*added));
9631 
9632  /* on conflict, fix the variable to the opposite value */
9633  if( conflict )
9634  {
9635  SCIPsetDebugMsg(set, " -> implication yields a conflict: fix <%s> == %d\n", SCIPvarGetName(var), !varfixing);
9636 
9637  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9638  * with the local bound, in this case we need to store the bound change as pending bound change
9639  */
9640  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9641  {
9642  assert(tree != NULL);
9643  assert(transprob != NULL);
9644  assert(SCIPprobIsTransformed(transprob));
9645 
9646  if( varfixing )
9647  {
9648  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9649  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
9650  }
9651  else
9652  {
9653  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9654  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
9655  }
9656  }
9657  else
9658  {
9659  if( varfixing )
9660  {
9661  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
9662  }
9663  else
9664  {
9665  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
9666  }
9667  }
9668  if( nbdchgs != NULL )
9669  (*nbdchgs)++;
9670 
9671  return SCIP_OKAY;
9672  }
9673  else if( *added )
9674  {
9675  /* issue IMPLADDED event */
9676  SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
9677  }
9678  else
9679  {
9680  /* the implication was redundant: the inverse is also redundant */
9681  return SCIP_OKAY;
9682  }
9683 
9684  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9685 
9686  /* check, whether implied variable is binary */
9687  if( !SCIPvarIsBinary(implvar) )
9688  {
9689  SCIP_Real lb;
9690  SCIP_Real ub;
9691 
9692  /* add inverse variable bound to the variable bounds of y with global bounds y \in [lb,ub]:
9693  * x == 0 -> y <= b <-> y <= (ub - b)*x + b
9694  * x == 1 -> y <= b <-> y <= (b - ub)*x + ub
9695  * x == 0 -> y >= b <-> y >= (lb - b)*x + b
9696  * x == 1 -> y >= b <-> y >= (b - lb)*x + lb
9697  * for numerical reasons, ignore variable bounds with large absolute coefficient
9698  */
9699  lb = SCIPvarGetLbGlobal(implvar);
9700  ub = SCIPvarGetUbGlobal(implvar);
9701  if( impltype == SCIP_BOUNDTYPE_UPPER )
9702  {
9703  if( REALABS(implbound - ub) <= MAXABSVBCOEF )
9704  {
9705  SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, var,
9706  varfixing ? implbound - ub : ub - implbound, varfixing ? ub : implbound) );
9707  }
9708  }
9709  else
9710  {
9711  if( REALABS(implbound - lb) <= MAXABSVBCOEF )
9712  {
9713  SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, var,
9714  varfixing ? implbound - lb : lb - implbound, varfixing ? lb : implbound) );
9715  }
9716  }
9717  }
9718 
9719  return SCIP_OKAY;
9720 }
9721 
9722 /** adds transitive closure for binary implication x = a -> y = b */
9723 static
9725  SCIP_VAR* var, /**< problem variable */
9726  BMS_BLKMEM* blkmem, /**< block memory */
9727  SCIP_SET* set, /**< global SCIP settings */
9728  SCIP_STAT* stat, /**< problem statistics */
9729  SCIP_PROB* transprob, /**< transformed problem */
9730  SCIP_PROB* origprob, /**< original problem */
9731  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9732  SCIP_REOPT* reopt, /**< reoptimization data structure */
9733  SCIP_LP* lp, /**< current LP data */
9734  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9735  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9736  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9737  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9738  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9739  SCIP_Bool implvarfixing, /**< fixing b in implication */
9740  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9741  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9742  )
9743 {
9744  SCIP_VAR** implvars;
9745  SCIP_BOUNDTYPE* impltypes;
9746  SCIP_Real* implbounds;
9747  int nimpls;
9748  int i;
9749 
9750  *infeasible = FALSE;
9751 
9752  /* binary variable: implications of implvar */
9753  nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
9754  implvars = SCIPimplicsGetVars(implvar->implics, implvarfixing);
9755  impltypes = SCIPimplicsGetTypes(implvar->implics, implvarfixing);
9756  implbounds = SCIPimplicsGetBounds(implvar->implics, implvarfixing);
9757 
9758  /* if variable has too many implications, the implication graph may become too dense */
9759  i = MIN(nimpls, MAXIMPLSCLOSURE) - 1;
9760 
9761  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9762  * implvars[i] is fixed, s.t. the implication y == varfixing -> z <= b / z >= b is deleted; this affects the
9763  * array over which we currently iterate; the only thing that can happen, is that elements of the array are
9764  * deleted; in this case, the subsequent elements are moved to the front; if we iterate from back to front, the
9765  * only thing that can happen is that we add the same implication twice - this does no harm
9766  */
9767  while ( i >= 0 && !(*infeasible) )
9768  {
9769  SCIP_Bool added;
9770 
9771  assert(implvars[i] != implvar);
9772 
9773  /* we have x == varfixing -> y == implvarfixing -> z <= b / z >= b:
9774  * add implication x == varfixing -> z <= b / z >= b to the implications list of x
9775  */
9776  if( SCIPvarIsActive(implvars[i]) )
9777  {
9778  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
9779  eventqueue, varfixing, implvars[i], impltypes[i], implbounds[i], TRUE, infeasible, nbdchgs, &added) );
9780  assert(SCIPimplicsGetNImpls(implvar->implics, implvarfixing) <= nimpls);
9781  nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
9782  i = MIN(i, nimpls); /* some elements from the array could have been removed */
9783  }
9784  --i;
9785  }
9786 
9787  return SCIP_OKAY;
9788 }
9789 
9790 /** adds given implication to the variable's implication list, and adds all implications directly implied by this
9791  * implication to the variable's implication list;
9792  * if the implication is conflicting, the variable is fixed to the opposite value;
9793  * if the variable is already fixed to the given value, the implication is performed immediately;
9794  * if the implication is redundant with respect to the variables' global bounds, it is ignored
9795  */
9796 static
9798  SCIP_VAR* var, /**< problem variable */
9799  BMS_BLKMEM* blkmem, /**< block memory */
9800  SCIP_SET* set, /**< global SCIP settings */
9801  SCIP_STAT* stat, /**< problem statistics */
9802  SCIP_PROB* transprob, /**< transformed problem */
9803  SCIP_PROB* origprob, /**< original problem */
9804  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9805  SCIP_REOPT* reopt, /**< reoptimization data structure */
9806  SCIP_LP* lp, /**< current LP data */
9807  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9808  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9809  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9810  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9811  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9812  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9813  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9814  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
9815  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9816  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9817  )
9818 {
9819  SCIP_Bool added;
9820 
9821  assert(var != NULL);
9822  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
9823  assert(SCIPvarIsActive(var));
9824  assert(implvar != NULL);
9825  assert(SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED);
9826  assert(infeasible != NULL);
9827 
9828  /* add implication x == varfixing -> y <= b / y >= b to the implications list of x */
9829  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
9830  eventqueue, varfixing, implvar, impltype, implbound, FALSE, infeasible, nbdchgs, &added) );
9831 
9832  if( *infeasible || var == implvar || !transitive || !added )
9833  return SCIP_OKAY;
9834 
9835  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9836 
9837  /* add transitive closure */
9838  if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
9839  {
9840  SCIP_Bool implvarfixing;
9841 
9842  implvarfixing = (impltype == SCIP_BOUNDTYPE_LOWER);
9843 
9844  /* binary variable: implications of implvar */
9845  SCIP_CALL( varAddTransitiveBinaryClosureImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9846  cliquetable, branchcand, eventqueue, varfixing, implvar, implvarfixing, infeasible, nbdchgs) );
9847 
9848  /* inverse implication */
9849  if( !(*infeasible) )
9850  {
9851  SCIP_CALL( varAddTransitiveBinaryClosureImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9852  cliquetable, branchcand, eventqueue, !implvarfixing, var, !varfixing, infeasible, nbdchgs) );
9853  }
9854  }
9855  else
9856  {
9857  /* non-binary variable: variable lower bounds of implvar */
9858  if( impltype == SCIP_BOUNDTYPE_UPPER && implvar->vlbs != NULL )
9859  {
9860  SCIP_VAR** vlbvars;
9861  SCIP_Real* vlbcoefs;
9862  SCIP_Real* vlbconstants;
9863  int nvlbvars;
9864  int i;
9865 
9866  nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
9867  vlbvars = SCIPvboundsGetVars(implvar->vlbs);
9868  vlbcoefs = SCIPvboundsGetCoefs(implvar->vlbs);
9869  vlbconstants = SCIPvboundsGetConstants(implvar->vlbs);
9870 
9871  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9872  * vlbvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
9873  * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
9874  * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
9875  * is that we add the same implication twice - this does no harm
9876  */
9877  i = nvlbvars-1;
9878  while ( i >= 0 && !(*infeasible) )
9879  {
9880  assert(vlbvars[i] != implvar);
9881  assert(!SCIPsetIsZero(set, vlbcoefs[i]));
9882 
9883  /* we have x == varfixing -> y <= b and y >= c*z + d:
9884  * c > 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
9885  * c < 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
9886  *
9887  * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
9888  * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
9889  * aggregation variable (the one which will stay active);
9890  *
9891  * W.l.o.g. we consider the variable upper bounds for now. Let "vubvar" be a variable upper bound of
9892  * the aggregated variable "aggvar"; During that copying of that variable upper bound variable
9893  * "vubvar" the variable lower and upper bounds of this variable "vubvar" are also considered; note
9894  * that the "aggvar" can be a variable lower bound variable of the variable "vubvar"; Due to that
9895  * situation it can happen that we reach that code place where "vlbvars[i] == aggvar". In particular
9896  * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
9897  * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
9898  * have to explicitly check that the active variable has not a variable status
9899  * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
9900  */
9901  if( SCIPvarIsActive(vlbvars[i]) && SCIPvarGetStatus(vlbvars[i]) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(vlbvars[i]) != SCIP_VARSTATUS_NEGATED )
9902  {
9903  SCIP_Real vbimplbound;
9904 
9905  vbimplbound = (implbound - vlbconstants[i])/vlbcoefs[i];
9906  if( vlbcoefs[i] >= 0.0 )
9907  {
9908  vbimplbound = adjustedUb(set, SCIPvarGetType(vlbvars[i]), vbimplbound);
9909  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9910  branchcand, eventqueue, varfixing, vlbvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
9911  infeasible, nbdchgs, &added) );
9912  }
9913  else
9914  {
9915  vbimplbound = adjustedLb(set, SCIPvarGetType(vlbvars[i]), vbimplbound);
9916  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9917  branchcand, eventqueue, varfixing, vlbvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
9918  infeasible, nbdchgs, &added) );
9919  }
9920  nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
9921  i = MIN(i, nvlbvars); /* some elements from the array could have been removed */
9922  }
9923  --i;
9924  }
9925  }
9926 
9927  /* non-binary variable: variable upper bounds of implvar */
9928  if( impltype == SCIP_BOUNDTYPE_LOWER && implvar->vubs != NULL )
9929  {
9930  SCIP_VAR** vubvars;
9931  SCIP_Real* vubcoefs;
9932  SCIP_Real* vubconstants;
9933  int nvubvars;
9934  int i;
9935 
9936  nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
9937  vubvars = SCIPvboundsGetVars(implvar->vubs);
9938  vubcoefs = SCIPvboundsGetCoefs(implvar->vubs);
9939  vubconstants = SCIPvboundsGetConstants(implvar->vubs);
9940 
9941  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9942  * vubvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
9943  * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
9944  * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
9945  * is that we add the same implication twice - this does no harm
9946  */
9947  i = nvubvars-1;
9948  while ( i >= 0 && !(*infeasible) )
9949  {
9950  assert(vubvars[i] != implvar);
9951  assert(!SCIPsetIsZero(set, vubcoefs[i]));
9952 
9953  /* we have x == varfixing -> y >= b and y <= c*z + d:
9954  * c > 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
9955  * c < 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
9956  *
9957  * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
9958  * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
9959  * aggregation variable (the one which will stay active);
9960  *
9961  * W.l.o.g. we consider the variable lower bounds for now. Let "vlbvar" be a variable lower bound of
9962  * the aggregated variable "aggvar"; During that copying of that variable lower bound variable
9963  * "vlbvar" the variable lower and upper bounds of this variable "vlbvar" are also considered; note
9964  * that the "aggvar" can be a variable upper bound variable of the variable "vlbvar"; Due to that
9965  * situation it can happen that we reach that code place where "vubvars[i] == aggvar". In particular
9966  * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
9967  * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
9968  * have to explicitly check that the active variable has not a variable status
9969  * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
9970  */
9971  if( SCIPvarIsActive(vubvars[i]) && SCIPvarGetStatus(vubvars[i]) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(vubvars[i]) != SCIP_VARSTATUS_NEGATED )
9972  {
9973  SCIP_Real vbimplbound;
9974 
9975  vbimplbound = (implbound - vubconstants[i])/vubcoefs[i];
9976  if( vubcoefs[i] >= 0.0 )
9977  {
9978  vbimplbound = adjustedLb(set, SCIPvarGetType(vubvars[i]), vbimplbound);
9979  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9980  branchcand, eventqueue, varfixing, vubvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
9981  infeasible, nbdchgs, &added) );
9982  }
9983  else
9984  {
9985  vbimplbound = adjustedUb(set, SCIPvarGetType(vubvars[i]), vbimplbound);
9986  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9987  branchcand, eventqueue, varfixing, vubvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
9988  infeasible, nbdchgs, &added) );
9989  }
9990  nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
9991  i = MIN(i, nvubvars); /* some elements from the array could have been removed */
9992  }
9993  --i;
9994  }
9995  }
9996  }
9997 
9998  return SCIP_OKAY;
9999 }
10000 
10001 /** informs variable x about a globally valid variable lower bound x >= b*z + d with integer variable z;
10002  * if z is binary, the corresponding valid implication for z is also added;
10003  * improves the global bounds of the variable and the vlb variable if possible
10004  */
10006  SCIP_VAR* var, /**< problem variable */
10007  BMS_BLKMEM* blkmem, /**< block memory */
10008  SCIP_SET* set, /**< global SCIP settings */
10009  SCIP_STAT* stat, /**< problem statistics */
10010  SCIP_PROB* transprob, /**< transformed problem */
10011  SCIP_PROB* origprob, /**< original problem */
10012  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10013  SCIP_REOPT* reopt, /**< reoptimization data structure */
10014  SCIP_LP* lp, /**< current LP data */
10015  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10016  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10017  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10018  SCIP_VAR* vlbvar, /**< variable z in x >= b*z + d */
10019  SCIP_Real vlbcoef, /**< coefficient b in x >= b*z + d */
10020  SCIP_Real vlbconstant, /**< constant d in x >= b*z + d */
10021  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
10022  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10023  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
10024  )
10025 {
10026  assert(var != NULL);
10027  assert(set != NULL);
10028  assert(var->scip == set->scip);
10029  assert(SCIPvarGetType(vlbvar) != SCIP_VARTYPE_CONTINUOUS);
10030  assert(infeasible != NULL);
10031 
10032  SCIPsetDebugMsg(set, "adding variable lower bound <%s> >= %g<%s> + %g\n", SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
10033 
10034  *infeasible = FALSE;
10035  if( nbdchgs != NULL )
10036  *nbdchgs = 0;
10037 
10038  switch( SCIPvarGetStatus(var) )
10039  {
10041  assert(var->data.original.transvar != NULL);
10042  SCIP_CALL( SCIPvarAddVlb(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10043  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef, vlbconstant, transitive, infeasible, nbdchgs) );
10044  break;
10045 
10046  case SCIP_VARSTATUS_COLUMN:
10047  case SCIP_VARSTATUS_LOOSE:
10048  case SCIP_VARSTATUS_FIXED:
10049  /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
10050  SCIP_CALL( SCIPvarGetProbvarSum(&vlbvar, set, &vlbcoef, &vlbconstant) );
10051  SCIPsetDebugMsg(set, " -> transformed to variable lower bound <%s> >= %g<%s> + %g\n", SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
10052 
10053  /* if the vlb coefficient is zero, just update the lower bound of the variable */
10054  if( SCIPsetIsZero(set, vlbcoef) )
10055  {
10056  if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetUbGlobal(var)) )
10057  *infeasible = TRUE;
10058  else if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetLbGlobal(var)) )
10059  {
10060  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10061  * with the local bound, in this case we need to store the bound change as pending bound change
10062  */
10063  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10064  {
10065  assert(tree != NULL);
10066  assert(transprob != NULL);
10067  assert(SCIPprobIsTransformed(transprob));
10068 
10069  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10070  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vlbconstant, SCIP_BOUNDTYPE_LOWER, FALSE) );
10071  }
10072  else
10073  {
10074  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vlbconstant) );
10075  }
10076 
10077  if( nbdchgs != NULL )
10078  (*nbdchgs)++;
10079  }
10080  }
10081  else if( var == vlbvar )
10082  {
10083  /* the variables cancels out, the variable bound constraint is either redundant or proves global infeasibility */
10084  if( SCIPsetIsEQ(set, vlbcoef, 1.0) )
10085  {
10086  if( SCIPsetIsPositive(set, vlbconstant) )
10087  *infeasible = TRUE;
10088  return SCIP_OKAY;
10089  }
10090  else
10091  {
10092  SCIP_Real lb = SCIPvarGetLbGlobal(var);
10093  SCIP_Real ub = SCIPvarGetUbGlobal(var);
10094 
10095  /* the variable bound constraint defines a new upper bound */
10096  if( SCIPsetIsGT(set, vlbcoef, 1.0) )
10097  {
10098  SCIP_Real newub = vlbconstant / (1.0 - vlbcoef);
10099 
10100  if( SCIPsetIsFeasLT(set, newub, lb) )
10101  {
10102  *infeasible = TRUE;
10103  return SCIP_OKAY;
10104  }
10105  else if( SCIPsetIsFeasLT(set, newub, ub) )
10106  {
10107  /* bound might be adjusted due to integrality condition */
10108  newub = adjustedUb(set, SCIPvarGetType(var), newub);
10109 
10110  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10111  * with the local bound, in this case we need to store the bound change as pending bound change
10112  */
10113  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10114  {
10115  assert(tree != NULL);
10116  assert(transprob != NULL);
10117  assert(SCIPprobIsTransformed(transprob));
10118 
10119  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10120  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10121  }
10122  else
10123  {
10124  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newub) );
10125  }
10126 
10127  if( nbdchgs != NULL )
10128  (*nbdchgs)++;
10129  }
10130  }
10131  /* the variable bound constraint defines a new lower bound */
10132  else
10133  {
10134  SCIP_Real newlb;
10135 
10136  assert(SCIPsetIsLT(set, vlbcoef, 1.0));
10137 
10138  newlb = vlbconstant / (1.0 - vlbcoef);
10139 
10140  if( SCIPsetIsFeasGT(set, newlb, ub) )
10141  {
10142  *infeasible = TRUE;
10143  return SCIP_OKAY;
10144  }
10145  else if( SCIPsetIsFeasGT(set, newlb, lb) )
10146  {
10147  /* bound might be adjusted due to integrality condition */
10148  newlb = adjustedLb(set, SCIPvarGetType(var), newlb);
10149 
10150  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10151  * with the local bound, in this case we need to store the bound change as pending bound change
10152  */
10153  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10154  {
10155  assert(tree != NULL);
10156  assert(transprob != NULL);
10157  assert(SCIPprobIsTransformed(transprob));
10158 
10159  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10160  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10161  }
10162  else
10163  {
10164  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newlb) );
10165  }
10166 
10167  if( nbdchgs != NULL )
10168  (*nbdchgs)++;
10169  }
10170  }
10171  }
10172  }
10173  else if( SCIPvarIsActive(vlbvar) )
10174  {
10175  SCIP_Real xlb;
10176  SCIP_Real xub;
10177  SCIP_Real zlb;
10178  SCIP_Real zub;
10179  SCIP_Real minvlb;
10180  SCIP_Real maxvlb;
10181 
10183  assert(vlbcoef != 0.0);
10184 
10185  minvlb = -SCIPsetInfinity(set);
10186  maxvlb = SCIPsetInfinity(set);
10187 
10188  xlb = SCIPvarGetLbGlobal(var);
10189  xub = SCIPvarGetUbGlobal(var);
10190  zlb = SCIPvarGetLbGlobal(vlbvar);
10191  zub = SCIPvarGetUbGlobal(vlbvar);
10192 
10193  /* improve global bounds of vlb variable, and calculate minimal and maximal value of variable bound */
10194  if( vlbcoef >= 0.0 )
10195  {
10196  SCIP_Real newzub;
10197 
10198  if( !SCIPsetIsInfinity(set, xub) )
10199  {
10200  /* x >= b*z + d -> z <= (x-d)/b */
10201  newzub = (xub - vlbconstant)/vlbcoef;
10202 
10203  /* return if the new bound is less than -infinity */
10204  if( SCIPsetIsInfinity(set, REALABS(newzub)) )
10205  return SCIP_OKAY;
10206 
10207  if( SCIPsetIsFeasLT(set, newzub, zlb) )
10208  {
10209  *infeasible = TRUE;
10210  return SCIP_OKAY;
10211  }
10212  if( SCIPsetIsFeasLT(set, newzub, zub) )
10213  {
10214  /* bound might be adjusted due to integrality condition */
10215  newzub = adjustedUb(set, SCIPvarGetType(vlbvar), newzub);
10216 
10217  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10218  * with the local bound, in this case we need to store the bound change as pending bound change
10219  */
10220  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10221  {
10222  assert(tree != NULL);
10223  assert(transprob != NULL);
10224  assert(SCIPprobIsTransformed(transprob));
10225 
10226  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10227  tree, reopt, lp, branchcand, eventqueue, cliquetable, vlbvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10228  }
10229  else
10230  {
10231  SCIP_CALL( SCIPvarChgUbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
10232  }
10233  zub = newzub;
10234 
10235  if( nbdchgs != NULL )
10236  (*nbdchgs)++;
10237  }
10238  maxvlb = vlbcoef * zub + vlbconstant;
10239  if( !SCIPsetIsInfinity(set, -zlb) )
10240  minvlb = vlbcoef * zlb + vlbconstant;
10241  }
10242  else
10243  {
10244  if( !SCIPsetIsInfinity(set, zub) )
10245  maxvlb = vlbcoef * zub + vlbconstant;
10246  if( !SCIPsetIsInfinity(set, -zlb) )
10247  minvlb = vlbcoef * zlb + vlbconstant;
10248  }
10249  }
10250  else
10251  {
10252  SCIP_Real newzlb;
10253 
10254  if( !SCIPsetIsInfinity(set, xub) )
10255  {
10256  /* x >= b*z + d -> z >= (x-d)/b */
10257  newzlb = (xub - vlbconstant)/vlbcoef;
10258 
10259  /* return if the new bound is larger than infinity */
10260  if( SCIPsetIsInfinity(set, REALABS(newzlb)) )
10261  return SCIP_OKAY;
10262 
10263  if( SCIPsetIsFeasGT(set, newzlb, zub) )
10264  {
10265  *infeasible = TRUE;
10266  return SCIP_OKAY;
10267  }
10268  if( SCIPsetIsFeasGT(set, newzlb, zlb) )
10269  {
10270  /* bound might be adjusted due to integrality condition */
10271  newzlb = adjustedLb(set, SCIPvarGetType(vlbvar), newzlb);
10272 
10273  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10274  * with the local bound, in this case we need to store the bound change as pending bound change
10275  */
10276  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10277  {
10278  assert(tree != NULL);
10279  assert(transprob != NULL);
10280  assert(SCIPprobIsTransformed(transprob));
10281 
10282  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10283  tree, reopt, lp, branchcand, eventqueue, cliquetable, vlbvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10284  }
10285  else
10286  {
10287  SCIP_CALL( SCIPvarChgLbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
10288  }
10289  zlb = newzlb;
10290 
10291  if( nbdchgs != NULL )
10292  (*nbdchgs)++;
10293  }
10294  maxvlb = vlbcoef * zlb + vlbconstant;
10295  if( !SCIPsetIsInfinity(set, zub) )
10296  minvlb = vlbcoef * zub + vlbconstant;
10297  }
10298  else
10299  {
10300  if( !SCIPsetIsInfinity(set, -zlb) )
10301  maxvlb = vlbcoef * zlb + vlbconstant;
10302  if( !SCIPsetIsInfinity(set, zub) )
10303  minvlb = vlbcoef * zub + vlbconstant;
10304  }
10305  }
10306  if( maxvlb < minvlb )
10307  maxvlb = minvlb;
10308 
10309  /* adjust bounds due to integrality of variable */
10310  minvlb = adjustedLb(set, SCIPvarGetType(var), minvlb);
10311  maxvlb = adjustedLb(set, SCIPvarGetType(var), maxvlb);
10312 
10313  /* check bounds for feasibility */
10314  if( SCIPsetIsFeasGT(set, minvlb, xub) || (var == vlbvar && SCIPsetIsEQ(set, vlbcoef, 1.0) && SCIPsetIsFeasPositive(set, vlbconstant)) )
10315  {
10316  *infeasible = TRUE;
10317  return SCIP_OKAY;
10318  }
10319  /* improve global lower bound of variable */
10320  if( SCIPsetIsFeasGT(set, minvlb, xlb) )
10321  {
10322  /* bound might be adjusted due to integrality condition */
10323  minvlb = adjustedLb(set, SCIPvarGetType(var), minvlb);
10324 
10325  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10326  * with the local bound, in this case we need to store the bound change as pending bound change
10327  */
10328  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10329  {
10330  assert(tree != NULL);
10331  assert(transprob != NULL);
10332  assert(SCIPprobIsTransformed(transprob));
10333 
10334  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10335  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, minvlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10336  }
10337  else
10338  {
10339  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, minvlb) );
10340  }
10341  xlb = minvlb;
10342 
10343  if( nbdchgs != NULL )
10344  (*nbdchgs)++;
10345  }
10346  minvlb = xlb;
10347 
10348  /* improve variable bound for binary z by moving the variable's global bound to the vlb constant */
10349  if( SCIPvarGetType(vlbvar) == SCIP_VARTYPE_BINARY )
10350  {
10351  /* b > 0: x >= (maxvlb - minvlb) * z + minvlb
10352  * b < 0: x >= (minvlb - maxvlb) * z + maxvlb
10353  */
10354 
10355  assert(!SCIPsetIsInfinity(set, maxvlb) && !SCIPsetIsInfinity(set, -minvlb));
10356 
10357  if( vlbcoef >= 0.0 )
10358  {
10359  vlbcoef = maxvlb - minvlb;
10360  vlbconstant = minvlb;
10361  }
10362  else
10363  {
10364  vlbcoef = minvlb - maxvlb;
10365  vlbconstant = maxvlb;
10366  }
10367  }
10368 
10369  /* add variable bound to the variable bounds list */
10370  if( SCIPsetIsFeasGT(set, maxvlb, xlb) )
10371  {
10372  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED);
10373  assert(!SCIPsetIsZero(set, vlbcoef));
10374 
10375  /* if one of the variables is binary, add the corresponding implication to the variable's implication
10376  * list, thereby also adding the variable bound (or implication) to the other variable
10377  */
10378  if( SCIPvarGetType(vlbvar) == SCIP_VARTYPE_BINARY )
10379  {
10380  /* add corresponding implication:
10381  * b > 0, x >= b*z + d <-> z == 1 -> x >= b+d
10382  * b < 0, x >= b*z + d <-> z == 0 -> x >= d
10383  */
10384  SCIP_CALL( varAddTransitiveImplic(vlbvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10385  cliquetable, branchcand, eventqueue, (vlbcoef >= 0.0), var, SCIP_BOUNDTYPE_LOWER, maxvlb, transitive,
10386  infeasible, nbdchgs) );
10387  }
10388  else if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
10389  {
10390  /* add corresponding implication:
10391  * b > 0, x >= b*z + d <-> x == 0 -> z <= -d/b
10392  * b < 0, x >= b*z + d <-> x == 0 -> z >= -d/b
10393  */
10394  SCIP_Real implbound;
10395  implbound = -vlbconstant/vlbcoef;
10396 
10397  /* tighten the implication bound if the variable is integer */
10398  if( SCIPvarIsIntegral(vlbvar) )
10399  {
10400  if( vlbcoef >= 0 )
10401  implbound = SCIPsetFloor(set, implbound);
10402  else
10403  implbound = SCIPsetCeil(set, implbound);
10404  }
10405  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10406  cliquetable, branchcand, eventqueue, FALSE, vlbvar, (vlbcoef >= 0.0 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER),
10407  implbound, transitive, infeasible, nbdchgs) );
10408  }
10409  else
10410  {
10411  SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, vlbvar, vlbcoef, vlbconstant) );
10412  }
10413  }
10414  }
10415  break;
10416 
10418  /* x = a*y + c: x >= b*z + d <=> a*y + c >= b*z + d <=> y >= b/a * z + (d-c)/a, if a > 0
10419  * y <= b/a * z + (d-c)/a, if a < 0
10420  */
10421  assert(var->data.aggregate.var != NULL);
10422  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
10423  {
10424  /* a > 0 -> add variable lower bound */
10425  SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10426  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef/var->data.aggregate.scalar,
10427  (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10428  }
10429  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
10430  {
10431  /* a < 0 -> add variable upper bound */
10432  SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10433  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef/var->data.aggregate.scalar,
10434  (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10435  }
10436  else
10437  {
10438  SCIPerrorMessage("scalar is zero in aggregation\n");
10439  return SCIP_INVALIDDATA;
10440  }
10441  break;
10442 
10444  /* nothing to do here */
10445  break;
10446 
10448  /* x = offset - x': x >= b*z + d <=> offset - x' >= b*z + d <=> x' <= -b*z + (offset-d) */
10449  assert(var->negatedvar != NULL);
10451  assert(var->negatedvar->negatedvar == var);
10452  SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10453  branchcand, eventqueue, vlbvar, -vlbcoef, var->data.negate.constant - vlbconstant, transitive, infeasible,
10454  nbdchgs) );
10455  break;
10456 
10457  default:
10458  SCIPerrorMessage("unknown variable status\n");
10459  return SCIP_INVALIDDATA;
10460  }
10461 
10462  return SCIP_OKAY;
10463 }
10464 
10465 /** informs variable x about a globally valid variable upper bound x <= b*z + d with integer variable z;
10466  * if z is binary, the corresponding valid implication for z is also added;
10467  * updates the global bounds of the variable and the vub variable correspondingly
10468  */
10470  SCIP_VAR* var, /**< problem variable */
10471  BMS_BLKMEM* blkmem, /**< block memory */
10472  SCIP_SET* set, /**< global SCIP settings */
10473  SCIP_STAT* stat, /**< problem statistics */
10474  SCIP_PROB* transprob, /**< transformed problem */
10475  SCIP_PROB* origprob, /**< original problem */
10476  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10477  SCIP_REOPT* reopt, /**< reoptimization data structure */
10478  SCIP_LP* lp, /**< current LP data */
10479  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10480  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10481  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10482  SCIP_VAR* vubvar, /**< variable z in x <= b*z + d */
10483  SCIP_Real vubcoef, /**< coefficient b in x <= b*z + d */
10484  SCIP_Real vubconstant, /**< constant d in x <= b*z + d */
10485  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
10486  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10487  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
10488  )
10489 {
10490  assert(var != NULL);
10491  assert(set != NULL);
10492  assert(var->scip == set->scip);
10493  assert(SCIPvarGetType(vubvar) != SCIP_VARTYPE_CONTINUOUS);
10494  assert(infeasible != NULL);
10495 
10496  SCIPsetDebugMsg(set, "adding variable upper bound <%s> <= %g<%s> + %g\n", SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
10497 
10498  *infeasible = FALSE;
10499  if( nbdchgs != NULL )
10500  *nbdchgs = 0;
10501 
10502  switch( SCIPvarGetStatus(var) )
10503  {
10505  assert(var->data.original.transvar != NULL);
10506  SCIP_CALL( SCIPvarAddVub(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10507  cliquetable, branchcand, eventqueue, vubvar, vubcoef, vubconstant, transitive, infeasible, nbdchgs) );
10508  break;
10509 
10510  case SCIP_VARSTATUS_COLUMN:
10511  case SCIP_VARSTATUS_LOOSE:
10512  case SCIP_VARSTATUS_FIXED:
10513  /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
10514  SCIP_CALL( SCIPvarGetProbvarSum(&vubvar, set, &vubcoef, &vubconstant) );
10515  SCIPsetDebugMsg(set, " -> transformed to variable upper bound <%s> <= %g<%s> + %g\n",
10516  SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
10517 
10518  /* if the vub coefficient is zero, just update the upper bound of the variable */
10519  if( SCIPsetIsZero(set, vubcoef) )
10520  {
10521  if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetLbGlobal(var)) )
10522  *infeasible = TRUE;
10523  else if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetUbGlobal(var)) )
10524  {
10525  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10526  * with the local bound, in this case we need to store the bound change as pending bound change
10527  */
10528  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10529  {
10530  assert(tree != NULL);
10531  assert(transprob != NULL);
10532  assert(SCIPprobIsTransformed(transprob));
10533 
10534  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10535  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vubconstant, SCIP_BOUNDTYPE_UPPER, FALSE) );
10536  }
10537  else
10538  {
10539  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vubconstant) );
10540  }
10541 
10542  if( nbdchgs != NULL )
10543  (*nbdchgs)++;
10544  }
10545  }
10546  else if( var == vubvar )
10547  {
10548  /* the variables cancels out, the variable bound constraint is either redundant or proves global infeasibility */
10549  if( SCIPsetIsEQ(set, vubcoef, 1.0) )
10550  {
10551  if( SCIPsetIsNegative(set, vubconstant) )
10552  *infeasible = TRUE;
10553  return SCIP_OKAY;
10554  }
10555  else
10556  {
10557  SCIP_Real lb = SCIPvarGetLbGlobal(var);
10558  SCIP_Real ub = SCIPvarGetUbGlobal(var);
10559 
10560  /* the variable bound constraint defines a new lower bound */
10561  if( SCIPsetIsGT(set, vubcoef, 1.0) )
10562  {
10563  SCIP_Real newlb = vubconstant / (1.0 - vubcoef);
10564 
10565  if( SCIPsetIsFeasGT(set, newlb, ub) )
10566  {
10567  *infeasible = TRUE;
10568  return SCIP_OKAY;
10569  }
10570  else if( SCIPsetIsFeasGT(set, newlb, lb) )
10571  {
10572  /* bound might be adjusted due to integrality condition */
10573  newlb = adjustedLb(set, SCIPvarGetType(var), newlb);
10574 
10575  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10576  * with the local bound, in this case we need to store the bound change as pending bound change
10577  */
10578  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10579  {
10580  assert(tree != NULL);
10581  assert(transprob != NULL);
10582  assert(SCIPprobIsTransformed(transprob));
10583 
10584  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10585  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10586  }
10587  else
10588  {
10589  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newlb) );
10590  }
10591 
10592  if( nbdchgs != NULL )
10593  (*nbdchgs)++;
10594  }
10595  }
10596  /* the variable bound constraint defines a new upper bound */
10597  else
10598  {
10599  SCIP_Real newub;
10600 
10601  assert(SCIPsetIsLT(set, vubcoef, 1.0));
10602 
10603  newub = vubconstant / (1.0 - vubcoef);
10604 
10605  if( SCIPsetIsFeasLT(set, newub, lb) )
10606  {
10607  *infeasible = TRUE;
10608  return SCIP_OKAY;
10609  }
10610  else if( SCIPsetIsFeasLT(set, newub, ub) )
10611  {
10612  /* bound might be adjusted due to integrality condition */
10613  newub = adjustedUb(set, SCIPvarGetType(var), newub);
10614 
10615  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10616  * with the local bound, in this case we need to store the bound change as pending bound change
10617  */
10618  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10619  {
10620  assert(tree != NULL);
10621  assert(transprob != NULL);
10622  assert(SCIPprobIsTransformed(transprob));
10623 
10624  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10625  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10626  }
10627  else
10628  {
10629  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newub) );
10630  }
10631 
10632  if( nbdchgs != NULL )
10633  (*nbdchgs)++;
10634  }
10635  }
10636  }
10637  }
10638  else if( SCIPvarIsActive(vubvar) )
10639  {
10640  SCIP_Real xlb;
10641  SCIP_Real xub;
10642  SCIP_Real zlb;
10643  SCIP_Real zub;
10644  SCIP_Real minvub;
10645  SCIP_Real maxvub;
10646 
10648  assert(vubcoef != 0.0);
10649 
10650  minvub = -SCIPsetInfinity(set);
10651  maxvub = SCIPsetInfinity(set);
10652 
10653  xlb = SCIPvarGetLbGlobal(var);
10654  xub = SCIPvarGetUbGlobal(var);
10655  zlb = SCIPvarGetLbGlobal(vubvar);
10656  zub = SCIPvarGetUbGlobal(vubvar);
10657 
10658  /* improve global bounds of vub variable, and calculate minimal and maximal value of variable bound */
10659  if( vubcoef >= 0.0 )
10660  {
10661  SCIP_Real newzlb;
10662 
10663  if( !SCIPsetIsInfinity(set, -xlb) )
10664  {
10665  /* x <= b*z + d -> z >= (x-d)/b */
10666  newzlb = (xlb - vubconstant)/vubcoef;
10667  if( SCIPsetIsFeasGT(set, newzlb, zub) )
10668  {
10669  *infeasible = TRUE;
10670  return SCIP_OKAY;
10671  }
10672  if( SCIPsetIsFeasGT(set, newzlb, zlb) )
10673  {
10674  /* bound might be adjusted due to integrality condition */
10675  newzlb = adjustedLb(set, SCIPvarGetType(vubvar), newzlb);
10676 
10677  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10678  * with the local bound, in this case we need to store the bound change as pending bound change
10679  */
10680  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10681  {
10682  assert(tree != NULL);
10683  assert(transprob != NULL);
10684  assert(SCIPprobIsTransformed(transprob));
10685 
10686  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10687  tree, reopt, lp, branchcand, eventqueue, cliquetable, vubvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10688  }
10689  else
10690  {
10691  SCIP_CALL( SCIPvarChgLbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
10692  }
10693  zlb = newzlb;
10694 
10695  if( nbdchgs != NULL )
10696  (*nbdchgs)++;
10697  }
10698  minvub = vubcoef * zlb + vubconstant;
10699  if( !SCIPsetIsInfinity(set, zub) )
10700  maxvub = vubcoef * zub + vubconstant;
10701  }
10702  else
10703  {
10704  if( !SCIPsetIsInfinity(set, zub) )
10705  maxvub = vubcoef * zub + vubconstant;
10706  if( !SCIPsetIsInfinity(set, -zlb) )
10707  minvub = vubcoef * zlb + vubconstant;
10708  }
10709  }
10710  else
10711  {
10712  SCIP_Real newzub;
10713 
10714  if( !SCIPsetIsInfinity(set, -xlb) )
10715  {
10716  /* x <= b*z + d -> z <= (x-d)/b */
10717  newzub = (xlb - vubconstant)/vubcoef;
10718  if( SCIPsetIsFeasLT(set, newzub, zlb) )
10719  {
10720  *infeasible = TRUE;
10721  return SCIP_OKAY;
10722  }
10723  if( SCIPsetIsFeasLT(set, newzub, zub) )
10724  {
10725  /* bound might be adjusted due to integrality condition */
10726  newzub = adjustedUb(set, SCIPvarGetType(vubvar), newzub);
10727 
10728  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10729  * with the local bound, in this case we need to store the bound change as pending bound change
10730  */
10731  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10732  {
10733  assert(tree != NULL);
10734  assert(transprob != NULL);
10735  assert(SCIPprobIsTransformed(transprob));
10736 
10737  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10738  tree, reopt, lp, branchcand, eventqueue, cliquetable, vubvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10739  }
10740  else
10741  {
10742  SCIP_CALL( SCIPvarChgUbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
10743  }
10744  zub = newzub;
10745 
10746  if( nbdchgs != NULL )
10747  (*nbdchgs)++;
10748  }
10749  minvub = vubcoef * zub + vubconstant;
10750  if( !SCIPsetIsInfinity(set, -zlb) )
10751  maxvub = vubcoef * zlb + vubconstant;
10752  }
10753  else
10754  {
10755  if( !SCIPsetIsInfinity(set, zub) )
10756  minvub = vubcoef * zub + vubconstant;
10757  if( !SCIPsetIsInfinity(set, -zlb) )
10758  maxvub = vubcoef * zlb + vubconstant;
10759  }
10760  }
10761  if( minvub > maxvub )
10762  minvub = maxvub;
10763 
10764  /* adjust bounds due to integrality of vub variable */
10765  minvub = adjustedUb(set, SCIPvarGetType(var), minvub);
10766  maxvub = adjustedUb(set, SCIPvarGetType(var), maxvub);
10767 
10768  /* check bounds for feasibility */
10769  if( SCIPsetIsFeasLT(set, maxvub, xlb) || (var == vubvar && SCIPsetIsEQ(set, vubcoef, 1.0) && SCIPsetIsFeasNegative(set, vubconstant)) )
10770  {
10771  *infeasible = TRUE;
10772  return SCIP_OKAY;
10773  }
10774 
10775  /* improve global upper bound of variable */
10776  if( SCIPsetIsFeasLT(set, maxvub, xub) )
10777  {
10778  /* bound might be adjusted due to integrality condition */
10779  maxvub = adjustedUb(set, SCIPvarGetType(var), maxvub);
10780 
10781  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10782  * with the local bound, in this case we need to store the bound change as pending bound change
10783  */
10784  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10785  {
10786  assert(tree != NULL);
10787  assert(transprob != NULL);
10788  assert(SCIPprobIsTransformed(transprob));
10789 
10790  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10791  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, maxvub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10792  }
10793  else
10794  {
10795  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, maxvub) );
10796  }
10797  xub = maxvub;
10798 
10799  if( nbdchgs != NULL )
10800  (*nbdchgs)++;
10801  }
10802  maxvub = xub;
10803 
10804  /* improve variable bound for binary z by moving the variable's global bound to the vub constant */
10805  if( SCIPvarIsBinary(vubvar) )
10806  {
10807  /* b > 0: x <= (maxvub - minvub) * z + minvub
10808  * b < 0: x <= (minvub - maxvub) * z + maxvub
10809  */
10810 
10811  assert(!SCIPsetIsInfinity(set, maxvub) && !SCIPsetIsInfinity(set, -minvub));
10812 
10813  if( vubcoef >= 0.0 )
10814  {
10815  vubcoef = maxvub - minvub;
10816  vubconstant = minvub;
10817  }
10818  else
10819  {
10820  vubcoef = minvub - maxvub;
10821  vubconstant = maxvub;
10822  }
10823  }
10824 
10825  /* add variable bound to the variable bounds list */
10826  if( SCIPsetIsFeasLT(set, minvub, xub) )
10827  {
10828  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED);
10829  assert(!SCIPsetIsZero(set, vubcoef));
10830 
10831  /* if one of the variables is binary, add the corresponding implication to the variable's implication
10832  * list, thereby also adding the variable bound (or implication) to the other variable
10833  */
10834  if( SCIPvarGetType(vubvar) == SCIP_VARTYPE_BINARY )
10835  {
10836  /* add corresponding implication:
10837  * b > 0, x <= b*z + d <-> z == 0 -> x <= d
10838  * b < 0, x <= b*z + d <-> z == 1 -> x <= b+d
10839  */
10840  SCIP_CALL( varAddTransitiveImplic(vubvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10841  cliquetable, branchcand, eventqueue, (vubcoef < 0.0), var, SCIP_BOUNDTYPE_UPPER, minvub, transitive,
10842  infeasible, nbdchgs) );
10843  }
10844  else if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
10845  {
10846  /* add corresponding implication:
10847  * b > 0, x <= b*z + d <-> x == 1 -> z >= (1-d)/b
10848  * b < 0, x <= b*z + d <-> x == 1 -> z <= (1-d)/b
10849  */
10850  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10851  cliquetable, branchcand, eventqueue, TRUE, vubvar, (vubcoef >= 0.0 ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER),
10852  (1.0-vubconstant)/vubcoef, transitive, infeasible, nbdchgs) );
10853  }
10854  else
10855  {
10856  SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, vubvar, vubcoef, vubconstant) );
10857  }
10858  }
10859  }
10860  break;
10861 
10863  /* x = a*y + c: x <= b*z + d <=> a*y + c <= b*z + d <=> y <= b/a * z + (d-c)/a, if a > 0
10864  * y >= b/a * z + (d-c)/a, if a < 0
10865  */
10866  assert(var->data.aggregate.var != NULL);
10867  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
10868  {
10869  /* a > 0 -> add variable upper bound */
10870  SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10871  cliquetable, branchcand, eventqueue, vubvar, vubcoef/var->data.aggregate.scalar,
10872  (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10873  }
10874  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
10875  {
10876  /* a < 0 -> add variable lower bound */
10877  SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10878  cliquetable, branchcand, eventqueue, vubvar, vubcoef/var->data.aggregate.scalar,
10879  (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10880  }
10881  else
10882  {
10883  SCIPerrorMessage("scalar is zero in aggregation\n");
10884  return SCIP_INVALIDDATA;
10885  }
10886  break;
10887 
10889  /* nothing to do here */
10890  break;
10891 
10893  /* x = offset - x': x <= b*z + d <=> offset - x' <= b*z + d <=> x' >= -b*z + (offset-d) */
10894  assert(var->negatedvar != NULL);
10896  assert(var->negatedvar->negatedvar == var);
10897  SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10898  branchcand, eventqueue, vubvar, -vubcoef, var->data.negate.constant - vubconstant, transitive, infeasible,
10899  nbdchgs) );
10900  break;
10901 
10902  default:
10903  SCIPerrorMessage("unknown variable status\n");
10904  return SCIP_INVALIDDATA;
10905  }
10906 
10907  return SCIP_OKAY;
10908 }
10909 
10910 /** informs binary variable x about a globally valid implication: x == 0 or x == 1 ==> y <= b or y >= b;
10911  * also adds the corresponding implication or variable bound to the implied variable;
10912  * if the implication is conflicting, the variable is fixed to the opposite value;
10913  * if the variable is already fixed to the given value, the implication is performed immediately;
10914  * if the implication is redundant with respect to the variables' global bounds, it is ignored
10915  */
10917  SCIP_VAR* var, /**< problem variable */
10918  BMS_BLKMEM* blkmem, /**< block memory */
10919  SCIP_SET* set, /**< global SCIP settings */
10920  SCIP_STAT* stat, /**< problem statistics */
10921  SCIP_PROB* transprob, /**< transformed problem */
10922  SCIP_PROB* origprob, /**< original problem */
10923  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10924  SCIP_REOPT* reopt, /**< reoptimization data structure */
10925  SCIP_LP* lp, /**< current LP data */
10926  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10927  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10928  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10929  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
10930  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
10931  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
10932  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
10933  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
10934  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10935  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
10936  )
10937 {
10938  assert(var != NULL);
10939  assert(set != NULL);
10940  assert(var->scip == set->scip);
10941  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
10942  assert(infeasible != NULL);
10943 
10944  *infeasible = FALSE;
10945  if( nbdchgs != NULL )
10946  *nbdchgs = 0;
10947 
10948  switch( SCIPvarGetStatus(var) )
10949  {
10951  assert(var->data.original.transvar != NULL);
10952  SCIP_CALL( SCIPvarAddImplic(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10953  cliquetable, branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible,
10954  nbdchgs) );
10955  break;
10956 
10957  case SCIP_VARSTATUS_COLUMN:
10958  case SCIP_VARSTATUS_LOOSE:
10959  /* if the variable is fixed (although it has no FIXED status), and varfixing corresponds to the fixed value of
10960  * the variable, the implication can be applied directly;
10961  * otherwise, add implication to the implications list (and add inverse of implication to the implied variable)
10962  */
10963  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
10964  {
10965  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
10966  {
10967  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
10968  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
10969  }
10970  }
10971  else
10972  {
10973  SCIP_CALL( SCIPvarGetProbvarBound(&implvar, &implbound, &impltype) );
10974  SCIPvarAdjustBd(implvar, set, impltype, &implbound);
10975  if( SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED )
10976  {
10977  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10978  branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
10979  }
10980  }
10981  break;
10982 
10983  case SCIP_VARSTATUS_FIXED:
10984  /* if varfixing corresponds to the fixed value of the variable, the implication can be applied directly */
10985  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
10986  {
10987  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
10988  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
10989  }
10990  break;
10991 
10993  /* implication added for x == 1:
10994  * x == 1 && x = 1*z + 0 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10995  * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10996  * implication added for x == 0:
10997  * x == 0 && x = 1*z + 0 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10998  * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10999  *
11000  * use only binary variables z
11001  */
11002  assert(var->data.aggregate.var != NULL);
11003  if( SCIPvarIsBinary(var->data.aggregate.var) )
11004  {
11005  assert( (SCIPsetIsEQ(set, var->data.aggregate.scalar, 1.0) && SCIPsetIsZero(set, var->data.aggregate.constant))
11006  || (SCIPsetIsEQ(set, var->data.aggregate.scalar, -1.0) && SCIPsetIsEQ(set, var->data.aggregate.constant, 1.0)) );
11007 
11008  if( var->data.aggregate.scalar > 0 )
11009  {
11010  SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11011  cliquetable, branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible,
11012  nbdchgs) );
11013  }
11014  else
11015  {
11016  SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11017  cliquetable, branchcand, eventqueue, !varfixing, implvar, impltype, implbound, transitive, infeasible,
11018  nbdchgs) );
11019  }
11020  }
11021  break;
11022 
11024  /* nothing to do here */
11025  break;
11026 
11028  /* implication added for x == 1:
11029  * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
11030  * implication added for x == 0:
11031  * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
11032  */
11033  assert(var->negatedvar != NULL);
11035  assert(var->negatedvar->negatedvar == var);
11036  assert(SCIPvarIsBinary(var->negatedvar));
11037 
11039  {
11040  SCIP_CALL( SCIPvarAddImplic(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11041  cliquetable, branchcand, eventqueue, !varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
11042  }
11043  /* in case one both variables are not of binary type we have to add the implication as variable bounds */
11044  else
11045  {
11046  /* if the implied variable is of binary type exchange the variables */
11047  if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
11048  {
11049  SCIP_CALL( SCIPvarAddImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
11050  branchcand, eventqueue, (impltype == SCIP_BOUNDTYPE_UPPER) ? TRUE : FALSE, var->negatedvar,
11051  varfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER, varfixing ? 1.0 : 0.0, transitive,
11052  infeasible, nbdchgs) );
11053  }
11054  else
11055  {
11056  /* both variables are not of binary type but are implicit binary; in that case we can only add this
11057  * implication as variable bounds
11058  */
11059 
11060  /* add variable lower bound on the negation of var */
11061  if( varfixing )
11062  {
11063  /* (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
11064  * as variable lower bound
11065  */
11066  SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11067  cliquetable, branchcand, eventqueue, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : -1.0,
11068  (impltype == SCIP_BOUNDTYPE_UPPER) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
11069  }
11070  else
11071  {
11072  /* (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
11073  * as variable upper bound
11074  */
11075  SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11076  cliquetable, branchcand, eventqueue, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? -1.0 : 1.0,
11077  (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : 0.0, transitive, infeasible, nbdchgs) );
11078  }
11079 
11080  /* add variable bound on implvar */
11081  if( impltype == SCIP_BOUNDTYPE_UPPER )
11082  {
11083  /* (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
11084  * as variable upper bound
11085  */
11086  SCIP_CALL( SCIPvarAddVub(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
11087  branchcand, eventqueue, var->negatedvar, (varfixing) ? 1.0 : -1.0,
11088  (varfixing) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
11089  }
11090  else
11091  {
11092  /* (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
11093  * as variable upper bound
11094  */
11095  SCIP_CALL( SCIPvarAddVlb(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
11096  branchcand, eventqueue, var->negatedvar, (varfixing) ? -1.0 : 1.0, (varfixing) ? 1.0 : 0.0,
11097  transitive, infeasible, nbdchgs) );
11098  }
11099  }
11100  }
11101  break;
11102 
11103  default:
11104  SCIPerrorMessage("unknown variable status\n");
11105  return SCIP_INVALIDDATA;
11106  }
11107 
11108  return SCIP_OKAY;
11109 }
11110 
11111 /** returns whether there is an implication x == varfixing -> y <= b or y >= b in the implication graph;
11112  * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
11113  * both variables must be active, variable x must be binary
11114  */
11116  SCIP_VAR* var, /**< problem variable x */
11117  SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
11118  SCIP_VAR* implvar, /**< variable y to search for */
11119  SCIP_BOUNDTYPE impltype /**< type of implication y <=/>= b to search for */
11120  )
11121 {
11122  assert(var != NULL);
11123  assert(implvar != NULL);
11124  assert(SCIPvarIsActive(var));
11125  assert(SCIPvarIsActive(implvar));
11126  assert(SCIPvarIsBinary(var));
11127 
11128  return var->implics != NULL && SCIPimplicsContainsImpl(var->implics, varfixing, implvar, impltype);
11129 }
11130 
11131 /** returns whether there is an implication x == varfixing -> y == implvarfixing in the implication graph;
11132  * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
11133  * both variables must be active binary variables
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_Bool implvarfixing /**< value of the implied variable to search for */
11140  )
11141 {
11142  assert(SCIPvarIsBinary(implvar));
11143 
11144  return SCIPvarHasImplic(var, varfixing, implvar, implvarfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER);
11145 }
11146 
11147 /** gets the values of b in implications x == varfixing -> y <= b or y >= b in the implication graph;
11148  * the values are set to SCIP_INVALID if there is no implied bound
11149  */
11151  SCIP_VAR* var, /**< problem variable x */
11152  SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
11153  SCIP_VAR* implvar, /**< variable y to search for */
11154  SCIP_Real* lb, /**< buffer to store the value of the implied lower bound */
11155  SCIP_Real* ub /**< buffer to store the value of the implied upper bound */
11156  )
11157 {
11158  int lowerpos;
11159  int upperpos;
11160  SCIP_Real* bounds;
11161 
11162  assert(lb != NULL);
11163  assert(ub != NULL);
11164 
11165  *lb = SCIP_INVALID;
11166  *ub = SCIP_INVALID;
11167 
11168  if( var->implics == NULL )
11169  return;
11170 
11171  SCIPimplicsGetVarImplicPoss(var->implics, varfixing, implvar, &lowerpos, &upperpos);
11172  bounds = SCIPvarGetImplBounds(var, varfixing);
11173 
11174  if( bounds == NULL )
11175  return;
11176 
11177  if( lowerpos >= 0 )
11178  *lb = bounds[lowerpos];
11179 
11180  if( upperpos >= 0 )
11181  *ub = bounds[upperpos];
11182 }
11183 
11184 
11185 /** fixes the bounds of a binary variable to the given value, counting bound changes and detecting infeasibility */
11187  SCIP_VAR* var, /**< problem variable */
11188  BMS_BLKMEM* blkmem, /**< block memory */
11189  SCIP_SET* set, /**< global SCIP settings */
11190  SCIP_STAT* stat, /**< problem statistics */
11191  SCIP_PROB* transprob, /**< transformed problem */
11192  SCIP_PROB* origprob, /**< original problem */
11193  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
11194  SCIP_REOPT* reopt, /**< reoptimization data structure */
11195  SCIP_LP* lp, /**< current LP data */
11196  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
11197  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
11198  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11199  SCIP_Bool value, /**< value to fix variable to */
11200  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
11201  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
11202  )
11203 {
11204  assert(var != NULL);
11205  assert(set != NULL);
11206  assert(var->scip == set->scip);
11207  assert(infeasible != NULL);
11208 
11209  *infeasible = FALSE;
11210 
11211  if( value == FALSE )
11212  {
11213  if( var->glbdom.lb > 0.5 )
11214  *infeasible = TRUE;
11215  else if( var->glbdom.ub > 0.5 )
11216  {
11217  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
11218  * with the local bound, in this case we need to store the bound change as pending bound change
11219  */
11220  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
11221  {
11222  assert(tree != NULL);
11223  assert(transprob != NULL);
11224  assert(SCIPprobIsTransformed(transprob));
11225 
11226  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
11227  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
11228  }
11229  else
11230  {
11231  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
11232  }
11233 
11234  if( nbdchgs != NULL )
11235  (*nbdchgs)++;
11236  }
11237  }
11238  else
11239  {
11240  if( var->glbdom.ub < 0.5 )
11241  *infeasible = TRUE;
11242  else if( var->glbdom.lb < 0.5 )
11243  {
11244  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
11245  * with the local bound, in this case we need to store the bound change as pending bound change
11246  */
11247  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
11248  {
11249  assert(tree != NULL);
11250  assert(transprob != NULL);
11251  assert(SCIPprobIsTransformed(transprob));
11252 
11253  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
11254  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
11255  }
11256  else
11257  {
11258  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
11259  }
11260 
11261  if( nbdchgs != NULL )
11262  (*nbdchgs)++;
11263  }
11264  }
11265 
11266  /* during presolving, the variable should have been removed immediately from all its cliques */
11267  assert(SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING || var->cliquelist == NULL);
11268 
11269  return SCIP_OKAY;
11270 }
11271 
11272 /** adds the variable to the given clique and updates the list of cliques the binary variable is member of;
11273  * if the variable now appears twice in the clique with the same value, it is fixed to the opposite value;
11274  * if the variable now appears twice in the clique with opposite values, all other variables are fixed to
11275  * the opposite of the value they take in the clique
11276  */
11278  SCIP_VAR* var, /**< problem variable */
11279  BMS_BLKMEM* blkmem, /**< block memory */
11280  SCIP_SET* set, /**< global SCIP settings */
11281  SCIP_STAT* stat, /**< problem statistics */
11282  SCIP_PROB* transprob, /**< transformed problem */
11283  SCIP_PROB* origprob, /**< original problem */
11284  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
11285  SCIP_REOPT* reopt, /**< reoptimization data structure */
11286  SCIP_LP* lp, /**< current LP data */
11287  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
11288  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
11289  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11290  SCIP_Bool value, /**< value of the variable in the clique */
11291  SCIP_CLIQUE* clique, /**< clique the variable should be added to */
11292  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
11293  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
11294  )
11295 {
11296  assert(var != NULL);
11297  assert(set != NULL);
11298  assert(var->scip == set->scip);
11299  assert(SCIPvarIsBinary(var));
11300  assert(infeasible != NULL);
11301 
11302  *infeasible = FALSE;
11303 
11304  /* get corresponding active problem variable */
11305  SCIP_CALL( SCIPvarGetProbvarBinary(&var, &value) );
11310  assert(SCIPvarIsBinary(var));
11311 
11312  /* only column and loose variables may be member of a clique */
11314  {
11315  SCIP_Bool doubleentry;
11316  SCIP_Bool oppositeentry;
11317 
11318  /* add variable to clique */
11319  SCIP_CALL( SCIPcliqueAddVar(clique, blkmem, set, var, value, &doubleentry, &oppositeentry) );
11320 
11321  /* add clique to variable's clique list */
11322  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
11323 
11324  /* check consistency of cliquelist */
11325  SCIPcliquelistCheck(var->cliquelist, var);
11326 
11327  /* if the variable now appears twice with the same value in the clique, it can be fixed to the opposite value */
11328  if( doubleentry )
11329  {
11330  SCIP_CALL( SCIPvarFixBinary(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
11331  eventqueue, cliquetable, !value, infeasible, nbdchgs) );
11332  }
11333 
11334  /* if the variable appears with both values in the clique, all other variables of the clique can be fixed
11335  * to the opposite of the value they take in the clique
11336  */
11337  if( oppositeentry )
11338  {
11339  SCIP_VAR** vars;
11340  SCIP_Bool* values;
11341  int nvars;
11342  int i;
11343 
11344  nvars = SCIPcliqueGetNVars(clique);
11345  vars = SCIPcliqueGetVars(clique);
11346  values = SCIPcliqueGetValues(clique);
11347  for( i = 0; i < nvars && !(*infeasible); ++i )
11348  {
11349  if( vars[i] == var )
11350  continue;
11351 
11352  SCIP_CALL( SCIPvarFixBinary(vars[i], blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
11353  eventqueue, cliquetable, !values[i], infeasible, nbdchgs) );
11354  }
11355  }
11356  }
11357 
11358  return SCIP_OKAY;
11359 }
11360 
11361 /** adds a filled clique to the cliquelists of all corresponding variables */
11363  SCIP_VAR** vars, /**< problem variables */
11364  SCIP_Bool* values, /**< values of the variables in the clique */
11365  int nvars, /**< number of problem variables */
11366  BMS_BLKMEM* blkmem, /**< block memory */
11367  SCIP_SET* set, /**< global SCIP settings */
11368  SCIP_CLIQUE* clique /**< clique that contains all given variables and values */
11369  )
11370 {
11371  SCIP_VAR* var;
11372  int v;
11373 
11374  assert(vars != NULL);
11375  assert(values != NULL);
11376  assert(nvars > 0);
11377  assert(set != NULL);
11378  assert(blkmem != NULL);
11379  assert(clique != NULL);
11380 
11381  for( v = nvars - 1; v >= 0; --v )
11382  {
11383  var = vars[v];
11384  assert(SCIPvarIsBinary(var));
11386 
11387  /* add clique to variable's clique list */
11388  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, values[v], clique) );
11389 
11390  /* check consistency of cliquelist */
11391  SCIPcliquelistCheck(var->cliquelist, var);
11392  }
11393 
11394  return SCIP_OKAY;
11395 }
11396 
11397 /** adds a clique to the list of cliques of the given binary variable, but does not change the clique
11398  * itself
11399  */
11401  SCIP_VAR* var, /**< problem variable */
11402  BMS_BLKMEM* blkmem, /**< block memory */
11403  SCIP_SET* set, /**< global SCIP settings */
11404  SCIP_Bool value, /**< value of the variable in the clique */
11405  SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
11406  )
11407 {
11408  assert(var != NULL);
11409  assert(SCIPvarIsBinary(var));
11411 
11412  /* add clique to variable's clique list */
11413  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
11414 
11415  return SCIP_OKAY;
11416 }
11417 
11418 
11419 /** deletes a clique from the list of cliques the binary variable is member of, but does not change the clique
11420  * itself
11421  */
11423  SCIP_VAR* var, /**< problem variable */
11424  BMS_BLKMEM* blkmem, /**< block memory */
11425  SCIP_Bool value, /**< value of the variable in the clique */
11426  SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
11427  )
11428 {
11429  assert(var != NULL);
11430  assert(SCIPvarIsBinary(var));
11431 
11432  /* delete clique from variable's clique list */
11433  SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
11434 
11435  return SCIP_OKAY;
11436 }
11437 
11438 /** deletes the variable from the given clique and updates the list of cliques the binary variable is member of */
11440  SCIP_VAR* var, /**< problem variable */
11441  BMS_BLKMEM* blkmem, /**< block memory */
11442  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11443  SCIP_Bool value, /**< value of the variable in the clique */
11444  SCIP_CLIQUE* clique /**< clique the variable should be removed from */
11445  )
11446 {
11447  assert(var != NULL);
11448  assert(SCIPvarIsBinary(var));
11449 
11450  /* get corresponding active problem variable */
11451  SCIP_CALL( SCIPvarGetProbvarBinary(&var, &value) );
11456  assert(SCIPvarIsBinary(var));
11457 
11458  /* only column and loose variables may be member of a clique */
11460  {
11461  /* delete clique from variable's clique list */
11462  SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
11463 
11464  /* delete variable from clique */
11465  SCIPcliqueDelVar(clique, cliquetable, var, value);
11466 
11467  /* check consistency of cliquelist */
11468  SCIPcliquelistCheck(var->cliquelist, var);
11469  }
11470 
11471  return SCIP_OKAY;
11472 }
11473 
11474 /** returns whether there is a clique that contains both given variable/value pairs;
11475  * the variables must be active binary variables;
11476  * if regardimplics is FALSE, only the cliques in the clique table are looked at;
11477  * if regardimplics is TRUE, both the cliques and the implications of the implication graph are regarded
11478  *
11479  * @note a variable with it's negated variable are NOT! in a clique
11480  * @note a variable with itself are in a clique
11481  */
11483  SCIP_VAR* var1, /**< first variable */
11484  SCIP_Bool value1, /**< value of first variable */
11485  SCIP_VAR* var2, /**< second variable */
11486  SCIP_Bool value2, /**< value of second variable */
11487  SCIP_Bool regardimplics /**< should the implication graph also be searched for a clique? */
11488  )
11489 {
11490  assert(var1 != NULL);
11491  assert(var2 != NULL);
11492  assert(SCIPvarIsActive(var1));
11493  assert(SCIPvarIsActive(var2));
11494  assert(SCIPvarIsBinary(var1));
11495  assert(SCIPvarIsBinary(var2));
11496 
11497  return (SCIPcliquelistsHaveCommonClique(var1->cliquelist, value1, var2->cliquelist, value2)
11498  || (regardimplics && SCIPvarHasImplic(var1, value1, var2, value2 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER)));
11499 }
11500 
11501 /** actually changes the branch factor of the variable and of all parent variables */
11502 static
11504  SCIP_VAR* var, /**< problem variable */
11505  SCIP_SET* set, /**< global SCIP settings */
11506  SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
11507  )
11508 {
11509  SCIP_VAR* parentvar;
11510  SCIP_Real eps;
11511  int i;
11512 
11513  assert(var != NULL);
11514  assert(set != NULL);
11515  assert(var->scip == set->scip);
11516 
11517  /* only use positive values */
11518  eps = SCIPsetEpsilon(set);
11519  branchfactor = MAX(branchfactor, eps);
11520 
11521  SCIPsetDebugMsg(set, "process changing branch factor of <%s> from %f to %f\n", var->name, var->branchfactor, branchfactor);
11522 
11523  if( SCIPsetIsEQ(set, branchfactor, var->branchfactor) )
11524  return SCIP_OKAY;
11525 
11526  /* change the branch factor */
11527  var->branchfactor = branchfactor;
11528 
11529  /* process parent variables */
11530  for( i = 0; i < var->nparentvars; ++i )
11531  {
11532  parentvar = var->parentvars[i];
11533  assert(parentvar != NULL);
11534 
11535  switch( SCIPvarGetStatus(parentvar) )
11536  {
11538  /* do not change priorities across the border between transformed and original problem */
11539  break;
11540 
11541  case SCIP_VARSTATUS_COLUMN:
11542  case SCIP_VARSTATUS_LOOSE:
11543  case SCIP_VARSTATUS_FIXED:
11545  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11546  SCIPABORT();
11547  return SCIP_INVALIDDATA; /*lint !e527*/
11548 
11551  SCIP_CALL( varProcessChgBranchFactor(parentvar, set, branchfactor) );
11552  break;
11553 
11554  default:
11555  SCIPerrorMessage("unknown variable status\n");
11556  SCIPABORT();
11557  return SCIP_ERROR; /*lint !e527*/
11558  }
11559  }
11560 
11561  return SCIP_OKAY;
11562 }
11563 
11564 /** sets the branch factor of the variable; this value can be used in the branching methods to scale the score
11565  * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
11566  */
11568  SCIP_VAR* var, /**< problem variable */
11569  SCIP_SET* set, /**< global SCIP settings */
11570  SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
11571  )
11572 {
11573  int v;
11574 
11575  assert(var != NULL);
11576  assert(set != NULL);
11577  assert(var->scip == set->scip);
11578  assert(branchfactor >= 0.0);
11579 
11580  SCIPdebugMessage("changing branch factor of <%s> from %g to %g\n", var->name, var->branchfactor, branchfactor);
11581 
11582  if( SCIPsetIsEQ(set, var->branchfactor, branchfactor) )
11583  return SCIP_OKAY;
11584 
11585  /* change priorities of attached variables */
11586  switch( SCIPvarGetStatus(var) )
11587  {
11589  if( var->data.original.transvar != NULL )
11590  {
11591  SCIP_CALL( SCIPvarChgBranchFactor(var->data.original.transvar, set, branchfactor) );
11592  }
11593  else
11594  {
11595  assert(set->stage == SCIP_STAGE_PROBLEM);
11596  var->branchfactor = branchfactor;
11597  }
11598  break;
11599 
11600  case SCIP_VARSTATUS_COLUMN:
11601  case SCIP_VARSTATUS_LOOSE:
11602  case SCIP_VARSTATUS_FIXED:
11603  SCIP_CALL( varProcessChgBranchFactor(var, set, branchfactor) );
11604  break;
11605 
11607  assert(!var->donotaggr);
11608  assert(var->data.aggregate.var != NULL);
11609  SCIP_CALL( SCIPvarChgBranchFactor(var->data.aggregate.var, set, branchfactor) );
11610  break;
11611 
11613  assert(!var->donotmultaggr);
11614  for( v = 0; v < var->data.multaggr.nvars; ++v )
11615  {
11616  SCIP_CALL( SCIPvarChgBranchFactor(var->data.multaggr.vars[v], set, branchfactor) );
11617  }
11618  break;
11619 
11621  assert(var->negatedvar != NULL);
11623  assert(var->negatedvar->negatedvar == var);
11624  SCIP_CALL( SCIPvarChgBranchFactor(var->negatedvar, set, branchfactor) );
11625  break;
11626 
11627  default:
11628  SCIPerrorMessage("unknown variable status\n");
11629  SCIPABORT();
11630  return SCIP_ERROR; /*lint !e527*/
11631  }
11632 
11633  return SCIP_OKAY;
11634 }
11635 
11636 /** actually changes the branch priority of the variable and of all parent variables */
11637 static
11639  SCIP_VAR* var, /**< problem variable */
11640  int branchpriority /**< branching priority of the variable */
11641  )
11642 {
11643  SCIP_VAR* parentvar;
11644  int i;
11645 
11646  assert(var != NULL);
11647 
11648  SCIPdebugMessage("process changing branch priority of <%s> from %d to %d\n",
11649  var->name, var->branchpriority, branchpriority);
11650 
11651  if( branchpriority == var->branchpriority )
11652  return SCIP_OKAY;
11653 
11654  /* change the branch priority */
11655  var->branchpriority = branchpriority;
11656 
11657  /* process parent variables */
11658  for( i = 0; i < var->nparentvars; ++i )
11659  {
11660  parentvar = var->parentvars[i];
11661  assert(parentvar != NULL);
11662 
11663  switch( SCIPvarGetStatus(parentvar) )
11664  {
11666  /* do not change priorities across the border between transformed and original problem */
11667  break;
11668 
11669  case SCIP_VARSTATUS_COLUMN:
11670  case SCIP_VARSTATUS_LOOSE:
11671  case SCIP_VARSTATUS_FIXED:
11673  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11674  SCIPABORT();
11675  return SCIP_INVALIDDATA; /*lint !e527*/
11676 
11679  SCIP_CALL( varProcessChgBranchPriority(parentvar, branchpriority) );
11680  break;
11681 
11682  default:
11683  SCIPerrorMessage("unknown variable status\n");
11684  return SCIP_ERROR;
11685  }
11686  }
11687 
11688  return SCIP_OKAY;
11689 }
11690 
11691 /** sets the branch priority of the variable; variables with higher branch priority are always preferred to variables
11692  * with lower priority in selection of branching variable
11693  */
11695  SCIP_VAR* var, /**< problem variable */
11696  int branchpriority /**< branching priority of the variable */
11697  )
11698 {
11699  int v;
11700 
11701  assert(var != NULL);
11702 
11703  SCIPdebugMessage("changing branch priority of <%s> from %d to %d\n", var->name, var->branchpriority, branchpriority);
11704 
11705  if( var->branchpriority == branchpriority )
11706  return SCIP_OKAY;
11707 
11708  /* change priorities of attached variables */
11709  switch( SCIPvarGetStatus(var) )
11710  {
11712  if( var->data.original.transvar != NULL )
11713  {
11714  SCIP_CALL( SCIPvarChgBranchPriority(var->data.original.transvar, branchpriority) );
11715  }
11716  else
11717  var->branchpriority = branchpriority;
11718  break;
11719 
11720  case SCIP_VARSTATUS_COLUMN:
11721  case SCIP_VARSTATUS_LOOSE:
11722  case SCIP_VARSTATUS_FIXED:
11723  SCIP_CALL( varProcessChgBranchPriority(var, branchpriority) );
11724  break;
11725 
11727  assert(!var->donotaggr);
11728  assert(var->data.aggregate.var != NULL);
11729  SCIP_CALL( SCIPvarChgBranchPriority(var->data.aggregate.var, branchpriority) );
11730  break;
11731 
11733  assert(!var->donotmultaggr);
11734  for( v = 0; v < var->data.multaggr.nvars; ++v )
11735  {
11736  SCIP_CALL( SCIPvarChgBranchPriority(var->data.multaggr.vars[v], branchpriority) );
11737  }
11738  break;
11739 
11741  assert(var->negatedvar != NULL);
11743  assert(var->negatedvar->negatedvar == var);
11744  SCIP_CALL( SCIPvarChgBranchPriority(var->negatedvar, branchpriority) );
11745  break;
11746 
11747  default:
11748  SCIPerrorMessage("unknown variable status\n");
11749  SCIPABORT();
11750  return SCIP_ERROR; /*lint !e527*/
11751  }
11752 
11753  return SCIP_OKAY;
11754 }
11755 
11756 /** actually changes the branch direction of the variable and of all parent variables */
11757 static
11759  SCIP_VAR* var, /**< problem variable */
11760  SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
11761  )
11762 {
11763  SCIP_VAR* parentvar;
11764  int i;
11765 
11766  assert(var != NULL);
11767 
11768  SCIPdebugMessage("process changing branch direction of <%s> from %u to %d\n",
11769  var->name, var->branchdirection, branchdirection);
11770 
11771  if( branchdirection == (SCIP_BRANCHDIR)var->branchdirection )
11772  return SCIP_OKAY;
11773 
11774  /* change the branch direction */
11775  var->branchdirection = branchdirection; /*lint !e641*/
11776 
11777  /* process parent variables */
11778  for( i = 0; i < var->nparentvars; ++i )
11779  {
11780  parentvar = var->parentvars[i];
11781  assert(parentvar != NULL);
11782 
11783  switch( SCIPvarGetStatus(parentvar) )
11784  {
11786  /* do not change directions across the border between transformed and original problem */
11787  break;
11788 
11789  case SCIP_VARSTATUS_COLUMN:
11790  case SCIP_VARSTATUS_LOOSE:
11791  case SCIP_VARSTATUS_FIXED:
11793  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11794  SCIPABORT();
11795  return SCIP_INVALIDDATA; /*lint !e527*/
11796 
11798  if( parentvar->data.aggregate.scalar > 0.0 )
11799  {
11800  SCIP_CALL( varProcessChgBranchDirection(parentvar, branchdirection) );
11801  }
11802  else
11803  {
11804  SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
11805  }
11806  break;
11807 
11809  SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
11810  break;
11811 
11812  default:
11813  SCIPerrorMessage("unknown variable status\n");
11814  SCIPABORT();
11815  return SCIP_ERROR; /*lint !e527*/
11816  }
11817  }
11818 
11819  return SCIP_OKAY;
11820 }
11821 
11822 /** sets the branch direction of the variable; variables with higher branch direction are always preferred to variables
11823  * with lower direction in selection of branching variable
11824  */
11826  SCIP_VAR* var, /**< problem variable */
11827  SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
11828  )
11829 {
11830  int v;
11831 
11832  assert(var != NULL);
11833 
11834  SCIPdebugMessage("changing branch direction of <%s> from %u to %d\n", var->name, var->branchdirection, branchdirection);
11835 
11836  if( (SCIP_BRANCHDIR)var->branchdirection == branchdirection )
11837  return SCIP_OKAY;
11838 
11839  /* change directions of attached variables */
11840  switch( SCIPvarGetStatus(var) )
11841  {
11843  if( var->data.original.transvar != NULL )
11844  {
11845  SCIP_CALL( SCIPvarChgBranchDirection(var->data.original.transvar, branchdirection) );
11846  }
11847  else
11848  var->branchdirection = branchdirection; /*lint !e641*/
11849  break;
11850 
11851  case SCIP_VARSTATUS_COLUMN:
11852  case SCIP_VARSTATUS_LOOSE:
11853  case SCIP_VARSTATUS_FIXED:
11854  SCIP_CALL( varProcessChgBranchDirection(var, branchdirection) );
11855  break;
11856 
11858  assert(!var->donotaggr);
11859  assert(var->data.aggregate.var != NULL);
11860  if( var->data.aggregate.scalar > 0.0 )
11861  {
11862  SCIP_CALL( SCIPvarChgBranchDirection(var->data.aggregate.var, branchdirection) );
11863  }
11864  else
11865  {
11867  }
11868  break;
11869 
11871  assert(!var->donotmultaggr);
11872  for( v = 0; v < var->data.multaggr.nvars; ++v )
11873  {
11874  /* only update branching direction of aggregation variables, if they don't have a preferred direction yet */
11875  assert(var->data.multaggr.vars[v] != NULL);
11877  {
11878  if( var->data.multaggr.scalars[v] > 0.0 )
11879  {
11880  SCIP_CALL( SCIPvarChgBranchDirection(var->data.multaggr.vars[v], branchdirection) );
11881  }
11882  else
11883  {
11885  }
11886  }
11887  }
11888  break;
11889 
11891  assert(var->negatedvar != NULL);
11893  assert(var->negatedvar->negatedvar == var);
11895  break;
11896 
11897  default:
11898  SCIPerrorMessage("unknown variable status\n");
11899  SCIPABORT();
11900  return SCIP_ERROR; /*lint !e527*/
11901  }
11902 
11903  return SCIP_OKAY;
11904 }
11905 
11906 /** compares the index of two variables, only active, fixed or negated variables are allowed, if a variable
11907  * is negated then the index of the corresponding active variable is taken, returns -1 if first is
11908  * smaller than, and +1 if first is greater than second variable index; returns 0 if both indices
11909  * are equal, which means both variables are equal
11910  */
11912  SCIP_VAR* var1, /**< first problem variable */
11913  SCIP_VAR* var2 /**< second problem variable */
11914  )
11915 {
11916  assert(var1 != NULL);
11917  assert(var2 != NULL);
11920 
11922  var1 = SCIPvarGetNegatedVar(var1);
11924  var2 = SCIPvarGetNegatedVar(var2);
11925 
11926  assert(var1 != NULL);
11927  assert(var2 != NULL);
11928 
11929  if( SCIPvarGetIndex(var1) < SCIPvarGetIndex(var2) )
11930  return -1;
11931  else if( SCIPvarGetIndex(var1) > SCIPvarGetIndex(var2) )
11932  return +1;
11933 
11934  assert(var1 == var2);
11935  return 0;
11936 }
11937 
11938 /** comparison method for sorting active and negated variables by non-decreasing index, active and negated
11939  * variables are handled as the same variables
11940  */
11941 SCIP_DECL_SORTPTRCOMP(SCIPvarCompActiveAndNegated)
11943  return SCIPvarCompareActiveAndNegated((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
11944 }
11945 
11946 /** compares the index of two variables, returns -1 if first is smaller than, and +1 if first is greater than second
11947  * variable index; returns 0 if both indices are equal, which means both variables are equal
11948  */
11949 int SCIPvarCompare(
11950  SCIP_VAR* var1, /**< first problem variable */
11951  SCIP_VAR* var2 /**< second problem variable */
11952  )
11953 {
11954  assert(var1 != NULL);
11955  assert(var2 != NULL);
11956 
11957  if( var1->index < var2->index )
11958  return -1;
11959  else if( var1->index > var2->index )
11960  return +1;
11961  else
11962  {
11963  assert(var1 == var2);
11964  return 0;
11965  }
11966 }
11967 
11968 /** comparison method for sorting variables by non-decreasing index */
11969 SCIP_DECL_SORTPTRCOMP(SCIPvarComp)
11971  return SCIPvarCompare((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
11972 }
11973 
11974 /** comparison method for sorting variables by non-decreasing objective coefficient */
11975 SCIP_DECL_SORTPTRCOMP(SCIPvarCompObj)
11977  SCIP_Real obj1;
11978  SCIP_Real obj2;
11979 
11980  obj1 = SCIPvarGetObj((SCIP_VAR*)elem1);
11981  obj2 = SCIPvarGetObj((SCIP_VAR*)elem2);
11982 
11983  if( obj1 < obj2 )
11984  return -1;
11985  else if( obj1 > obj2 )
11986  return +1;
11987  else
11988  return 0;
11989 }
11990 
11991 /** hash key retrieval function for variables */
11992 SCIP_DECL_HASHGETKEY(SCIPvarGetHashkey)
11993 { /*lint --e{715}*/
11994  return elem;
11995 }
11996 
11997 /** returns TRUE iff the indices of both variables are equal */
11998 SCIP_DECL_HASHKEYEQ(SCIPvarIsHashkeyEq)
11999 { /*lint --e{715}*/
12000  if( key1 == key2 )
12001  return TRUE;
12002  return FALSE;
12003 }
12004 
12005 /** returns the hash value of the key */
12006 SCIP_DECL_HASHKEYVAL(SCIPvarGetHashkeyVal)
12007 { /*lint --e{715}*/
12008  assert( SCIPvarGetIndex((SCIP_VAR*) key) >= 0 );
12009  return (unsigned int) SCIPvarGetIndex((SCIP_VAR*) key);
12010 }
12011 
12012 /** return for given variables all their active counterparts; all active variables will be pairwise different */
12014  SCIP_SET* set, /**< global SCIP settings */
12015  SCIP_VAR** vars, /**< variable array with given variables and as output all active
12016  * variables, if enough slots exist
12017  */
12018  int* nvars, /**< number of given variables, and as output number of active variables,
12019  * if enough slots exist
12020  */
12021  int varssize, /**< available slots in vars array */
12022  int* requiredsize /**< pointer to store the required array size for the active variables */
12023  )
12024 {
12025  SCIP_VAR** activevars;
12026  int nactivevars;
12027  int activevarssize;
12028 
12029  SCIP_VAR* var;
12030  int v;
12031 
12032  SCIP_VAR** tmpvars;
12033  SCIP_VAR** multvars;
12034  int tmpvarssize;
12035  int ntmpvars;
12036  int noldtmpvars;
12037  int nmultvars;
12038 
12039  assert(set != NULL);
12040  assert(nvars != NULL);
12041  assert(vars != NULL || *nvars == 0);
12042  assert(varssize >= *nvars);
12043  assert(requiredsize != NULL);
12044 
12045  *requiredsize = 0;
12046 
12047  if( *nvars == 0 )
12048  return SCIP_OKAY;
12049 
12050  nactivevars = 0;
12051  activevarssize = *nvars;
12052  ntmpvars = *nvars;
12053  tmpvarssize = *nvars;
12054 
12055  /* temporary memory */
12056  SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
12057  /* coverity[copy_paste_error] */
12058  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
12059 
12060  noldtmpvars = ntmpvars;
12061 
12062  /* sort all variables to combine equal variables easily */
12063  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
12064  for( v = ntmpvars - 1; v > 0; --v )
12065  {
12066  /* combine same variables */
12067  if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
12068  {
12069  --ntmpvars;
12070  tmpvars[v] = tmpvars[ntmpvars];
12071  }
12072  }
12073  /* sort all variables again to combine equal variables later on */
12074  if( noldtmpvars > ntmpvars )
12075  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
12076 
12077  /* collect for each variable the representation in active variables */
12078  while( ntmpvars >= 1 )
12079  {
12080  --ntmpvars;
12081  var = tmpvars[ntmpvars];
12082  assert( var != NULL );
12083 
12084  switch( SCIPvarGetStatus(var) )
12085  {
12087  if( var->data.original.transvar == NULL )
12088  {
12089  SCIPerrorMessage("original variable has no transformed variable attached\n");
12090  SCIPABORT();
12091  return SCIP_INVALIDDATA; /*lint !e527*/
12092  }
12093  tmpvars[ntmpvars] = var->data.original.transvar;
12094  ++ntmpvars;
12095  break;
12096 
12098  tmpvars[ntmpvars] = var->data.aggregate.var;
12099  ++ntmpvars;
12100  break;
12101 
12103  tmpvars[ntmpvars] = var->negatedvar;
12104  ++ntmpvars;
12105  break;
12106 
12107  case SCIP_VARSTATUS_LOOSE:
12108  case SCIP_VARSTATUS_COLUMN:
12109  /* check for space in temporary memory */
12110  if( nactivevars >= activevarssize )
12111  {
12112  activevarssize *= 2;
12113  SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
12114  assert(nactivevars < activevarssize);
12115  }
12116  activevars[nactivevars] = var;
12117  nactivevars++;
12118  break;
12119 
12121  /* x = a_1*y_1 + ... + a_n*y_n + c */
12122  nmultvars = var->data.multaggr.nvars;
12123  multvars = var->data.multaggr.vars;
12124 
12125  /* check for space in temporary memory */
12126  if( nmultvars + ntmpvars > tmpvarssize )
12127  {
12128  while( nmultvars + ntmpvars > tmpvarssize )
12129  tmpvarssize *= 2;
12130  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
12131  assert(nmultvars + ntmpvars <= tmpvarssize);
12132  }
12133 
12134  /* copy all multi-aggregation variables into our working array */
12135  BMScopyMemoryArray(&tmpvars[ntmpvars], multvars, nmultvars); /*lint !e866*/
12136 
12137  /* get active, fixed or multi-aggregated corresponding variables for all new ones */
12138  SCIPvarsGetProbvar(&tmpvars[ntmpvars], nmultvars);
12139 
12140  ntmpvars += nmultvars;
12141  noldtmpvars = ntmpvars;
12142 
12143  /* sort all variables to combine equal variables easily */
12144  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
12145  for( v = ntmpvars - 1; v > 0; --v )
12146  {
12147  /* combine same variables */
12148  if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
12149  {
12150  --ntmpvars;
12151  tmpvars[v] = tmpvars[ntmpvars];
12152  }
12153  }
12154  /* sort all variables again to combine equal variables later on */
12155  if( noldtmpvars > ntmpvars )
12156  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
12157 
12158  break;
12159 
12160  case SCIP_VARSTATUS_FIXED:
12161  /* no need for memorizing fixed variables */
12162  break;
12163 
12164  default:
12165  SCIPerrorMessage("unknown variable status\n");
12166  SCIPABORT();
12167  return SCIP_INVALIDDATA; /*lint !e527*/
12168  }
12169  }
12170 
12171  /* sort variable array by variable index */
12172  SCIPsortPtr((void**)activevars, SCIPvarComp, nactivevars);
12173 
12174  /* eliminate duplicates and count required size */
12175  v = nactivevars - 1;
12176  while( v > 0 )
12177  {
12178  /* combine both variable since they are the same */
12179  if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
12180  {
12181  --nactivevars;
12182  activevars[v] = activevars[nactivevars];
12183  }
12184  --v;
12185  }
12186  *requiredsize = nactivevars;
12187 
12188  if( varssize >= *requiredsize )
12189  {
12190  assert(vars != NULL);
12191 
12192  *nvars = *requiredsize;
12193  BMScopyMemoryArray(vars, activevars, nactivevars);
12194  }
12195 
12196  SCIPsetFreeBufferArray(set, &tmpvars);
12197  SCIPsetFreeBufferArray(set, &activevars);
12198 
12199  return SCIP_OKAY;
12200 }
12201 
12202 /** gets corresponding active, fixed, or multi-aggregated problem variables of given variables,
12203  * @note the content of the given array will/might change
12204  */
12205 void SCIPvarsGetProbvar(
12206  SCIP_VAR** vars, /**< array of problem variables */
12207  int nvars /**< number of variables */
12208  )
12209 {
12210  int v;
12211 
12212  assert(vars != NULL || nvars == 0);
12213 
12214  for( v = nvars - 1; v >= 0; --v )
12215  {
12216  assert(vars != NULL);
12217  assert(vars[v] != NULL);
12218 
12219  vars[v] = SCIPvarGetProbvar(vars[v]);
12220  assert(vars[v] != NULL);
12221  }
12222 }
12223 
12224 /** gets corresponding active, fixed, or multi-aggregated problem variable of a variable */
12226  SCIP_VAR* var /**< problem variable */
12227  )
12228 {
12229  SCIP_VAR* retvar;
12230 
12231  assert(var != NULL);
12232 
12233  retvar = var;
12234 
12235  SCIPdebugMessage("get problem variable of <%s>\n", var->name);
12236 
12237  while( TRUE ) /*lint !e716 */
12238  {
12239  assert(retvar != NULL);
12240 
12241  switch( SCIPvarGetStatus(retvar) )
12242  {
12244  if( retvar->data.original.transvar == NULL )
12245  {
12246  SCIPerrorMessage("original variable has no transformed variable attached\n");
12247  SCIPABORT();
12248  return NULL; /*lint !e527 */
12249  }
12250  retvar = retvar->data.original.transvar;
12251  break;
12252 
12253  case SCIP_VARSTATUS_LOOSE:
12254  case SCIP_VARSTATUS_COLUMN:
12255  case SCIP_VARSTATUS_FIXED:
12256  return retvar;
12257 
12259  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12260  if ( retvar->data.multaggr.nvars == 1 )
12261  retvar = retvar->data.multaggr.vars[0];
12262  else
12263  return retvar;
12264  break;
12265 
12267  retvar = retvar->data.aggregate.var;
12268  break;
12269 
12271  retvar = retvar->negatedvar;
12272  break;
12273 
12274  default:
12275  SCIPerrorMessage("unknown variable status\n");
12276  SCIPABORT();
12277  return NULL; /*lint !e527*/
12278  }
12279  }
12280 }
12281 
12282 /** gets corresponding active, fixed, or multi-aggregated problem variables of binary variables and updates the given
12283  * negation status of each variable
12284  */
12286  SCIP_VAR*** vars, /**< pointer to binary problem variables */
12287  SCIP_Bool** negatedarr, /**< pointer to corresponding array to update the negation status */
12288  int nvars /**< number of variables and values in vars and negated array */
12289  )
12290 {
12291  SCIP_VAR** var;
12292  SCIP_Bool* negated;
12293  int v;
12294 
12295  assert(vars != NULL);
12296  assert(*vars != NULL || nvars == 0);
12297  assert(negatedarr != NULL);
12298  assert(*negatedarr != NULL || nvars == 0);
12299 
12300  for( v = nvars - 1; v >= 0; --v )
12301  {
12302  var = &((*vars)[v]);
12303  negated = &((*negatedarr)[v]);
12304 
12305  /* get problem variable */
12306  SCIP_CALL( SCIPvarGetProbvarBinary(var, negated) );
12307  }
12308 
12309  return SCIP_OKAY;
12310 }
12311 
12312 
12313 /** gets corresponding active, fixed, or multi-aggregated problem variable of a binary variable and updates the given
12314  * negation status (this means you have to assign a value to SCIP_Bool negated before calling this method, usually
12315  * FALSE is used)
12316  */
12318  SCIP_VAR** var, /**< pointer to binary problem variable */
12319  SCIP_Bool* negated /**< pointer to update the negation status */
12320  )
12321 {
12323 #ifndef NDEBUG
12324  SCIP_Real constant = 0.0;
12325  SCIP_Bool orignegated;
12326 #endif
12327 
12328  assert(var != NULL);
12329  assert(*var != NULL);
12330  assert(negated != NULL);
12331  assert(SCIPvarIsBinary(*var));
12332 
12333 #ifndef NDEBUG
12334  orignegated = *negated;
12335 #endif
12336 
12337  while( !active && *var != NULL )
12338  {
12339  switch( SCIPvarGetStatus(*var) )
12340  {
12342  if( (*var)->data.original.transvar == NULL )
12343  return SCIP_OKAY;
12344  *var = (*var)->data.original.transvar;
12345  break;
12346 
12347  case SCIP_VARSTATUS_LOOSE:
12348  case SCIP_VARSTATUS_COLUMN:
12349  case SCIP_VARSTATUS_FIXED:
12350  active = TRUE;
12351  break;
12352 
12354  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12355  if ( (*var)->data.multaggr.nvars == 1 )
12356  {
12357  assert( (*var)->data.multaggr.vars != NULL );
12358  assert( (*var)->data.multaggr.scalars != NULL );
12359  assert( SCIPvarIsBinary((*var)->data.multaggr.vars[0]) );
12360  assert(!EPSZ((*var)->data.multaggr.scalars[0], 1e-06));
12361 
12362  /* if not all variables were fully propagated, it might happen that a variable is multi-aggregated to
12363  * another variable which needs to be fixed
12364  *
12365  * e.g. x = y - 1 => (x = 0 && y = 1)
12366  * e.g. x = y + 1 => (x = 1 && y = 0)
12367  *
12368  * is this special case we need to return the muti-aggregation
12369  */
12370  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)) )
12371  {
12372  assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06));
12373  }
12374  else
12375  {
12376  /* @note due to fixations, a multi-aggregation can have a constant of zero and a negative scalar or even
12377  * a scalar in absolute value unequal to one, in this case this aggregation variable needs to be
12378  * fixed to zero, but this should be done by another enforcement; so not depending on the scalar,
12379  * we will return the aggregated variable;
12380  */
12381  if( !EPSEQ(REALABS((*var)->data.multaggr.scalars[0]), 1.0, 1e-06) )
12382  {
12383  active = TRUE;
12384  break;
12385  }
12386 
12387  /* @note it may also happen that the constant is larger than 1 or smaller than 0, in that case the
12388  * aggregation variable needs to be fixed to one, but this should be done by another enforcement;
12389  * so if this is the case, we will return the aggregated variable
12390  */
12391  assert(EPSZ((*var)->data.multaggr.constant, 1e-06) || EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06)
12392  || EPSZ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1e-06)
12393  || EPSEQ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1.0, 1e-06));
12394 
12395  if( !EPSZ((*var)->data.multaggr.constant, 1e-06) && !EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06) )
12396  {
12397  active = TRUE;
12398  break;
12399  }
12400 
12401  assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06) || EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
12402 
12403  if( EPSZ((*var)->data.multaggr.constant, 1e-06) )
12404  {
12405  /* if the scalar is negative, either the aggregation variable is already fixed to zero or has at
12406  * least one uplock (that hopefully will enforce this fixation to zero); can it happen that this
12407  * variable itself is multi-aggregated again?
12408  */
12409  assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06) ?
12410  ((SCIPvarGetUbGlobal((*var)->data.multaggr.vars[0]) < 0.5) ||
12411  SCIPvarGetNLocksUpType((*var)->data.multaggr.vars[0], SCIP_LOCKTYPE_MODEL) > 0) : TRUE);
12412  }
12413  else
12414  {
12415  assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
12416 #ifndef NDEBUG
12417  constant += (*negated) != orignegated ? -1.0 : 1.0;
12418 #endif
12419 
12420  *negated = !(*negated);
12421  }
12422  *var = (*var)->data.multaggr.vars[0];
12423  break;
12424  }
12425  }
12426  active = TRUE; /*lint !e838*/
12427  break;
12428 
12429  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
12430  assert((*var)->data.aggregate.var != NULL);
12431  assert(EPSEQ((*var)->data.aggregate.scalar, 1.0, 1e-06) || EPSEQ((*var)->data.aggregate.scalar, -1.0, 1e-06));
12432  assert(EPSLE((*var)->data.aggregate.var->glbdom.ub - (*var)->data.aggregate.var->glbdom.lb, 1.0, 1e-06));
12433 #ifndef NDEBUG
12434  constant += (*negated) != orignegated ? -(*var)->data.aggregate.constant : (*var)->data.aggregate.constant;
12435 #endif
12436 
12437  *negated = ((*var)->data.aggregate.scalar > 0.0) ? *negated : !(*negated);
12438  *var = (*var)->data.aggregate.var;
12439  break;
12440 
12441  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
12442  assert((*var)->negatedvar != NULL);
12443 #ifndef NDEBUG
12444  constant += (*negated) != orignegated ? -1.0 : 1.0;
12445 #endif
12446 
12447  *negated = !(*negated);
12448  *var = (*var)->negatedvar;
12449  break;
12450 
12451  default:
12452  SCIPerrorMessage("unknown variable status\n");
12453  return SCIP_INVALIDDATA;
12454  }
12455  }
12456  assert(active == (*var != NULL));
12457 
12458  if( active )
12459  {
12460  assert(SCIPvarIsBinary(*var));
12461  assert(EPSZ(constant, 1e-06) || EPSEQ(constant, 1.0, 1e-06));
12462  assert(EPSZ(constant, 1e-06) == ((*negated) == orignegated));
12463 
12464  return SCIP_OKAY;
12465  }
12466  else
12467  {
12468  SCIPerrorMessage("active variable path leads to NULL pointer\n");
12469  return SCIP_INVALIDDATA;
12470  }
12471 }
12472 
12473 /** transforms given variable, boundtype and bound to the corresponding active, fixed, or multi-aggregated variable
12474  * values
12475  */
12477  SCIP_VAR** var, /**< pointer to problem variable */
12478  SCIP_Real* bound, /**< pointer to bound value to transform */
12479  SCIP_BOUNDTYPE* boundtype /**< pointer to type of bound: lower or upper bound */
12480  )
12481 {
12482  assert(var != NULL);
12483  assert(*var != NULL);
12484  assert(bound != NULL);
12485  assert(boundtype != NULL);
12486 
12487  SCIPdebugMessage("get probvar bound %g of type %d of variable <%s>\n", *bound, *boundtype, (*var)->name);
12488 
12489  switch( SCIPvarGetStatus(*var) )
12490  {
12492  if( (*var)->data.original.transvar == NULL )
12493  {
12494  SCIPerrorMessage("original variable has no transformed variable attached\n");
12495  return SCIP_INVALIDDATA;
12496  }
12497  *var = (*var)->data.original.transvar;
12498  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12499  break;
12500 
12501  case SCIP_VARSTATUS_LOOSE:
12502  case SCIP_VARSTATUS_COLUMN:
12503  case SCIP_VARSTATUS_FIXED:
12504  break;
12505 
12507  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12508  if ( (*var)->data.multaggr.nvars == 1 )
12509  {
12510  assert( (*var)->data.multaggr.vars != NULL );
12511  assert( (*var)->data.multaggr.scalars != NULL );
12512  assert( (*var)->data.multaggr.scalars[0] != 0.0 );
12513 
12514  (*bound) /= (*var)->data.multaggr.scalars[0];
12515  (*bound) -= (*var)->data.multaggr.constant/(*var)->data.multaggr.scalars[0];
12516  if ( (*var)->data.multaggr.scalars[0] < 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.multaggr.vars[0];
12524  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12525  }
12526  break;
12527 
12528  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
12529  assert((*var)->data.aggregate.var != NULL);
12530  assert((*var)->data.aggregate.scalar != 0.0);
12531 
12532  (*bound) /= (*var)->data.aggregate.scalar;
12533  (*bound) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12534  if( (*var)->data.aggregate.scalar < 0.0 )
12535  {
12536  if( *boundtype == SCIP_BOUNDTYPE_LOWER )
12537  *boundtype = SCIP_BOUNDTYPE_UPPER;
12538  else
12539  *boundtype = SCIP_BOUNDTYPE_LOWER;
12540  }
12541  *var = (*var)->data.aggregate.var;
12542  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12543  break;
12544 
12545  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12546  assert((*var)->negatedvar != NULL);
12547  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12548  assert((*var)->negatedvar->negatedvar == *var);
12549  (*bound) = (*var)->data.negate.constant - *bound;
12550  if( *boundtype == SCIP_BOUNDTYPE_LOWER )
12551  *boundtype = SCIP_BOUNDTYPE_UPPER;
12552  else
12553  *boundtype = SCIP_BOUNDTYPE_LOWER;
12554  *var = (*var)->negatedvar;
12555  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12556  break;
12557 
12558  default:
12559  SCIPerrorMessage("unknown variable status\n");
12560  return SCIP_INVALIDDATA;
12561  }
12562 
12563  return SCIP_OKAY;
12564 }
12565 
12566 /** transforms given variable and domain hole to the corresponding active, fixed, or multi-aggregated variable
12567  * values
12568  */
12570  SCIP_VAR** var, /**< pointer to problem variable */
12571  SCIP_Real* left, /**< pointer to left bound of open interval in hole to transform */
12572  SCIP_Real* right /**< pointer to right bound of open interval in hole to transform */
12573  )
12574 {
12575  assert(var != NULL);
12576  assert(*var != NULL);
12577  assert(left != NULL);
12578  assert(right != NULL);
12579 
12580  SCIPdebugMessage("get probvar hole (%g,%g) of variable <%s>\n", *left, *right, (*var)->name);
12581 
12582  switch( SCIPvarGetStatus(*var) )
12583  {
12585  if( (*var)->data.original.transvar == NULL )
12586  {
12587  SCIPerrorMessage("original variable has no transformed variable attached\n");
12588  return SCIP_INVALIDDATA;
12589  }
12590  *var = (*var)->data.original.transvar;
12591  SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
12592  break;
12593 
12594  case SCIP_VARSTATUS_LOOSE:
12595  case SCIP_VARSTATUS_COLUMN:
12596  case SCIP_VARSTATUS_FIXED:
12598  break;
12599 
12600  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
12601  assert((*var)->data.aggregate.var != NULL);
12602  assert((*var)->data.aggregate.scalar != 0.0);
12603 
12604  /* scale back */
12605  (*left) /= (*var)->data.aggregate.scalar;
12606  (*right) /= (*var)->data.aggregate.scalar;
12607 
12608  /* shift back */
12609  (*left) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12610  (*right) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12611 
12612  *var = (*var)->data.aggregate.var;
12613 
12614  /* check if the interval bounds have to swapped */
12615  if( (*var)->data.aggregate.scalar < 0.0 )
12616  {
12617  SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
12618  }
12619  else
12620  {
12621  SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
12622  }
12623  break;
12624 
12625  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12626  assert((*var)->negatedvar != NULL);
12627  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12628  assert((*var)->negatedvar->negatedvar == *var);
12629 
12630  /* shift and scale back */
12631  (*left) = (*var)->data.negate.constant - (*left);
12632  (*right) = (*var)->data.negate.constant - (*right);
12633 
12634  *var = (*var)->negatedvar;
12635 
12636  /* through the negated variable the left and right interval bound have to swapped */
12637  SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
12638  break;
12639 
12640  default:
12641  SCIPerrorMessage("unknown variable status\n");
12642  return SCIP_INVALIDDATA;
12643  }
12644 
12645  return SCIP_OKAY;
12646 }
12647 
12648 /** transforms given variable, scalar and constant to the corresponding active, fixed, or
12649  * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed variable,
12650  * "scalar" will be 0.0 and the value of the sum will be stored in "constant"; a multi-aggregation
12651  * with only one active variable (this can happen due to fixings after the multi-aggregation),
12652  * is treated like an aggregation; if the multi-aggregation constant is infinite, "scalar" will be 0.0
12653  */
12655  SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
12656  SCIP_SET* set, /**< global SCIP settings */
12657  SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
12658  SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
12659  )
12660 {
12661  assert(var != NULL);
12662  assert(scalar != NULL);
12663  assert(constant != NULL);
12664 
12665  while( *var != NULL )
12666  {
12667  switch( SCIPvarGetStatus(*var) )
12668  {
12670  if( (*var)->data.original.transvar == NULL )
12671  {
12672  SCIPerrorMessage("original variable has no transformed variable attached\n");
12673  return SCIP_INVALIDDATA;
12674  }
12675  *var = (*var)->data.original.transvar;
12676  break;
12677 
12678  case SCIP_VARSTATUS_LOOSE:
12679  case SCIP_VARSTATUS_COLUMN:
12680  return SCIP_OKAY;
12681 
12682  case SCIP_VARSTATUS_FIXED: /* x = c' => a*x + c == (a*c' + c) */
12683  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12684  {
12685  if( SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)) )
12686  {
12687  assert(*scalar != 0.0);
12688  if( (*scalar) * (*var)->glbdom.lb > 0.0 )
12689  (*constant) = SCIPsetInfinity(set);
12690  else
12691  (*constant) = -SCIPsetInfinity(set);
12692  }
12693  else
12694  (*constant) += *scalar * (*var)->glbdom.lb;
12695  }
12696 #ifndef NDEBUG
12697  else
12698  {
12699  assert(!SCIPsetIsInfinity(set, (*constant)) || !((*scalar) * (*var)->glbdom.lb < 0.0 &&
12700  (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
12701  assert(!SCIPsetIsInfinity(set, -(*constant)) || !((*scalar) * (*var)->glbdom.lb > 0.0 &&
12702  (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
12703  }
12704 #endif
12705  *scalar = 0.0;
12706  return SCIP_OKAY;
12707 
12709  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12710  if ( (*var)->data.multaggr.nvars == 1 )
12711  {
12712  assert((*var)->data.multaggr.vars != NULL);
12713  assert((*var)->data.multaggr.scalars != NULL);
12714  assert((*var)->data.multaggr.vars[0] != NULL);
12715  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12716  {
12717  /* the multi-aggregation constant can be infinite, if one of the multi-aggregation variables
12718  * was fixed to +/-infinity; ensure that the constant is set to +/-infinity, too, and the scalar
12719  * is set to 0.0, because the multi-aggregated variable can be seen as fixed, too
12720  */
12721  if( SCIPsetIsInfinity(set, (*var)->data.multaggr.constant)
12722  || SCIPsetIsInfinity(set, -((*var)->data.multaggr.constant)) )
12723  {
12724  if( (*scalar) * (*var)->data.multaggr.constant > 0 )
12725  {
12726  assert(!SCIPsetIsInfinity(set, -(*constant)));
12727  (*constant) = SCIPsetInfinity(set);
12728  }
12729  else
12730  {
12731  assert(!SCIPsetIsInfinity(set, *constant));
12732  (*constant) = -SCIPsetInfinity(set);
12733  }
12734  (*scalar) = 0.0;
12735  }
12736  else
12737  (*constant) += *scalar * (*var)->data.multaggr.constant;
12738  }
12739  (*scalar) *= (*var)->data.multaggr.scalars[0];
12740  *var = (*var)->data.multaggr.vars[0];
12741  break;
12742  }
12743  return SCIP_OKAY;
12744 
12745  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
12746  assert((*var)->data.aggregate.var != NULL);
12747  assert(!SCIPsetIsInfinity(set, (*var)->data.aggregate.constant)
12748  && !SCIPsetIsInfinity(set, (*var)->data.aggregate.constant));
12749  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12750  (*constant) += *scalar * (*var)->data.aggregate.constant;
12751  (*scalar) *= (*var)->data.aggregate.scalar;
12752  *var = (*var)->data.aggregate.var;
12753  break;
12754 
12755  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
12756  assert((*var)->negatedvar != NULL);
12757  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12758  assert((*var)->negatedvar->negatedvar == *var);
12759  assert(!SCIPsetIsInfinity(set, (*var)->data.negate.constant)
12760  && !SCIPsetIsInfinity(set, (*var)->data.negate.constant));
12761  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12762  (*constant) += *scalar * (*var)->data.negate.constant;
12763  (*scalar) *= -1.0;
12764  *var = (*var)->negatedvar;
12765  break;
12766 
12767  default:
12768  SCIPerrorMessage("unknown variable status\n");
12769  SCIPABORT();
12770  return SCIP_INVALIDDATA; /*lint !e527*/
12771  }
12772  }
12773  *scalar = 0.0;
12774 
12775  return SCIP_OKAY;
12776 }
12777 
12778 /** retransforms given variable, scalar and constant to the corresponding original variable, scalar
12779  * and constant, if possible; if the retransformation is impossible, NULL is returned as variable
12780  */
12782  SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
12783  SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
12784  SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
12785  )
12786 {
12787  SCIP_VAR* parentvar;
12788 
12789  assert(var != NULL);
12790  assert(*var != NULL);
12791  assert(scalar != NULL);
12792  assert(constant != NULL);
12793 
12794  while( !SCIPvarIsOriginal(*var) )
12795  {
12796  /* if the variable has no parent variables, it was generated during solving and has no corresponding original
12797  * var
12798  */
12799  if( (*var)->nparentvars == 0 )
12800  {
12801  /* negated variables do not need to have a parent variables, and negated variables can exist in original
12802  * space
12803  */
12805  ((*var)->negatedvar->nparentvars == 0 || (*var)->negatedvar->parentvars[0] != *var) )
12806  {
12807  *scalar *= -1.0;
12808  *constant -= (*var)->data.negate.constant * (*scalar);
12809  *var = (*var)->negatedvar;
12810 
12811  continue;
12812  }
12813  /* if the variables does not have any parent the variables was created during solving and has no original
12814  * counterpart
12815  */
12816  else
12817  {
12818  *var = NULL;
12819 
12820  return SCIP_OKAY;
12821  }
12822  }
12823 
12824  /* follow the link to the first parent variable */
12825  parentvar = (*var)->parentvars[0];
12826  assert(parentvar != NULL);
12827 
12828  switch( SCIPvarGetStatus(parentvar) )
12829  {
12831  break;
12832 
12833  case SCIP_VARSTATUS_COLUMN:
12834  case SCIP_VARSTATUS_LOOSE:
12835  case SCIP_VARSTATUS_FIXED:
12837  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
12838  return SCIP_INVALIDDATA;
12839 
12840  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + b -> y = (x-b)/a, s*y + c = (s/a)*x + c-b*s/a */
12841  assert(parentvar->data.aggregate.var == *var);
12842  assert(parentvar->data.aggregate.scalar != 0.0);
12843  *scalar /= parentvar->data.aggregate.scalar;
12844  *constant -= parentvar->data.aggregate.constant * (*scalar);
12845  break;
12846 
12847  case SCIP_VARSTATUS_NEGATED: /* x = b - y -> y = b - x, s*y + c = -s*x + c+b*s */
12848  assert(parentvar->negatedvar != NULL);
12849  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
12850  assert(parentvar->negatedvar->negatedvar == parentvar);
12851  *scalar *= -1.0;
12852  *constant -= parentvar->data.negate.constant * (*scalar);
12853  break;
12854 
12855  default:
12856  SCIPerrorMessage("unknown variable status\n");
12857  return SCIP_INVALIDDATA;
12858  }
12859 
12860  assert( parentvar != NULL );
12861  *var = parentvar;
12862  }
12863 
12864  return SCIP_OKAY;
12865 }
12866 
12867 /** returns whether the given variable is the direct counterpart of an original problem variable */
12869  SCIP_VAR* var /**< problem variable */
12870  )
12871 {
12872  SCIP_VAR* parentvar;
12873  assert(var != NULL);
12874 
12875  if( !SCIPvarIsTransformed(var) || var->nparentvars < 1 )
12876  return FALSE;
12877 
12878  assert(var->parentvars != NULL);
12879  parentvar = var->parentvars[0];
12880  assert(parentvar != NULL);
12881 
12882  /* we follow the aggregation tree to the root unless an original variable has been found - the first entries in the parentlist are candidates */
12883  while( parentvar->nparentvars >= 1 && SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL )
12884  parentvar = parentvar->parentvars[0];
12885  assert( parentvar != NULL );
12886 
12887  return ( SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_ORIGINAL );
12888 }
12889 
12890 /** gets objective value of variable in current SCIP_LP; the value can be different from the objective value stored in
12891  * the variable's own data due to diving, that operate only on the LP without updating the variables
12892  */
12894  SCIP_VAR* var /**< problem variable */
12895  )
12896 {
12897  assert(var != NULL);
12898 
12899  /* get bounds of attached variables */
12900  switch( SCIPvarGetStatus(var) )
12901  {
12903  assert(var->data.original.transvar != NULL);
12904  return SCIPvarGetObjLP(var->data.original.transvar);
12905 
12906  case SCIP_VARSTATUS_COLUMN:
12907  assert(var->data.col != NULL);
12908  return SCIPcolGetObj(var->data.col);
12909 
12910  case SCIP_VARSTATUS_LOOSE:
12911  case SCIP_VARSTATUS_FIXED:
12912  return var->obj;
12913 
12914  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12915  assert(var->data.aggregate.var != NULL);
12916  return var->data.aggregate.scalar * SCIPvarGetObjLP(var->data.aggregate.var);
12917 
12919  SCIPerrorMessage("cannot get the objective value of a multiple aggregated variable\n");
12920  SCIPABORT();
12921  return 0.0; /*lint !e527*/
12922 
12923  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12924  assert(var->negatedvar != NULL);
12926  assert(var->negatedvar->negatedvar == var);
12927  return -SCIPvarGetObjLP(var->negatedvar);
12928 
12929  default:
12930  SCIPerrorMessage("unknown variable status\n");
12931  SCIPABORT();
12932  return 0.0; /*lint !e527*/
12933  }
12934 }
12935 
12936 /** gets lower bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
12937  * data due to diving or conflict analysis, that operate only on the LP without updating the variables
12938  */
12940  SCIP_VAR* var, /**< problem variable */
12941  SCIP_SET* set /**< global SCIP settings */
12942  )
12943 {
12944  assert(var != NULL);
12945  assert(set != NULL);
12946  assert(var->scip == set->scip);
12947 
12948  /* get bounds of attached variables */
12949  switch( SCIPvarGetStatus(var) )
12950  {
12952  assert(var->data.original.transvar != NULL);
12953  return SCIPvarGetLbLP(var->data.original.transvar, set);
12954 
12955  case SCIP_VARSTATUS_COLUMN:
12956  assert(var->data.col != NULL);
12957  return SCIPcolGetLb(var->data.col);
12958 
12959  case SCIP_VARSTATUS_LOOSE:
12960  case SCIP_VARSTATUS_FIXED:
12961  return var->locdom.lb;
12962 
12963  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12964  assert(var->data.aggregate.var != NULL);
12965  if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set)))
12966  || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set))) )
12967  {
12968  return -SCIPsetInfinity(set);
12969  }
12970  else if( var->data.aggregate.scalar > 0.0 )
12971  {
12972  /* a > 0 -> get lower bound of y */
12973  return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12974  }
12975  else if( var->data.aggregate.scalar < 0.0 )
12976  {
12977  /* a < 0 -> get upper bound of y */
12978  return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12979  }
12980  else
12981  {
12982  SCIPerrorMessage("scalar is zero in aggregation\n");
12983  SCIPABORT();
12984  return SCIP_INVALID; /*lint !e527*/
12985  }
12986 
12988  /**@todo get the sides of the corresponding linear constraint */
12989  SCIPerrorMessage("getting the bounds of a multiple aggregated variable is not implemented yet\n");
12990  SCIPABORT();
12991  return SCIP_INVALID; /*lint !e527*/
12992 
12993  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12994  assert(var->negatedvar != NULL);
12996  assert(var->negatedvar->negatedvar == var);
12997  return var->data.negate.constant - SCIPvarGetUbLP(var->negatedvar, set);
12998 
12999  default:
13000  SCIPerrorMessage("unknown variable status\n");
13001  SCIPABORT();
13002  return SCIP_INVALID; /*lint !e527*/
13003  }
13004 }
13005 
13006 /** gets upper bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
13007  * data due to diving or conflict analysis, that operate only on the LP without updating the variables
13008  */
13010  SCIP_VAR* var, /**< problem variable */
13011  SCIP_SET* set /**< global SCIP settings */
13012  )
13013 {
13014  assert(var != NULL);
13015  assert(set != NULL);
13016  assert(var->scip == set->scip);
13017 
13018  /* get bounds of attached variables */
13019  switch( SCIPvarGetStatus(var) )
13020  {
13022  assert(var->data.original.transvar != NULL);
13023  return SCIPvarGetUbLP(var->data.original.transvar, set);
13024 
13025  case SCIP_VARSTATUS_COLUMN:
13026  assert(var->data.col != NULL);
13027  return SCIPcolGetUb(var->data.col);
13028 
13029  case SCIP_VARSTATUS_LOOSE:
13030  case SCIP_VARSTATUS_FIXED:
13031  return var->locdom.ub;
13032 
13033  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
13034  assert(var->data.aggregate.var != NULL);
13035  if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set)))
13036  || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set))) )
13037  {
13038  return SCIPsetInfinity(set);
13039  }
13040  if( var->data.aggregate.scalar > 0.0 )
13041  {
13042  /* a > 0 -> get upper bound of y */
13043  return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
13044  }
13045  else if( var->data.aggregate.scalar < 0.0 )
13046  {
13047  /* a < 0 -> get lower bound of y */
13048  return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
13049  }
13050  else
13051  {
13052  SCIPerrorMessage("scalar is zero in aggregation\n");
13053  SCIPABORT();
13054  return SCIP_INVALID; /*lint !e527*/
13055  }
13056 
13058  SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
13059  SCIPABORT();
13060  return SCIP_INVALID; /*lint !e527*/
13061 
13062  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13063  assert(var->negatedvar != NULL);
13065  assert(var->negatedvar->negatedvar == var);
13066  return var->data.negate.constant - SCIPvarGetLbLP(var->negatedvar, set);
13067 
13068  default:
13069  SCIPerrorMessage("unknown variable status\n");
13070  SCIPABORT();
13071  return SCIP_INVALID; /*lint !e527*/
13072  }
13073 }
13074 
13075 /** gets primal LP solution value of variable */
13077  SCIP_VAR* var /**< problem variable */
13078  )
13079 {
13080  assert(var != NULL);
13081 
13082  switch( SCIPvarGetStatus(var) )
13083  {
13085  if( var->data.original.transvar == NULL )
13086  return SCIP_INVALID;
13087  return SCIPvarGetLPSol(var->data.original.transvar);
13088 
13089  case SCIP_VARSTATUS_LOOSE:
13090  return SCIPvarGetBestBoundLocal(var);
13091 
13092  case SCIP_VARSTATUS_COLUMN:
13093  assert(var->data.col != NULL);
13094  return SCIPcolGetPrimsol(var->data.col);
13095 
13096  case SCIP_VARSTATUS_FIXED:
13097  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13098  return var->locdom.lb;
13099 
13101  {
13102  SCIP_Real lpsolval;
13103 
13104  assert(!var->donotaggr);
13105  assert(var->data.aggregate.var != NULL);
13106  lpsolval = SCIPvarGetLPSol(var->data.aggregate.var);
13107 
13108  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13109  * corresponding infinity value instead of performing an arithmetical transformation (compare method
13110  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13111  * (or is called by) a public interface method; instead, we only assert that values are finite
13112  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13113  * positives and negatives if the parameter <numerics/infinity> is modified by the user
13114  */
13115  assert(lpsolval > -SCIP_DEFAULT_INFINITY);
13116  assert(lpsolval < +SCIP_DEFAULT_INFINITY);
13117  return var->data.aggregate.scalar * lpsolval + var->data.aggregate.constant;
13118  }
13120  {
13121  SCIP_Real primsol;
13122  int i;
13123 
13124  assert(!var->donotmultaggr);
13125  assert(var->data.multaggr.vars != NULL);
13126  assert(var->data.multaggr.scalars != NULL);
13127  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13128  * assert(var->data.multaggr.nvars >= 2);
13129  */
13130  primsol = var->data.multaggr.constant;
13131  for( i = 0; i < var->data.multaggr.nvars; ++i )
13132  primsol += var->data.multaggr.scalars[i] * SCIPvarGetLPSol(var->data.multaggr.vars[i]);
13133  return primsol;
13134  }
13135  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13136  assert(var->negatedvar != NULL);
13138  assert(var->negatedvar->negatedvar == var);
13139  return var->data.negate.constant - SCIPvarGetLPSol(var->negatedvar);
13140 
13141  default:
13142  SCIPerrorMessage("unknown variable status\n");
13143  SCIPABORT();
13144  return SCIP_INVALID; /*lint !e527*/
13145  }
13146 }
13147 
13148 /** gets primal NLP solution value of variable */
13150  SCIP_VAR* var /**< problem variable */
13151  )
13152 {
13153  SCIP_Real solval;
13154  int i;
13155 
13156  assert(var != NULL);
13157 
13158  /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
13159  switch( SCIPvarGetStatus(var) )
13160  {
13162  return SCIPvarGetNLPSol(var->data.original.transvar);
13163 
13164  case SCIP_VARSTATUS_LOOSE:
13165  case SCIP_VARSTATUS_COLUMN:
13166  return var->nlpsol;
13167 
13168  case SCIP_VARSTATUS_FIXED:
13169  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
13170  assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
13171  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
13172  return SCIPvarGetLbGlobal(var);
13173 
13174  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13175  solval = SCIPvarGetNLPSol(var->data.aggregate.var);
13176  return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
13177 
13179  solval = var->data.multaggr.constant;
13180  for( i = 0; i < var->data.multaggr.nvars; ++i )
13181  solval += var->data.multaggr.scalars[i] * SCIPvarGetNLPSol(var->data.multaggr.vars[i]);
13182  return solval;
13183 
13185  solval = SCIPvarGetNLPSol(var->negatedvar);
13186  return var->data.negate.constant - solval;
13187 
13188  default:
13189  SCIPerrorMessage("unknown variable status\n");
13190  SCIPABORT();
13191  return SCIP_INVALID; /*lint !e527*/
13192  }
13193 }
13194 
13195 /** gets pseudo solution value of variable at current node */
13196 static
13198  SCIP_VAR* var /**< problem variable */
13199  )
13200 {
13201  SCIP_Real pseudosol;
13202  int i;
13203 
13204  assert(var != NULL);
13205 
13206  switch( SCIPvarGetStatus(var) )
13207  {
13209  if( var->data.original.transvar == NULL )
13210  return SCIP_INVALID;
13212 
13213  case SCIP_VARSTATUS_LOOSE:
13214  case SCIP_VARSTATUS_COLUMN:
13215  return SCIPvarGetBestBoundLocal(var);
13216 
13217  case SCIP_VARSTATUS_FIXED:
13218  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13219  return var->locdom.lb;
13220 
13222  {
13223  SCIP_Real pseudosolval;
13224  assert(!var->donotaggr);
13225  assert(var->data.aggregate.var != NULL);
13226  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13227  * corresponding infinity value instead of performing an arithmetical transformation (compare method
13228  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13229  * (or is called by) a public interface method; instead, we only assert that values are finite
13230  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13231  * positives and negatives if the parameter <numerics/infinity> is modified by the user
13232  */
13233  pseudosolval = SCIPvarGetPseudoSol(var->data.aggregate.var);
13234  assert(pseudosolval > -SCIP_DEFAULT_INFINITY);
13235  assert(pseudosolval < +SCIP_DEFAULT_INFINITY);
13236  return var->data.aggregate.scalar * pseudosolval + var->data.aggregate.constant;
13237  }
13239  assert(!var->donotmultaggr);
13240  assert(var->data.multaggr.vars != NULL);
13241  assert(var->data.multaggr.scalars != NULL);
13242  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13243  * assert(var->data.multaggr.nvars >= 2);
13244  */
13245  pseudosol = var->data.multaggr.constant;
13246  for( i = 0; i < var->data.multaggr.nvars; ++i )
13247  pseudosol += var->data.multaggr.scalars[i] * SCIPvarGetPseudoSol(var->data.multaggr.vars[i]);
13248  return pseudosol;
13249 
13250  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13251  assert(var->negatedvar != NULL);
13253  assert(var->negatedvar->negatedvar == var);
13254  return var->data.negate.constant - SCIPvarGetPseudoSol(var->negatedvar);
13255 
13256  default:
13257  SCIPerrorMessage("unknown variable status\n");
13258  SCIPABORT();
13259  return SCIP_INVALID; /*lint !e527*/
13260  }
13261 }
13262 
13263 /** gets current LP or pseudo solution value of variable */
13265  SCIP_VAR* var, /**< problem variable */
13266  SCIP_Bool getlpval /**< should the LP solution value be returned? */
13267  )
13268 {
13269  if( getlpval )
13270  return SCIPvarGetLPSol(var);
13271  else
13272  return SCIPvarGetPseudoSol(var);
13273 }
13274 
13275 /** remembers the current solution as root solution in the problem variables */
13276 void SCIPvarStoreRootSol(
13277  SCIP_VAR* var, /**< problem variable */
13278  SCIP_Bool roothaslp /**< is the root solution from LP? */
13279  )
13280 {
13281  assert(var != NULL);
13282 
13283  var->rootsol = SCIPvarGetSol(var, roothaslp);
13284 }
13285 
13286 /** updates the current solution as best root solution of the given variable if it is better */
13288  SCIP_VAR* var, /**< problem variable */
13289  SCIP_SET* set, /**< global SCIP settings */
13290  SCIP_Real rootsol, /**< root solution value */
13291  SCIP_Real rootredcost, /**< root reduced cost */
13292  SCIP_Real rootlpobjval /**< objective value of the root LP */
13293  )
13294 {
13295  assert(var != NULL);
13296  assert(set != NULL);
13297  assert(var->scip == set->scip);
13298 
13299  /* if reduced cost are zero nothing to update */
13300  if( SCIPsetIsDualfeasZero(set, rootredcost) )
13301  return;
13302 
13303  /* check if we have already a best combination stored */
13304  if( !SCIPsetIsDualfeasZero(set, var->bestrootredcost) )
13305  {
13306  SCIP_Real currcutoffbound;
13307  SCIP_Real cutoffbound;
13308  SCIP_Real bound;
13309 
13310  /* compute the cutoff bound which would improve the corresponding bound with the current stored root solution,
13311  * root reduced cost, and root LP objective value combination
13312  */
13313  if( var->bestrootredcost > 0.0 )
13314  bound = SCIPvarGetUbGlobal(var);
13315  else
13316  bound = SCIPvarGetLbGlobal(var);
13317 
13318  currcutoffbound = (bound - var->bestrootsol) * var->bestrootredcost + var->bestrootlpobjval;
13319 
13320  /* compute the cutoff bound which would improve the corresponding bound with new root solution, root reduced
13321  * cost, and root LP objective value combination
13322  */
13323  if( rootredcost > 0.0 )
13324  bound = SCIPvarGetUbGlobal(var);
13325  else
13326  bound = SCIPvarGetLbGlobal(var);
13327 
13328  cutoffbound = (bound - rootsol) * rootredcost + rootlpobjval;
13329 
13330  /* check if an improving root solution, root reduced cost, and root LP objective value is at hand */
13331  if( cutoffbound > currcutoffbound )
13332  {
13333  SCIPsetDebugMsg(set, "-> <%s> update potential cutoff bound <%g> -> <%g>\n",
13334  SCIPvarGetName(var), currcutoffbound, cutoffbound);
13335 
13336  var->bestrootsol = rootsol;
13337  var->bestrootredcost = rootredcost;
13338  var->bestrootlpobjval = rootlpobjval;
13339  }
13340  }
13341  else
13342  {
13343  SCIPsetDebugMsg(set, "-> <%s> initialize best root reduced cost information\n", SCIPvarGetName(var));
13344  SCIPsetDebugMsg(set, " -> rootsol <%g>\n", rootsol);
13345  SCIPsetDebugMsg(set, " -> rootredcost <%g>\n", rootredcost);
13346  SCIPsetDebugMsg(set, " -> rootlpobjval <%g>\n", rootlpobjval);
13347 
13348  var->bestrootsol = rootsol;
13349  var->bestrootredcost = rootredcost;
13350  var->bestrootlpobjval = rootlpobjval;
13351  }
13352 }
13353 
13354 /** returns the solution of the variable in the last root node's relaxation, if the root relaxation is not yet
13355  * completely solved, zero is returned
13356  */
13358  SCIP_VAR* var /**< problem variable */
13359  )
13360 {
13361  SCIP_Real rootsol;
13362  int i;
13363 
13364  assert(var != NULL);
13365 
13366  switch( SCIPvarGetStatus(var) )
13367  {
13369  if( var->data.original.transvar == NULL )
13370  return 0.0;
13371  return SCIPvarGetRootSol(var->data.original.transvar);
13372 
13373  case SCIP_VARSTATUS_LOOSE:
13374  case SCIP_VARSTATUS_COLUMN:
13375  return var->rootsol;
13376 
13377  case SCIP_VARSTATUS_FIXED:
13378  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13379  return var->locdom.lb;
13380 
13382  assert(!var->donotaggr);
13383  assert(var->data.aggregate.var != NULL);
13384  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13385  * corresponding infinity value instead of performing an arithmetical transformation (compare method
13386  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13387  * (or is called by) a public interface method; instead, we only assert that values are finite
13388  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13389  * positives and negatives if the parameter <numerics/infinity> is modified by the user
13390  */
13394 
13396  assert(!var->donotmultaggr);
13397  assert(var->data.multaggr.vars != NULL);
13398  assert(var->data.multaggr.scalars != NULL);
13399  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13400  * assert(var->data.multaggr.nvars >= 2);
13401  */
13402  rootsol = var->data.multaggr.constant;
13403  for( i = 0; i < var->data.multaggr.nvars; ++i )
13404  rootsol += var->data.multaggr.scalars[i] * SCIPvarGetRootSol(var->data.multaggr.vars[i]);
13405  return rootsol;
13406 
13407  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13408  assert(var->negatedvar != NULL);
13410  assert(var->negatedvar->negatedvar == var);
13411  return var->data.negate.constant - SCIPvarGetRootSol(var->negatedvar);
13412 
13413  default:
13414  SCIPerrorMessage("unknown variable status\n");
13415  SCIPABORT();
13416  return SCIP_INVALID; /*lint !e527*/
13417  }
13418 }
13419 
13420 /** returns for given variable the reduced cost */
13421 static
13423  SCIP_VAR* var, /**< problem variable */
13424  SCIP_SET* set, /**< global SCIP settings */
13425  SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
13426  SCIP_STAT* stat, /**< problem statistics */
13427  SCIP_LP* lp /**< current LP data */
13428  )
13429 {
13431  {
13432  SCIP_COL* col;
13433  SCIP_Real primsol;
13434  SCIP_BASESTAT basestat;
13435  SCIP_Bool lpissolbasic;
13436 
13437  col = SCIPvarGetCol(var);
13438  assert(col != NULL);
13439 
13440  basestat = SCIPcolGetBasisStatus(col);
13441  lpissolbasic = SCIPlpIsSolBasic(lp);
13442  primsol = SCIPcolGetPrimsol(col);
13443 
13444  if( (lpissolbasic && (basestat == SCIP_BASESTAT_LOWER || basestat == SCIP_BASESTAT_UPPER)) ||
13445  (!lpissolbasic && (SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol) || SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol))) )
13446  {
13447  SCIP_Real redcost = SCIPcolGetRedcost(col, stat, lp);
13448 
13449  assert(((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)) ||
13450  (lpissolbasic && basestat == SCIP_BASESTAT_LOWER)) ? (!SCIPsetIsDualfeasNegative(set, redcost) ||
13452  assert(((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)) ||
13453  (lpissolbasic && basestat == SCIP_BASESTAT_UPPER)) ? (!SCIPsetIsDualfeasPositive(set, redcost) ||
13454  SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var))) : TRUE);
13455 
13456  if( (varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_LOWER) ||
13457  (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)))) ||
13458  (!varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_UPPER) ||
13459  (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)))) )
13460  return redcost;
13461  else
13462  return 0.0;
13463  }
13464 
13465  return 0.0;
13466  }
13467 
13468  return 0.0;
13469 }
13470 
13471 #define MAX_CLIQUELENGTH 50
13472 /** returns for the given binary variable the reduced cost which are given by the variable itself and its implication if
13473  * the binary variable is fixed to the given value
13474  */
13476  SCIP_VAR* var, /**< problem variable */
13477  SCIP_SET* set, /**< global SCIP settings */
13478  SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
13479  SCIP_STAT* stat, /**< problem statistics */
13480  SCIP_PROB* prob, /**< transformed problem, or NULL */
13481  SCIP_LP* lp /**< current LP data */
13482  )
13483 {
13484  SCIP_Real implredcost;
13485  int ncliques;
13486  int nvars;
13487 
13488  assert(SCIPvarIsBinary(var));
13489  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
13490 
13491  /* get reduced cost of given variable */
13492  implredcost = getImplVarRedcost(var, set, varfixing, stat, lp);
13493 
13494 #ifdef SCIP_MORE_DEBUG
13495  SCIPsetDebugMsg(set, "variable <%s> itself has reduced cost of %g\n", SCIPvarGetName(var), implredcost);
13496 #endif
13497 
13498  /* the following algorithm is expensive */
13499  ncliques = SCIPvarGetNCliques(var, varfixing);
13500 
13501  if( ncliques > 0 )
13502  {
13503  SCIP_CLIQUE** cliques;
13504  SCIP_CLIQUE* clique;
13505  SCIP_VAR** clqvars;
13506  SCIP_VAR** probvars;
13507  SCIP_VAR* clqvar;
13508  SCIP_Bool* clqvalues;
13509  int* entries;
13510  int* ids;
13511  SCIP_Real redcost;
13512  SCIP_Bool cleanedup;
13513  int nclqvars;
13514  int nentries;
13515  int nids;
13516  int id;
13517  int c;
13518  int v;
13519 
13520  assert(prob != NULL);
13521  assert(SCIPprobIsTransformed(prob));
13522 
13523  nentries = SCIPprobGetNVars(prob) - SCIPprobGetNContVars(prob) + 1;
13524 
13525  SCIP_CALL_ABORT( SCIPsetAllocBufferArray(set, &ids, nentries) );
13526  nids = 0;
13527  SCIP_CALL_ABORT( SCIPsetAllocCleanBufferArray(set, &entries, nentries) );
13528 
13529  cliques = SCIPvarGetCliques(var, varfixing);
13530  assert(cliques != NULL);
13531 
13532  for( c = ncliques - 1; c >= 0; --c )
13533  {
13534  clique = cliques[c];
13535  assert(clique != NULL);
13536  nclqvars = SCIPcliqueGetNVars(clique);
13537  assert(nclqvars > 0);
13538 
13539  if( nclqvars > MAX_CLIQUELENGTH )
13540  continue;
13541 
13542  clqvars = SCIPcliqueGetVars(clique);
13543  clqvalues = SCIPcliqueGetValues(clique);
13544  assert(clqvars != NULL);
13545  assert(clqvalues != NULL);
13546 
13547  cleanedup = SCIPcliqueIsCleanedUp(clique);
13548 
13549  for( v = nclqvars - 1; v >= 0; --v )
13550  {
13551  clqvar = clqvars[v];
13552  assert(clqvar != NULL);
13553 
13554  /* ignore binary variable which are fixed */
13555  if( clqvar != var && (cleanedup || SCIPvarIsActive(clqvar)) &&
13556  (SCIPvarGetLbLocal(clqvar) < 0.5 && SCIPvarGetUbLocal(clqvar) > 0.5) )
13557  {
13558  int probindex = SCIPvarGetProbindex(clqvar) + 1;
13559  assert(0 < probindex && probindex < nentries);
13560 
13561 #if 0
13562  /* check that the variable was not yet visited or does not appear with two contradicting implications, ->
13563  * can appear since there is no guarantee that all these infeasible bounds were found
13564  */
13565  assert(!entries[probindex] || entries[probindex] == (clqvalues[v] ? probindex : -probindex));
13566 #endif
13567  if( entries[probindex] == 0 )
13568  {
13569  ids[nids] = probindex;
13570  ++nids;
13571 
13572  /* mark variable as visited */
13573  entries[probindex] = (clqvalues[v] ? probindex : -probindex);
13574  }
13575  }
13576  }
13577  }
13578 
13579  probvars = SCIPprobGetVars(prob);
13580  assert(probvars != NULL);
13581 
13582  /* add all implied reduced cost */
13583  for( v = nids - 1; v >= 0; --v )
13584  {
13585  id = ids[v];
13586  assert(0 < id && id < nentries);
13587  assert(entries[id] != 0);
13588  assert(probvars[id - 1] != NULL);
13589  assert(SCIPvarIsActive(probvars[id - 1]));
13590  assert(SCIPvarIsBinary(probvars[id - 1]));
13591  assert(SCIPvarGetLbLocal(probvars[id - 1]) < 0.5 && SCIPvarGetUbLocal(probvars[id - 1]) > 0.5);
13592 
13593  if( (entries[id] > 0) != varfixing )
13594  redcost = getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
13595  else
13596  redcost = -getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
13597 
13598  if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
13599  implredcost += redcost;
13600 
13601  /* reset entries clear buffer array */
13602  entries[id] = 0;
13603  }
13604 
13605  SCIPsetFreeCleanBufferArray(set, &entries);
13606  SCIPsetFreeBufferArray(set, &ids);
13607  }
13608 
13609 #ifdef SCIP_MORE_DEBUG
13610  SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) has implied reduced cost of %g\n", SCIPvarGetName(var), ncliques,
13611  implredcost);
13612 #endif
13613 
13614  /* collect non-binary implication information */
13615  nvars = SCIPimplicsGetNImpls(var->implics, varfixing);
13616 
13617  if( nvars > 0 )
13618  {
13619  SCIP_VAR** vars;
13620  SCIP_VAR* implvar;
13621  SCIP_COL* col;
13622  SCIP_Real* bounds;
13623  SCIP_BOUNDTYPE* boundtypes;
13624  SCIP_Real redcost;
13625  SCIP_Real lb;
13626  SCIP_Real ub;
13627  SCIP_Bool lpissolbasic;
13628  int v;
13629 
13630  vars = SCIPimplicsGetVars(var->implics, varfixing);
13631  boundtypes = SCIPimplicsGetTypes(var->implics, varfixing);
13632  bounds = SCIPimplicsGetBounds(var->implics, varfixing);
13633  lpissolbasic = SCIPlpIsSolBasic(lp);
13634 
13635  for( v = nvars - 1; v >= 0; --v )
13636  {
13637  implvar = vars[v];
13638  assert(implvar != NULL);
13639 
13640  lb = SCIPvarGetLbLocal(implvar);
13641  ub = SCIPvarGetUbLocal(implvar);
13642 
13643  /* ignore binary variable which are fixed or not of column status */
13644  if( SCIPvarGetStatus(implvar) != SCIP_VARSTATUS_COLUMN || SCIPsetIsFeasEQ(set, lb, ub) )
13645  continue;
13646 
13647  col = SCIPvarGetCol(implvar);
13648  assert(col != NULL);
13649  redcost = 0.0;
13650 
13651  /* solved lp with basis information or not? */
13652  if( lpissolbasic )
13653  {
13654  SCIP_BASESTAT basestat = SCIPcolGetBasisStatus(col);
13655 
13656  /* check if the implication is not not yet applied */
13657  if( basestat == SCIP_BASESTAT_LOWER && boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGT(set, bounds[v], lb) )
13658  {
13659  redcost = SCIPcolGetRedcost(col, stat, lp);
13660  assert(!SCIPsetIsDualfeasNegative(set, redcost));
13661 
13662  if( !varfixing )
13663  redcost *= (lb - bounds[v]);
13664  else
13665  redcost *= (bounds[v] - lb);
13666  }
13667  else if( basestat == SCIP_BASESTAT_UPPER && boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLT(set, bounds[v], ub) )
13668  {
13669  redcost = SCIPcolGetRedcost(col, stat, lp);
13670  assert(!SCIPsetIsDualfeasPositive(set, redcost));
13671 
13672  if( varfixing )
13673  redcost *= (bounds[v] - ub);
13674  else
13675  redcost *= (ub - bounds[v]);
13676  }
13677  }
13678  else
13679  {
13680  SCIP_Real primsol = SCIPcolGetPrimsol(col);
13681 
13682  /* check if the implication is not not yet applied */
13683  if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasEQ(set, lb, primsol) && SCIPsetIsFeasGT(set, bounds[v], lb) )
13684  {
13685  redcost = SCIPcolGetRedcost(col, stat, lp);
13686  assert(!SCIPsetIsDualfeasNegative(set, redcost));
13687 
13688  if( varfixing )
13689  redcost *= (lb - bounds[v]);
13690  else
13691  redcost *= (bounds[v] - lb);
13692  }
13693  else if( boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasEQ(set, ub, primsol) && SCIPsetIsFeasLT(set, bounds[v], ub) )
13694  {
13695  redcost = SCIPcolGetRedcost(col, stat, lp);
13696  assert(!SCIPsetIsDualfeasPositive(set, redcost));
13697 
13698  if( varfixing )
13699  redcost *= (bounds[v] - ub);
13700  else
13701  redcost *= (ub - bounds[v]);
13702  }
13703  }
13704 
13705  /* improve implied reduced cost */
13706  if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
13707  implredcost += redcost;
13708  }
13709  }
13710 
13711 #ifdef SCIP_MORE_DEBUG
13712  SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) and implications (%d) has implied reduced cost of %g\n",
13713  SCIPvarGetName(var), ncliques, nvars, implredcost);
13714 #endif
13715 
13716  return implredcost;
13717 }
13718 
13719 /** returns the best solution (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation, if
13720  * the root relaxation is not yet completely solved, zero is returned
13721  */
13723  SCIP_VAR* var /**< problem variable */
13724  )
13725 {
13726  SCIP_Real rootsol;
13727  int i;
13728 
13729  assert(var != NULL);
13730 
13731  switch( SCIPvarGetStatus(var) )
13732  {
13734  if( var->data.original.transvar == NULL )
13735  return 0.0;
13737 
13738  case SCIP_VARSTATUS_LOOSE:
13739  case SCIP_VARSTATUS_COLUMN:
13740  return var->bestrootsol;
13741 
13742  case SCIP_VARSTATUS_FIXED:
13743  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13744  return var->locdom.lb;
13745 
13747  assert(!var->donotaggr);
13748  assert(var->data.aggregate.var != NULL);
13749  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13750  * corresponding infinity value instead of performing an arithmetical transformation (compare method
13751  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13752  * (or is called by) a public interface method; instead, we only assert that values are finite
13753  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13754  * positives and negatives if the parameter <numerics/infinity> is modified by the user
13755  */
13759 
13761  assert(!var->donotmultaggr);
13762  assert(var->data.multaggr.vars != NULL);
13763  assert(var->data.multaggr.scalars != NULL);
13764  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13765  * assert(var->data.multaggr.nvars >= 2);
13766  */
13767  rootsol = var->data.multaggr.constant;
13768  for( i = 0; i < var->data.multaggr.nvars; ++i )
13769  rootsol += var->data.multaggr.scalars[i] * SCIPvarGetBestRootSol(var->data.multaggr.vars[i]);
13770  return rootsol;
13771 
13772  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13773  assert(var->negatedvar != NULL);
13775  assert(var->negatedvar->negatedvar == var);
13776  return var->data.negate.constant - SCIPvarGetBestRootSol(var->negatedvar);
13777 
13778  default:
13779  SCIPerrorMessage("unknown variable status\n");
13780  SCIPABORT();
13781  return 0.0; /*lint !e527*/
13782  }
13783 }
13784 
13785 /** returns the best reduced costs (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation,
13786  * if the root relaxation is not yet completely solved, or the variable was no column of the root LP, SCIP_INVALID is
13787  * returned
13788  */
13790  SCIP_VAR* var /**< problem variable */
13791  )
13792 {
13793  assert(var != NULL);
13794 
13795  switch( SCIPvarGetStatus(var) )
13796  {
13798  if( var->data.original.transvar == NULL )
13799  return SCIP_INVALID;
13801 
13802  case SCIP_VARSTATUS_LOOSE:
13803  case SCIP_VARSTATUS_COLUMN:
13804  return var->bestrootredcost;
13805 
13806  case SCIP_VARSTATUS_FIXED:
13810  return 0.0;
13811 
13812  default:
13813  SCIPerrorMessage("unknown variable status\n");
13814  SCIPABORT();
13815  return 0.0; /*lint !e527*/
13816  }
13817 }
13818 
13819 /** returns the best objective value (w.r.t. root reduced cost propagation) of the root LP which belongs the root
13820  * reduced cost which is accessible via SCIPvarGetRootRedcost() or the variable was no column of the root LP,
13821  * SCIP_INVALID is returned
13822  */
13824  SCIP_VAR* var /**< problem variable */
13825  )
13826 {
13827  assert(var != NULL);
13828 
13829  switch( SCIPvarGetStatus(var) )
13830  {
13832  if( var->data.original.transvar == NULL )
13833  return SCIP_INVALID;
13835 
13836  case SCIP_VARSTATUS_LOOSE:
13837  case SCIP_VARSTATUS_COLUMN:
13838  return var->bestrootlpobjval;
13839 
13840  case SCIP_VARSTATUS_FIXED:
13844  return SCIP_INVALID;
13845 
13846  default:
13847  SCIPerrorMessage("unknown variable status\n");
13848  SCIPABORT();
13849  return SCIP_INVALID; /*lint !e527*/
13850  }
13851 }
13852 
13853 /** set the given solution as the best root solution w.r.t. root reduced cost propagation in the variables */
13855  SCIP_VAR* var, /**< problem variable */
13856  SCIP_Real rootsol, /**< root solution value */
13857  SCIP_Real rootredcost, /**< root reduced cost */
13858  SCIP_Real rootlpobjval /**< objective value of the root LP */
13859  )
13860 {
13861  assert(var != NULL);
13862 
13863  var->bestrootsol = rootsol;
13864  var->bestrootredcost = rootredcost;
13865  var->bestrootlpobjval = rootlpobjval;
13866 }
13867 
13868 /** stores the solution value as relaxation solution in the problem variable */
13870  SCIP_VAR* var, /**< problem variable */
13871  SCIP_SET* set, /**< global SCIP settings */
13872  SCIP_RELAXATION* relaxation, /**< global relaxation data */
13873  SCIP_Real solval, /**< solution value in the current relaxation solution */
13874  SCIP_Bool updateobj /**< should the objective value be updated? */
13875  )
13876 {
13877  assert(var != NULL);
13878  assert(relaxation != NULL);
13879  assert(set != NULL);
13880  assert(var->scip == set->scip);
13881 
13882  /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
13883  switch( SCIPvarGetStatus(var) )
13884  {
13886  SCIP_CALL( SCIPvarSetRelaxSol(var->data.original.transvar, set, relaxation, solval, updateobj) );
13887  break;
13888 
13889  case SCIP_VARSTATUS_LOOSE:
13890  case SCIP_VARSTATUS_COLUMN:
13891  if( updateobj )
13892  SCIPrelaxationSolObjAdd(relaxation, var->obj * (solval - var->relaxsol));
13893  var->relaxsol = solval;
13894  break;
13895 
13896  case SCIP_VARSTATUS_FIXED:
13897  if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
13898  {
13899  SCIPerrorMessage("cannot set relaxation solution value for variable <%s> fixed to %.15g to different value %.15g\n",
13900  SCIPvarGetName(var), var->glbdom.lb, solval);
13901  return SCIP_INVALIDDATA;
13902  }
13903  break;
13904 
13905  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13906  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
13907  SCIP_CALL( SCIPvarSetRelaxSol(var->data.aggregate.var, set, relaxation,
13908  (solval - var->data.aggregate.constant)/var->data.aggregate.scalar, updateobj) );
13909  break;
13911  SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
13912  return SCIP_INVALIDDATA;
13913 
13915  SCIP_CALL( SCIPvarSetRelaxSol(var->negatedvar, set, relaxation, var->data.negate.constant - solval, updateobj) );
13916  break;
13917 
13918  default:
13919  SCIPerrorMessage("unknown variable status\n");
13920  return SCIP_INVALIDDATA;
13921  }
13922 
13923  return SCIP_OKAY;
13924 }
13925 
13926 /** returns the solution value of the problem variable in the relaxation solution
13927  *
13928  * @todo Inline this function - similar to SCIPvarGetLPSol_rec.
13929  */
13931  SCIP_VAR* var, /**< problem variable */
13932  SCIP_SET* set /**< global SCIP settings */
13933  )
13934 {
13935  SCIP_Real solvalsum;
13936  SCIP_Real solval;
13937  int i;
13938 
13939  assert(var != NULL);
13940  assert(set != NULL);
13941  assert(var->scip == set->scip);
13942 
13943  /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
13944  switch( SCIPvarGetStatus(var) )
13945  {
13947  return SCIPvarGetRelaxSol(var->data.original.transvar, set);
13948 
13949  case SCIP_VARSTATUS_LOOSE:
13950  case SCIP_VARSTATUS_COLUMN:
13951  return var->relaxsol;
13952 
13953  case SCIP_VARSTATUS_FIXED:
13954  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
13955  assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
13956  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
13957  return SCIPvarGetLbGlobal(var);
13958 
13959  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13960  solval = SCIPvarGetRelaxSol(var->data.aggregate.var, set);
13961  if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
13962  {
13963  if( var->data.aggregate.scalar * solval > 0.0 )
13964  return SCIPsetInfinity(set);
13965  if( var->data.aggregate.scalar * solval < 0.0 )
13966  return -SCIPsetInfinity(set);
13967  }
13968  return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
13969 
13971  solvalsum = var->data.multaggr.constant;
13972  for( i = 0; i < var->data.multaggr.nvars; ++i )
13973  {
13974  solval = SCIPvarGetRelaxSol(var->data.multaggr.vars[i], set);
13975  if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
13976  {
13977  if( var->data.multaggr.scalars[i] * solval > 0.0 )
13978  return SCIPsetInfinity(set);
13979  if( var->data.multaggr.scalars[i] * solval < 0.0 )
13980  return -SCIPsetInfinity(set);
13981  }
13982  solvalsum += var->data.multaggr.scalars[i] * solval;
13983  }
13984  return solvalsum;
13985 
13987  solval = SCIPvarGetRelaxSol(var->negatedvar, set);
13988  if( SCIPsetIsInfinity(set, solval) )
13989  return -SCIPsetInfinity(set);
13990  if( SCIPsetIsInfinity(set, -solval) )
13991  return SCIPsetInfinity(set);
13992  return var->data.negate.constant - solval;
13993 
13994  default:
13995  SCIPerrorMessage("unknown variable status\n");
13996  SCIPABORT();
13997  return SCIP_INVALID; /*lint !e527*/
13998  }
13999 }
14000 
14001 /** returns the solution value of the transformed problem variable in the relaxation solution */
14003  SCIP_VAR* var /**< problem variable */
14004  )
14005 {
14006  assert(var != NULL);
14008 
14009  return var->relaxsol;
14010 }
14011 
14012 /** stores the solution value as NLP solution in the problem variable */
14014  SCIP_VAR* var, /**< problem variable */
14015  SCIP_SET* set, /**< global SCIP settings */
14016  SCIP_Real solval /**< solution value in the current NLP solution */
14017  )
14018 {
14019  assert(var != NULL);
14020  assert(set != NULL);
14021  assert(var->scip == set->scip);
14022 
14023  /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
14024  switch( SCIPvarGetStatus(var) )
14025  {
14027  SCIP_CALL( SCIPvarSetNLPSol(var->data.original.transvar, set, solval) );
14028  break;
14029 
14030  case SCIP_VARSTATUS_LOOSE:
14031  case SCIP_VARSTATUS_COLUMN:
14032  var->nlpsol = solval;
14033  break;
14034 
14035  case SCIP_VARSTATUS_FIXED:
14036  if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
14037  {
14038  SCIPerrorMessage("cannot set NLP solution value for variable <%s> fixed to %.15g to different value %.15g\n",
14039  SCIPvarGetName(var), var->glbdom.lb, solval);
14040  SCIPABORT();
14041  return SCIP_INVALIDCALL; /*lint !e527*/
14042  }
14043  break;
14044 
14045  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
14046  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
14047  SCIP_CALL( SCIPvarSetNLPSol(var->data.aggregate.var, set, (solval - var->data.aggregate.constant)/var->data.aggregate.scalar) );
14048  break;
14049 
14051  SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
14052  SCIPABORT();
14053  return SCIP_INVALIDCALL; /*lint !e527*/
14054 
14056  SCIP_CALL( SCIPvarSetNLPSol(var->negatedvar, set, var->data.negate.constant - solval) );
14057  break;
14058 
14059  default:
14060  SCIPerrorMessage("unknown variable status\n");
14061  SCIPABORT();
14062  return SCIP_ERROR; /*lint !e527*/
14063  }
14064 
14065  return SCIP_OKAY;
14066 }
14067 
14068 /** returns a weighted average solution value of the variable in all feasible primal solutions found so far */
14070  SCIP_VAR* var /**< problem variable */
14071  )
14072 {
14073  SCIP_Real avgsol;
14074  int i;
14075 
14076  assert(var != NULL);
14077 
14078  switch( SCIPvarGetStatus(var) )
14079  {
14081  if( var->data.original.transvar == NULL )
14082  return 0.0;
14083  return SCIPvarGetAvgSol(var->data.original.transvar);
14084 
14085  case SCIP_VARSTATUS_LOOSE:
14086  case SCIP_VARSTATUS_COLUMN:
14087  avgsol = var->primsolavg;
14088  avgsol = MAX(avgsol, var->glbdom.lb);
14089  avgsol = MIN(avgsol, var->glbdom.ub);
14090  return avgsol;
14091 
14092  case SCIP_VARSTATUS_FIXED:
14093  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
14094  return var->locdom.lb;
14095 
14097  assert(!var->donotaggr);
14098  assert(var->data.aggregate.var != NULL);
14099  return var->data.aggregate.scalar * SCIPvarGetAvgSol(var->data.aggregate.var)
14100  + var->data.aggregate.constant;
14101 
14103  assert(!var->donotmultaggr);
14104  assert(var->data.multaggr.vars != NULL);
14105  assert(var->data.multaggr.scalars != NULL);
14106  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
14107  * assert(var->data.multaggr.nvars >= 2);
14108  */
14109  avgsol = var->data.multaggr.constant;
14110  for( i = 0; i < var->data.multaggr.nvars; ++i )
14111  avgsol += var->data.multaggr.scalars[i] * SCIPvarGetAvgSol(var->data.multaggr.vars[i]);
14112  return avgsol;
14113 
14114  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
14115  assert(var->negatedvar != NULL);
14117  assert(var->negatedvar->negatedvar == var);
14118  return var->data.negate.constant - SCIPvarGetAvgSol(var->negatedvar);
14119 
14120  default:
14121  SCIPerrorMessage("unknown variable status\n");
14122  SCIPABORT();
14123  return 0.0; /*lint !e527*/
14124  }
14125 }
14126 
14127 /** returns solution value and index of variable lower bound that is closest to the variable's value in the given primal solution
14128  * or current LP solution if no primal solution is given; returns an index of -1 if no variable lower bound is available
14129  */
14131  SCIP_VAR* var, /**< active problem variable */
14132  SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
14133  SCIP_SET* set, /**< global SCIP settings */
14134  SCIP_STAT* stat, /**< problem statistics */
14135  SCIP_Real* closestvlb, /**< pointer to store the value of the closest variable lower bound */
14136  int* closestvlbidx /**< pointer to store the index of the closest variable lower bound */
14137  )
14138 {
14139  int nvlbs;
14140 
14141  assert(var != NULL);
14142  assert(stat != NULL);
14143  assert(set != NULL);
14144  assert(var->scip == set->scip);
14145  assert(closestvlb != NULL);
14146  assert(closestvlbidx != NULL);
14147 
14148  *closestvlbidx = -1;
14149  *closestvlb = SCIP_REAL_MIN;
14150 
14151  nvlbs = SCIPvarGetNVlbs(var);
14152  if( nvlbs > 0 )
14153  {
14154  SCIP_VAR** vlbvars;
14155  SCIP_Real* vlbcoefs;
14156  SCIP_Real* vlbconsts;
14157  int i;
14158 
14159  vlbvars = SCIPvarGetVlbVars(var);
14160  vlbcoefs = SCIPvarGetVlbCoefs(var);
14161  vlbconsts = SCIPvarGetVlbConstants(var);
14162 
14163  /* check for cached values */
14164  if( var->closestvblpcount == stat->lpcount && var->closestvlbidx != -1 && sol == NULL)
14165  {
14166  i = var->closestvlbidx;
14167  assert(0 <= i && i < nvlbs);
14168  assert(SCIPvarIsActive(vlbvars[i]));
14169  *closestvlbidx = i;
14170  *closestvlb = vlbcoefs[i] * SCIPvarGetLPSol(vlbvars[i]) + vlbconsts[i];
14171  }
14172  else
14173  {
14174  /* search best VUB */
14175  for( i = 0; i < nvlbs; i++ )
14176  {
14177  if( SCIPvarIsActive(vlbvars[i]) )
14178  {
14179  SCIP_Real vlbsol;
14180 
14181  vlbsol = vlbcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vlbvars[i]) : SCIPsolGetVal(sol, set, stat, vlbvars[i])) + vlbconsts[i];
14182  if( vlbsol > *closestvlb )
14183  {
14184  *closestvlb = vlbsol;
14185  *closestvlbidx = i;
14186  }
14187  }
14188  }
14189 
14190  if( sol == NULL )
14191  {
14192  /* update cached value */
14193  if( var->closestvblpcount != stat->lpcount )
14194  var->closestvubidx = -1;
14195  var->closestvlbidx = *closestvlbidx;
14196  var->closestvblpcount = stat->lpcount;
14197  }
14198  }
14199  }
14200 }
14201 
14202 /** returns solution value and index of variable upper bound that is closest to the variable's value in the given primal solution;
14203  * or current LP solution if no primal solution is given; returns an index of -1 if no variable upper bound is available
14204  */
14206  SCIP_VAR* var, /**< active problem variable */
14207  SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
14208  SCIP_SET* set, /**< global SCIP settings */
14209  SCIP_STAT* stat, /**< problem statistics */
14210  SCIP_Real* closestvub, /**< pointer to store the value of the closest variable upper bound */
14211  int* closestvubidx /**< pointer to store the index of the closest variable upper bound */
14212  )
14213 {
14214  int nvubs;
14215 
14216  assert(var != NULL);
14217  assert(set != NULL);
14218  assert(var->scip == set->scip);
14219  assert(closestvub != NULL);
14220  assert(closestvubidx != NULL);
14221 
14222  *closestvubidx = -1;
14223  *closestvub = SCIP_REAL_MAX;
14224 
14225  nvubs = SCIPvarGetNVubs(var);
14226  if( nvubs > 0 )
14227  {
14228  SCIP_VAR** vubvars;
14229  SCIP_Real* vubcoefs;
14230  SCIP_Real* vubconsts;
14231  int i;
14232 
14233  vubvars = SCIPvarGetVubVars(var);
14234  vubcoefs = SCIPvarGetVubCoefs(var);
14235  vubconsts = SCIPvarGetVubConstants(var);
14236 
14237  /* check for cached values */
14238  if( var->closestvblpcount == stat->lpcount && var->closestvubidx != -1 && sol == NULL)
14239  {
14240  i = var->closestvubidx;
14241  assert(0 <= i && i < nvubs);
14242  assert(SCIPvarIsActive(vubvars[i]));
14243  *closestvubidx = i;
14244  *closestvub = vubcoefs[i] * SCIPvarGetLPSol(vubvars[i]) + vubconsts[i];
14245  }
14246  else
14247  {
14248  /* search best VUB */
14249  for( i = 0; i < nvubs; i++ )
14250  {
14251  if( SCIPvarIsActive(vubvars[i]) )
14252  {
14253  SCIP_Real vubsol;
14254 
14255  vubsol = vubcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vubvars[i]) : SCIPsolGetVal(sol, set, stat, vubvars[i])) + vubconsts[i];
14256  if( vubsol < *closestvub )
14257  {
14258  *closestvub = vubsol;
14259  *closestvubidx = i;
14260  }
14261  }
14262  }
14263 
14264  if( sol == NULL )
14265  {
14266  /* update cached value */
14267  if( var->closestvblpcount != stat->lpcount )
14268  var->closestvlbidx = -1;
14269  var->closestvubidx = *closestvubidx;
14270  var->closestvblpcount = stat->lpcount;
14271  }
14272  }
14273  }
14274 }
14275 
14276 /** resolves variable to columns and adds them with the coefficient to the row */
14278  SCIP_VAR* var, /**< problem variable */
14279  BMS_BLKMEM* blkmem, /**< block memory */
14280  SCIP_SET* set, /**< global SCIP settings */
14281  SCIP_STAT* stat, /**< problem statistics */
14282  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
14283  SCIP_PROB* prob, /**< problem data */
14284  SCIP_LP* lp, /**< current LP data */
14285  SCIP_ROW* row, /**< LP row */
14286  SCIP_Real val /**< value of coefficient */
14287  )
14288 {
14289  int i;
14290 
14291  assert(var != NULL);
14292  assert(set != NULL);
14293  assert(var->scip == set->scip);
14294  assert(row != NULL);
14295  assert(!SCIPsetIsInfinity(set, REALABS(val)));
14296 
14297  SCIPsetDebugMsg(set, "adding coefficient %g<%s> to row <%s>\n", val, var->name, row->name);
14298 
14299  if ( SCIPsetIsZero(set, val) )
14300  return SCIP_OKAY;
14301 
14302  switch( SCIPvarGetStatus(var) )
14303  {
14305  if( var->data.original.transvar == NULL )
14306  {
14307  SCIPerrorMessage("cannot add untransformed original variable <%s> to LP row <%s>\n", var->name, row->name);
14308  return SCIP_INVALIDDATA;
14309  }
14310  SCIP_CALL( SCIPvarAddToRow(var->data.original.transvar, blkmem, set, stat, eventqueue, prob, lp, row, val) );
14311  return SCIP_OKAY;
14312 
14313  case SCIP_VARSTATUS_LOOSE:
14314  /* add globally fixed variables as constant */
14315  if( SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub) )
14316  {
14317  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->glbdom.lb) );
14318  return SCIP_OKAY;
14319  }
14320  /* convert loose variable into column */
14321  SCIP_CALL( SCIPvarColumn(var, blkmem, set, stat, prob, lp) );
14322  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
14323  /*lint -fallthrough*/
14324 
14325  case SCIP_VARSTATUS_COLUMN:
14326  assert(var->data.col != NULL);
14327  assert(var->data.col->var == var);
14328  SCIP_CALL( SCIProwIncCoef(row, blkmem, set, eventqueue, lp, var->data.col, val) );
14329  return SCIP_OKAY;
14330 
14331  case SCIP_VARSTATUS_FIXED:
14332  assert(var->glbdom.lb == var->glbdom.ub); /*lint !e777*/
14333  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
14334  assert(var->locdom.lb == var->glbdom.lb); /*lint !e777*/
14335  assert(!SCIPsetIsInfinity(set, REALABS(var->locdom.lb)));
14336  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->locdom.lb) );
14337  return SCIP_OKAY;
14338 
14340  assert(!var->donotaggr);
14341  assert(var->data.aggregate.var != NULL);
14342  SCIP_CALL( SCIPvarAddToRow(var->data.aggregate.var, blkmem, set, stat, eventqueue, prob, lp,
14343  row, var->data.aggregate.scalar * val) );
14344  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.aggregate.constant * val) );
14345  return SCIP_OKAY;
14346 
14348  assert(!var->donotmultaggr);
14349  assert(var->data.multaggr.vars != NULL);
14350  assert(var->data.multaggr.scalars != NULL);
14351  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
14352  * assert(var->data.multaggr.nvars >= 2);
14353  */
14354  for( i = 0; i < var->data.multaggr.nvars; ++i )
14355  {
14356  SCIP_CALL( SCIPvarAddToRow(var->data.multaggr.vars[i], blkmem, set, stat, eventqueue, prob, lp,
14357  row, var->data.multaggr.scalars[i] * val) );
14358  }
14359  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.multaggr.constant * val) );
14360  return SCIP_OKAY;
14361 
14362  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
14363  assert(var->negatedvar != NULL);
14365  assert(var->negatedvar->negatedvar == var);
14366  SCIP_CALL( SCIPvarAddToRow(var->negatedvar, blkmem, set, stat, eventqueue, prob, lp, row, -val) );
14367  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.negate.constant * val) );
14368  return SCIP_OKAY;
14369 
14370  default:
14371  SCIPerrorMessage("unknown variable status\n");
14372  return SCIP_INVALIDDATA;
14373  }
14374 }
14375 
14376 /* optionally, define this compiler flag to write complete variable histories to a file */
14377 #ifdef SCIP_HISTORYTOFILE
14378 SCIP_Longint counter = 0l;
14379 const char* historypath="."; /* allows for user-defined path; use '.' for calling directory of SCIP */
14380 #include "scip/scip.h"
14381 #endif
14382 
14383 /** updates the pseudo costs of the given variable and the global pseudo costs after a change of
14384  * "solvaldelta" in the variable's solution value and resulting change of "objdelta" in the in the LP's objective value
14385  */
14387  SCIP_VAR* var, /**< problem variable */
14388  SCIP_SET* set, /**< global SCIP settings */
14389  SCIP_STAT* stat, /**< problem statistics */
14390  SCIP_Real solvaldelta, /**< difference of variable's new LP value - old LP value */
14391  SCIP_Real objdelta, /**< difference of new LP's objective value - old LP's objective value */
14392  SCIP_Real weight /**< weight in (0,1] of this update in pseudo cost sum */
14393  )
14394 {
14395  SCIP_Real oldrootpseudocosts;
14396  assert(var != NULL);
14397  assert(set != NULL);
14398  assert(var->scip == set->scip);
14399  assert(stat != NULL);
14400 
14401  /* check if history statistics should be collected for a variable */
14402  if( !stat->collectvarhistory )
14403  return SCIP_OKAY;
14404 
14405  switch( SCIPvarGetStatus(var) )
14406  {
14408  if( var->data.original.transvar == NULL )
14409  {
14410  SCIPerrorMessage("cannot update pseudo costs of original untransformed variable\n");
14411  return SCIP_INVALIDDATA;
14412  }
14413  SCIP_CALL( SCIPvarUpdatePseudocost(var->data.original.transvar, set, stat, solvaldelta, objdelta, weight) );
14414  return SCIP_OKAY;
14415 
14416  case SCIP_VARSTATUS_LOOSE:
14417  case SCIP_VARSTATUS_COLUMN:
14418  /* store old pseudo-costs for root LP best-estimate update */
14419  oldrootpseudocosts = SCIPvarGetMinPseudocostScore(var, stat, set, SCIPvarGetRootSol(var));
14420 
14421  /* update history */
14422  SCIPhistoryUpdatePseudocost(var->history, set, solvaldelta, objdelta, weight);
14423  SCIPhistoryUpdatePseudocost(var->historycrun, set, solvaldelta, objdelta, weight);
14424  SCIPhistoryUpdatePseudocost(stat->glbhistory, set, solvaldelta, objdelta, weight);
14425  SCIPhistoryUpdatePseudocost(stat->glbhistorycrun, set, solvaldelta, objdelta, weight);
14426 
14427  /* update root LP best-estimate */
14428  SCIP_CALL( SCIPstatUpdateVarRootLPBestEstimate(stat, set, var, oldrootpseudocosts) );
14429 
14430  /* append history to file */
14431 #ifdef SCIP_HISTORYTOFILE
14432  {
14433  FILE* f;
14434  char filename[256];
14435  SCIP_NODE* currentnode;
14436  SCIP_NODE* parentnode;
14437  currentnode = SCIPgetFocusNode(set->scip);
14438  parentnode = SCIPnodeGetParent(currentnode);
14439 
14440  sprintf(filename, "%s/%s.pse", historypath, SCIPgetProbName(set->scip));
14441  f = fopen(filename, "a");
14442  if( NULL != f )
14443  {
14444  fprintf(f, "%lld %s \t %lld \t %lld \t %lld \t %d \t %15.9f \t %.3f\n",
14445  ++counter,
14446  SCIPvarGetName(var),
14447  SCIPnodeGetNumber(currentnode),
14448  parentnode != NULL ? SCIPnodeGetNumber(parentnode) : -1,
14449  SCIPgetNLPIterations(set->scip),
14450  SCIPgetDepth(set->scip),
14451  objdelta,
14452  solvaldelta);
14453  fclose(f);
14454  }
14455  }
14456 #endif
14457  return SCIP_OKAY;
14458 
14459  case SCIP_VARSTATUS_FIXED:
14460  SCIPerrorMessage("cannot update pseudo cost values of a fixed variable\n");
14461  return SCIP_INVALIDDATA;
14462 
14464  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
14466  solvaldelta/var->data.aggregate.scalar, objdelta, weight) );
14467  return SCIP_OKAY;
14468 
14470  SCIPerrorMessage("cannot update pseudo cost values of a multi-aggregated variable\n");
14471  return SCIP_INVALIDDATA;
14472 
14474  SCIP_CALL( SCIPvarUpdatePseudocost(var->negatedvar, set, stat, -solvaldelta, objdelta, weight) );
14475  return SCIP_OKAY;
14476 
14477  default:
14478  SCIPerrorMessage("unknown variable status\n");
14479  return SCIP_INVALIDDATA;
14480  }
14481 }
14482 
14483 /** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value */
14485  SCIP_VAR* var, /**< problem variable */
14486  SCIP_STAT* stat, /**< problem statistics */
14487  SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
14488  )
14489 {
14490  SCIP_BRANCHDIR dir;
14491 
14492  assert(var != NULL);
14493  assert(stat != NULL);
14494 
14495  switch( SCIPvarGetStatus(var) )
14496  {
14498  if( var->data.original.transvar == NULL )
14499  return SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
14500  else
14501  return SCIPvarGetPseudocost(var->data.original.transvar, stat, solvaldelta);
14502 
14503  case SCIP_VARSTATUS_LOOSE:
14504  case SCIP_VARSTATUS_COLUMN:
14505  dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
14506 
14507  return SCIPhistoryGetPseudocostCount(var->history, dir) > 0.0
14508  ? SCIPhistoryGetPseudocost(var->history, solvaldelta)
14509  : SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
14510 
14511  case SCIP_VARSTATUS_FIXED:
14512  return 0.0;
14513 
14515  return SCIPvarGetPseudocost(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
14516 
14518  return 0.0;
14519 
14521  return SCIPvarGetPseudocost(var->negatedvar, stat, -solvaldelta);
14522 
14523  default:
14524  SCIPerrorMessage("unknown variable status\n");
14525  SCIPABORT();
14526  return 0.0; /*lint !e527*/
14527  }
14528 }
14529 
14530 /** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value,
14531  * only using the pseudo cost information of the current run
14532  */
14534  SCIP_VAR* var, /**< problem variable */
14535  SCIP_STAT* stat, /**< problem statistics */
14536  SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
14537  )
14538 {
14539  SCIP_BRANCHDIR dir;
14540 
14541  assert(var != NULL);
14542  assert(stat != NULL);
14543 
14544  switch( SCIPvarGetStatus(var) )
14545  {
14547  if( var->data.original.transvar == NULL )
14548  return SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
14549  else
14550  return SCIPvarGetPseudocostCurrentRun(var->data.original.transvar, stat, solvaldelta);
14551 
14552  case SCIP_VARSTATUS_LOOSE:
14553  case SCIP_VARSTATUS_COLUMN:
14554  dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
14555 
14556  return SCIPhistoryGetPseudocostCount(var->historycrun, dir) > 0.0
14557  ? SCIPhistoryGetPseudocost(var->historycrun, solvaldelta)
14558  : SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
14559 
14560  case SCIP_VARSTATUS_FIXED:
14561  return 0.0;
14562 
14564  return SCIPvarGetPseudocostCurrentRun(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
14565 
14567  return 0.0;
14568 
14570  return SCIPvarGetPseudocostCurrentRun(var->negatedvar, stat, -solvaldelta);
14571 
14572  default:
14573  SCIPerrorMessage("unknown variable status\n");
14574  SCIPABORT();
14575  return 0.0; /*lint !e527*/
14576  }
14577 }
14578 
14579 /** gets the variable's (possible fractional) number of pseudo cost updates for the given direction */
14581  SCIP_VAR* var, /**< problem variable */
14582  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14583  )
14584 {
14585  assert(var != NULL);
14586  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14587 
14588  switch( SCIPvarGetStatus(var) )
14589  {
14591  if( var->data.original.transvar == NULL )
14592  return 0.0;
14593  else
14594  return SCIPvarGetPseudocostCount(var->data.original.transvar, dir);
14595 
14596  case SCIP_VARSTATUS_LOOSE:
14597  case SCIP_VARSTATUS_COLUMN:
14598  return SCIPhistoryGetPseudocostCount(var->history, dir);
14599 
14600  case SCIP_VARSTATUS_FIXED:
14601  return 0.0;
14602 
14604  if( var->data.aggregate.scalar > 0.0 )
14605  return SCIPvarGetPseudocostCount(var->data.aggregate.var, dir);
14606  else
14608 
14610  return 0.0;
14611 
14614 
14615  default:
14616  SCIPerrorMessage("unknown variable status\n");
14617  SCIPABORT();
14618  return 0.0; /*lint !e527*/
14619  }
14620 }
14621 
14622 /** gets the variable's (possible fractional) number of pseudo cost updates for the given direction,
14623  * only using the pseudo cost information of the current run
14624  */
14626  SCIP_VAR* var, /**< problem variable */
14627  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14628  )
14629 {
14630  assert(var != NULL);
14631  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14632 
14633  switch( SCIPvarGetStatus(var) )
14634  {
14636  if( var->data.original.transvar == NULL )
14637  return 0.0;
14638  else
14640 
14641  case SCIP_VARSTATUS_LOOSE:
14642  case SCIP_VARSTATUS_COLUMN:
14643  return SCIPhistoryGetPseudocostCount(var->historycrun, dir);
14644 
14645  case SCIP_VARSTATUS_FIXED:
14646  return 0.0;
14647 
14649  if( var->data.aggregate.scalar > 0.0 )
14651  else
14653 
14655  return 0.0;
14656 
14659 
14660  default:
14661  SCIPerrorMessage("unknown variable status\n");
14662  SCIPABORT();
14663  return 0.0; /*lint !e527*/
14664  }
14665 }
14666 
14667 /** compares both possible directions for rounding the given solution value and returns the minimum pseudo-costs of the variable */
14669  SCIP_VAR* var, /**< problem variable */
14670  SCIP_STAT* stat, /**< problem statistics */
14671  SCIP_SET* set, /**< global SCIP settings */
14672  SCIP_Real solval /**< solution value, e.g., LP solution value */
14673  )
14674 {
14675  SCIP_Real upscore;
14676  SCIP_Real downscore;
14677  SCIP_Real solvaldeltaup;
14678  SCIP_Real solvaldeltadown;
14679 
14680  /* LP root estimate only works for variables with fractional LP root solution */
14681  if( SCIPsetIsFeasIntegral(set, solval) )
14682  return 0.0;
14683 
14684  /* no min pseudo-cost score is calculated as long as the variable was not initialized in a direction */
14686  return 0.0;
14687 
14688  /* compute delta's to ceil and floor of root LP solution value */
14689  solvaldeltaup = SCIPsetCeil(set, solval) - solval;
14690  solvaldeltadown = SCIPsetFloor(set, solval) - solval;
14691 
14692  upscore = SCIPvarGetPseudocost(var, stat, solvaldeltaup);
14693  downscore = SCIPvarGetPseudocost(var, stat, solvaldeltadown);
14694 
14695  return MIN(upscore, downscore);
14696 }
14697 
14698 /** gets the an estimate of the variable's pseudo cost variance in direction \p dir */
14700  SCIP_VAR* var, /**< problem variable */
14701  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
14702  SCIP_Bool onlycurrentrun /**< return pseudo cost variance only for current branch and bound run */
14703  )
14704 {
14705  assert(var != NULL);
14706  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14707 
14708  switch( SCIPvarGetStatus(var) )
14709  {
14711  if( var->data.original.transvar == NULL )
14712  return 0.0;
14713  else
14714  return SCIPvarGetPseudocostVariance(var->data.original.transvar, dir, onlycurrentrun);
14715 
14716  case SCIP_VARSTATUS_LOOSE:
14717  case SCIP_VARSTATUS_COLUMN:
14718  if( onlycurrentrun )
14720  else
14721  return SCIPhistoryGetPseudocostVariance(var->history, dir);
14722 
14723  case SCIP_VARSTATUS_FIXED:
14724  return 0.0;
14725 
14727  if( var->data.aggregate.scalar > 0.0 )
14728  return SCIPvarGetPseudocostVariance(var->data.aggregate.var, dir, onlycurrentrun);
14729  else
14730  return SCIPvarGetPseudocostVariance(var->data.aggregate.var, SCIPbranchdirOpposite(dir), onlycurrentrun);
14731 
14733  return 0.0;
14734 
14736  return SCIPvarGetPseudocostVariance(var->negatedvar, SCIPbranchdirOpposite(dir), onlycurrentrun);
14737 
14738  default:
14739  SCIPerrorMessage("unknown variable status\n");
14740  SCIPABORT();
14741  return 0.0; /*lint !e527*/
14742  }
14743 }
14744 
14745 /** calculates a confidence bound for this variable under the assumption of normally distributed pseudo costs
14746  *
14747  * The confidence bound \f$ \theta \geq 0\f$ denotes the interval borders \f$ [X - \theta, \ X + \theta]\f$, which contains
14748  * the true pseudo costs of the variable, i.e., the expected value of the normal distribution, with a probability
14749  * of 2 * clevel - 1.
14750  *
14751  * @return value of confidence bound for this variable
14752  */
14754  SCIP_VAR* var, /**< variable in question */
14755  SCIP_SET* set, /**< global SCIP settings */
14756  SCIP_BRANCHDIR dir, /**< the branching direction for the confidence bound */
14757  SCIP_Bool onlycurrentrun, /**< should only the current run be taken into account */
14758  SCIP_CONFIDENCELEVEL clevel /**< confidence level for the interval */
14759  )
14760 {
14761  SCIP_Real confidencebound;
14762 
14763  confidencebound = SCIPvarGetPseudocostVariance(var, dir, onlycurrentrun);
14764  if( SCIPsetIsFeasPositive(set, confidencebound) )
14765  {
14766  SCIP_Real count;
14767 
14768  if( onlycurrentrun )
14769  count = SCIPvarGetPseudocostCountCurrentRun(var, dir);
14770  else
14771  count = SCIPvarGetPseudocostCount(var, dir);
14772  /* assertion is valid because variance is positive */
14773  assert(count >= 1.9);
14774 
14775  confidencebound /= count; /*lint !e414 division by zero can obviously not occur */
14776  confidencebound = sqrt(confidencebound);
14777 
14778  /* the actual, underlying distribution of the mean is a student-t-distribution with degrees of freedom equal to
14779  * the number of pseudo cost evaluations of this variable in the respective direction. */
14780  confidencebound *= SCIPstudentTGetCriticalValue(clevel, (int)SCIPsetFloor(set, count) - 1);
14781  }
14782  else
14783  confidencebound = 0.0;
14784 
14785  return confidencebound;
14786 }
14787 
14788 /** check if the current pseudo cost relative error in a direction violates the given threshold. The Relative
14789  * Error is calculated at a specific confidence level
14790  */
14792  SCIP_VAR* var, /**< variable in question */
14793  SCIP_SET* set, /**< global SCIP settings */
14794  SCIP_STAT* stat, /**< problem statistics */
14795  SCIP_Real threshold, /**< threshold for relative errors to be considered reliable (enough) */
14796  SCIP_CONFIDENCELEVEL clevel /**< a given confidence level */
14797  )
14798 {
14799  SCIP_Real downsize;
14800  SCIP_Real upsize;
14801  SCIP_Real size;
14802  SCIP_Real relerrorup;
14803  SCIP_Real relerrordown;
14804  SCIP_Real relerror;
14805 
14806  /* check, if the pseudo cost score of the variable is reliable */
14809  size = MIN(downsize, upsize);
14810 
14811  /* Pseudo costs relative error can only be reliable if both directions have been tried at least twice */
14812  if( size <= 1.9 )
14813  return FALSE;
14814 
14815  /* use the relative error between the current mean pseudo cost value of the candidate and its upper
14816  * confidence interval bound at confidence level of 95% for individual variable reliability.
14817  * this is only possible if we have at least 2 measurements and therefore a valid variance estimate.
14818  */
14819  if( downsize >= 1.9 )
14820  {
14821  SCIP_Real normval;
14822 
14823  relerrordown = SCIPvarCalcPscostConfidenceBound(var, set, SCIP_BRANCHDIR_DOWNWARDS, TRUE, clevel);
14824  normval = SCIPvarGetPseudocostCurrentRun(var, stat, -1.0);
14825  normval = MAX(1.0, normval);
14826 
14827  relerrordown /= normval;
14828  }
14829  else
14830  relerrordown = 0.0;
14831 
14832  if( upsize >= 1.9 )
14833  {
14834  SCIP_Real normval;
14835 
14836  relerrorup = SCIPvarCalcPscostConfidenceBound(var, set, SCIP_BRANCHDIR_UPWARDS, TRUE, clevel);
14837  normval = SCIPvarGetPseudocostCurrentRun(var, stat, +1.0);
14838  normval = MAX(1.0, normval);
14839  relerrorup /= normval;
14840  }
14841  else
14842  relerrorup = 0.0;
14843 
14844  /* consider the relative error threshold violated, if it is violated in at least one branching direction */
14845  relerror = MAX(relerrorup, relerrordown);
14846 
14847  return (relerror <= threshold);
14848 }
14849 
14850 /** check if variable pseudo-costs have a significant difference in location. The significance depends on
14851  * the choice of \p clevel and on the kind of tested hypothesis. The one-sided hypothesis, which
14852  * should be rejected, is that fracy * mu_y >= fracx * mu_x, where mu_y and mu_x denote the
14853  * unknown location means of the underlying pseudo-cost distributions of x and y.
14854  *
14855  * This method is applied best if variable x has a better pseudo-cost score than y. The method hypothesizes that y were actually
14856  * better than x (despite the current information), meaning that y can be expected to yield branching
14857  * decisions as least as good as x in the long run. If the method returns TRUE, the current history information is
14858  * sufficient to safely rely on the alternative hypothesis that x yields indeed a better branching score (on average)
14859  * than y.
14860  *
14861  * @note The order of x and y matters for the one-sided hypothesis
14862  *
14863  * @note set \p onesided to FALSE if you are not sure which variable is better. The hypothesis tested then reads
14864  * fracy * mu_y == fracx * mu_x vs the alternative hypothesis fracy * mu_y != fracx * mu_x.
14865  *
14866  * @return TRUE if the hypothesis can be safely rejected at the given confidence level
14867  */
14869  SCIP_SET* set, /**< global SCIP settings */
14870  SCIP_STAT* stat, /**< problem statistics */
14871  SCIP_VAR* varx, /**< variable x */
14872  SCIP_Real fracx, /**< the fractionality of variable x */
14873  SCIP_VAR* vary, /**< variable y */
14874  SCIP_Real fracy, /**< the fractionality of variable y */
14875  SCIP_BRANCHDIR dir, /**< branching direction */
14876  SCIP_CONFIDENCELEVEL clevel, /**< confidence level for rejecting hypothesis */
14877  SCIP_Bool onesided /**< should a one-sided hypothesis y >= x be tested? */
14878  )
14879 {
14880  SCIP_Real meanx;
14881  SCIP_Real meany;
14882  SCIP_Real variancex;
14883  SCIP_Real variancey;
14884  SCIP_Real countx;
14885  SCIP_Real county;
14886  SCIP_Real tresult;
14887  SCIP_Real realdirection;
14888 
14889  if( varx == vary )
14890  return FALSE;
14891 
14892  countx = SCIPvarGetPseudocostCount(varx, dir);
14893  county = SCIPvarGetPseudocostCount(vary, dir);
14894 
14895  /* if not at least 2 measurements were taken, return FALSE */
14896  if( countx <= 1.9 || county <= 1.9 )
14897  return FALSE;
14898 
14899  realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
14900 
14901  meanx = fracx * SCIPvarGetPseudocost(varx, stat, realdirection);
14902  meany = fracy * SCIPvarGetPseudocost(vary, stat, realdirection);
14903 
14904  variancex = SQR(fracx) * SCIPvarGetPseudocostVariance(varx, dir, FALSE);
14905  variancey = SQR(fracy) * SCIPvarGetPseudocostVariance(vary, dir, FALSE);
14906 
14907  /* if there is no variance, the means are taken from a constant distribution */
14908  if( SCIPsetIsFeasEQ(set, variancex + variancey, 0.0) )
14909  return (onesided ? SCIPsetIsFeasGT(set, meanx, meany) : !SCIPsetIsFeasEQ(set, meanx, meany));
14910 
14911  tresult = SCIPcomputeTwoSampleTTestValue(meanx, meany, variancex, variancey, countx, county);
14912 
14913  /* for the two-sided hypothesis, just take the absolute of t */
14914  if( !onesided )
14915  tresult = REALABS(tresult);
14916 
14917  return (tresult >= SCIPstudentTGetCriticalValue(clevel, (int)(countx + county - 2)));
14918 }
14919 
14920 /** tests at a given confidence level whether the variable pseudo-costs only have a small probability to
14921  * exceed a \p threshold. This is useful to determine if past observations provide enough evidence
14922  * to skip an expensive strong-branching step if there is already a candidate that has been proven to yield an improvement
14923  * of at least \p threshold.
14924  *
14925  * @note use \p clevel to adjust the level of confidence. For SCIP_CONFIDENCELEVEL_MIN, the method returns TRUE if
14926  * the estimated probability to exceed \p threshold is less than 25 %.
14927  *
14928  * @see SCIP_Confidencelevel for a list of available levels. The used probability limits refer to the one-sided levels
14929  * of confidence.
14930  *
14931  * @return TRUE if the variable pseudo-cost probabilistic model is likely to be smaller than \p threshold
14932  * at the given confidence level \p clevel.
14933  */
14935  SCIP_SET* set, /**< global SCIP settings */
14936  SCIP_STAT* stat, /**< problem statistics */
14937  SCIP_VAR* var, /**< variable x */
14938  SCIP_Real frac, /**< the fractionality of variable x */
14939  SCIP_Real threshold, /**< the threshold to test against */
14940  SCIP_BRANCHDIR dir, /**< branching direction */
14941  SCIP_CONFIDENCELEVEL clevel /**< confidence level for rejecting hypothesis */
14942  )
14943 {
14944  SCIP_Real mean;
14945  SCIP_Real variance;
14946  SCIP_Real count;
14947  SCIP_Real realdirection;
14948  SCIP_Real probability;
14949  SCIP_Real problimit;
14950 
14951  count = SCIPvarGetPseudocostCount(var, dir);
14952 
14953  /* if not at least 2 measurements were taken, return FALSE */
14954  if( count <= 1.9 )
14955  return FALSE;
14956 
14957  realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
14958 
14959  mean = frac * SCIPvarGetPseudocost(var, stat, realdirection);
14960  variance = SQR(frac) * SCIPvarGetPseudocostVariance(var, dir, FALSE);
14961 
14962  /* if mean is at least threshold, it has at least a 50% probability to exceed threshold, we therefore return FALSE */
14963  if( SCIPsetIsFeasGE(set, mean, threshold) )
14964  return FALSE;
14965 
14966  /* if there is no variance, the means are taken from a constant distribution */
14967  if( SCIPsetIsFeasEQ(set, variance, 0.0) )
14968  return SCIPsetIsFeasLT(set, mean, threshold);
14969 
14970  /* obtain probability of a normally distributed random variable at given mean and variance to yield at most threshold */
14971  probability = SCIPnormalCDF(mean, variance, threshold);
14972 
14973  /* determine a probability limit corresponding to the given confidence level */
14974  switch( clevel )
14975  {
14977  problimit = 0.75;
14978  break;
14980  problimit = 0.875;
14981  break;
14983  problimit = 0.9;
14984  break;
14986  problimit = 0.95;
14987  break;
14989  problimit = 0.975;
14990  break;
14991  default:
14992  problimit = -1;
14993  SCIPerrorMessage("Confidence level set to unknown value <%d>", (int)clevel);
14994  SCIPABORT();
14995  break;
14996  }
14997 
14998  return (probability >= problimit);
14999 }
15000 
15001 /** find the corresponding history entry if already existing, otherwise create new entry */
15002 static
15004  SCIP_VAR* var, /**< problem variable */
15005  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15006  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15007  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15008  SCIP_HISTORY** history /**< pointer to store the value based history, or NULL */
15009  )
15010 {
15011  assert(var != NULL);
15012  assert(blkmem != NULL);
15013  assert(set != NULL);
15014  assert(history != NULL);
15015 
15016  (*history) = NULL;
15017 
15018  if( var->valuehistory == NULL )
15019  {
15020  SCIP_CALL( SCIPvaluehistoryCreate(&var->valuehistory, blkmem) );
15021  }
15022 
15023  SCIP_CALL( SCIPvaluehistoryFind(var->valuehistory, blkmem, set, value, history) );
15024 
15025  return SCIP_OKAY;
15026 }
15027 
15028 /** check if value based history should be used */
15029 static
15031  SCIP_VAR* var, /**< problem variable */
15032  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15033  SCIP_SET* set /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15034  )
15035 {
15036  /* check if the domain value is unknown (not specific) */
15037  if( value == SCIP_UNKNOWN ) /*lint !e777*/
15038  return FALSE;
15039 
15040  assert(set != NULL);
15041 
15042  /* check if value based history should be collected */
15043  if( !set->history_valuebased )
15044  return FALSE;
15045 
15046  /* value based history is not collected for binary variable since the standard history already contains all information */
15047  if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
15048  return FALSE;
15049 
15050  /* value based history is not collected for continuous variables */
15052  return FALSE;
15053 
15054  return TRUE;
15055 }
15056 
15057 /** increases VSIDS of the variable by the given weight */
15059  SCIP_VAR* var, /**< problem variable */
15060  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15061  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15062  SCIP_STAT* stat, /**< problem statistics */
15063  SCIP_BRANCHDIR dir, /**< branching direction */
15064  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15065  SCIP_Real weight /**< weight of this update in VSIDS */
15066  )
15067 {
15068  assert(var != NULL);
15069  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15070 
15071  /* check if history statistics should be collected for a variable */
15072  if( !stat->collectvarhistory )
15073  return SCIP_OKAY;
15074 
15075  if( SCIPsetIsZero(set, weight) )
15076  return SCIP_OKAY;
15077 
15078  switch( SCIPvarGetStatus(var) )
15079  {
15081  if( var->data.original.transvar == NULL )
15082  {
15083  SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
15084  return SCIP_INVALIDDATA;
15085  }
15086  SCIP_CALL( SCIPvarIncVSIDS(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
15087  return SCIP_OKAY;
15088 
15089  case SCIP_VARSTATUS_LOOSE:
15090  case SCIP_VARSTATUS_COLUMN:
15091  {
15092  SCIPhistoryIncVSIDS(var->history, dir, weight);
15093  SCIPhistoryIncVSIDS(var->historycrun, dir, weight);
15094 
15095  if( useValuehistory(var, value, set) )
15096  {
15097  SCIP_HISTORY* history;
15098 
15099  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15100  assert(history != NULL);
15101 
15102  SCIPhistoryIncVSIDS(history, dir, weight);
15103  SCIPsetDebugMsg(set, "variable (<%s> %s %g) + <%g> = <%g>\n", SCIPvarGetName(var), dir == SCIP_BRANCHDIR_UPWARDS ? ">=" : "<=",
15104  value, weight, SCIPhistoryGetVSIDS(history, dir));
15105  }
15106 
15107  return SCIP_OKAY;
15108  }
15109  case SCIP_VARSTATUS_FIXED:
15110  SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
15111  return SCIP_INVALIDDATA;
15112 
15114  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15115 
15116  if( var->data.aggregate.scalar > 0.0 )
15117  {
15118  SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
15119  }
15120  else
15121  {
15122  assert(var->data.aggregate.scalar < 0.0);
15123  SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15124  }
15125  return SCIP_OKAY;
15126 
15128  SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
15129  return SCIP_INVALIDDATA;
15130 
15132  value = 1.0 - value;
15133 
15134  SCIP_CALL( SCIPvarIncVSIDS(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15135  return SCIP_OKAY;
15136 
15137  default:
15138  SCIPerrorMessage("unknown variable status\n");
15139  return SCIP_INVALIDDATA;
15140  }
15141 }
15142 
15143 /** scales the VSIDS of the variable by the given scalar */
15145  SCIP_VAR* var, /**< problem variable */
15146  SCIP_Real scalar /**< scalar to multiply the VSIDSs with */
15147  )
15148 {
15149  assert(var != NULL);
15150 
15151  switch( SCIPvarGetStatus(var) )
15152  {
15154  if( var->data.original.transvar == NULL )
15155  {
15156  SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
15157  return SCIP_INVALIDDATA;
15158  }
15160  return SCIP_OKAY;
15161 
15162  case SCIP_VARSTATUS_LOOSE:
15163  case SCIP_VARSTATUS_COLUMN:
15164  {
15165  SCIPhistoryScaleVSIDS(var->history, scalar);
15166  SCIPhistoryScaleVSIDS(var->historycrun, scalar);
15168 
15169  return SCIP_OKAY;
15170  }
15171  case SCIP_VARSTATUS_FIXED:
15172  SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
15173  return SCIP_INVALIDDATA;
15174 
15176  SCIP_CALL( SCIPvarScaleVSIDS(var->data.aggregate.var, scalar) );
15177  return SCIP_OKAY;
15178 
15180  SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
15181  return SCIP_INVALIDDATA;
15182 
15184  SCIP_CALL( SCIPvarScaleVSIDS(var->negatedvar, scalar) );
15185  return SCIP_OKAY;
15186 
15187  default:
15188  SCIPerrorMessage("unknown variable status\n");
15189  return SCIP_INVALIDDATA;
15190  }
15191 }
15192 
15193 /** increases the number of active conflicts by one and the overall length of the variable by the given length */
15195  SCIP_VAR* var, /**< problem variable */
15196  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15197  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15198  SCIP_STAT* stat, /**< problem statistics */
15199  SCIP_BRANCHDIR dir, /**< branching direction */
15200  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15201  SCIP_Real length /**< length of the conflict */
15202  )
15203 {
15204  assert(var != NULL);
15205  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15206 
15207  /* check if history statistics should be collected for a variable */
15208  if( !stat->collectvarhistory )
15209  return SCIP_OKAY;
15210 
15211  switch( SCIPvarGetStatus(var) )
15212  {
15214  if( var->data.original.transvar == NULL )
15215  {
15216  SCIPerrorMessage("cannot update conflict score of original untransformed variable\n");
15217  return SCIP_INVALIDDATA;
15218  }
15219  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.original.transvar, blkmem, set, stat, dir, value, length) );
15220  return SCIP_OKAY;
15221 
15222  case SCIP_VARSTATUS_LOOSE:
15223  case SCIP_VARSTATUS_COLUMN:
15224  {
15225  SCIPhistoryIncNActiveConflicts(var->history, dir, length);
15226  SCIPhistoryIncNActiveConflicts(var->historycrun, dir, length);
15227 
15228  if( useValuehistory(var, value, set) )
15229  {
15230  SCIP_HISTORY* history;
15231 
15232  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15233  assert(history != NULL);
15234 
15235  SCIPhistoryIncNActiveConflicts(history, dir, length);
15236  }
15237 
15238  return SCIP_OKAY;
15239  }
15240  case SCIP_VARSTATUS_FIXED:
15241  SCIPerrorMessage("cannot update conflict score of a fixed variable\n");
15242  return SCIP_INVALIDDATA;
15243 
15245  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15246 
15247  if( var->data.aggregate.scalar > 0.0 )
15248  {
15249  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, dir, value, length) );
15250  }
15251  else
15252  {
15253  assert(var->data.aggregate.scalar < 0.0);
15254  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
15255  }
15256  return SCIP_OKAY;
15257 
15259  SCIPerrorMessage("cannot update conflict score of a multi-aggregated variable\n");
15260  return SCIP_INVALIDDATA;
15261 
15263  value = 1.0 - value;
15264 
15265  SCIP_CALL( SCIPvarIncNActiveConflicts(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
15266  return SCIP_OKAY;
15267 
15268  default:
15269  SCIPerrorMessage("unknown variable status\n");
15270  return SCIP_INVALIDDATA;
15271  }
15272 }
15273 
15274 /** gets the number of active conflicts containing this variable in given direction */
15276  SCIP_VAR* var, /**< problem variable */
15277  SCIP_STAT* stat, /**< problem statistics */
15278  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15279  )
15280 {
15281  assert(var != NULL);
15282  assert(stat != NULL);
15283  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15284 
15285  switch( SCIPvarGetStatus(var) )
15286  {
15288  if( var->data.original.transvar == NULL )
15289  return 0;
15290  else
15291  return SCIPvarGetNActiveConflicts(var->data.original.transvar, stat, dir);
15292 
15293  case SCIP_VARSTATUS_LOOSE:
15294  case SCIP_VARSTATUS_COLUMN:
15295  return SCIPhistoryGetNActiveConflicts(var->history, dir);
15296 
15297  case SCIP_VARSTATUS_FIXED:
15298  return 0;
15299 
15301  if( var->data.aggregate.scalar > 0.0 )
15302  return SCIPvarGetNActiveConflicts(var->data.aggregate.var, stat, dir);
15303  else
15305 
15307  return 0;
15308 
15311 
15312  default:
15313  SCIPerrorMessage("unknown variable status\n");
15314  SCIPABORT();
15315  return 0; /*lint !e527*/
15316  }
15317 }
15318 
15319 /** gets the number of active conflicts containing this variable in given direction
15320  * in the current run
15321  */
15323  SCIP_VAR* var, /**< problem variable */
15324  SCIP_STAT* stat, /**< problem statistics */
15325  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15326  )
15327 {
15328  assert(var != NULL);
15329  assert(stat != NULL);
15330  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15331 
15332  switch( SCIPvarGetStatus(var) )
15333  {
15335  if( var->data.original.transvar == NULL )
15336  return 0;
15337  else
15339 
15340  case SCIP_VARSTATUS_LOOSE:
15341  case SCIP_VARSTATUS_COLUMN:
15342  return SCIPhistoryGetNActiveConflicts(var->historycrun, dir);
15343 
15344  case SCIP_VARSTATUS_FIXED:
15345  return 0;
15346 
15348  if( var->data.aggregate.scalar > 0.0 )
15349  return SCIPvarGetNActiveConflictsCurrentRun(var->data.aggregate.var, stat, dir);
15350  else
15352 
15354  return 0;
15355 
15358 
15359  default:
15360  SCIPerrorMessage("unknown variable status\n");
15361  SCIPABORT();
15362  return 0; /*lint !e527*/
15363  }
15364 }
15365 
15366 /** gets the average conflict length in given direction due to branching on the variable */
15368  SCIP_VAR* var, /**< problem variable */
15369  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15370  )
15371 {
15372  assert(var != NULL);
15373  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15374 
15375  switch( SCIPvarGetStatus(var) )
15376  {
15378  if( var->data.original.transvar == NULL )
15379  return 0.0;
15380  else
15382 
15383  case SCIP_VARSTATUS_LOOSE:
15384  case SCIP_VARSTATUS_COLUMN:
15385  return SCIPhistoryGetAvgConflictlength(var->history, dir);
15386  case SCIP_VARSTATUS_FIXED:
15387  return 0.0;
15388 
15390  if( var->data.aggregate.scalar > 0.0 )
15391  return SCIPvarGetAvgConflictlength(var->data.aggregate.var, dir);
15392  else
15394 
15396  return 0.0;
15397 
15400 
15401  default:
15402  SCIPerrorMessage("unknown variable status\n");
15403  SCIPABORT();
15404  return 0.0; /*lint !e527*/
15405  }
15406 }
15407 
15408 /** gets the average conflict length in given direction due to branching on the variable
15409  * in the current run
15410  */
15412  SCIP_VAR* var, /**< problem variable */
15413  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15414  )
15415 {
15416  assert(var != NULL);
15417  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15418 
15419  switch( SCIPvarGetStatus(var) )
15420  {
15422  if( var->data.original.transvar == NULL )
15423  return 0.0;
15424  else
15426 
15427  case SCIP_VARSTATUS_LOOSE:
15428  case SCIP_VARSTATUS_COLUMN:
15429  return SCIPhistoryGetAvgConflictlength(var->historycrun, dir);
15430 
15431  case SCIP_VARSTATUS_FIXED:
15432  return 0.0;
15433 
15435  if( var->data.aggregate.scalar > 0.0 )
15437  else
15439 
15441  return 0.0;
15442 
15445 
15446  default:
15447  SCIPerrorMessage("unknown variable status\n");
15448  SCIPABORT();
15449  return 0.0; /*lint !e527*/
15450  }
15451 }
15452 
15453 /** increases the number of branchings counter of the variable */
15455  SCIP_VAR* var, /**< problem variable */
15456  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15457  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15458  SCIP_STAT* stat, /**< problem statistics */
15459  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
15460  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15461  int depth /**< depth at which the bound change took place */
15462  )
15463 {
15464  assert(var != NULL);
15465  assert(stat != NULL);
15466  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15467 
15468  /* check if history statistics should be collected for a variable */
15469  if( !stat->collectvarhistory )
15470  return SCIP_OKAY;
15471 
15472  switch( SCIPvarGetStatus(var) )
15473  {
15475  if( var->data.original.transvar == NULL )
15476  {
15477  SCIPerrorMessage("cannot update branching counter of original untransformed variable\n");
15478  return SCIP_INVALIDDATA;
15479  }
15480  SCIP_CALL( SCIPvarIncNBranchings(var->data.original.transvar, blkmem, set, stat, dir, value, depth) );
15481  return SCIP_OKAY;
15482 
15483  case SCIP_VARSTATUS_LOOSE:
15484  case SCIP_VARSTATUS_COLUMN:
15485  {
15486  SCIPhistoryIncNBranchings(var->history, dir, depth);
15487  SCIPhistoryIncNBranchings(var->historycrun, dir, depth);
15488  SCIPhistoryIncNBranchings(stat->glbhistory, dir, depth);
15489  SCIPhistoryIncNBranchings(stat->glbhistorycrun, dir, depth);
15490 
15491  if( useValuehistory(var, value, set) )
15492  {
15493  SCIP_HISTORY* history;
15494 
15495  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15496  assert(history != NULL);
15497 
15498  SCIPhistoryIncNBranchings(history, dir, depth);
15499  }
15500 
15501  return SCIP_OKAY;
15502  }
15503  case SCIP_VARSTATUS_FIXED:
15504  SCIPerrorMessage("cannot update branching counter of a fixed variable\n");
15505  return SCIP_INVALIDDATA;
15506 
15508  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15509 
15510  if( var->data.aggregate.scalar > 0.0 )
15511  {
15512  SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, dir, value, depth) );
15513  }
15514  else
15515  {
15516  assert(var->data.aggregate.scalar < 0.0);
15517  SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
15518  }
15519  return SCIP_OKAY;
15520 
15522  SCIPerrorMessage("cannot update branching counter of a multi-aggregated variable\n");
15523  return SCIP_INVALIDDATA;
15524 
15526  value = 1.0 - value;
15527 
15528  SCIP_CALL( SCIPvarIncNBranchings(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
15529  return SCIP_OKAY;
15530 
15531  default:
15532  SCIPerrorMessage("unknown variable status\n");
15533  return SCIP_INVALIDDATA;
15534  }
15535 }
15536 
15537 /** increases the inference sum of the variable by the given weight */
15539  SCIP_VAR* var, /**< problem variable */
15540  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15541  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15542  SCIP_STAT* stat, /**< problem statistics */
15543  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
15544  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15545  SCIP_Real weight /**< weight of this update in inference score */
15546  )
15547 {
15548  assert(var != NULL);
15549  assert(stat != NULL);
15550  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15551 
15552  /* check if history statistics should be collected for a variable */
15553  if( !stat->collectvarhistory )
15554  return SCIP_OKAY;
15555 
15556  switch( SCIPvarGetStatus(var) )
15557  {
15559  if( var->data.original.transvar == NULL )
15560  {
15561  SCIPerrorMessage("cannot update inference counter of original untransformed variable\n");
15562  return SCIP_INVALIDDATA;
15563  }
15564  SCIP_CALL( SCIPvarIncInferenceSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
15565  return SCIP_OKAY;
15566 
15567  case SCIP_VARSTATUS_LOOSE:
15568  case SCIP_VARSTATUS_COLUMN:
15569  {
15570  SCIPhistoryIncInferenceSum(var->history, dir, weight);
15571  SCIPhistoryIncInferenceSum(var->historycrun, dir, weight);
15572  SCIPhistoryIncInferenceSum(stat->glbhistory, dir, weight);
15573  SCIPhistoryIncInferenceSum(stat->glbhistorycrun, dir, weight);
15574 
15575  if( useValuehistory(var, value, set) )
15576  {
15577  SCIP_HISTORY* history;
15578 
15579  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15580  assert(history != NULL);
15581 
15582  SCIPhistoryIncInferenceSum(history, dir, weight);
15583  }
15584 
15585  return SCIP_OKAY;
15586  }
15587  case SCIP_VARSTATUS_FIXED:
15588  SCIPerrorMessage("cannot update inference counter of a fixed variable\n");
15589  return SCIP_INVALIDDATA;
15590 
15592  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15593 
15594  if( var->data.aggregate.scalar > 0.0 )
15595  {
15596  SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
15597  }
15598  else
15599  {
15600  assert(var->data.aggregate.scalar < 0.0);
15601  SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15602  }
15603  return SCIP_OKAY;
15604 
15606  SCIPerrorMessage("cannot update inference counter of a multi-aggregated variable\n");
15607  return SCIP_INVALIDDATA;
15608 
15610  value = 1.0 - value;
15611 
15612  SCIP_CALL( SCIPvarIncInferenceSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15613  return SCIP_OKAY;
15614 
15615  default:
15616  SCIPerrorMessage("unknown variable status\n");
15617  return SCIP_INVALIDDATA;
15618  }
15619 }
15620 
15621 /** increases the cutoff sum of the variable by the given weight */
15623  SCIP_VAR* var, /**< problem variable */
15624  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15625  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15626  SCIP_STAT* stat, /**< problem statistics */
15627  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
15628  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15629  SCIP_Real weight /**< weight of this update in cutoff score */
15630  )
15631 {
15632  assert(var != NULL);
15633  assert(stat != NULL);
15634  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15635 
15636  /* check if history statistics should be collected for a variable */
15637  if( !stat->collectvarhistory )
15638  return SCIP_OKAY;
15639 
15640  switch( SCIPvarGetStatus(var) )
15641  {
15643  if( var->data.original.transvar == NULL )
15644  {
15645  SCIPerrorMessage("cannot update cutoff sum of original untransformed variable\n");
15646  return SCIP_INVALIDDATA;
15647  }
15648  SCIP_CALL( SCIPvarIncCutoffSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
15649  return SCIP_OKAY;
15650 
15651  case SCIP_VARSTATUS_LOOSE:
15652  case SCIP_VARSTATUS_COLUMN:
15653  {
15654  SCIPhistoryIncCutoffSum(var->history, dir, weight);
15655  SCIPhistoryIncCutoffSum(var->historycrun, dir, weight);
15656  SCIPhistoryIncCutoffSum(stat->glbhistory, dir, weight);
15657  SCIPhistoryIncCutoffSum(stat->glbhistorycrun, dir, weight);
15658 
15659  if( useValuehistory(var, value, set) )
15660  {
15661  SCIP_HISTORY* history;
15662 
15663  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15664  assert(history != NULL);
15665 
15666  SCIPhistoryIncCutoffSum(history, dir, weight);
15667  }
15668 
15669  return SCIP_OKAY;
15670  }
15671  case SCIP_VARSTATUS_FIXED:
15672  SCIPerrorMessage("cannot update cutoff sum of a fixed variable\n");
15673  return SCIP_INVALIDDATA;
15674 
15676  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15677 
15678  if( var->data.aggregate.scalar > 0.0 )
15679  {
15680  SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
15681  }
15682  else
15683  {
15684  assert(var->data.aggregate.scalar < 0.0);
15685  SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15686  }
15687  return SCIP_OKAY;
15688 
15690  SCIPerrorMessage("cannot update cutoff sum of a multi-aggregated variable\n");
15691  return SCIP_INVALIDDATA;
15692 
15694  value = 1.0 - value;
15695 
15696  SCIP_CALL( SCIPvarIncCutoffSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15697  return SCIP_OKAY;
15698 
15699  default:
15700  SCIPerrorMessage("unknown variable status\n");
15701  return SCIP_INVALIDDATA;
15702  }
15703 }
15704 
15705 /** returns the number of times, a bound of the variable was changed in given direction due to branching */
15707  SCIP_VAR* var, /**< problem variable */
15708  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15709  )
15710 {
15711  assert(var != NULL);
15712  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15713 
15714  switch( SCIPvarGetStatus(var) )
15715  {
15717  if( var->data.original.transvar == NULL )
15718  return 0;
15719  else
15720  return SCIPvarGetNBranchings(var->data.original.transvar, dir);
15721 
15722  case SCIP_VARSTATUS_LOOSE:
15723  case SCIP_VARSTATUS_COLUMN:
15724  return SCIPhistoryGetNBranchings(var->history, dir);
15725 
15726  case SCIP_VARSTATUS_FIXED:
15727  return 0;
15728 
15730  if( var->data.aggregate.scalar > 0.0 )
15731  return SCIPvarGetNBranchings(var->data.aggregate.var, dir);
15732  else
15734 
15736  return 0;
15737 
15740 
15741  default:
15742  SCIPerrorMessage("unknown variable status\n");
15743  SCIPABORT();
15744  return 0; /*lint !e527*/
15745  }
15746 }
15747 
15748 /** returns the number of times, a bound of the variable was changed in given direction due to branching
15749  * in the current run
15750  */
15752  SCIP_VAR* var, /**< problem variable */
15753  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15754  )
15755 {
15756  assert(var != NULL);
15757  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15758 
15759  switch( SCIPvarGetStatus(var) )
15760  {
15762  if( var->data.original.transvar == NULL )
15763  return 0;
15764  else
15766 
15767  case SCIP_VARSTATUS_LOOSE:
15768  case SCIP_VARSTATUS_COLUMN:
15769  return SCIPhistoryGetNBranchings(var->historycrun, dir);
15770 
15771  case SCIP_VARSTATUS_FIXED:
15772  return 0;
15773 
15775  if( var->data.aggregate.scalar > 0.0 )
15777  else
15779 
15781  return 0;
15782 
15785 
15786  default:
15787  SCIPerrorMessage("unknown variable status\n");
15788  SCIPABORT();
15789  return 0; /*lint !e527*/
15790  }
15791 }
15792 
15793 /** returns the average depth of bound changes in given direction due to branching on the variable */
15795  SCIP_VAR* var, /**< problem variable */
15796  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15797  )
15798 {
15799  assert(var != NULL);
15800  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15801 
15802  switch( SCIPvarGetStatus(var) )
15803  {
15805  if( var->data.original.transvar == NULL )
15806  return 0.0;
15807  else
15808  return SCIPvarGetAvgBranchdepth(var->data.original.transvar, dir);
15809 
15810  case SCIP_VARSTATUS_LOOSE:
15811  case SCIP_VARSTATUS_COLUMN:
15812  return SCIPhistoryGetAvgBranchdepth(var->history, dir);
15813 
15814  case SCIP_VARSTATUS_FIXED:
15815  return 0.0;
15816 
15818  if( var->data.aggregate.scalar > 0.0 )
15819  return SCIPvarGetAvgBranchdepth(var->data.aggregate.var, dir);
15820  else
15822 
15824  return 0.0;
15825 
15828 
15829  default:
15830  SCIPerrorMessage("unknown variable status\n");
15831  SCIPABORT();
15832  return 0.0; /*lint !e527*/
15833  }
15834 }
15835 
15836 /** returns the average depth of bound changes in given direction due to branching on the variable
15837  * in the current run
15838  */
15840  SCIP_VAR* var, /**< problem variable */
15841  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15842  )
15843 {
15844  assert(var != NULL);
15845  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15846 
15847  switch( SCIPvarGetStatus(var) )
15848  {
15850  if( var->data.original.transvar == NULL )
15851  return 0.0;
15852  else
15854 
15855  case SCIP_VARSTATUS_LOOSE:
15856  case SCIP_VARSTATUS_COLUMN:
15857  return SCIPhistoryGetAvgBranchdepth(var->historycrun, dir);
15858 
15859  case SCIP_VARSTATUS_FIXED:
15860  return 0.0;
15861 
15863  if( var->data.aggregate.scalar > 0.0 )
15865  else
15868 
15870  return 0.0;
15871 
15874  dir == SCIP_BRANCHDIR_DOWNWARDS ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
15875 
15876  default:
15877  SCIPerrorMessage("unknown variable status\n");
15878  SCIPABORT();
15879  return 0.0; /*lint !e527*/
15880  }
15881 }
15882 
15883 /** returns the variable's VSIDS score */
15885  SCIP_VAR* var, /**< problem variable */
15886  SCIP_STAT* stat, /**< problem statistics */
15887  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15888  )
15889 {
15890  assert(var != NULL);
15891  assert(stat != NULL);
15892  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15893 
15895  return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
15896 
15897  switch( SCIPvarGetStatus(var) )
15898  {
15900  if( var->data.original.transvar == NULL )
15901  return 0.0;
15902  else
15903  return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
15904 
15905  case SCIP_VARSTATUS_LOOSE:
15906  case SCIP_VARSTATUS_COLUMN:
15907  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE); /* column case already handled in if condition above */
15908  return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
15909 
15910  case SCIP_VARSTATUS_FIXED:
15911  return 0.0;
15912 
15914  if( var->data.aggregate.scalar > 0.0 )
15915  return SCIPvarGetVSIDS(var->data.aggregate.var, stat, dir);
15916  else
15917  /* coverity[overrun-local] */
15918  return SCIPvarGetVSIDS(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
15919 
15921  return 0.0;
15922 
15924  /* coverity[overrun-local] */
15925  return SCIPvarGetVSIDS(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15926 
15927  default:
15928  SCIPerrorMessage("unknown variable status\n");
15929  SCIPABORT();
15930  return 0.0; /*lint !e527*/
15931  }
15932 }
15933 
15934 /** returns the variable's VSIDS score only using conflicts of the current run */
15936  SCIP_VAR* var, /**< problem variable */
15937  SCIP_STAT* stat, /**< problem statistics */
15938  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15939  )
15940 {
15941  assert(var != NULL);
15942  assert(stat != NULL);
15943  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15944 
15945  if( dir != SCIP_BRANCHDIR_DOWNWARDS && dir != SCIP_BRANCHDIR_UPWARDS )
15946  {
15947  SCIPerrorMessage("invalid branching direction %d when asking for VSIDS value\n", dir);
15948  return SCIP_INVALID;
15949  }
15950 
15951  switch( SCIPvarGetStatus(var) )
15952  {
15954  if( var->data.original.transvar == NULL )
15955  return 0.0;
15956  else
15957  return SCIPvarGetVSIDSCurrentRun(var->data.original.transvar, stat, dir);
15958 
15959  case SCIP_VARSTATUS_LOOSE:
15960  case SCIP_VARSTATUS_COLUMN:
15961  return SCIPhistoryGetVSIDS(var->historycrun, dir)/stat->vsidsweight;
15962 
15963  case SCIP_VARSTATUS_FIXED:
15964  return 0.0;
15965 
15967  if( var->data.aggregate.scalar > 0.0 )
15968  return SCIPvarGetVSIDSCurrentRun(var->data.aggregate.var, stat, dir);
15969  else
15971 
15973  return 0.0;
15974 
15977 
15978  default:
15979  SCIPerrorMessage("unknown variable status\n");
15980  SCIPABORT();
15981  return 0.0; /*lint !e527*/
15982  }
15983 }
15984 
15985 /** returns the number of inferences branching on this variable in given direction triggered */
15987  SCIP_VAR* var, /**< problem variable */
15988  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15989  )
15990 {
15991  assert(var != NULL);
15992  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15993 
15994  switch( SCIPvarGetStatus(var) )
15995  {
15997  if( var->data.original.transvar == NULL )
15998  return 0.0;
15999  else
16000  return SCIPvarGetInferenceSum(var->data.original.transvar, dir);
16001 
16002  case SCIP_VARSTATUS_LOOSE:
16003  case SCIP_VARSTATUS_COLUMN:
16004  return SCIPhistoryGetInferenceSum(var->history, dir);
16005 
16006  case SCIP_VARSTATUS_FIXED:
16007  return 0.0;
16008 
16010  if( var->data.aggregate.scalar > 0.0 )
16011  return SCIPvarGetInferenceSum(var->data.aggregate.var, dir);
16012  else
16014 
16016  return 0.0;
16017 
16020 
16021  default:
16022  SCIPerrorMessage("unknown variable status\n");
16023  SCIPABORT();
16024  return 0.0; /*lint !e527*/
16025  }
16026 }
16027 
16028 /** returns the number of inferences branching on this variable in given direction triggered
16029  * in the current run
16030  */
16032  SCIP_VAR* var, /**< problem variable */
16033  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16034  )
16035 {
16036  assert(var != NULL);
16037  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16038 
16039  switch( SCIPvarGetStatus(var) )
16040  {
16042  if( var->data.original.transvar == NULL )
16043  return 0.0;
16044  else
16046 
16047  case SCIP_VARSTATUS_LOOSE:
16048  case SCIP_VARSTATUS_COLUMN:
16049  return SCIPhistoryGetInferenceSum(var->historycrun, dir);
16050 
16051  case SCIP_VARSTATUS_FIXED:
16052  return 0.0;
16053 
16055  if( var->data.aggregate.scalar > 0.0 )
16057  else
16059 
16061  return 0.0;
16062 
16065 
16066  default:
16067  SCIPerrorMessage("unknown variable status\n");
16068  SCIPABORT();
16069  return 0.0; /*lint !e527*/
16070  }
16071 }
16072 
16073 /** returns the average number of inferences found after branching on the variable in given direction */
16075  SCIP_VAR* var, /**< problem variable */
16076  SCIP_STAT* stat, /**< problem statistics */
16077  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16078  )
16079 {
16080  assert(var != NULL);
16081  assert(stat != NULL);
16082  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16083 
16084  switch( SCIPvarGetStatus(var) )
16085  {
16087  if( var->data.original.transvar == NULL )
16088  return SCIPhistoryGetAvgInferences(stat->glbhistory, dir);
16089  else
16090  return SCIPvarGetAvgInferences(var->data.original.transvar, stat, dir);
16091 
16092  case SCIP_VARSTATUS_LOOSE:
16093  case SCIP_VARSTATUS_COLUMN:
16094  if( SCIPhistoryGetNBranchings(var->history, dir) > 0 )
16095  return SCIPhistoryGetAvgInferences(var->history, dir);
16096  else
16097  {
16098  int nimpls;
16099  int ncliques;
16100 
16101  nimpls = SCIPvarGetNImpls(var, dir == SCIP_BRANCHDIR_UPWARDS);
16102  ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
16103  return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistory, dir); /*lint !e790*/
16104  }
16105 
16106  case SCIP_VARSTATUS_FIXED:
16107  return 0.0;
16108 
16110  if( var->data.aggregate.scalar > 0.0 )
16111  return SCIPvarGetAvgInferences(var->data.aggregate.var, stat, dir);
16112  else
16114 
16116  return 0.0;
16117 
16119  return SCIPvarGetAvgInferences(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
16120 
16121  default:
16122  SCIPerrorMessage("unknown variable status\n");
16123  SCIPABORT();
16124  return 0.0; /*lint !e527*/
16125  }
16126 }
16127 
16128 /** returns the average number of inferences found after branching on the variable in given direction
16129  * in the current run
16130  */
16132  SCIP_VAR* var, /**< problem variable */
16133  SCIP_STAT* stat, /**< problem statistics */
16134  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16135  )
16136 {
16137  assert(var != NULL);
16138  assert(stat != NULL);
16139  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16140 
16141  switch( SCIPvarGetStatus(var) )
16142  {
16144  if( var->data.original.transvar == NULL )
16145  return SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir);
16146  else
16147  return SCIPvarGetAvgInferencesCurrentRun(var->data.original.transvar, stat, dir);
16148 
16149  case SCIP_VARSTATUS_LOOSE:
16150  case SCIP_VARSTATUS_COLUMN:
16151  if( SCIPhistoryGetNBranchings(var->historycrun, dir) > 0 )
16152  return SCIPhistoryGetAvgInferences(var->historycrun, dir);
16153  else
16154  {
16155  int nimpls;
16156  int ncliques;
16157 
16158  nimpls = SCIPvarGetNImpls(var, dir == SCIP_BRANCHDIR_UPWARDS);
16159  ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
16160  return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir); /*lint !e790*/
16161  }
16162 
16163  case SCIP_VARSTATUS_FIXED:
16164  return 0.0;
16165 
16167  if( var->data.aggregate.scalar > 0.0 )
16168  return SCIPvarGetAvgInferencesCurrentRun(var->data.aggregate.var, stat, dir);
16169  else
16171 
16173  return 0.0;
16174 
16177 
16178  default:
16179  SCIPerrorMessage("unknown variable status\n");
16180  SCIPABORT();
16181  return 0.0; /*lint !e527*/
16182  }
16183 }
16184 
16185 /** returns the number of cutoffs branching on this variable in given direction produced */
16187  SCIP_VAR* var, /**< problem variable */
16188  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16189  )
16190 {
16191  assert(var != NULL);
16192  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16193 
16194  switch( SCIPvarGetStatus(var) )
16195  {
16197  if( var->data.original.transvar == NULL )
16198  return 0;
16199  else
16200  return SCIPvarGetCutoffSum(var->data.original.transvar, dir);
16201 
16202  case SCIP_VARSTATUS_LOOSE:
16203  case SCIP_VARSTATUS_COLUMN:
16204  return SCIPhistoryGetCutoffSum(var->history, dir);
16205 
16206  case SCIP_VARSTATUS_FIXED:
16207  return 0;
16208 
16210  if( var->data.aggregate.scalar > 0.0 )
16211  return SCIPvarGetCutoffSum(var->data.aggregate.var, dir);
16212  else
16214 
16216  return 0;
16217 
16220 
16221  default:
16222  SCIPerrorMessage("unknown variable status\n");
16223  SCIPABORT();
16224  return 0; /*lint !e527*/
16225  }
16226 }
16227 
16228 /** returns the number of cutoffs branching on this variable in given direction produced in the current run */
16230  SCIP_VAR* var, /**< problem variable */
16231  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16232  )
16233 {
16234  assert(var != NULL);
16235  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16236 
16237  switch( SCIPvarGetStatus(var) )
16238  {
16240  if( var->data.original.transvar == NULL )
16241  return 0;
16242  else
16244 
16245  case SCIP_VARSTATUS_LOOSE:
16246  case SCIP_VARSTATUS_COLUMN:
16247  return SCIPhistoryGetCutoffSum(var->historycrun, dir);
16248 
16249  case SCIP_VARSTATUS_FIXED:
16250  return 0;
16251 
16253  if( var->data.aggregate.scalar > 0.0 )
16254  return SCIPvarGetCutoffSumCurrentRun(var->data.aggregate.var, dir);
16255  else
16257 
16259  return 0;
16260 
16263 
16264  default:
16265  SCIPerrorMessage("unknown variable status\n");
16266  SCIPABORT();
16267  return 0; /*lint !e527*/
16268  }
16269 }
16270 
16271 /** returns the average number of cutoffs found after branching on the variable in given direction */
16273  SCIP_VAR* var, /**< problem variable */
16274  SCIP_STAT* stat, /**< problem statistics */
16275  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16276  )
16277 {
16278  assert(var != NULL);
16279  assert(stat != NULL);
16280  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16281 
16282  switch( SCIPvarGetStatus(var) )
16283  {
16285  if( var->data.original.transvar == NULL )
16286  return SCIPhistoryGetAvgCutoffs(stat->glbhistory, dir);
16287  else
16288  return SCIPvarGetAvgCutoffs(var->data.original.transvar, stat, dir);
16289 
16290  case SCIP_VARSTATUS_LOOSE:
16291  case SCIP_VARSTATUS_COLUMN:
16292  return SCIPhistoryGetNBranchings(var->history, dir) > 0
16293  ? SCIPhistoryGetAvgCutoffs(var->history, dir)
16294  : SCIPhistoryGetAvgCutoffs(stat->glbhistory, dir);
16295 
16296  case SCIP_VARSTATUS_FIXED:
16297  return 0.0;
16298 
16300  if( var->data.aggregate.scalar > 0.0 )
16301  return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, dir);
16302  else
16303  return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
16304 
16306  return 0.0;
16307 
16309  return SCIPvarGetAvgCutoffs(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
16310 
16311  default:
16312  SCIPerrorMessage("unknown variable status\n");
16313  SCIPABORT();
16314  return 0.0; /*lint !e527*/
16315  }
16316 }
16317 
16318 /** returns the average number of cutoffs found after branching on the variable in given direction in the current run */
16320  SCIP_VAR* var, /**< problem variable */
16321  SCIP_STAT* stat, /**< problem statistics */
16322  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16323  )
16324 {
16325  assert(var != NULL);
16326  assert(stat != NULL);
16327  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16328 
16329  switch( SCIPvarGetStatus(var) )
16330  {
16332  if( var->data.original.transvar == NULL )
16333  return SCIPhistoryGetAvgCutoffs(stat->glbhistorycrun, dir);
16334  else
16335  return SCIPvarGetAvgCutoffsCurrentRun(var->data.original.transvar, stat, dir);
16336 
16337  case SCIP_VARSTATUS_LOOSE:
16338  case SCIP_VARSTATUS_COLUMN:
16339  return SCIPhistoryGetNBranchings(var->historycrun, dir) > 0
16342 
16343  case SCIP_VARSTATUS_FIXED:
16344  return 0.0;
16345 
16347  if( var->data.aggregate.scalar > 0.0 )
16348  return SCIPvarGetAvgCutoffsCurrentRun(var->data.aggregate.var, stat, dir);
16349  else
16351 
16353  return 0.0;
16354 
16357 
16358  default:
16359  SCIPerrorMessage("unknown variable status\n");
16360  SCIPABORT();
16361  return 0.0; /*lint !e527*/
16362  }
16363 }
16364 
16365 
16366 
16367 
16368 /*
16369  * information methods for bound changes
16370  */
16371 
16372 /** creates an artificial bound change information object with depth = INT_MAX and pos = -1 */
16374  SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
16375  BMS_BLKMEM* blkmem, /**< block memory */
16376  SCIP_VAR* var, /**< active variable that changed the bounds */
16377  SCIP_BOUNDTYPE boundtype, /**< type of bound for var: lower or upper bound */
16378  SCIP_Real oldbound, /**< old value for bound */
16379  SCIP_Real newbound /**< new value for bound */
16380  )
16381 {
16382  assert(bdchginfo != NULL);
16383 
16384  SCIP_ALLOC( BMSallocBlockMemory(blkmem, bdchginfo) );
16385  (*bdchginfo)->oldbound = oldbound;
16386  (*bdchginfo)->newbound = newbound;
16387  (*bdchginfo)->var = var;
16388  (*bdchginfo)->inferencedata.var = var;
16389  (*bdchginfo)->inferencedata.reason.prop = NULL;
16390  (*bdchginfo)->inferencedata.info = 0;
16391  (*bdchginfo)->bdchgidx.depth = INT_MAX;
16392  (*bdchginfo)->bdchgidx.pos = -1;
16393  (*bdchginfo)->pos = 0;
16394  (*bdchginfo)->boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
16395  (*bdchginfo)->boundtype = boundtype; /*lint !e641*/
16396  (*bdchginfo)->inferboundtype = boundtype; /*lint !e641*/
16397  (*bdchginfo)->redundant = FALSE;
16398 
16399  return SCIP_OKAY;
16400 }
16401 
16402 /** frees a bound change information object */
16403 void SCIPbdchginfoFree(
16404  SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
16405  BMS_BLKMEM* blkmem /**< block memory */
16406  )
16407 {
16408  assert(bdchginfo != NULL);
16409 
16410  BMSfreeBlockMemory(blkmem, bdchginfo);
16411 }
16412 
16413 /** returns the bound change information for the last lower bound change on given active problem variable before or
16414  * after the bound change with the given index was applied;
16415  * returns NULL, if no change to the lower bound was applied up to this point of time
16416  */
16418  SCIP_VAR* var, /**< active problem variable */
16419  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16420  SCIP_Bool after /**< should the bound change with given index be included? */
16421  )
16422 {
16423  int i;
16424 
16425  assert(var != NULL);
16426  assert(SCIPvarIsActive(var));
16427 
16428  /* search the correct bound change information for the given bound change index */
16429  if( after )
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(bdchgidx, &var->lbchginfos[i].bdchgidx) )
16444  return &var->lbchginfos[i];
16445  }
16446  }
16447  else
16448  {
16449  for( i = var->nlbchginfos-1; i >= 0; --i )
16450  {
16451  assert(var->lbchginfos[i].var == var);
16453  assert(var->lbchginfos[i].pos == i);
16454 
16455  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16456  if( var->lbchginfos[i].redundant )
16457  return NULL;
16458  assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
16459 
16460  /* if we reached the bound change index, return the current bound change info */
16461  if( SCIPbdchgidxIsEarlier(&var->lbchginfos[i].bdchgidx, bdchgidx) )
16462  return &var->lbchginfos[i];
16463  }
16464  }
16465 
16466  return NULL;
16467 }
16468 
16469 /** returns the bound change information for the last upper bound change on given active problem variable before or
16470  * after the bound change with the given index was applied;
16471  * returns NULL, if no change to the upper bound was applied up to this point of time
16472  */
16474  SCIP_VAR* var, /**< active problem variable */
16475  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16476  SCIP_Bool after /**< should the bound change with given index be included? */
16477  )
16478 {
16479  int i;
16480 
16481  assert(var != NULL);
16482  assert(SCIPvarIsActive(var));
16483 
16484  /* search the correct bound change information for the given bound change index */
16485  if( after )
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(bdchgidx, &var->ubchginfos[i].bdchgidx) )
16500  return &var->ubchginfos[i];
16501  }
16502  }
16503  else
16504  {
16505  for( i = var->nubchginfos-1; i >= 0; --i )
16506  {
16507  assert(var->ubchginfos[i].var == var);
16509  assert(var->ubchginfos[i].pos == i);
16510 
16511  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16512  if( var->ubchginfos[i].redundant )
16513  return NULL;
16514  assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
16515 
16516  /* if we reached the bound change index, return the current bound change info */
16517  if( SCIPbdchgidxIsEarlier(&var->ubchginfos[i].bdchgidx, bdchgidx) )
16518  return &var->ubchginfos[i];
16519  }
16520  }
16521 
16522  return NULL;
16523 }
16524 
16525 /** returns the bound change information for the last lower or upper bound change on given active problem variable
16526  * before or after the bound change with the given index was applied;
16527  * returns NULL, if no change to the lower/upper bound was applied up to this point of time
16528  */
16530  SCIP_VAR* var, /**< active problem variable */
16531  SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
16532  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16533  SCIP_Bool after /**< should the bound change with given index be included? */
16534  )
16535 {
16536  if( boundtype == SCIP_BOUNDTYPE_LOWER )
16537  return SCIPvarGetLbchgInfo(var, bdchgidx, after);
16538  else
16539  {
16540  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16541  return SCIPvarGetUbchgInfo(var, bdchgidx, after);
16542  }
16543 }
16544 
16545 /** returns lower bound of variable directly before or after the bound change given by the bound change index
16546  * was applied
16547  *
16548  * @deprecated Please use SCIPgetVarLbAtIndex()
16549  */
16551  SCIP_VAR* var, /**< problem variable */
16552  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16553  SCIP_Bool after /**< should the bound change with given index be included? */
16554  )
16555 {
16556  SCIP_VARSTATUS varstatus;
16557  assert(var != NULL);
16558 
16559  varstatus = SCIPvarGetStatus(var);
16560 
16561  /* get bounds of attached variables */
16562  switch( varstatus )
16563  {
16565  assert(var->data.original.transvar != NULL);
16566  return SCIPvarGetLbAtIndex(var->data.original.transvar, bdchgidx, after);
16567 
16568  case SCIP_VARSTATUS_LOOSE:
16569  case SCIP_VARSTATUS_COLUMN:
16570  if( bdchgidx == NULL )
16571  return SCIPvarGetLbLocal(var);
16572  else
16573  {
16574  SCIP_BDCHGINFO* bdchginfo;
16575 
16576  bdchginfo = SCIPvarGetLbchgInfo(var, bdchgidx, after);
16577  if( bdchginfo != NULL )
16578  return SCIPbdchginfoGetNewbound(bdchginfo);
16579  else
16580  return var->glbdom.lb;
16581  }
16582  case SCIP_VARSTATUS_FIXED:
16583  return var->glbdom.lb;
16584 
16585  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
16586  assert(var->data.aggregate.var != NULL);
16587  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
16588  * corresponding infinity value instead of performing an arithmetical transformation (compare method
16589  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
16590  * (or is called by) a public interface method; instead, we only assert that values are finite
16591  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
16592  * positives and negatives if the parameter <numerics/infinity> is modified by the user
16593  */
16594  if( var->data.aggregate.scalar > 0.0 )
16595  {
16596  /* a > 0 -> get lower bound of y */
16597  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16598  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16599  return var->data.aggregate.scalar * SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after)
16600  + var->data.aggregate.constant;
16601  }
16602  else if( var->data.aggregate.scalar < 0.0 )
16603  {
16604  /* a < 0 -> get upper bound of y */
16605  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16606  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16607  return var->data.aggregate.scalar * SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after)
16608  + var->data.aggregate.constant;
16609  }
16610  else
16611  {
16612  SCIPerrorMessage("scalar is zero in aggregation\n");
16613  SCIPABORT();
16614  return SCIP_INVALID; /*lint !e527*/
16615  }
16616 
16618  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
16619  if ( var->data.multaggr.nvars == 1 )
16620  {
16621  assert(var->data.multaggr.vars != NULL);
16622  assert(var->data.multaggr.scalars != NULL);
16623  assert(var->data.multaggr.vars[0] != NULL);
16624 
16625  if( var->data.multaggr.scalars[0] > 0.0 )
16626  {
16627  /* a > 0 -> get lower bound of y */
16628  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16629  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16630  return var->data.multaggr.scalars[0] * SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16631  + var->data.multaggr.constant;
16632  }
16633  else if( var->data.multaggr.scalars[0] < 0.0 )
16634  {
16635  /* a < 0 -> get upper bound of y */
16636  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16637  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16638  return var->data.multaggr.scalars[0] * SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16639  + var->data.multaggr.constant;
16640  }
16641  else
16642  {
16643  SCIPerrorMessage("scalar is zero in multi-aggregation\n");
16644  SCIPABORT();
16645  return SCIP_INVALID; /*lint !e527*/
16646  }
16647  }
16648  SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
16649  SCIPABORT();
16650  return SCIP_INVALID; /*lint !e527*/
16651 
16652  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
16653  assert(var->negatedvar != NULL);
16655  assert(var->negatedvar->negatedvar == var);
16656  return var->data.negate.constant - SCIPvarGetUbAtIndex(var->negatedvar, bdchgidx, after);
16657  default:
16658  SCIPerrorMessage("unknown variable status\n");
16659  SCIPABORT();
16660  return SCIP_INVALID; /*lint !e527*/
16661  }
16662 }
16663 
16664 /** returns upper bound of variable directly before or after the bound change given by the bound change index
16665  * was applied
16666  *
16667  * @deprecated Please use SCIPgetVarUbAtIndex()
16668  */
16670  SCIP_VAR* var, /**< problem variable */
16671  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16672  SCIP_Bool after /**< should the bound change with given index be included? */
16673  )
16674 {
16675  SCIP_VARSTATUS varstatus;
16676  assert(var != NULL);
16677 
16678  varstatus = SCIPvarGetStatus(var);
16679 
16680  /* get bounds of attached variables */
16681  switch( varstatus )
16682  {
16684  assert(var->data.original.transvar != NULL);
16685  return SCIPvarGetUbAtIndex(var->data.original.transvar, bdchgidx, after);
16686 
16687  case SCIP_VARSTATUS_COLUMN:
16688  case SCIP_VARSTATUS_LOOSE:
16689  if( bdchgidx == NULL )
16690  return SCIPvarGetUbLocal(var);
16691  else
16692  {
16693  SCIP_BDCHGINFO* bdchginfo;
16694 
16695  bdchginfo = SCIPvarGetUbchgInfo(var, bdchgidx, after);
16696  if( bdchginfo != NULL )
16697  return SCIPbdchginfoGetNewbound(bdchginfo);
16698  else
16699  return var->glbdom.ub;
16700  }
16701 
16702  case SCIP_VARSTATUS_FIXED:
16703  return var->glbdom.ub;
16704 
16705  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
16706  assert(var->data.aggregate.var != NULL);
16707  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
16708  * corresponding infinity value instead of performing an arithmetical transformation (compare method
16709  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
16710  * (or is called by) a public interface method; instead, we only assert that values are finite
16711  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
16712  * positives and negatives if the parameter <numerics/infinity> is modified by the user
16713  */
16714  if( var->data.aggregate.scalar > 0.0 )
16715  {
16716  /* a > 0 -> get lower bound of y */
16717  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16718  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16719  return var->data.aggregate.scalar * SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after)
16720  + var->data.aggregate.constant;
16721  }
16722  else if( var->data.aggregate.scalar < 0.0 )
16723  {
16724  /* a < 0 -> get upper bound of y */
16725  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16726  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16727  return var->data.aggregate.scalar * SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after)
16728  + var->data.aggregate.constant;
16729  }
16730  else
16731  {
16732  SCIPerrorMessage("scalar is zero in aggregation\n");
16733  SCIPABORT();
16734  return SCIP_INVALID; /*lint !e527*/
16735  }
16736 
16738  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
16739  if ( var->data.multaggr.nvars == 1 )
16740  {
16741  assert(var->data.multaggr.vars != NULL);
16742  assert(var->data.multaggr.scalars != NULL);
16743  assert(var->data.multaggr.vars[0] != NULL);
16744 
16745  if( var->data.multaggr.scalars[0] > 0.0 )
16746  {
16747  /* a > 0 -> get lower bound of y */
16748  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16749  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16750  return var->data.multaggr.scalars[0] * SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16751  + var->data.multaggr.constant;
16752  }
16753  else if( var->data.multaggr.scalars[0] < 0.0 )
16754  {
16755  /* a < 0 -> get upper bound of y */
16756  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16757  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16758  return var->data.multaggr.scalars[0] * SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16759  + var->data.multaggr.constant;
16760  }
16761  else
16762  {
16763  SCIPerrorMessage("scalar is zero in multi-aggregation\n");
16764  SCIPABORT();
16765  return SCIP_INVALID; /*lint !e527*/
16766  }
16767  }
16768  SCIPerrorMessage("cannot get the bounds of a multiple aggregated variable.\n");
16769  SCIPABORT();
16770  return SCIP_INVALID; /*lint !e527*/
16771 
16772  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
16773  assert(var->negatedvar != NULL);
16775  assert(var->negatedvar->negatedvar == var);
16776  return var->data.negate.constant - SCIPvarGetLbAtIndex(var->negatedvar, bdchgidx, after);
16777 
16778  default:
16779  SCIPerrorMessage("unknown variable status\n");
16780  SCIPABORT();
16781  return SCIP_INVALID; /*lint !e527*/
16782  }
16783 }
16784 
16785 /** returns lower or upper bound of variable directly before or after the bound change given by the bound change index
16786  * was applied
16787  *
16788  * @deprecated Please use SCIPgetVarBdAtIndex()
16789  */
16791  SCIP_VAR* var, /**< problem variable */
16792  SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
16793  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16794  SCIP_Bool after /**< should the bound change with given index be included? */
16795  )
16796 {
16797  if( boundtype == SCIP_BOUNDTYPE_LOWER )
16798  return SCIPvarGetLbAtIndex(var, bdchgidx, after);
16799  else
16800  {
16801  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16802  return SCIPvarGetUbAtIndex(var, bdchgidx, after);
16803  }
16804 }
16805 
16806 /** returns whether the binary variable was fixed at the time given by the bound change index
16807  *
16808  * @deprecated Please use SCIPgetVarWasFixedAtIndex()
16809  */
16811  SCIP_VAR* var, /**< problem variable */
16812  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16813  SCIP_Bool after /**< should the bound change with given index be included? */
16814  )
16815 {
16816  assert(var != NULL);
16817  assert(SCIPvarIsBinary(var));
16818 
16819  /* check the current bounds first in order to decide at which bound change information we have to look
16820  * (which is expensive because we have to follow the aggregation tree to the active variable)
16821  */
16822  return ((SCIPvarGetLbLocal(var) > 0.5 && SCIPvarGetLbAtIndex(var, bdchgidx, after) > 0.5)
16823  || (SCIPvarGetUbLocal(var) < 0.5 && SCIPvarGetUbAtIndex(var, bdchgidx, after) < 0.5));
16824 }
16825 
16826 /** bound change index representing the initial time before any bound changes took place */
16827 static SCIP_BDCHGIDX initbdchgidx = {-2, 0};
16829 /** bound change index representing the presolving stage */
16830 static SCIP_BDCHGIDX presolvebdchgidx = {-1, 0};
16832 /** returns the last bound change index, at which the bounds of the given variable were tightened */
16834  SCIP_VAR* var /**< problem variable */
16835  )
16836 {
16837  SCIP_BDCHGIDX* lbchgidx;
16838  SCIP_BDCHGIDX* ubchgidx;
16839 
16840  assert(var != NULL);
16841 
16842  var = SCIPvarGetProbvar(var);
16843 
16844  /* check, if variable is original without transformed variable */
16845  if( var == NULL )
16846  return &initbdchgidx;
16847 
16848  /* check, if variable was fixed in presolving */
16849  if( !SCIPvarIsActive(var) )
16850  return &presolvebdchgidx;
16851 
16853 
16854  /* get depths of last bound change information for the lower and upper bound */
16855  lbchgidx = (var->nlbchginfos > 0 && !var->lbchginfos[var->nlbchginfos-1].redundant
16856  ? &var->lbchginfos[var->nlbchginfos-1].bdchgidx : &initbdchgidx);
16857  ubchgidx = (var->nubchginfos > 0 && !var->ubchginfos[var->nubchginfos-1].redundant
16858  ? &var->ubchginfos[var->nubchginfos-1].bdchgidx : &initbdchgidx);
16859 
16860  if( SCIPbdchgidxIsEarlierNonNull(lbchgidx, ubchgidx) )
16861  return ubchgidx;
16862  else
16863  return lbchgidx;
16864 }
16865 
16866 /** returns the last depth level, at which the bounds of the given variable were tightened;
16867  * returns -2, if the variable's bounds are still the global bounds
16868  * returns -1, if the variable was fixed in presolving
16869  */
16871  SCIP_VAR* var /**< problem variable */
16872  )
16873 {
16874  SCIP_BDCHGIDX* bdchgidx;
16875 
16876  bdchgidx = SCIPvarGetLastBdchgIndex(var);
16877  assert(bdchgidx != NULL);
16878 
16879  return bdchgidx->depth;
16880 }
16881 
16882 /** returns at which depth in the tree a bound change was applied to the variable that conflicts with the
16883  * given bound; returns -1 if the bound does not conflict with the current local bounds of the variable
16884  */
16886  SCIP_VAR* var, /**< problem variable */
16887  SCIP_SET* set, /**< global SCIP settings */
16888  SCIP_BOUNDTYPE boundtype, /**< bound type of the conflicting bound */
16889  SCIP_Real bound /**< conflicting bound */
16890  )
16891 {
16892  int i;
16893 
16894  assert(var != NULL);
16895  assert(set != NULL);
16896  assert(var->scip == set->scip);
16897 
16898  if( boundtype == SCIP_BOUNDTYPE_LOWER )
16899  {
16900  /* check if the bound is in conflict with the current local bounds */
16901  if( SCIPsetIsLE(set, bound, var->locdom.ub) )
16902  return -1;
16903 
16904  /* check if the bound is in conflict with the global bound */
16905  if( SCIPsetIsGT(set, bound, var->glbdom.ub) )
16906  return 0;
16907 
16908  /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
16909  assert(var->nubchginfos > 0);
16910  assert(SCIPsetIsGT(set, bound, var->ubchginfos[var->nubchginfos-1].newbound));
16911 
16912  /* search for the first conflicting bound change */
16913  for( i = var->nubchginfos-1; i > 0 && SCIPsetIsGT(set, bound, var->ubchginfos[i-1].newbound); --i )
16914  {
16915  assert(var->ubchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
16917  }
16918  assert(SCIPsetIsGT(set, bound, var->ubchginfos[i].newbound)); /* bound change i is conflicting */
16919  assert(i == 0 || SCIPsetIsLE(set, bound, var->ubchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
16920 
16921  /* return the depth at which the first conflicting bound change took place */
16922  return var->ubchginfos[i].bdchgidx.depth;
16923  }
16924  else
16925  {
16926  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16927 
16928  /* check if the bound is in conflict with the current local bounds */
16929  if( SCIPsetIsGE(set, bound, var->locdom.lb) )
16930  return -1;
16931 
16932  /* check if the bound is in conflict with the global bound */
16933  if( SCIPsetIsLT(set, bound, var->glbdom.lb) )
16934  return 0;
16935 
16936  /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
16937  assert(var->nlbchginfos > 0);
16938  assert(SCIPsetIsLT(set, bound, var->lbchginfos[var->nlbchginfos-1].newbound));
16939 
16940  /* search for the first conflicting bound change */
16941  for( i = var->nlbchginfos-1; i > 0 && SCIPsetIsLT(set, bound, var->lbchginfos[i-1].newbound); --i )
16942  {
16943  assert(var->lbchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
16945  }
16946  assert(SCIPsetIsLT(set, bound, var->lbchginfos[i].newbound)); /* bound change i is conflicting */
16947  assert(i == 0 || SCIPsetIsGE(set, bound, var->lbchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
16948 
16949  /* return the depth at which the first conflicting bound change took place */
16950  return var->lbchginfos[i].bdchgidx.depth;
16951  }
16952 }
16953 
16954 /** returns whether the first binary variable was fixed earlier than the second one;
16955  * returns FALSE, if the first variable is not fixed, and returns TRUE, if the first variable is fixed, but the
16956  * second one is not fixed
16957  */
16959  SCIP_VAR* var1, /**< first binary variable */
16960  SCIP_VAR* var2 /**< second binary variable */
16961  )
16962 {
16963  SCIP_BDCHGIDX* bdchgidx1;
16964  SCIP_BDCHGIDX* bdchgidx2;
16965 
16966  assert(var1 != NULL);
16967  assert(var2 != NULL);
16968  assert(SCIPvarIsBinary(var1));
16969  assert(SCIPvarIsBinary(var2));
16970 
16971  var1 = SCIPvarGetProbvar(var1);
16972  var2 = SCIPvarGetProbvar(var2);
16973  assert(var1 != NULL);
16974  assert(var2 != NULL);
16975 
16976  /* check, if variables are globally fixed */
16977  if( !SCIPvarIsActive(var2) || var2->glbdom.lb > 0.5 || var2->glbdom.ub < 0.5 )
16978  return FALSE;
16979  if( !SCIPvarIsActive(var1) || var1->glbdom.lb > 0.5 || var1->glbdom.ub < 0.5 )
16980  return TRUE;
16981 
16984  assert(SCIPvarIsBinary(var1));
16985  assert(SCIPvarIsBinary(var2));
16986  assert(var1->nlbchginfos + var1->nubchginfos <= 1);
16987  assert(var2->nlbchginfos + var2->nubchginfos <= 1);
16988  assert(var1->nlbchginfos == 0 || !var1->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
16989  assert(var1->nubchginfos == 0 || !var1->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
16990  assert(var2->nlbchginfos == 0 || !var2->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
16991  assert(var2->nubchginfos == 0 || !var2->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
16992 
16993  if( var1->nlbchginfos == 1 )
16994  bdchgidx1 = &var1->lbchginfos[0].bdchgidx;
16995  else if( var1->nubchginfos == 1 )
16996  bdchgidx1 = &var1->ubchginfos[0].bdchgidx;
16997  else
16998  bdchgidx1 = NULL;
16999 
17000  if( var2->nlbchginfos == 1 )
17001  bdchgidx2 = &var2->lbchginfos[0].bdchgidx;
17002  else if( var2->nubchginfos == 1 )
17003  bdchgidx2 = &var2->ubchginfos[0].bdchgidx;
17004  else
17005  bdchgidx2 = NULL;
17006 
17007  return SCIPbdchgidxIsEarlier(bdchgidx1, bdchgidx2);
17008 }
17009 
17010 
17011 
17012 /*
17013  * Hash functions
17014  */
17015 
17016 /** gets the key (i.e. the name) of the given variable */
17017 SCIP_DECL_HASHGETKEY(SCIPhashGetKeyVar)
17018 { /*lint --e{715}*/
17019  SCIP_VAR* var = (SCIP_VAR*)elem;
17020 
17021  assert(var != NULL);
17022  return var->name;
17023 }
17024 
17025 
17026 
17027 
17028 /*
17029  * simple functions implemented as defines
17030  */
17031 
17032 /* In debug mode, the following methods are implemented as function calls to ensure
17033  * type validity.
17034  * In optimized mode, the methods are implemented as defines to improve performance.
17035  * However, we want to have them in the library anyways, so we have to undef the defines.
17036  */
17037 
17038 #undef SCIPboundchgGetNewbound
17039 #undef SCIPboundchgGetVar
17040 #undef SCIPboundchgGetBoundchgtype
17041 #undef SCIPboundchgGetBoundtype
17042 #undef SCIPboundchgIsRedundant
17043 #undef SCIPdomchgGetNBoundchgs
17044 #undef SCIPdomchgGetBoundchg
17045 #undef SCIPholelistGetLeft
17046 #undef SCIPholelistGetRight
17047 #undef SCIPholelistGetNext
17048 #undef SCIPvarGetName
17049 #undef SCIPvarGetNUses
17050 #undef SCIPvarGetData
17051 #undef SCIPvarSetData
17052 #undef SCIPvarSetDelorigData
17053 #undef SCIPvarSetTransData
17054 #undef SCIPvarSetDeltransData
17055 #undef SCIPvarGetStatus
17056 #undef SCIPvarIsOriginal
17057 #undef SCIPvarIsTransformed
17058 #undef SCIPvarIsNegated
17059 #undef SCIPvarGetType
17060 #undef SCIPvarIsBinary
17061 #undef SCIPvarIsIntegral
17062 #undef SCIPvarIsInitial
17063 #undef SCIPvarIsRemovable
17064 #undef SCIPvarIsDeleted
17065 #undef SCIPvarIsDeletable
17066 #undef SCIPvarMarkDeletable
17067 #undef SCIPvarMarkNotDeletable
17068 #undef SCIPvarIsActive
17069 #undef SCIPvarGetIndex
17070 #undef SCIPvarGetProbindex
17071 #undef SCIPvarGetTransVar
17072 #undef SCIPvarGetCol
17073 #undef SCIPvarIsInLP
17074 #undef SCIPvarGetAggrVar
17075 #undef SCIPvarGetAggrScalar
17076 #undef SCIPvarGetAggrConstant
17077 #undef SCIPvarGetMultaggrNVars
17078 #undef SCIPvarGetMultaggrVars
17079 #undef SCIPvarGetMultaggrScalars
17080 #undef SCIPvarGetMultaggrConstant
17081 #undef SCIPvarGetNegatedVar
17082 #undef SCIPvarGetNegationVar
17083 #undef SCIPvarGetNegationConstant
17084 #undef SCIPvarGetObj
17085 #undef SCIPvarGetLbOriginal
17086 #undef SCIPvarGetUbOriginal
17087 #undef SCIPvarGetHolelistOriginal
17088 #undef SCIPvarGetLbGlobal
17089 #undef SCIPvarGetUbGlobal
17090 #undef SCIPvarGetHolelistGlobal
17091 #undef SCIPvarGetBestBoundGlobal
17092 #undef SCIPvarGetWorstBoundGlobal
17093 #undef SCIPvarGetLbLocal
17094 #undef SCIPvarGetUbLocal
17095 #undef SCIPvarGetHolelistLocal
17096 #undef SCIPvarGetBestBoundLocal
17097 #undef SCIPvarGetWorstBoundLocal
17098 #undef SCIPvarGetBestBoundType
17099 #undef SCIPvarGetWorstBoundType
17100 #undef SCIPvarGetLbLazy
17101 #undef SCIPvarGetUbLazy
17102 #undef SCIPvarGetBranchFactor
17103 #undef SCIPvarGetBranchPriority
17104 #undef SCIPvarGetBranchDirection
17105 #undef SCIPvarGetNVlbs
17106 #undef SCIPvarGetVlbVars
17107 #undef SCIPvarGetVlbCoefs
17108 #undef SCIPvarGetVlbConstants
17109 #undef SCIPvarGetNVubs
17110 #undef SCIPvarGetVubVars
17111 #undef SCIPvarGetVubCoefs
17112 #undef SCIPvarGetVubConstants
17113 #undef SCIPvarGetNImpls
17114 #undef SCIPvarGetImplVars
17115 #undef SCIPvarGetImplTypes
17116 #undef SCIPvarGetImplBounds
17117 #undef SCIPvarGetImplIds
17118 #undef SCIPvarGetNCliques
17119 #undef SCIPvarGetCliques
17120 #undef SCIPvarGetLPSol
17121 #undef SCIPvarGetNLPSol
17122 #undef SCIPvarGetBdchgInfoLb
17123 #undef SCIPvarGetNBdchgInfosLb
17124 #undef SCIPvarGetBdchgInfoUb
17125 #undef SCIPvarGetNBdchgInfosUb
17126 #undef SCIPvarGetValuehistory
17127 #undef SCIPvarGetPseudoSol
17128 #undef SCIPvarCatchEvent
17129 #undef SCIPvarDropEvent
17130 #undef SCIPvarGetVSIDS
17131 #undef SCIPvarGetCliqueComponentIdx
17132 #undef SCIPvarIsRelaxationOnly
17133 #undef SCIPvarMarkRelaxationOnly
17134 #undef SCIPbdchgidxGetPos
17135 #undef SCIPbdchgidxIsEarlierNonNull
17136 #undef SCIPbdchgidxIsEarlier
17137 #undef SCIPbdchginfoGetOldbound
17138 #undef SCIPbdchginfoGetNewbound
17139 #undef SCIPbdchginfoGetVar
17140 #undef SCIPbdchginfoGetChgtype
17141 #undef SCIPbdchginfoGetBoundtype
17142 #undef SCIPbdchginfoGetDepth
17143 #undef SCIPbdchginfoGetPos
17144 #undef SCIPbdchginfoGetIdx
17145 #undef SCIPbdchginfoGetInferVar
17146 #undef SCIPbdchginfoGetInferCons
17147 #undef SCIPbdchginfoGetInferProp
17148 #undef SCIPbdchginfoGetInferInfo
17149 #undef SCIPbdchginfoGetInferBoundtype
17150 #undef SCIPbdchginfoIsRedundant
17151 #undef SCIPbdchginfoHasInferenceReason
17152 #undef SCIPbdchginfoIsTighter
17153 
17154 
17155 /** returns the new value of the bound in the bound change data */
17157  SCIP_BOUNDCHG* boundchg /**< bound change data */
17158  )
17159 {
17160  assert(boundchg != NULL);
17161 
17162  return boundchg->newbound;
17163 }
17164 
17165 /** returns the variable of the bound change in the bound change data */
17167  SCIP_BOUNDCHG* boundchg /**< bound change data */
17168  )
17169 {
17170  assert(boundchg != NULL);
17171 
17172  return boundchg->var;
17173 }
17174 
17175 /** returns the bound change type of the bound change in the bound change data */
17177  SCIP_BOUNDCHG* boundchg /**< bound change data */
17178  )
17179 {
17180  assert(boundchg != NULL);
17181 
17182  return (SCIP_BOUNDCHGTYPE)(boundchg->boundchgtype);
17183 }
17184 
17185 /** returns the bound type of the bound change in the bound change data */
17187  SCIP_BOUNDCHG* boundchg /**< bound change data */
17188  )
17189 {
17190  assert(boundchg != NULL);
17191 
17192  return (SCIP_BOUNDTYPE)(boundchg->boundtype);
17193 }
17194 
17195 /** returns whether the bound change is redundant due to a more global bound that is at least as strong */
17197  SCIP_BOUNDCHG* boundchg /**< bound change data */
17198  )
17199 {
17200  assert(boundchg != NULL);
17201 
17202  return boundchg->redundant;
17203 }
17204 
17205 /** returns the number of bound changes in the domain change data */
17207  SCIP_DOMCHG* domchg /**< domain change data */
17208  )
17209 {
17210  return domchg != NULL ? domchg->domchgbound.nboundchgs : 0;
17211 }
17212 
17213 /** returns a particular bound change in the domain change data */
17215  SCIP_DOMCHG* domchg, /**< domain change data */
17216  int pos /**< position of the bound change in the domain change data */
17217  )
17218 {
17219  assert(domchg != NULL);
17220  assert(0 <= pos && pos < (int)domchg->domchgbound.nboundchgs);
17221 
17222  return &domchg->domchgbound.boundchgs[pos];
17223 }
17224 
17225 /** returns left bound of open interval in hole */
17227  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
17228  )
17229 {
17230  assert(holelist != NULL);
17231 
17232  return holelist->hole.left;
17233 }
17234 
17235 /** returns right bound of open interval in hole */
17237  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
17238  )
17239 {
17240  assert(holelist != NULL);
17241 
17242  return holelist->hole.right;
17243 }
17244 
17245 /** returns next hole in list */
17247  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
17248  )
17249 {
17250  assert(holelist != NULL);
17251 
17252  return holelist->next;
17253 }
17254 
17255 /** returns the name of the variable
17256  *
17257  * @note to change the name of a variable, use SCIPchgVarName() from scip.h
17258  */
17259 const char* SCIPvarGetName(
17260  SCIP_VAR* var /**< problem variable */
17261  )
17262 {
17263  assert(var != NULL);
17264 
17265  return var->name;
17266 }
17267 
17268 /** gets number of times, the variable is currently captured */
17269 int SCIPvarGetNUses(
17270  SCIP_VAR* var /**< problem variable */
17271  )
17272 {
17273  assert(var != NULL);
17274 
17275  return var->nuses;
17276 }
17277 
17278 /** returns the user data of the variable */
17280  SCIP_VAR* var /**< problem variable */
17281  )
17282 {
17283  assert(var != NULL);
17284 
17285  return var->vardata;
17286 }
17287 
17288 /** sets the user data for the variable */
17289 void SCIPvarSetData(
17290  SCIP_VAR* var, /**< problem variable */
17291  SCIP_VARDATA* vardata /**< user variable data */
17292  )
17293 {
17294  assert(var != NULL);
17295 
17296  var->vardata = vardata;
17297 }
17298 
17299 /** sets method to free user data for the original variable */
17301  SCIP_VAR* var, /**< problem variable */
17302  SCIP_DECL_VARDELORIG ((*vardelorig)) /**< frees user data of original variable */
17303  )
17304 {
17305  assert(var != NULL);
17306  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
17307 
17308  var->vardelorig = vardelorig;
17309 }
17310 
17311 /** sets method to transform user data of the variable */
17312 void SCIPvarSetTransData(
17313  SCIP_VAR* var, /**< problem variable */
17314  SCIP_DECL_VARTRANS ((*vartrans)) /**< creates transformed user data by transforming original user data */
17315  )
17316 {
17317  assert(var != NULL);
17318  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
17319 
17320  var->vartrans = vartrans;
17321 }
17322 
17323 /** sets method to free transformed user data for the variable */
17325  SCIP_VAR* var, /**< problem variable */
17326  SCIP_DECL_VARDELTRANS ((*vardeltrans)) /**< frees user data of transformed variable */
17327  )
17328 {
17329  assert(var != NULL);
17330 
17331  var->vardeltrans = vardeltrans;
17332 }
17333 
17334 /** sets method to copy this variable into sub-SCIPs */
17335 void SCIPvarSetCopyData(
17336  SCIP_VAR* var, /**< problem variable */
17337  SCIP_DECL_VARCOPY ((*varcopy)) /**< copy method of the variable */
17338  )
17339 {
17340  assert(var != NULL);
17341 
17342  var->varcopy = varcopy;
17343 }
17344 
17345 /** sets the initial flag of a variable; only possible for original or loose variables */
17347  SCIP_VAR* var, /**< problem variable */
17348  SCIP_Bool initial /**< initial flag */
17349  )
17350 {
17351  assert(var != NULL);
17352 
17354  return SCIP_INVALIDCALL;
17355 
17356  var->initial = initial;
17357 
17358  return SCIP_OKAY;
17359 }
17360 
17361 /** sets the removable flag of a variable; only possible for original or loose variables */
17363  SCIP_VAR* var, /**< problem variable */
17364  SCIP_Bool removable /**< removable flag */
17365  )
17366 {
17367  assert(var != NULL);
17368 
17370  return SCIP_INVALIDCALL;
17371 
17372  var->removable = removable;
17373 
17374  return SCIP_OKAY;
17375 }
17376 
17377 /** gets status of variable */
17379  SCIP_VAR* var /**< problem variable */
17380  )
17381 {
17382  assert(var != NULL);
17383 
17384  return (SCIP_VARSTATUS)(var->varstatus);
17385 }
17386 
17387 /** returns whether the variable belongs to the original problem */
17389  SCIP_VAR* var /**< problem variable */
17390  )
17391 {
17392  assert(var != NULL);
17393  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED || var->negatedvar != NULL);
17394 
17398 }
17399 
17400 /** returns whether the variable belongs to the transformed problem */
17402  SCIP_VAR* var /**< problem variable */
17403  )
17404 {
17405  assert(var != NULL);
17406  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED || var->negatedvar != NULL);
17407 
17411 }
17412 
17413 /** returns whether the variable was created by negation of a different variable */
17415  SCIP_VAR* var /**< problem variable */
17416  )
17417 {
17418  assert(var != NULL);
17419 
17420  return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17421 }
17422 
17423 /** gets type of variable */
17425  SCIP_VAR* var /**< problem variable */
17426  )
17427 {
17428  assert(var != NULL);
17429 
17430  return (SCIP_VARTYPE)(var->vartype);
17431 }
17432 
17433 /** returns TRUE if the variable is of binary type; this is the case if:
17434  * (1) variable type is binary
17435  * (2) variable type is integer or implicit integer and
17436  * (i) the global lower bound is greater than or equal to zero
17437  * (ii) the global upper bound is less than or equal to one
17438  */
17440  SCIP_VAR* var /**< problem variable */
17441  )
17442 {
17443  assert(var != NULL);
17444 
17445  return (SCIPvarGetType(var) == SCIP_VARTYPE_BINARY ||
17446  (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && var->glbdom.lb >= 0.0 && var->glbdom.ub <= 1.0));
17447 }
17448 
17449 /** returns whether variable is of integral type (binary, integer, or implicit integer) */
17451  SCIP_VAR* var /**< problem variable */
17452  )
17453 {
17454  assert(var != NULL);
17455 
17456  return (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
17457 }
17458 
17459 /** returns whether variable's column should be present in the initial root LP */
17461  SCIP_VAR* var /**< problem variable */
17462  )
17463 {
17464  assert(var != NULL);
17465 
17466  return var->initial;
17467 }
17468 
17469 /** returns whether variable's column is removable from the LP (due to aging or cleanup) */
17471  SCIP_VAR* var /**< problem variable */
17472  )
17473 {
17474  assert(var != NULL);
17475 
17476  return var->removable;
17477 }
17478 
17479 /** returns whether the variable was deleted from the problem */
17481  SCIP_VAR* var /**< problem variable */
17482  )
17483 {
17484  assert(var != NULL);
17485 
17486  return var->deleted;
17487 }
17488 
17489 /** marks the variable to be deletable, i.e., it may be deleted completely from the problem;
17490  * method can only be called before the variable is added to the problem by SCIPaddVar() or SCIPaddPricedVar()
17491  */
17493  SCIP_VAR* var /**< problem variable */
17494  )
17495 {
17496  assert(var != NULL);
17497  assert(var->probindex == -1);
17498 
17499  var->deletable = TRUE;
17500 }
17501 
17502 /** marks the variable to be not deletable from the problem */
17505  )
17506 {
17507  assert(var != NULL);
17508 
17509  var->deletable = FALSE;
17510 }
17511 
17512 /** marks variable to be deleted from global structures (cliques etc.) when cleaning up
17513  *
17514  * @note: this is not equivalent to marking the variable itself for deletion, this is done by using SCIPvarMarkDeletable()
17515  */
17517  SCIP_VAR* var /**< problem variable */
17518  )
17519 {
17520  assert(var != NULL);
17521 
17522  var->delglobalstructs = TRUE;
17523 }
17524 
17525 /** returns whether the variable was flagged for deletion from global structures (cliques etc.) */
17527  SCIP_VAR* var /**< problem variable */
17528  )
17529 {
17530  assert(var != NULL);
17531 
17532  return var->delglobalstructs;
17533 }
17534 
17535 /** returns whether a variable has been introduced to define a relaxation
17536  *
17537  * These variables are only valid for the current SCIP solve round,
17538  * they are not contained in any (checked) constraints, but may be used
17539  * in cutting planes, for example.
17540  * Relaxation-only variables are not copied by SCIPcopyVars and cuts
17541  * that contain these variables are not added as linear constraints when
17542  * restarting or transferring information from a copied SCIP to a SCIP.
17543  * Also conflicts with relaxation-only variables are not generated at
17544  * the moment.
17545  */
17547  SCIP_VAR* var /**< problem variable */
17548  )
17549 {
17550  assert(var != NULL);
17551 
17552  return var->relaxationonly;
17553 }
17554 
17555 /** marks that this variable has only been introduced to define a relaxation
17556  *
17557  * The variable must not have a coefficient in the objective and must be deletable.
17558  * If it is not marked deletable, it will be marked as deletable, which is only possible
17559  * before the variable is added to a problem.
17560  *
17561  * @see SCIPvarIsRelaxationOnly
17562  * @see SCIPvarMarkDeletable
17563  */
17565  SCIP_VAR* var /**< problem variable */
17566  )
17567 {
17568  assert(var != NULL);
17569  assert(SCIPvarGetObj(var) == 0.0);
17570 
17571  if( !SCIPvarIsDeletable(var) )
17572  SCIPvarMarkDeletable(var);
17573 
17574  var->relaxationonly = TRUE;
17575 }
17576 
17577 /** returns whether variable is allowed to be deleted completely from the problem */
17580  )
17581 {
17582  assert(var != NULL);
17583 
17584  return var->deletable;
17585 }
17586 
17587 /** returns whether variable is an active (neither fixed nor aggregated) variable */
17589  SCIP_VAR* var /**< problem variable */
17590  )
17591 {
17592  assert(var != NULL);
17593 
17594  return (var->probindex >= 0);
17595 }
17596 
17597 /** gets unique index of variable */
17598 int SCIPvarGetIndex(
17599  SCIP_VAR* var /**< problem variable */
17600  )
17601 {
17602  assert(var != NULL);
17603 
17604  return var->index;
17605 }
17606 
17607 /** gets position of variable in problem, or -1 if variable is not active */
17609  SCIP_VAR* var /**< problem variable */
17610  )
17611 {
17612  assert(var != NULL);
17613 
17614  return var->probindex;
17615 }
17616 
17617 /** gets transformed variable of ORIGINAL variable */
17619  SCIP_VAR* var /**< problem variable */
17620  )
17621 {
17622  assert(var != NULL);
17623  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
17624 
17625  return var->data.original.transvar;
17626 }
17627 
17628 /** gets column of COLUMN variable */
17630  SCIP_VAR* var /**< problem variable */
17631  )
17632 {
17633  assert(var != NULL);
17634  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
17635 
17636  return var->data.col;
17637 }
17638 
17639 /** returns whether the variable is a COLUMN variable that is member of the current LP */
17641  SCIP_VAR* var /**< problem variable */
17642  )
17643 {
17644  assert(var != NULL);
17645 
17646  return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN && SCIPcolIsInLP(var->data.col));
17647 }
17648 
17649 /** gets aggregation variable y of an aggregated variable x = a*y + c */
17651  SCIP_VAR* var /**< problem variable */
17652  )
17653 {
17654  assert(var != NULL);
17656  assert(!var->donotaggr);
17657 
17658  return var->data.aggregate.var;
17659 }
17660 
17661 /** gets aggregation scalar a of an aggregated variable x = a*y + c */
17663  SCIP_VAR* var /**< problem variable */
17664  )
17665 {
17666  assert(var != NULL);
17668  assert(!var->donotaggr);
17669 
17670  return var->data.aggregate.scalar;
17671 }
17672 
17673 /** gets aggregation constant c of an aggregated variable x = a*y + c */
17675  SCIP_VAR* var /**< problem variable */
17676  )
17677 {
17678  assert(var != NULL);
17680  assert(!var->donotaggr);
17681 
17682  return var->data.aggregate.constant;
17683 }
17684 
17685 /** gets number n of aggregation variables of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17687  SCIP_VAR* var /**< problem variable */
17688  )
17689 {
17690  assert(var != NULL);
17691  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17692  assert(!var->donotmultaggr);
17693 
17694  return var->data.multaggr.nvars;
17695 }
17696 
17697 /** gets vector of aggregation variables y of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17699  SCIP_VAR* var /**< problem variable */
17700  )
17701 {
17702  assert(var != NULL);
17703  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17704  assert(!var->donotmultaggr);
17705 
17706  return var->data.multaggr.vars;
17707 }
17708 
17709 /** gets vector of aggregation scalars a of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17711  SCIP_VAR* var /**< problem variable */
17712  )
17713 {
17714  assert(var != NULL);
17715  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17716  assert(!var->donotmultaggr);
17717 
17718  return var->data.multaggr.scalars;
17719 }
17720 
17721 /** gets aggregation constant c of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17723  SCIP_VAR* var /**< problem variable */
17724  )
17725 {
17726  assert(var != NULL);
17727  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17728  assert(!var->donotmultaggr);
17729 
17730  return var->data.multaggr.constant;
17731 }
17732 
17733 /** gets the negation of the given variable; may return NULL, if no negation is existing yet */
17735  SCIP_VAR* var /**< negated problem variable */
17736  )
17737 {
17738  assert(var != NULL);
17739 
17740  return var->negatedvar;
17741 }
17742 
17743 /** gets the negation variable x of a negated variable x' = offset - x */
17745  SCIP_VAR* var /**< negated problem variable */
17746  )
17747 {
17748  assert(var != NULL);
17749  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17750 
17751  return var->negatedvar;
17752 }
17753 
17754 /** gets the negation offset of a negated variable x' = offset - x */
17756  SCIP_VAR* var /**< negated problem variable */
17757  )
17758 {
17759  assert(var != NULL);
17760  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17761 
17762  return var->data.negate.constant;
17763 }
17764 
17765 /** gets objective function value of variable */
17767  SCIP_VAR* var /**< problem variable */
17768  )
17769 {
17770  assert(var != NULL);
17771 
17772  return var->obj;
17773 }
17774 
17775 /** gets the unchanged objective function value of a variable (ignoring temproray changes performed in probing mode) */
17777  SCIP_VAR* var /**< problem variable */
17778  )
17779 {
17780  assert(var != NULL);
17781 
17782  return var->unchangedobj;
17783 }
17784 
17785 /** gets corresponding objective value of active, fixed, or multi-aggregated problem variable of given variable
17786  * e.g. obj(x) = 1 this method returns for ~x the value -1
17787  */
17789  SCIP_VAR* var, /**< problem variable */
17790  SCIP_Real* aggrobj /**< pointer to store the aggregated objective value */
17791  )
17792 {
17793  SCIP_VAR* probvar = var;
17794  SCIP_Real mult = 1.0;
17795 
17796  assert(probvar != NULL);
17797  assert(aggrobj != NULL);
17798 
17799  while( probvar != NULL )
17800  {
17801  switch( SCIPvarGetStatus(probvar) )
17802  {
17804  case SCIP_VARSTATUS_LOOSE:
17805  case SCIP_VARSTATUS_COLUMN:
17806  (*aggrobj) = mult * SCIPvarGetObj(probvar);
17807  return SCIP_OKAY;
17808 
17809  case SCIP_VARSTATUS_FIXED:
17810  assert(SCIPvarGetObj(probvar) == 0.0);
17811  (*aggrobj) = 0.0;
17812  return SCIP_OKAY;
17813 
17815  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
17816  if ( probvar->data.multaggr.nvars == 1 )
17817  {
17818  assert( probvar->data.multaggr.vars != NULL );
17819  assert( probvar->data.multaggr.scalars != NULL );
17820  assert( probvar->data.multaggr.vars[0] != NULL );
17821  mult *= probvar->data.multaggr.scalars[0];
17822  probvar = probvar->data.multaggr.vars[0];
17823  break;
17824  }
17825  else
17826  {
17827  SCIP_Real tmpobj;
17828  int v;
17829 
17830  (*aggrobj) = 0.0;
17831 
17832  for( v = probvar->data.multaggr.nvars - 1; v >= 0; --v )
17833  {
17834  SCIP_CALL( SCIPvarGetAggregatedObj(probvar->data.multaggr.vars[v], &tmpobj) );
17835  (*aggrobj) += probvar->data.multaggr.scalars[v] * tmpobj;
17836  }
17837  return SCIP_OKAY;
17838  }
17839 
17840  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
17841  assert(probvar->data.aggregate.var != NULL);
17842  mult *= probvar->data.aggregate.scalar;
17843  probvar = probvar->data.aggregate.var;
17844  break;
17845 
17846  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
17847  assert(probvar->negatedvar != NULL);
17848  assert(SCIPvarGetStatus(probvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
17849  assert(probvar->negatedvar->negatedvar == probvar);
17850  mult *= -1.0;
17851  probvar = probvar->negatedvar;
17852  break;
17853 
17854  default:
17855  SCIPABORT();
17856  return SCIP_INVALIDDATA; /*lint !e527*/
17857  }
17858  }
17859 
17860  return SCIP_INVALIDDATA;
17861 }
17862 
17863 /** gets original lower bound of original problem variable (i.e. the bound set in problem creation) */
17865  SCIP_VAR* var /**< original problem variable */
17866  )
17867 {
17868  assert(var != NULL);
17869  assert(SCIPvarIsOriginal(var));
17870 
17872  return var->data.original.origdom.lb;
17873  else
17874  {
17875  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17876  assert(var->negatedvar != NULL);
17878 
17879  return var->data.negate.constant - var->negatedvar->data.original.origdom.ub;
17880  }
17881 }
17882 
17883 /** gets original upper bound of original problem variable (i.e. the bound set in problem creation) */
17885  SCIP_VAR* var /**< original problem variable */
17886  )
17887 {
17888  assert(var != NULL);
17889  assert(SCIPvarIsOriginal(var));
17890 
17892  return var->data.original.origdom.ub;
17893  else
17894  {
17895  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17896  assert(var->negatedvar != NULL);
17898 
17899  return var->data.negate.constant - var->negatedvar->data.original.origdom.lb;
17900  }
17901 }
17902 
17903 /** gets the original hole list of an original variable */
17905  SCIP_VAR* var /**< problem variable */
17906  )
17907 {
17908  assert(var != NULL);
17909  assert(SCIPvarIsOriginal(var));
17910 
17912  return var->data.original.origdom.holelist;
17913 
17914  return NULL;
17915 }
17916 
17917 /** gets global lower bound of variable */
17919  SCIP_VAR* var /**< problem variable */
17920  )
17921 {
17922  assert(var != NULL);
17923 
17924  return var->glbdom.lb;
17925 }
17926 
17927 /** gets global upper bound of variable */
17929  SCIP_VAR* var /**< problem variable */
17930  )
17931 {
17932  assert(var != NULL);
17933 
17934  return var->glbdom.ub;
17935 }
17936 
17937 /** gets the global hole list of an active variable */
17939  SCIP_VAR* var /**< problem variable */
17940  )
17941 {
17942  assert(var != NULL);
17943 
17944  return var->glbdom.holelist;
17945 }
17946 
17947 /** gets best global bound of variable with respect to the objective function */
17949  SCIP_VAR* var /**< problem variable */
17950  )
17951 {
17952  assert(var != NULL);
17953 
17954  if( var->obj >= 0.0 )
17955  return var->glbdom.lb;
17956  else
17957  return var->glbdom.ub;
17958 }
17959 
17960 /** gets worst global bound of variable with respect to the objective function */
17962  SCIP_VAR* var /**< problem variable */
17963  )
17964 {
17965  assert(var != NULL);
17966 
17967  if( var->obj >= 0.0 )
17968  return var->glbdom.ub;
17969  else
17970  return var->glbdom.lb;
17971 }
17972 
17973 /** gets current lower bound of variable */
17975  SCIP_VAR* var /**< problem variable */
17976  )
17977 {
17978  assert(var != NULL);
17979 
17980  return var->locdom.lb;
17981 }
17982 
17983 /** gets current upper bound of variable */
17985  SCIP_VAR* var /**< problem variable */
17986  )
17987 {
17988  assert(var != NULL);
17989 
17990  return var->locdom.ub;
17991 }
17992 
17993 /** gets the current hole list of an active variable */
17995  SCIP_VAR* var /**< problem variable */
17996  )
17997 {
17998  assert(var != NULL);
17999 
18000  return var->locdom.holelist;
18001 }
18002 
18003 /** gets best local bound of variable with respect to the objective function */
18005  SCIP_VAR* var /**< problem variable */
18006  )
18007 {
18008  assert(var != NULL);
18009 
18010  if( var->obj >= 0.0 )
18011  return var->locdom.lb;
18012  else
18013  return var->locdom.ub;
18014 }
18015 
18016 /** gets worst local bound of variable with respect to the objective function */
18018  SCIP_VAR* var /**< problem variable */
18019  )
18020 {
18021  assert(var != NULL);
18022 
18023  if( var->obj >= 0.0 )
18024  return var->locdom.ub;
18025  else
18026  return var->locdom.lb;
18027 }
18028 
18029 /** gets type (lower or upper) of best bound of variable with respect to the objective function */
18031  SCIP_VAR* var /**< problem variable */
18032  )
18033 {
18034  assert(var != NULL);
18035 
18036  if( var->obj >= 0.0 )
18037  return SCIP_BOUNDTYPE_LOWER;
18038  else
18039  return SCIP_BOUNDTYPE_UPPER;
18040 }
18041 
18042 /** gets type (lower or upper) of worst bound of variable with respect to the objective function */
18044  SCIP_VAR* var /**< problem variable */
18045  )
18046 {
18047  assert(var != NULL);
18048 
18049  if( var->obj >= 0.0 )
18050  return SCIP_BOUNDTYPE_UPPER;
18051  else
18052  return SCIP_BOUNDTYPE_LOWER;
18053 }
18054 
18055 /** gets lazy lower bound of variable, returns -infinity if the variable has no lazy lower bound */
18057  SCIP_VAR* var /**< problem variable */
18058  )
18059 {
18060  assert(var != NULL);
18061 
18062  return var->lazylb;
18063 }
18064 
18065 /** gets lazy upper bound of variable, returns infinity if the variable has no lazy upper bound */
18067  SCIP_VAR* var /**< problem variable */
18068  )
18069 {
18070  assert(var != NULL);
18071 
18072  return var->lazyub;
18073 }
18074 
18075 /** gets the branch factor of the variable; this value can be used in the branching methods to scale the score
18076  * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
18077  */
18079  SCIP_VAR* var /**< problem variable */
18080  )
18081 {
18082  assert(var != NULL);
18083 
18084  return var->branchfactor;
18085 }
18086 
18087 /** gets the branch priority of the variable; variables with higher priority should always be preferred to variables
18088  * with lower priority
18089  */
18091  SCIP_VAR* var /**< problem variable */
18092  )
18093 {
18094  assert(var != NULL);
18095 
18096  return var->branchpriority;
18097 }
18098 
18099 /** gets the preferred branch direction of the variable (downwards, upwards, or auto) */
18101  SCIP_VAR* var /**< problem variable */
18102  )
18103 {
18104  assert(var != NULL);
18105 
18106  return (SCIP_BRANCHDIR)var->branchdirection;
18107 }
18108 
18109 /** gets number of variable lower bounds x >= b_i*z_i + d_i of given variable x */
18110 int SCIPvarGetNVlbs(
18111  SCIP_VAR* var /**< problem variable */
18112  )
18113 {
18114  assert(var != NULL);
18115 
18116  return SCIPvboundsGetNVbds(var->vlbs);
18117 }
18118 
18119 /** gets array with bounding variables z_i in variable lower bounds x >= b_i*z_i + d_i of given variable x;
18120  * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
18121  */
18123  SCIP_VAR* var /**< problem variable */
18124  )
18125 {
18126  assert(var != NULL);
18127 
18128  return SCIPvboundsGetVars(var->vlbs);
18129 }
18130 
18131 /** gets array with bounding coefficients b_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
18133  SCIP_VAR* var /**< problem variable */
18134  )
18135 {
18136  assert(var != NULL);
18137 
18138  return SCIPvboundsGetCoefs(var->vlbs);
18139 }
18140 
18141 /** gets array with bounding constants d_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
18143  SCIP_VAR* var /**< problem variable */
18144  )
18145 {
18146  assert(var != NULL);
18147 
18148  return SCIPvboundsGetConstants(var->vlbs);
18149 }
18150 
18151 /** gets number of variable upper bounds x <= b_i*z_i + d_i of given variable x */
18152 int SCIPvarGetNVubs(
18153  SCIP_VAR* var /**< problem variable */
18154  )
18155 {
18156  assert(var != NULL);
18157 
18158  return SCIPvboundsGetNVbds(var->vubs);
18159 }
18160 
18161 /** gets array with bounding variables z_i in variable upper bounds x <= b_i*z_i + d_i of given variable x;
18162  * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
18163  */
18165  SCIP_VAR* var /**< problem variable */
18166  )
18167 {
18168  assert(var != NULL);
18169 
18170  return SCIPvboundsGetVars(var->vubs);
18171 }
18172 
18173 /** gets array with bounding coefficients b_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
18175  SCIP_VAR* var /**< problem variable */
18176  )
18177 {
18178  assert(var != NULL);
18179 
18180  return SCIPvboundsGetCoefs(var->vubs);
18181 }
18182 
18183 /** gets array with bounding constants d_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
18185  SCIP_VAR* var /**< problem variable */
18186  )
18187 {
18188  assert(var != NULL);
18189 
18190  return SCIPvboundsGetConstants(var->vubs);
18191 }
18192 
18193 /** gets number of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
18194  * there are no implications for nonbinary variable x
18195  */
18196 int SCIPvarGetNImpls(
18197  SCIP_VAR* var, /**< active problem variable */
18198  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
18199  )
18200 {
18201  assert(var != NULL);
18202  assert(SCIPvarIsActive(var));
18203 
18204  return SCIPimplicsGetNImpls(var->implics, varfixing);
18205 }
18206 
18207 /** gets array with implication variables y of implications y <= b or y >= b for x == 0 or x == 1 of given active
18208  * problem variable x, there are no implications for nonbinary variable x;
18209  * the implications are sorted such that implications with binary implied variables precede the ones with non-binary
18210  * implied variables, and as a second criteria, the implied variables are sorted by increasing variable index
18211  * (see SCIPvarGetIndex())
18212  */
18214  SCIP_VAR* var, /**< active problem variable */
18215  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
18216  )
18217 {
18218  assert(var != NULL);
18219  assert(SCIPvarIsActive(var));
18220 
18221  return SCIPimplicsGetVars(var->implics, varfixing);
18222 }
18223 
18224 /** gets array with implication types of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
18225  * variable x (SCIP_BOUNDTYPE_UPPER if y <= b, SCIP_BOUNDTYPE_LOWER if y >= b),
18226  * there are no implications for nonbinary variable x
18227  */
18229  SCIP_VAR* var, /**< active problem variable */
18230  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
18231  )
18232 {
18233  assert(var != NULL);
18234  assert(SCIPvarIsActive(var));
18235 
18236  return SCIPimplicsGetTypes(var->implics, varfixing);
18237 }
18238 
18239 /** gets array with implication bounds b of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
18240  * variable x, there are no implications for nonbinary variable x
18241  */
18243  SCIP_VAR* var, /**< active problem variable */
18244  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
18245  )
18246 {
18247  assert(var != NULL);
18248  assert(SCIPvarIsActive(var));
18249 
18250  return SCIPimplicsGetBounds(var->implics, varfixing);
18251 }
18252 
18253 /** Gets array with unique ids of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
18254  * there are no implications for nonbinary variable x.
18255  * If an implication is a shortcut, i.e., it was added as part of the transitive closure of another implication,
18256  * its id is negative, otherwise it is nonnegative.
18257  */
18258 int* SCIPvarGetImplIds(
18259  SCIP_VAR* var, /**< active problem variable */
18260  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
18261  )
18262 {
18263  assert(var != NULL);
18264  assert(SCIPvarIsActive(var));
18265 
18266  return SCIPimplicsGetIds(var->implics, varfixing);
18267 }
18268 
18269 /** gets number of cliques, the active variable is contained in */
18270 int SCIPvarGetNCliques(
18271  SCIP_VAR* var, /**< active problem variable */
18272  SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
18273  )
18274 {
18275  assert(var != NULL);
18276 
18277  return SCIPcliquelistGetNCliques(var->cliquelist, varfixing);
18278 }
18279 
18280 /** gets array of cliques, the active variable is contained in */
18282  SCIP_VAR* var, /**< active problem variable */
18283  SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
18284  )
18285 {
18286  assert(var != NULL);
18287 
18288  return SCIPcliquelistGetCliques(var->cliquelist, varfixing);
18289 }
18290 
18291 /** gets primal LP solution value of variable */
18293  SCIP_VAR* var /**< problem variable */
18294  )
18295 {
18296  assert(var != NULL);
18297 
18299  return SCIPcolGetPrimsol(var->data.col);
18300  else
18301  return SCIPvarGetLPSol_rec(var);
18302 }
18303 
18304 /** gets primal NLP solution value of variable */
18306  SCIP_VAR* var /**< problem variable */
18307  )
18308 {
18309  assert(var != NULL);
18310 
18312  return var->nlpsol;
18313  else
18314  return SCIPvarGetNLPSol_rec(var);
18315 }
18316 
18317 /** return lower bound change info at requested position */
18319  SCIP_VAR* var, /**< problem variable */
18320  int pos /**< requested position */
18321  )
18322 {
18323  assert(pos >= 0);
18324  assert(pos < var->nlbchginfos);
18325 
18326  return &var->lbchginfos[pos];
18327 }
18328 
18329 /** gets the number of lower bound change info array */
18331  SCIP_VAR* var /**< problem variable */
18332  )
18333 {
18334  return var->nlbchginfos;
18335 }
18336 
18337 /** return upper bound change info at requested position */
18339  SCIP_VAR* var, /**< problem variable */
18340  int pos /**< requested position */
18341  )
18342 {
18343  assert(pos >= 0);
18344  assert(pos < var->nubchginfos);
18345 
18346  return &var->ubchginfos[pos];
18347 }
18348 
18349 /** gets the number upper bound change info array */
18351  SCIP_VAR* var /**< problem variable */
18352  )
18353 {
18354  assert(var != NULL);
18355 
18356  return var->nubchginfos;
18357 }
18358 
18359 /** returns the value based history for the variable */
18361  SCIP_VAR* var /**< problem variable */
18362  )
18363 {
18364  assert(var != NULL);
18365 
18366  return var->valuehistory;
18367 }
18368 
18369 /** gets pseudo solution value of variable */
18371  SCIP_VAR* var /**< problem variable */
18372  )
18373 {
18374  assert(var != NULL);
18375 
18377  return SCIPvarGetBestBoundLocal(var);
18378  else
18379  return SCIPvarGetPseudoSol_rec(var);
18380 }
18381 
18382 /** returns the variable's VSIDS score */
18384  SCIP_VAR* var, /**< problem variable */
18385  SCIP_STAT* stat, /**< problem statistics */
18386  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
18387  )
18388 {
18389  assert(var != NULL);
18390 
18392  return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
18393  else
18394  return SCIPvarGetVSIDS_rec(var, stat, dir);
18395 }
18396 
18397 /** includes event handler with given data in variable's event filter */
18399  SCIP_VAR* var, /**< problem variable */
18400  BMS_BLKMEM* blkmem, /**< block memory */
18401  SCIP_SET* set, /**< global SCIP settings */
18402  SCIP_EVENTTYPE eventtype, /**< event type to catch */
18403  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
18404  SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
18405  int* filterpos /**< pointer to store position of event filter entry, or NULL */
18406  )
18407 {
18408  assert(var != NULL);
18409  assert(set != NULL);
18410  assert(var->scip == set->scip);
18411  assert(var->eventfilter != NULL);
18412  assert((eventtype & ~SCIP_EVENTTYPE_VARCHANGED) == 0);
18413  assert((eventtype & SCIP_EVENTTYPE_VARCHANGED) != 0);
18414  assert(SCIPvarIsTransformed(var));
18415 
18416  SCIPsetDebugMsg(set, "catch event of type 0x%" SCIP_EVENTTYPE_FORMAT " of variable <%s> with handler %p and data %p\n",
18417  eventtype, var->name, (void*)eventhdlr, (void*)eventdata);
18418 
18419  SCIP_CALL( SCIPeventfilterAdd(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
18420 
18421  return SCIP_OKAY;
18422 }
18423 
18424 /** deletes event handler with given data from variable's event filter */
18426  SCIP_VAR* var, /**< problem variable */
18427  BMS_BLKMEM* blkmem, /**< block memory */
18428  SCIP_SET* set, /**< global SCIP settings */
18429  SCIP_EVENTTYPE eventtype, /**< event type mask of dropped event */
18430  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
18431  SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
18432  int filterpos /**< position of event filter entry returned by SCIPvarCatchEvent(), or -1 */
18433  )
18434 {
18435  assert(var != NULL);
18436  assert(set != NULL);
18437  assert(var->scip == set->scip);
18438  assert(var->eventfilter != NULL);
18439  assert(SCIPvarIsTransformed(var));
18440 
18441  SCIPsetDebugMsg(set, "drop event of variable <%s> with handler %p and data %p\n", var->name, (void*)eventhdlr,
18442  (void*)eventdata);
18443 
18444  SCIP_CALL( SCIPeventfilterDel(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
18445 
18446  return SCIP_OKAY;
18447 }
18448 
18449 /** returns the position of the bound change index */
18450 int SCIPbdchgidxGetPos(
18451  SCIP_BDCHGIDX* bdchgidx /**< bound change index */
18452  )
18453 {
18454  assert(bdchgidx != NULL);
18455 
18456  return bdchgidx->pos;
18457 }
18458 
18459 /** returns whether first bound change index belongs to an earlier applied bound change than second one */
18461  SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index */
18462  SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index */
18463  )
18464 {
18465  assert(bdchgidx1 != NULL);
18466  assert(bdchgidx1->depth >= -2);
18467  assert(bdchgidx1->pos >= 0);
18468  assert(bdchgidx2 != NULL);
18469  assert(bdchgidx2->depth >= -2);
18470  assert(bdchgidx2->pos >= 0);
18471 
18472  return (bdchgidx1->depth < bdchgidx2->depth)
18473  || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
18474 }
18475 
18476 /** returns whether first bound change index belongs to an earlier applied bound change than second one;
18477  * if a bound change index is NULL, the bound change index represents the current time, i.e. the time after the
18478  * last bound change was applied to the current node
18479  */
18481  SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index, or NULL */
18482  SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index, or NULL */
18483  )
18484 {
18485  assert(bdchgidx1 == NULL || bdchgidx1->depth >= -2);
18486  assert(bdchgidx1 == NULL || bdchgidx1->pos >= 0);
18487  assert(bdchgidx2 == NULL || bdchgidx2->depth >= -2);
18488  assert(bdchgidx2 == NULL || bdchgidx2->pos >= 0);
18489 
18490  if( bdchgidx1 == NULL )
18491  return FALSE;
18492  else if( bdchgidx2 == NULL )
18493  return TRUE;
18494  else
18495  return (bdchgidx1->depth < bdchgidx2->depth)
18496  || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
18497 }
18498 
18499 /** returns old bound that was overwritten for given bound change information */
18501  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18502  )
18503 {
18504  assert(bdchginfo != NULL);
18505 
18506  return bdchginfo->oldbound;
18507 }
18508 
18509 /** returns new bound installed for given bound change information */
18511  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18512  )
18513 {
18514  assert(bdchginfo != NULL);
18515 
18516  return bdchginfo->newbound;
18517 }
18518 
18519 /** returns variable that belongs to the given bound change information */
18521  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18522  )
18523 {
18524  assert(bdchginfo != NULL);
18525 
18526  return bdchginfo->var;
18527 }
18528 
18529 /** returns whether the bound change information belongs to a branching decision or a deduction */
18531  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18532  )
18533 {
18534  assert(bdchginfo != NULL);
18535 
18536  return (SCIP_BOUNDCHGTYPE)(bdchginfo->boundchgtype);
18537 }
18538 
18539 /** returns whether the bound change information belongs to a lower or upper bound change */
18541  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18542  )
18543 {
18544  assert(bdchginfo != NULL);
18545 
18546  return (SCIP_BOUNDTYPE)(bdchginfo->boundtype);
18547 }
18548 
18549 /** returns depth level of given bound change information */
18551  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18552  )
18553 {
18554  assert(bdchginfo != NULL);
18555 
18556  return bdchginfo->bdchgidx.depth;
18557 }
18558 
18559 /** returns bound change position in its depth level of given bound change information */
18561  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18562  )
18563 {
18564  assert(bdchginfo != NULL);
18565 
18566  return bdchginfo->bdchgidx.pos;
18567 }
18568 
18569 /** returns bound change index of given bound change information */
18571  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18572  )
18573 {
18574  assert(bdchginfo != NULL);
18575 
18576  return &bdchginfo->bdchgidx;
18577 }
18578 
18579 /** returns inference variable of given bound change information */
18581  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18582  )
18583 {
18584  assert(bdchginfo != NULL);
18587 
18588  return bdchginfo->inferencedata.var;
18589 }
18590 
18591 /** returns inference constraint of given bound change information */
18593  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18594  )
18595 {
18596  assert(bdchginfo != NULL);
18598  assert(bdchginfo->inferencedata.reason.cons != NULL);
18599 
18600  return bdchginfo->inferencedata.reason.cons;
18601 }
18602 
18603 /** returns inference propagator of given bound change information, or NULL if no propagator was responsible */
18605  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18606  )
18607 {
18608  assert(bdchginfo != NULL);
18610 
18611  return bdchginfo->inferencedata.reason.prop;
18612 }
18613 
18614 /** returns inference user information of given bound change information */
18616  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18617  )
18618 {
18619  assert(bdchginfo != NULL);
18622 
18623  return bdchginfo->inferencedata.info;
18624 }
18625 
18626 /** returns inference bound of inference variable of given bound change information */
18628  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18629  )
18630 {
18631  assert(bdchginfo != NULL);
18634 
18635  return (SCIP_BOUNDTYPE)(bdchginfo->inferboundtype);
18636 }
18637 
18638 /** returns the relaxed bound change type */
18640  SCIP_BDCHGINFO* bdchginfo /**< bound change to add to the conflict set */
18641  )
18642 {
18643  return ((SCIP_BOUNDTYPE)(bdchginfo->boundtype) == SCIP_BOUNDTYPE_LOWER ? bdchginfo->var->conflictrelaxedlb : bdchginfo->var->conflictrelaxedub);
18644 }
18645 
18646 
18647 /** returns whether the bound change information belongs to a redundant bound change */
18649  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18650  )
18651 {
18652  assert(bdchginfo != NULL);
18653  assert(bdchginfo->redundant == (bdchginfo->oldbound == bdchginfo->newbound)); /*lint !e777*/
18654 
18655  return bdchginfo->redundant;
18656 }
18657 
18658 /** returns whether the bound change has an inference reason (constraint or propagator), that can be resolved */
18660  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18661  )
18662 {
18663  assert(bdchginfo != NULL);
18664 
18667  && bdchginfo->inferencedata.reason.prop != NULL);
18668 }
18669 
18670 /** for two bound change informations belonging to the same variable and bound, returns whether the first bound change
18671  * has a tighter new bound as the second bound change
18672  */
18674  SCIP_BDCHGINFO* bdchginfo1, /**< first bound change information */
18675  SCIP_BDCHGINFO* bdchginfo2 /**< second bound change information */
18676  )
18677 {
18678  assert(bdchginfo1 != NULL);
18679  assert(bdchginfo2 != NULL);
18680  assert(bdchginfo1->var == bdchginfo2->var);
18681  assert(bdchginfo1->boundtype == bdchginfo2->boundtype);
18682 
18683  return (SCIPbdchginfoGetBoundtype(bdchginfo1) == SCIP_BOUNDTYPE_LOWER
18684  ? bdchginfo1->newbound > bdchginfo2->newbound
18685  : bdchginfo1->newbound < bdchginfo2->newbound);
18686 }
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:18640
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:15412
SCIP_Real SCIPvarGetWorstBoundLocal(SCIP_VAR *var)
Definition: var.c:18018
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6215
SCIP_Real * SCIPvarGetVlbCoefs(SCIP_VAR *var)
Definition: var.c:18133
#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:14131
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:18044
static void checkImplic(SCIP_SET *set, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool *redundant, SCIP_Bool *infeasible)
Definition: var.c:9387
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:15539
SCIP_Bool SCIPvarsHaveCommonClique(SCIP_VAR *var1, SCIP_Bool value1, SCIP_VAR *var2, SCIP_Bool value2, SCIP_Bool regardimplics)
Definition: var.c:11483
SCIP_BRANCHINGDATA branchingdata
Definition: struct_var.h:96
void SCIPhistoryIncNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, int depth)
Definition: history.c:584
SCIP_VAR ** SCIPcliqueGetVars(SCIP_CLIQUE *clique)
Definition: implics.c:3377
SCIP_Bool SCIPsetIsLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6273
SCIP_Bool SCIPsetIsFeasZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6723
internal methods for storing primal CIP solutions
void SCIPhistoryIncVSIDS(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition: history.c:503
SCIP_RETCODE SCIPvarIncVSIDS(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_BRANCHDIR dir, SCIP_Real value, SCIP_Real weight)
Definition: var.c:15059
static SCIP_RETCODE varEventImplAdded(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:9269
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:10470
SCIP_Real SCIPvarGetBdAtIndex(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16791
SCIP_PROP * SCIPbdchginfoGetInferProp(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18605
void SCIPvarMarkNotDeletable(SCIP_VAR *var)
Definition: var.c:17504
void SCIPvarUpdateBestRootSol(SCIP_VAR *var, SCIP_SET *set, SCIP_Real rootsol, SCIP_Real rootredcost, SCIP_Real rootlpobjval)
Definition: var.c:13288
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:14014
int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:3298
public methods for branching and inference history structure
SCIP_Bool SCIPlpDiving(SCIP_LP *lp)
Definition: lp.c:17839
int nubchginfos
Definition: struct_var.h:269
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoLb(SCIP_VAR *var, int pos)
Definition: var.c:18319
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition: var.c:17711
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:16320
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:18079
unsigned int inferboundtype
Definition: struct_var.h:102
SCIP_Real SCIPbdchginfoGetOldbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18501
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:18101
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:18067
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:6840
SCIP_Bool SCIPsetIsFeasEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6613
int SCIPvarGetNVlbs(SCIP_VAR *var)
Definition: var.c:18111
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18521
#define SCIPsetDuplicateBufferArray(set, ptr, source, num)
Definition: set.h:1736
SCIP_Real SCIPvarGetWorstBoundGlobal(SCIP_VAR *var)
Definition: var.c:17962
#define SCIP_DECL_VARTRANS(x)
Definition: type_var.h:147
SCIP_RETCODE SCIPvarChgLbGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Real newbound)
Definition: var.c:7190
enum SCIP_BaseStat SCIP_BASESTAT
Definition: type_lpi.h:96
SCIP_Bool SCIPvarDoNotMultaggr(SCIP_VAR *var)
Definition: var.c:5885
SCIP_RETCODE SCIPvarCreateTransformed(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
Definition: var.c:2121
public methods for implications, variable bounds, and cliques
SCIP_Real SCIPvarGetPseudocostCountCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14626
methods for implications, variable bounds, and cliques
int SCIPvarGetLastBdchgDepth(SCIP_VAR *var)
Definition: var.c:16871
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:17919
SCIP_Real SCIPvarGetAvgBranchdepth(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15795
SCIP_RETCODE SCIPvarGetProbvarBinary(SCIP_VAR **var, SCIP_Bool *negated)
Definition: var.c:12318
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:14792
#define SCIP_MAXSTRLEN
Definition: def.h:302
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:3356
SCIP_DOM origdom
Definition: struct_var.h:178
SCIP_BASESTAT SCIPcolGetBasisStatus(SCIP_COL *col)
Definition: lp.c:17023
SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition: var.c:17461
SCIP_RETCODE SCIPeventCreateImplAdded(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition: event.c:814
SCIP_VAR ** SCIPimplicsGetVars(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3328
SCIP_RETCODE SCIPvarChgLbOriginal(SCIP_VAR *var, SCIP_SET *set, SCIP_Real newbound)
Definition: var.c:6572
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:17699
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:2975
#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:13423
SCIP_RETCODE SCIPbdchginfoCreate(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_Real oldbound, SCIP_Real newbound)
Definition: var.c:16374
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:17975
SCIP_RETCODE SCIPvarChgLbLazy(SCIP_VAR *var, SCIP_SET *set, SCIP_Real lazylb)
Definition: var.c:7474
SCIP_Real constant
Definition: struct_var.h:193
SCIP_CLIQUE ** SCIPvarGetCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18282
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:8571
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:18361
int SCIPcliquelistGetNCliques(SCIP_CLIQUELIST *cliquelist, SCIP_Bool value)
Definition: implics.c:3443
SCIP_NODE * SCIPnodeGetParent(SCIP_NODE *node)
Definition: tree.c:7723
void SCIPprobAddObjoffset(SCIP_PROB *prob, SCIP_Real addval)
Definition: prob.c:1440
void SCIPvarSetTransData(SCIP_VAR *var, SCIP_DECL_VARTRANS((*vartrans)))
Definition: var.c:17313
SCIP_RETCODE SCIPvarChgUbOriginal(SCIP_VAR *var, SCIP_SET *set, SCIP_Real newbound)
Definition: var.c:6631
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:8879
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:2499
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:17440
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:6767
SCIP_VAR ** SCIPvboundsGetVars(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3295
SCIP_Real SCIPsetInfinity(SCIP_SET *set)
Definition: set.c:6080
SCIP_DOMCHGBOTH domchgboth
Definition: struct_var.h:163
SCIP_RETCODE SCIPcolChgObj(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newobj)
Definition: lp.c:3702
SCIP_Real SCIPvarGetSol(SCIP_VAR *var, SCIP_Bool getlpval)
Definition: var.c:13265
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:18481
SCIP_Bool SCIPvarWasFixedAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16811
SCIP_Real SCIPvarGetBestBoundLocal(SCIP_VAR *var)
Definition: var.c:18005
SCIP_Real SCIPvarGetRootSol(SCIP_VAR *var)
Definition: var.c:13358
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:6146
SCIP_RETCODE SCIPvarScaleVSIDS(SCIP_VAR *var, SCIP_Real scalar)
Definition: var.c:15145
SCIP_Real SCIPvarGetLbLP(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:12940
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:17187
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:18399
SCIP_RETCODE SCIPcolCreate(SCIP_COL **col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var, int len, SCIP_ROW **rows, SCIP_Real *vals, SCIP_Bool removable)
Definition: lp.c:3283
SCIP_HOLELIST * newlist
Definition: struct_var.h:68
SCIP_Real right
Definition: struct_var.h:54
void SCIPvaluehistoryScaleVSIDS(SCIP_VALUEHISTORY *valuehistory, SCIP_Real scalar)
Definition: history.c:326
void SCIPvarSetProbindex(SCIP_VAR *var, int probindex)
Definition: var.c:6030
#define NLOCKTYPES
Definition: type_var.h:90
SCIP_RETCODE SCIPhistoryCreate(SCIP_HISTORY **history, BMS_BLKMEM *blkmem)
Definition: history.c:51
SCIP_HOLELIST * SCIPholelistGetNext(SCIP_HOLELIST *holelist)
Definition: var.c:17247
#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:17829
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:18331
static SCIP_RETCODE varAddUbchginfo(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real oldbound, SCIP_Real newbound, int depth, int pos, SCIP_VAR *infervar, SCIP_CONS *infercons, SCIP_PROP *inferprop, int inferinfo, SCIP_BOUNDTYPE inferboundtype, SCIP_BOUNDCHGTYPE boundchgtype)
Definition: var.c:555
struct SCIP_VarData SCIP_VARDATA
Definition: type_var.h:116
SCIP_RETCODE SCIPdomchgUndo(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:1349
SCIP_Real SCIPcolGetUb(SCIP_COL *col)
Definition: lp.c:16965
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:3464
void SCIPhistoryReset(SCIP_HISTORY *history)
Definition: history.c:78
SCIP_Real SCIPcolGetObj(SCIP_COL *col)
Definition: lp.c:16945
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:3149
SCIP_Real constant
Definition: struct_var.h:203
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10764
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:15031
#define TRUE
Definition: def.h:95
SCIP_Bool SCIPvarHasImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition: var.c:11116
static void varSetProbindex(SCIP_VAR *var, int probindex)
Definition: var.c:6011
SCIP_Real SCIPvarGetAvgConflictlength(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15368
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:17756
#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:18153
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:18616
int nlbchginfos
Definition: struct_var.h:267
static SCIP_BDCHGIDX presolvebdchgidx
Definition: var.c:16831
enum SCIP_Varstatus SCIP_VARSTATUS
Definition: type_var.h:57
#define SCIPsetAllocBufferArray(set, ptr, num)
Definition: set.h:1734
SCIP_RETCODE SCIPvarCreateOriginal(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
Definition: var.c:2078
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:17609
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:10917
#define SCIP_DECL_VARCOPY(x)
Definition: type_var.h:190
SCIP_RETCODE SCIPvarChgLbDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newbound)
Definition: var.c:8254
void SCIPvarSetNamePointer(SCIP_VAR *var, const char *name)
Definition: var.c:6045
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:8228
SCIP_Real SCIPvarGetAggrScalar(SCIP_VAR *var)
Definition: var.c:17663
void SCIPvarInitSolve(SCIP_VAR *var)
Definition: var.c:2934
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:7333
public methods for problem variables
static GRAPHNODE ** active
SCIP_Real SCIPvarGetInferenceSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15987
void SCIPvarMarkDeletable(SCIP_VAR *var)
Definition: var.c:17493
static SCIP_RETCODE varCreate(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARCOPY((*varcopy)), SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_VARDATA *vardata)
Definition: var.c:1933
SCIP_RETCODE SCIPimplicsDel(SCIP_IMPLICS **implics, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition: implics.c:836
SCIP_Real SCIPvarGetAvgInferences(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:16075
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:11278
SCIP_VAR ** SCIPvarGetVlbVars(SCIP_VAR *var)
Definition: var.c:18123
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:12014
int SCIPbdchgidxGetPos(SCIP_BDCHGIDX *bdchgidx)
Definition: var.c:18451
SCIP_CLIQUE ** SCIPcliquelistGetCliques(SCIP_CLIQUELIST *cliquelist, SCIP_Bool value)
Definition: implics.c:3452
SCIP_PROB * transprob
Definition: struct_scip.h:98
int index
Definition: struct_var.h:254
SCIP_Real constant
Definition: struct_var.h:186
unsigned int domchgtype
Definition: struct_var.h:151
SCIP_Bool SCIPsetIsNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6349
SCIP_RETCODE SCIPvarChgType(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_EVENTQUEUE *eventqueue, SCIP_VARTYPE vartype)
Definition: var.c:6182
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:17579
int SCIPvarGetConflictingBdchgDepth(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real bound)
Definition: var.c:16886
SCIP_RETCODE SCIPvarUpdatePseudocost(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition: var.c:14387
#define SCIPsetFreeBufferArray(set, ptr)
Definition: set.h:1741
SCIP_Longint SCIPvarGetNBranchingsCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15752
SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
Definition: var.c:17471
void SCIPvarAdjustLb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *lb)
Definition: var.c:6522
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:11826
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:17745
SCIP_RETCODE SCIProwIncCoef(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_COL *col, SCIP_Real incval)
Definition: lp.c:5532
SCIP_Real relaxsol
Definition: struct_var.h:216
SCIP_RETCODE SCIPvarRemoveCliquesImplicsVbs(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_CLIQUETABLE *cliquetable, SCIP_SET *set, SCIP_Bool irrelevantvar, SCIP_Bool onlyredundant, SCIP_Bool removefromvar)
Definition: var.c:1610
static SCIP_RETCODE boundchgCaptureData(SCIP_BOUNDCHG *boundchg)
Definition: var.c:971
SCIP_Real SCIPsetCeil(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6413
int conflictlbcount
Definition: struct_var.h:270
SCIP_Real SCIPvarGetRelaxSolTransVar(SCIP_VAR *var)
Definition: var.c:14003
#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:16834
int SCIPvarGetNCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18271
Definition: heur_padm.c:132
SCIP_PROB * origprob
Definition: struct_scip.h:80
SCIP_Real SCIPvarGetLPSol_rec(SCIP_VAR *var)
Definition: var.c:13077
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:16230
int * SCIPvarGetImplIds(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18259
SCIP_HOLELIST * SCIPvarGetHolelistOriginal(SCIP_VAR *var)
Definition: var.c:17905
SCIP_RETCODE SCIPeventCreateObjChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldobj, SCIP_Real newobj)
Definition: event.c:605
internal methods for collecting primal CIP solutions and primal informations
SCIP_Real SCIPsolGetVal(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var)
Definition: sol.c:1347
static SCIP_RETCODE varParse(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, const char *str, char *name, SCIP_Real *lb, SCIP_Real *ub, SCIP_Real *obj, SCIP_VARTYPE *vartype, SCIP_Real *lazylb, SCIP_Real *lazyub, SCIP_Bool local, char **endptr, SCIP_Bool *success)
Definition: var.c:2352
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:12007
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:13010
int nrootboundchgs
Definition: struct_stat.h:222
#define SCIP_DECL_VARDELTRANS(x)
Definition: type_var.h:160
SCIP_Bool SCIPsetIsGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6309
static SCIP_RETCODE varEventLbChanged(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real oldbound, SCIP_Real newbound)
Definition: var.c:7551
SCIP_HISTORY * glbhistorycrun
Definition: struct_stat.h:182
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:17735
const char * SCIPgetProbName(SCIP *scip)
Definition: scip_prob.c:1075
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3372
SCIP_Real SCIPvarGetVSIDSCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15936
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:9304
SCIP_Real SCIPvarGetNLPSol_rec(SCIP_VAR *var)
Definition: var.c:13150
int SCIPvarGetNBdchgInfosUb(SCIP_VAR *var)
Definition: var.c:18351
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:7443
SCIP_Bool SCIPbdchginfoIsTighter(SCIP_BDCHGINFO *bdchginfo1, SCIP_BDCHGINFO *bdchginfo2)
Definition: var.c:18674
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:7975
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17929
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:12226
SCIP_Real SCIPvarGetObjLP(SCIP_VAR *var)
Definition: var.c:12894
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:13824
void SCIPvarSetHistory(SCIP_VAR *var, SCIP_HISTORY *history, SCIP_STAT *stat)
Definition: var.c:4528
public methods for managing constraints
static SCIP_RETCODE varProcessChgBranchFactor(SCIP_VAR *var, SCIP_SET *set, SCIP_Real branchfactor)
Definition: var.c:11504
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:13476
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:17301
enum SCIP_Confidencelevel SCIP_CONFIDENCELEVEL
Definition: type_misc.h:53
SCIP_RETCODE SCIPvarChgBranchPriority(SCIP_VAR *var, int branchpriority)
Definition: var.c:11695
SCIP_Real SCIPvarGetPseudocost(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition: var.c:14485
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:16988
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:7589
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:4543
void SCIPvarSetDeltransData(SCIP_VAR *var, SCIP_DECL_VARDELTRANS((*vardeltrans)))
Definition: var.c:17325
SCIP_RETCODE SCIPvarChgUbLazy(SCIP_VAR *var, SCIP_SET *set, SCIP_Real lazyub)
Definition: var.c:7497
SCIP_Real SCIPvarGetBestBoundGlobal(SCIP_VAR *var)
Definition: var.c:17949
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:7809
void SCIPvarMergeHistories(SCIP_VAR *targetvar, SCIP_VAR *othervar, SCIP_STAT *stat)
Definition: var.c:4512
enum SCIP_LockType SCIP_LOCKTYPE
Definition: type_var.h:96
void SCIPhistoryIncNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real length)
Definition: history.c:542
SCIP_BOUNDTYPE * SCIPimplicsGetTypes(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3337
SCIP_Bool SCIPvarDoNotAggr(SCIP_VAR *var)
Definition: var.c:5852
internal methods for storing and manipulating the main problem
#define MAX_CLIQUELENGTH
Definition: var.c:13472
#define SCIPerrorMessage
Definition: pub_message.h:64
SCIP_Bool SCIPboundchgIsRedundant(SCIP_BOUNDCHG *boundchg)
Definition: var.c:17197
void SCIPlpDecNLoosevars(SCIP_LP *lp)
Definition: lp.c:14333
SCIP_Real SCIPvarGetLbOriginal(SCIP_VAR *var)
Definition: var.c:17865
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:16828
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:14935
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:18461
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:6269
int SCIPvarCompareActiveAndNegated(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11912
int lbchginfossize
Definition: struct_var.h:266
SCIP_Real SCIPvarGetAvgBranchdepthCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15840
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:2875
SCIP_Real SCIPvarGetUbOriginal(SCIP_VAR *var)
Definition: var.c:17885
SCIP_Bool SCIPvarIsTransformedOrigvar(SCIP_VAR *var)
Definition: var.c:12869
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:6459
SCIP_EVENTTYPE eventmask
Definition: struct_event.h:198
SCIP_DECL_SORTPTRCOMP(SCIPvarCompActiveAndNegated)
Definition: var.c:11942
SCIP_Real SCIPvarGetPseudocostCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition: var.c:14534
SCIP_Real SCIPvarGetUbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16670
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:10895
SCIP_Bool SCIPvarHasBinaryImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_Bool implvarfixing)
Definition: var.c:11136
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:3170
SCIP_RETCODE SCIPvarGetTransformed(SCIP_VAR *origvar, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **transvar)
Definition: var.c:3551
#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:8094
union SCIP_BoundChg::@20 data
SCIP_Real * SCIPvarGetVubConstants(SCIP_VAR *var)
Definition: var.c:18185
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:7016
SCIP_OBJSENSE objsense
Definition: struct_prob.h:86
unsigned int pos
Definition: struct_var.h:122
static SCIP_RETCODE varSetName(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_STAT *stat, const char *name)
Definition: var.c:1901
SCIP_Real SCIPvarGetAggrConstant(SCIP_VAR *var)
Definition: var.c:17675
SCIP_Real SCIPcolGetLb(SCIP_COL *col)
Definition: lp.c:16955
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:173
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17260
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:5046
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:11993
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:14206
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:7642
SCIP_RETCODE SCIPvarSetRelaxSol(SCIP_VAR *var, SCIP_SET *set, SCIP_RELAXATION *relaxation, SCIP_Real solval, SCIP_Bool updateobj)
Definition: var.c:13870
SCIP_HISTORY * glbhistory
Definition: struct_stat.h:181
SCIP_Real SCIPboundchgGetNewbound(SCIP_BOUNDCHG *boundchg)
Definition: var.c:17157
SCIP_Real * SCIPvboundsGetCoefs(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3303
#define REALABS(x)
Definition: def.h:210
int nparentvars
Definition: struct_var.h:261
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition: var.c:18293
SCIP_Real unchangedobj
Definition: struct_var.h:210
SCIP_HOLELIST * SCIPvarGetHolelistGlobal(SCIP_VAR *var)
Definition: var.c:17939
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:10006
SCIP_Longint SCIPvarGetNActiveConflicts(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15276
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:17789
SCIP_Real SCIPvarCalcPscostConfidenceBound(SCIP_VAR *var, SCIP_SET *set, SCIP_BRANCHDIR dir, SCIP_Bool onlycurrentrun, SCIP_CONFIDENCELEVEL clevel)
Definition: var.c:14754
#define SCIP_CALL(x)
Definition: def.h:393
SCIP main data structure.
SCIP_Bool SCIPbdchginfoHasInferenceReason(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18660
SCIP_VBOUNDS * vubs
Definition: struct_var.h:244
SCIP_Real SCIPvarGetLbLazy(SCIP_VAR *var)
Definition: var.c:18057
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:18143
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:15455
SCIP_Real SCIPvarGetMultaggrConstant(SCIP_VAR *var)
Definition: var.c:17723
SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
Definition: var.c:17547
int SCIPprobGetNContVars(SCIP_PROB *prob)
Definition: prob.c:2388
SCIP_Real SCIPvarGetPseudocostCount(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14581
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:9725
static SCIP_VAR * varGetActiveVar(SCIP_VAR *var)
Definition: var.c:5803
SCIP_Real * SCIPvboundsGetConstants(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3311
SCIP_Real SCIPvarGetCutoffSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:16187
SCIP_Real * SCIPvarGetVubCoefs(SCIP_VAR *var)
Definition: var.c:18175
SCIP_Bool SCIPbdchginfoIsRedundant(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18649
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:14669
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:11639
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:8102
#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:18571
SCIP_Longint SCIPvarGetNActiveConflictsCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15323
SCIP_RETCODE SCIPvarPrint(SCIP_VAR *var, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: var.c:3009
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:13855
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:6556
#define BMSfreeBlockMemory(mem, ptr)
Definition: memory.h:467
internal methods for problem variables
SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
Definition: var.c:17389
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:6234
SCIP_RETCODE SCIPvarChgBranchFactor(SCIP_VAR *var, SCIP_SET *set, SCIP_Real branchfactor)
Definition: var.c:11568
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:5284
#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:18229
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:15623
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:6691
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:17237
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:8998
#define SCIP_Bool
Definition: def.h:93
void SCIPvarCapture(SCIP_VAR *var)
Definition: var.c:2850
#define BMSreallocBlockMemorySize(mem, ptr, oldsize, newsize)
Definition: memory.h:458
SCIP_BOUNDCHGTYPE SCIPboundchgGetBoundchgtype(SCIP_BOUNDCHG *boundchg)
Definition: var.c:17177
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:4734
int SCIPbdchginfoGetPos(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18561
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:16959
SCIP_Real SCIPvarGetInferenceSumCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:16032
SCIP_Bool SCIPvarIsInLP(SCIP_VAR *var)
Definition: var.c:17641
SCIP_RETCODE SCIPvarRemove(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_CLIQUETABLE *cliquetable, SCIP_SET *set, SCIP_Bool final)
Definition: var.c:6063
SCIP_RETCODE SCIPconsRelease(SCIP_CONS **cons, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: cons.c:6212
void SCIPvarMarkRelaxationOnly(SCIP_VAR *var)
Definition: var.c:17565
void SCIPvarStoreRootSol(SCIP_VAR *var, SCIP_Bool roothaslp)
Definition: var.c:13277
SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
Definition: var.c:18306
int SCIPvarGetBranchPriority(SCIP_VAR *var)
Definition: var.c:18091
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:3752
SCIP_Real SCIPvarGetLbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16551
SCIP_Bool divingobjchg
Definition: struct_lp.h:381
int SCIPvarGetNImpls(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18197
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:8344
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition: memory.h:469
SCIP_RETCODE SCIPeventCreateGlbChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition: event.c:628
unsigned int deleted
Definition: struct_var.h:277
union SCIP_Var::@21 data
int * SCIPimplicsGetIds(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3358
SCIP_VARDATA * SCIPvarGetData(SCIP_VAR *var)
Definition: var.c:17280
SCIP_RETCODE SCIPcolChgLb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newlb)
Definition: lp.c:3761
int SCIPvarGetNLocksUp(SCIP_VAR *var)
Definition: var.c:3432
#define MAX(x, y)
Definition: tclique_def.h:92
SCIP_Bool SCIPstrToRealValue(const char *str, SCIP_Real *value, char **endptr)
Definition: misc.c:10865
int SCIPimplicsGetNImpls(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3319
SCIP_RETCODE SCIPboundchgApply(SCIP_BOUNDCHG *boundchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, int depth, int pos, SCIP_Bool *cutoff)
Definition: var.c:629
SCIP_VAR * SCIPboundchgGetVar(SCIP_BOUNDCHG *boundchg)
Definition: var.c:17167
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11950
SCIP_Bool * SCIPcliqueGetValues(SCIP_CLIQUE *clique)
Definition: implics.c:3389
SCIP_BOUNDCHG * SCIPdomchgGetBoundchg(SCIP_DOMCHG *domchg, int pos)
Definition: var.c:17215
SCIP_Real SCIPvarGetUnchangedObj(SCIP_VAR *var)
Definition: var.c:17777
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:2646
SCIP_Real SCIPvarGetMultaggrUbGlobal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8637
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:17767
SCIP_RETCODE SCIPvarAddCliqueToList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:11401
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18511
SCIP_Real SCIPvarGetBestRootRedcost(SCIP_VAR *var)
Definition: var.c:13790
SCIP_VAR * SCIPvarGetAggrVar(SCIP_VAR *var)
Definition: var.c:17651
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:4417
int nuses
Definition: struct_var.h:262
SCIP_Real SCIPvarGetAvgInferencesCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:16132
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:11187
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:11440
#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:17630
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:8750
SCIP_RETCODE SCIPvarCopy(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP *sourcescip, SCIP_VAR *sourcevar, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global)
Definition: var.c:2163
SCIP_Real SCIPvarGetRelaxSol(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:13931
datastructures for problem statistics
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:17687
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:18243
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12782
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:6344
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:15195
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:9517
SCIP_NODE * SCIPgetFocusNode(SCIP *scip)
Definition: scip_tree.c:72
SCIP_RETCODE SCIPcolChgUb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newub)
Definition: lp.c:3806
SCIP_RETCODE SCIPcolFree(SCIP_COL **col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: lp.c:3381
SCIP * scip
Definition: struct_var.h:288
SCIP_EVENTFILTER * eventfilter
Definition: struct_var.h:247
static SCIP_Real SCIPvarGetPseudoSol_rec(SCIP_VAR *var)
Definition: var.c:13198
SCIP_BDCHGINFO * SCIPvarGetLbchgInfo(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16418
SCIP_Bool SCIPprobIsTransformed(SCIP_PROB *prob)
Definition: prob.c:2287
SCIP_BOUNDTYPE SCIPbdchginfoGetInferBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18628
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:16474
int conflictubcount
Definition: struct_var.h:271
int SCIPvboundsGetNVbds(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3287
SCIP_RETCODE SCIPvarGetProbvarBound(SCIP_VAR **var, SCIP_Real *bound, SCIP_BOUNDTYPE *boundtype)
Definition: var.c:12477
static SCIP_RETCODE parseValue(SCIP_SET *set, const char *str, SCIP_Real *value, char **endptr)
Definition: var.c:2276
SCIP_DOM locdom
Definition: struct_var.h:226
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoUb(SCIP_VAR *var, int pos)
Definition: var.c:18339
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:9798
SCIP_BDCHGINFO * SCIPvarGetBdchgInfo(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16530
#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:2947
static SCIP_RETCODE varAddLbchginfo(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real oldbound, SCIP_Real newbound, int depth, int pos, SCIP_VAR *infervar, SCIP_CONS *infercons, SCIP_PROP *inferprop, int inferinfo, SCIP_BOUNDTYPE inferboundtype, SCIP_BOUNDCHGTYPE boundchgtype)
Definition: var.c:480
#define SCIP_DECL_VARDELORIG(x)
Definition: type_var.h:127
SCIP_Real SCIPhistoryGetCutoffSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:671
datastructures for storing and manipulating the main problem
SCIP_RETCODE SCIPvarAddToRow(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *prob, SCIP_LP *lp, SCIP_ROW *row, SCIP_Real val)
Definition: var.c:14278
SCIP_RETCODE SCIPvarLoose(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *prob, SCIP_LP *lp)
Definition: var.c:3616
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:3657
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:18214
static SCIP_RETCODE varFreeParents(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:2674
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:7523
#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:3419
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:6200
SCIP_Real SCIPhistoryGetInferenceSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:645
#define BMSallocBlockMemorySize(mem, ptr, size)
Definition: memory.h:455
unsigned int boundtype
Definition: struct_var.h:124
#define SCIPsetFreeCleanBufferArray(set, ptr)
Definition: set.h:1748
void SCIPrelaxationSolObjAdd(SCIP_RELAXATION *relaxation, SCIP_Real val)
Definition: relax.c:849
static const SCIP_Real scalars[]
Definition: lp.c:5747
SCIP_RETCODE SCIPvarMultiaggregate(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, int naggvars, SCIP_VAR **aggvars, SCIP_Real *scalars, SCIP_Real constant, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition: var.c:5450
int lpipos
Definition: struct_lp.h:173
SCIP_NODE * SCIPtreeGetRootNode(SCIP_TREE *tree)
Definition: tree.c:8453
int SCIPdomchgGetNBoundchgs(SCIP_DOMCHG *domchg)
Definition: var.c:17207
SCIP_RETCODE SCIPvarColumn(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_LP *lp)
Definition: var.c:3582
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:18551
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:3922
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:14869
SCIP_RETCODE SCIPvarMarkDoNotAggr(SCIP_VAR *var)
Definition: var.c:6110
SCIP_DECL_HASHKEYEQ(SCIPvarIsHashkeyEq)
Definition: var.c:11999
SCIP_Real SCIPvarGetBestRootSol(SCIP_VAR *var)
Definition: var.c:13723
SCIP_VAR * var
Definition: struct_var.h:119
public methods for message output
data structures for LP management
int nrootboundchgsrun
Definition: struct_stat.h:223
void SCIPcliquelistCheck(SCIP_CLIQUELIST *cliquelist, SCIP_VAR *var)
Definition: implics.c:3461
SCIP_VAR * a
Definition: circlepacking.c:66
void SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr,...)
Definition: message.c:618
void SCIPvarSetCopyData(SCIP_VAR *var, SCIP_DECL_VARCOPY((*varcopy)))
Definition: var.c:17336
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:9289
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:17227
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:17379
SCIP_RETCODE SCIPvarResetBounds(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat)
Definition: var.c:9236
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:9418
#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:2747
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:15707
SCIP_RETCODE SCIPvarsGetProbvarBinary(SCIP_VAR ***vars, SCIP_Bool **negatedarr, int nvars)
Definition: var.c:12286
SCIP_VAR * SCIPbdchginfoGetInferVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18581
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:17347
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:12570
SCIP_RETCODE SCIPlpUpdateVarLoose(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:14312
SCIP_Real SCIPvarGetVSIDS(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:18384
#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:17270
void SCIPvarsGetProbvar(SCIP_VAR **vars, int nvars)
Definition: var.c:12206
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:2563
static SCIP_RETCODE parseBounds(SCIP_SET *set, const char *str, char *type, SCIP_Real *lb, SCIP_Real *ub, char **endptr)
Definition: var.c:2308
SCIP_VAR ** SCIPvarGetVubVars(SCIP_VAR *var)
Definition: var.c:18165
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:18031
SCIP_CONS * SCIPbdchginfoGetInferCons(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18593
SCIP_Bool SCIPsetIsDualfeasZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6934
SCIP_Real SCIPvarGetAvgSol(SCIP_VAR *var)
Definition: var.c:14070
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:17599
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:2622
SCIP_Real SCIPvarGetAvgCutoffs(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:16273
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:9127
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:17425
SCIP_Real SCIPvarGetMultaggrUbLocal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8505
SCIP_RETCODE SCIPvarChgName(SCIP_VAR *var, BMS_BLKMEM *blkmem, const char *name)
Definition: var.c:2916
SCIP_DOM glbdom
Definition: struct_var.h:225
SCIP_Real SCIPsetEpsilon(SCIP_SET *set)
Definition: set.c:6102
SCIP_Real SCIPhistoryGetAvgInferences(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:658
SCIP_STAGE SCIPsetGetStage(SCIP_SET *set)
Definition: set.c:2997
enum SCIP_Vartype SCIP_VARTYPE
Definition: type_var.h:69
static SCIP_RETCODE varEventGubChanged(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real oldbound, SCIP_Real newbound)
Definition: var.c:6729
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:17527
SCIP_Bool SCIPcliqueIsCleanedUp(SCIP_CLIQUE *clique)
Definition: implics.c:3423
SCIP_Real newbound
Definition: struct_var.h:118
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17985
int SCIPcliqueGetNVars(SCIP_CLIQUE *clique)
Definition: implics.c:3367
SCIP_RETCODE SCIPvarAddHoleOriginal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real left, SCIP_Real right)
Definition: var.c:8698
void SCIPbdchginfoFree(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem)
Definition: var.c:16404
void SCIPvarAdjustUb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *ub)
Definition: var.c:6539
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:17402
static void varIncRootboundchgs(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat)
Definition: var.c:6799
#define BMSallocBlockMemory(mem, ptr)
Definition: memory.h:453
SCIP_HOLELIST * SCIPvarGetHolelistLocal(SCIP_VAR *var)
Definition: var.c:17995
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:18541
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:18426
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:3105
SCIP_RETCODE SCIPlpUpdateVarColumn(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:14188
SCIP_HISTORY * history
Definition: struct_var.h:250
SCIP_RETCODE SCIPvarSetRemovable(SCIP_VAR *var, SCIP_Bool removable)
Definition: var.c:17363
SCIP_Real SCIPvarGetVSIDS_rec(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15885
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:12655
#define SCIP_EVENTTYPE_GUBCHANGED
Definition: type_event.h:76
#define SCIP_CALL_ABORT(x)
Definition: def.h:372
SCIP_Real SCIPvarGetPseudoSol(SCIP_VAR *var)
Definition: var.c:18371
enum SCIP_BoundchgType SCIP_BOUNDCHGTYPE
Definition: type_var.h:87
SCIP_Real * SCIPimplicsGetBounds(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3346
SCIP_ORIGINAL original
Definition: struct_var.h:229
SCIP_Real SCIPcolGetRedcost(SCIP_COL *col, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:3956
SCIP_VAR * SCIPvarGetTransVar(SCIP_VAR *var)
Definition: var.c:17619
#define SCIP_ALLOC(x)
Definition: def.h:404
#define SCIPABORT()
Definition: def.h:365
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:17451
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:8439
const char * SCIPprobGetName(SCIP_PROB *prob)
Definition: prob.c:2343
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9031
unsigned int applied
Definition: struct_var.h:103
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition: var.c:17481
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:11363
void SCIPvarGetImplicVarBounds(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_Real *lb, SCIP_Real *ub)
Definition: var.c:11151
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:6099
void SCIPvarSetData(SCIP_VAR *var, SCIP_VARDATA *vardata)
Definition: var.c:17290
SCIP_Bool SCIPcolIsInLP(SCIP_COL *col)
Definition: lp.c:17107
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:5921
SCIP_Real left
Definition: struct_var.h:53
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9283
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:3454
#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:11759
SCIP_Bool SCIPvarMayRoundDown(SCIP_VAR *var)
Definition: var.c:3443
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:14700
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:17589
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:15004
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:17415
SCIP_RETCODE SCIProwAddConstant(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_Real addval)
Definition: lp.c:5644
SCIP_Real scalar
Definition: struct_var.h:185
uint64_t SCIP_EVENTTYPE
Definition: type_event.h:151
void SCIPvarMarkDeleteGlobalStructures(SCIP_VAR *var)
Definition: var.c:17517
SCIP_BOUNDCHGTYPE SCIPbdchginfoGetChgtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18531
SCIP_RETCODE SCIPvarDelCliqueFromList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:11423