SCIP Doxygen Documentation
Loading...
Searching...
No Matches
var.c
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the program and library */
4/* SCIP --- Solving Constraint Integer Programs */
5/* */
6/* Copyright (c) 2002-2026 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file var.c
26 * @ingroup OTHER_CFILES
27 * @brief methods for problem variables
28 * @author Tobias Achterberg
29 * @author Timo Berthold
30 * @author Gerald Gamrath
31 * @author Stefan Heinz
32 * @author Marc Pfetsch
33 * @author Michael Winkler
34 * @author Kati Wolter
35 * @author Stefan Vigerske
36 *
37 * @todo Possibly implement the access of bounds of multi-aggregated variables by accessing the
38 * corresponding linear constraint if it exists. This seems to require some work, since the linear
39 * constraint has to be stored. Moreover, it has even to be created in case the original constraint
40 * was deleted after multi-aggregation, but the bounds of the multi-aggregated variable should be
41 * changed. This has to be done with care in order to not loose the performance gains of
42 * multi-aggregation.
43 */
44
45/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
46#include "scip/cons.h"
47#include "scip/certificate.h"
48#include "scip/event.h"
49#include "scip/history.h"
50#include "scip/implics.h"
51#include "scip/lp.h"
52#include "scip/lpexact.h"
53#include "scip/primal.h"
54#include "scip/prob.h"
55#include "scip/pub_cons.h"
56#include "scip/pub_history.h"
57#include "scip/pub_implics.h"
58#include "scip/pub_lp.h"
59#include "scip/pub_message.h"
60#include "scip/pub_misc.h"
61#include "scip/pub_misc_sort.h"
62#include "scip/pub_prop.h"
63#include "scip/pub_var.h"
64#include "scip/relax.h"
66#include "scip/scip_exact.h"
67#include "scip/scip_prob.h"
68#include "scip/scip_probing.h"
69#include "scip/set.h"
70#include "scip/sol.h"
71#include "scip/stat.h"
72#include "scip/struct_event.h"
73#include "scip/struct_lp.h"
74#include "scip/struct_lpexact.h"
75#include "scip/struct_prob.h"
76#include "scip/struct_set.h"
77#include "scip/struct_stat.h"
78#include "scip/struct_var.h"
79#include "scip/tree.h"
80#include "scip/var.h"
81#include <string.h>
82
83#define MAXIMPLSCLOSURE 100 /**< maximal number of descendants of implied variable for building closure
84 * in implication graph */
85#define MAXABSVBCOEF 1e+5 /**< maximal absolute coefficient in variable bounds added due to implications */
86
87
88/*
89 * Debugging variable release and capture
90 *
91 * Define DEBUGUSES_VARNAME to the name of the variable for which to print
92 * a backtrace when it is captured and released.
93 * Optionally define DEBUGUSES_PROBNAME to the name of a SCIP problem to consider.
94 * Have DEBUGUSES_NOADDR2LINE defined if you do not have addr2line installed on your system.
95 */
96/* #define DEBUGUSES_VARNAME "t_t_b7" */
97/* #define DEBUGUSES_PROBNAME "t_st_e35_rens" */
98/* #define DEBUGUSES_NOADDR2LINE */
99
100#ifdef DEBUGUSES_VARNAME
101#include <execinfo.h>
102#include <stdio.h>
103#include <stdlib.h>
104#include "scip/struct_scip.h"
105
106/** obtains a backtrace and prints it to stdout. */
107static
108void print_backtrace(void)
109{
110 void* array[10];
111 char** strings;
112 int size;
113 int i;
114
115 size = backtrace(array, 10);
116 strings = backtrace_symbols(array, size);
117 if( strings == NULL )
118 return;
119
120 /* skip first entry, which is the print_backtrace function */
121 for( i = 1; i < size; ++i )
122 {
123 /* if string is something like
124 * /path/to/scip/bin/../lib/shared/libscip-7.0.1.3.linux.x86_64.gnu.dbg.so(+0x2675dd3)
125 * (that is, no function name because it is a inlined function), then call
126 * addr2line -e <libname> <addr> to get func and code line
127 * dladdr() may be an alternative
128 */
129 char* openpar;
130 char* closepar = NULL;
131#ifndef DEBUGUSES_NOADDR2LINE
132 openpar = strchr(strings[i], '(');
133 if( openpar != NULL && openpar[1] == '+' )
134 closepar = strchr(openpar+2, ')');
135#endif
136 if( closepar != NULL )
137 {
138 char cmd[SCIP_MAXSTRLEN];
139 (void) SCIPsnprintf(cmd, SCIP_MAXSTRLEN, "addr2line -f -p -e \"%.*s\" %.*s", openpar - strings[i], strings[i], closepar-openpar-1, openpar+1);
140 printf(" ");
141 fflush(stdout);
142 system(cmd);
143 }
144 else
145 printf(" %s\n", strings[i]);
146 }
147
148 free(strings);
149}
150#endif
151
152/*
153 * hole, holelist, and domain methods
154 */
155
156/** creates a new holelist element */
157static
159 SCIP_HOLELIST** holelist, /**< pointer to holelist to create */
160 BMS_BLKMEM* blkmem, /**< block memory for target holelist */
161 SCIP_SET* set, /**< global SCIP settings */
162 SCIP_Real left, /**< left bound of open interval in new hole */
163 SCIP_Real right /**< right bound of open interval in new hole */
164 )
165{
166 assert(holelist != NULL);
167 assert(blkmem != NULL);
168 assert(SCIPsetIsLT(set, left, right));
169
170 SCIPsetDebugMsg(set, "create hole list element (%.15g,%.15g) in blkmem %p\n", left, right, (void*)blkmem);
171
172 SCIP_ALLOC( BMSallocBlockMemory(blkmem, holelist) );
173 (*holelist)->hole.left = left;
174 (*holelist)->hole.right = right;
175 (*holelist)->next = NULL;
176
177 return SCIP_OKAY;
178}
179
180/** frees all elements in the holelist */
181static
183 SCIP_HOLELIST** holelist, /**< pointer to holelist to free */
184 BMS_BLKMEM* blkmem /**< block memory for target holelist */
185 )
186{
187 assert(holelist != NULL);
188 assert(blkmem != NULL);
189
190 while( *holelist != NULL )
191 {
192 SCIP_HOLELIST* next;
193
194 SCIPdebugMessage("free hole list element (%.15g,%.15g) in blkmem %p\n",
195 (*holelist)->hole.left, (*holelist)->hole.right, (void*)blkmem);
196
197 next = (*holelist)->next;
198 BMSfreeBlockMemory(blkmem, holelist);
199 assert(*holelist == NULL);
200
201 *holelist = next;
202 }
203 assert(*holelist == NULL);
204}
205
206/** duplicates a list of holes */
207static
209 SCIP_HOLELIST** target, /**< pointer to target holelist */
210 BMS_BLKMEM* blkmem, /**< block memory for target holelist */
211 SCIP_SET* set, /**< global SCIP settings */
212 SCIP_HOLELIST* source /**< holelist to duplicate */
213 )
214{
215 assert(target != NULL);
216
217 while( source != NULL )
218 {
219 assert(source->next == NULL || SCIPsetIsGE(set, source->next->hole.left, source->hole.right));
220 SCIP_CALL( holelistCreate(target, blkmem, set, source->hole.left, source->hole.right) );
221 source = source->next;
222 target = &(*target)->next;
223 }
224
225 return SCIP_OKAY;
226}
227
228/** adds a hole to the domain */
229static
231 SCIP_DOM* dom, /**< domain to add hole to */
232 BMS_BLKMEM* blkmem, /**< block memory */
233 SCIP_SET* set, /**< global SCIP settings */
234 SCIP_Real left, /**< left bound of open interval in new hole */
235 SCIP_Real right, /**< right bound of open interval in new hole */
236 SCIP_Bool* added /**< pointer to store whether the hole was added (variable didn't had that hole before), or NULL */
237 )
238{
239 SCIP_HOLELIST** insertpos;
240 SCIP_HOLELIST* next;
241
242 assert(dom != NULL);
243 assert(added != NULL);
244
245 /* search for the position of the new hole */
246 insertpos = &dom->holelist;
247 while( *insertpos != NULL && (*insertpos)->hole.left < left )
248 insertpos = &(*insertpos)->next;
249
250 /* check if new hole already exists in the hole list or is a sub hole of an existing one */
251 if( *insertpos != NULL && (*insertpos)->hole.left == left && (*insertpos)->hole.right >= right ) /*lint !e777 */
252 {
253 SCIPsetDebugMsg(set, "new hole (%.15g,%.15g) is redundant through known hole (%.15g,%.15g)\n",
254 left, right, (*insertpos)->hole.left, (*insertpos)->hole.right);
255 *added = FALSE;
256 return SCIP_OKAY;
257 }
258
259 /* add hole */
260 *added = TRUE;
261
262 next = *insertpos;
263 SCIP_CALL( holelistCreate(insertpos, blkmem, set, left, right) );
264 (*insertpos)->next = next;
265
266 return SCIP_OKAY;
267}
268
269/** merges overlapping holes into single holes, computes and moves lower and upper bound, respectively */
270/**@todo the domMerge() method is currently called if a lower or an upper bound locally or globally changed; this could
271 * be more efficient if performed with the knowledge if it was a lower or an upper bound which triggered this
272 * merge */
273static
275 SCIP_DOM* dom, /**< domain to merge */
276 BMS_BLKMEM* blkmem, /**< block memory */
277 SCIP_SET* set, /**< global SCIP settings */
278 SCIP_Real* newlb, /**< pointer to store new lower bound */
279 SCIP_Real* newub /**< pointer to store new upper bound */
280 )
281{
282 SCIP_HOLELIST** holelistptr;
283 SCIP_HOLELIST** lastnextptr;
284 SCIP_Real* lastrightptr;
285
286 assert(dom != NULL);
287 assert(SCIPsetIsLE(set, dom->lb, dom->ub));
288
289#ifndef NDEBUG
290 {
291 /* check if the holelist is sorted w.r.t. to the left interval bounds */
292 SCIP_Real lastleft;
293
294 holelistptr = &dom->holelist;
295
296 lastleft = -SCIPsetInfinity(set);
297
298 while( *holelistptr != NULL )
299 {
300 if( (*holelistptr)->next != NULL )
301 {
302 assert( SCIPsetIsLE(set, lastleft, (*holelistptr)->hole.left) );
303 lastleft = (*holelistptr)->hole.left;
304 }
305
306 holelistptr = &(*holelistptr)->next;
307 }
308 }
309#endif
310
311 SCIPsetDebugMsg(set, "merge hole list\n");
312
313 holelistptr = &dom->holelist;
314 lastrightptr = &dom->lb; /* lower bound is the right bound of the hole (-infinity,lb) */
315 lastnextptr = holelistptr;
316
317 while( *holelistptr != NULL )
318 {
319 SCIPsetDebugMsg(set, "check hole (%.15g,%.15g) last right interval was <%.15g>\n", (*holelistptr)->hole.left, (*holelistptr)->hole.right, *lastrightptr);
320
321 /* check that the hole is not empty */
322 assert(SCIPsetIsLT(set, (*holelistptr)->hole.left, (*holelistptr)->hole.right));
323
324 if( SCIPsetIsGE(set, (*holelistptr)->hole.left, dom->ub) )
325 {
326 /* the remaining holes start behind the upper bound: remove them */
327 SCIPsetDebugMsg(set, "remove remaining hole since upper bound <%.15g> is less then the left hand side of the current hole\n", dom->ub);
328 holelistFree(holelistptr, blkmem);
329 assert(*holelistptr == NULL);
330
331 /* unlink this hole from the previous hole */
332 *lastnextptr = NULL;
333 }
334 else if( SCIPsetIsGT(set, (*holelistptr)->hole.right, dom->ub) )
335 {
336 /* the hole overlaps the upper bound: decrease upper bound, remove this hole and all remaining holes */
337 SCIPsetDebugMsg(set, "upper bound <%.15g> lays in current hole; store new upper bound and remove this and all remaining holes\n", dom->ub);
338
339 assert(SCIPsetIsLT(set, (*holelistptr)->hole.left, dom->ub));
340
341 /* adjust upper bound */
342 dom->ub = (*holelistptr)->hole.left;
343
344 if(newub != NULL )
345 *newub = (*holelistptr)->hole.left;
346
347 /* remove remaining hole list */
348 holelistFree(holelistptr, blkmem);
349 assert(*holelistptr == NULL);
350
351 /* unlink this hole from the previous hole */
352 *lastnextptr = NULL;
353 }
354 else if( SCIPsetIsGT(set, *lastrightptr, (*holelistptr)->hole.left) )
355 {
356 /* the right bound of the last hole is greater than the left bound of this hole: increase the right bound of
357 * the last hole, delete this hole */
358 SCIP_HOLELIST* nextholelist;
359
360 if( SCIPsetIsEQ(set, *lastrightptr, dom->lb ) )
361 {
362 /* the reason for the overlap results from the lower bound hole (-infinity,lb); therefore, we can increase
363 * the lower bound */
364 SCIPsetDebugMsg(set, "lower bound <%.15g> lays in current hole; store new lower bound and remove hole\n", dom->lb);
365 *lastrightptr = MAX(*lastrightptr, (*holelistptr)->hole.right);
366
367 /* adjust lower bound */
368 dom->lb = *lastrightptr;
369
370 if(newlb != NULL )
371 *newlb = *lastrightptr;
372 }
373 else
374 {
375 SCIPsetDebugMsg(set, "current hole overlaps with the previous one (...,%.15g); merge to (...,%.15g)\n",
376 *lastrightptr, MAX(*lastrightptr, (*holelistptr)->hole.right) );
377 *lastrightptr = MAX(*lastrightptr, (*holelistptr)->hole.right);
378 }
379 nextholelist = (*holelistptr)->next;
380 (*holelistptr)->next = NULL;
381 holelistFree(holelistptr, blkmem);
382
383 /* connect the linked list after removing the hole */
384 *lastnextptr = nextholelist;
385
386 /* get next hole */
387 *holelistptr = nextholelist;
388 }
389 else
390 {
391 /* the holes do not overlap: update lastholelist and lastrightptr */
392 lastrightptr = &(*holelistptr)->hole.right;
393 lastnextptr = &(*holelistptr)->next;
394
395 /* get next hole */
396 holelistptr = &(*holelistptr)->next;
397 }
398 }
399
400#ifndef NDEBUG
401 {
402 /* check that holes are merged */
403 SCIP_Real lastright;
404
405 lastright = dom->lb; /* lower bound is the right bound of the hole (-infinity,lb) */
406 holelistptr = &dom->holelist;
407
408 while( *holelistptr != NULL )
409 {
410 /* check the the last right interval is smaller or equal to the current left interval (none overlapping) */
411 assert( SCIPsetIsLE(set, lastright, (*holelistptr)->hole.left) );
412
413 /* check the hole property (check that the hole is not empty) */
414 assert( SCIPsetIsLT(set, (*holelistptr)->hole.left, (*holelistptr)->hole.right) );
415 lastright = (*holelistptr)->hole.right;
416
417 /* get next hole */
418 holelistptr = &(*holelistptr)->next;
419 }
420
421 /* check the the last right interval is smaller or equal to the upper bound (none overlapping) */
422 assert( SCIPsetIsLE(set, lastright, dom->ub) );
423 }
424#endif
425}
426
427/*
428 * domain change methods
429 */
430
431/** ensures, that bound change info array for lower bound changes can store at least num entries */
432static
434 SCIP_VAR* var, /**< problem variable */
435 BMS_BLKMEM* blkmem, /**< block memory */
436 SCIP_SET* set, /**< global SCIP settings */
437 int num /**< minimum number of entries to store */
438 )
439{
440 assert(var != NULL);
441 assert(var->nlbchginfos <= var->lbchginfossize);
443
444 if( num > var->lbchginfossize )
445 {
446 int newsize;
447
448 newsize = SCIPsetCalcMemGrowSize(set, num);
449 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->lbchginfos, var->lbchginfossize, newsize) );
450 var->lbchginfossize = newsize;
451 }
452 assert(num <= var->lbchginfossize);
453
454 return SCIP_OKAY;
455}
456
457/** ensures, that bound change info array for upper bound changes can store at least num entries */
458static
460 SCIP_VAR* var, /**< problem variable */
461 BMS_BLKMEM* blkmem, /**< block memory */
462 SCIP_SET* set, /**< global SCIP settings */
463 int num /**< minimum number of entries to store */
464 )
465{
466 assert(var != NULL);
467 assert(var->nubchginfos <= var->ubchginfossize);
469
470 if( num > var->ubchginfossize )
471 {
472 int newsize;
473
474 newsize = SCIPsetCalcMemGrowSize(set, num);
475 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->ubchginfos, var->ubchginfossize, newsize) );
476 var->ubchginfossize = newsize;
477 }
478 assert(num <= var->ubchginfossize);
479
480 return SCIP_OKAY;
481}
482
483/** adds domain change info to the variable's lower bound change info array */
484static
486 SCIP_VAR* var, /**< problem variable */
487 BMS_BLKMEM* blkmem, /**< block memory */
488 SCIP_SET* set, /**< global SCIP settings */
489 SCIP_Real oldbound, /**< old value for bound */
490 SCIP_Real newbound, /**< new value for bound */
491 int depth, /**< depth in the tree, where the bound change takes place */
492 int pos, /**< position of the bound change in its bound change array */
493 SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself) */
494 SCIP_CONS* infercons, /**< constraint that inferred this bound change, or NULL */
495 SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
496 int inferinfo, /**< user information for inference to help resolving the conflict */
497 SCIP_BOUNDTYPE inferboundtype, /**< type of bound for inference var: lower or upper bound */
498 SCIP_BOUNDCHGTYPE boundchgtype /**< bound change type: branching decision or inferred bound change */
499 )
500{
501 assert(var != NULL);
502 assert(SCIPsetIsLT(set, oldbound, newbound));
505 assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, oldbound, 0.0));
506 assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, 1.0));
507 assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
508 assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
509 assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
510
511 SCIPsetDebugMsg(set, "adding lower bound change info to var <%s>[%g,%g]: depth=%d, pos=%d, infer%s=<%s>, inferinfo=%d, %g -> %g\n",
512 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, depth, pos, infercons != NULL ? "cons" : "prop",
513 infercons != NULL ? SCIPconsGetName(infercons) : (inferprop != NULL ? SCIPpropGetName(inferprop) : "-"), inferinfo,
514 oldbound, newbound);
515
516 SCIP_CALL( varEnsureLbchginfosSize(var, blkmem, set, var->nlbchginfos+1) );
517 var->lbchginfos[var->nlbchginfos].oldbound = oldbound;
518 var->lbchginfos[var->nlbchginfos].newbound = newbound;
519 var->lbchginfos[var->nlbchginfos].var = var;
520 var->lbchginfos[var->nlbchginfos].bdchgidx.depth = depth;
521 var->lbchginfos[var->nlbchginfos].bdchgidx.pos = pos;
522 var->lbchginfos[var->nlbchginfos].pos = var->nlbchginfos; /*lint !e732*/
523 var->lbchginfos[var->nlbchginfos].boundchgtype = boundchgtype; /*lint !e641*/
524 var->lbchginfos[var->nlbchginfos].boundtype = SCIP_BOUNDTYPE_LOWER; /*lint !e641*/
525 var->lbchginfos[var->nlbchginfos].redundant = FALSE;
526 var->lbchginfos[var->nlbchginfos].inferboundtype = inferboundtype; /*lint !e641*/
527 var->lbchginfos[var->nlbchginfos].inferencedata.var = infervar;
528 var->lbchginfos[var->nlbchginfos].inferencedata.info = inferinfo;
529
530 /**@note The "pos" data member of the bound change info has a size of 27 bits */
531 assert(var->nlbchginfos < 1 << 27);
532
533 switch( boundchgtype )
534 {
536 break;
538 assert(infercons != NULL);
539 var->lbchginfos[var->nlbchginfos].inferencedata.reason.cons = infercons;
540 break;
542 var->lbchginfos[var->nlbchginfos].inferencedata.reason.prop = inferprop;
543 break;
544 default:
545 SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
546 return SCIP_INVALIDDATA;
547 }
548
549 var->nlbchginfos++;
550
551 assert(var->nlbchginfos < 2
552 || SCIPbdchgidxIsEarlier(&var->lbchginfos[var->nlbchginfos-2].bdchgidx,
553 &var->lbchginfos[var->nlbchginfos-1].bdchgidx));
554
555 return SCIP_OKAY;
556}
557
558/** adds domain change info to the variable's upper bound change info array */
559static
561 SCIP_VAR* var, /**< problem variable */
562 BMS_BLKMEM* blkmem, /**< block memory */
563 SCIP_SET* set, /**< global SCIP settings */
564 SCIP_Real oldbound, /**< old value for bound */
565 SCIP_Real newbound, /**< new value for bound */
566 int depth, /**< depth in the tree, where the bound change takes place */
567 int pos, /**< position of the bound change in its bound change array */
568 SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself) */
569 SCIP_CONS* infercons, /**< constraint that inferred this bound change, or NULL */
570 SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
571 int inferinfo, /**< user information for inference to help resolving the conflict */
572 SCIP_BOUNDTYPE inferboundtype, /**< type of bound for inference var: lower or upper bound */
573 SCIP_BOUNDCHGTYPE boundchgtype /**< bound change type: branching decision or inferred bound change */
574 )
575{
576 assert(var != NULL);
577 assert(SCIPsetIsGT(set, oldbound, newbound));
580 assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, oldbound, 1.0));
581 assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, 0.0));
582 assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
583 assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
584 assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
585
586 SCIPsetDebugMsg(set, "adding upper bound change info to var <%s>[%g,%g]: depth=%d, pos=%d, infer%s=<%s>, inferinfo=%d, %g -> %g\n",
587 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, depth, pos, infercons != NULL ? "cons" : "prop",
588 infercons != NULL ? SCIPconsGetName(infercons) : (inferprop != NULL ? SCIPpropGetName(inferprop) : "-"), inferinfo,
589 oldbound, newbound);
590
591 SCIP_CALL( varEnsureUbchginfosSize(var, blkmem, set, var->nubchginfos+1) );
592 var->ubchginfos[var->nubchginfos].oldbound = oldbound;
593 var->ubchginfos[var->nubchginfos].newbound = newbound;
594 var->ubchginfos[var->nubchginfos].var = var;
595 var->ubchginfos[var->nubchginfos].bdchgidx.depth = depth;
596 var->ubchginfos[var->nubchginfos].bdchgidx.pos = pos;
597 var->ubchginfos[var->nubchginfos].pos = var->nubchginfos; /*lint !e732*/
598 var->ubchginfos[var->nubchginfos].boundchgtype = boundchgtype; /*lint !e641*/
599 var->ubchginfos[var->nubchginfos].boundtype = SCIP_BOUNDTYPE_UPPER; /*lint !e641*/
600 var->ubchginfos[var->nubchginfos].redundant = FALSE;
601 var->ubchginfos[var->nubchginfos].inferboundtype = inferboundtype; /*lint !e641*/
602 var->ubchginfos[var->nubchginfos].inferencedata.var = infervar;
603 var->ubchginfos[var->nubchginfos].inferencedata.info = inferinfo;
604
605 /**@note The "pos" data member of the bound change info has a size of 27 bits */
606 assert(var->nubchginfos < 1 << 27);
607
608 switch( boundchgtype )
609 {
611 break;
613 assert(infercons != NULL);
614 var->ubchginfos[var->nubchginfos].inferencedata.reason.cons = infercons;
615 break;
617 var->ubchginfos[var->nubchginfos].inferencedata.reason.prop = inferprop;
618 break;
619 default:
620 SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
621 return SCIP_INVALIDDATA;
622 }
623
624 var->nubchginfos++;
625
626 assert(var->nubchginfos < 2
627 || SCIPbdchgidxIsEarlier(&var->ubchginfos[var->nubchginfos-2].bdchgidx,
628 &var->ubchginfos[var->nubchginfos-1].bdchgidx));
629
630 return SCIP_OKAY;
631}
632
633/** applies single bound change */
634static
636 SCIP_BOUNDCHG* boundchg, /**< bound change to apply */
637 BMS_BLKMEM* blkmem, /**< block memory */
638 SCIP_SET* set, /**< global SCIP settings */
639 SCIP_STAT* stat, /**< problem statistics */
640 SCIP_LP* lp, /**< current LP data */
641 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
642 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
643 int depth, /**< depth in the tree, where the bound change takes place */
644 int pos, /**< position of the bound change in its bound change array */
645 SCIP_Bool* cutoff /**< pointer to store whether an infeasible bound change was detected */
646 )
647{
648 SCIP_VAR* var;
649
650 assert(boundchg != NULL);
651 assert(stat != NULL);
652 assert(depth > 0);
653 assert(pos >= 0);
654 assert(cutoff != NULL);
655 assert(boundchg->newboundexact != NULL);
656
657 *cutoff = FALSE;
658
659 /* ignore redundant bound changes */
660 if( boundchg->redundant )
661 return SCIP_OKAY;
662
663 var = boundchg->var;
664 assert(var != NULL);
667
668 /* apply bound change */
669 switch( boundchg->boundtype )
670 {
672 /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
674 {
676 {
677 /* add the bound change info to the variable's bound change info array */
678 switch( boundchg->boundchgtype )
679 {
681 SCIPsetDebugMsg(set, " -> branching: new lower bound of <%s>[%g,%g]: %g\n",
682 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
683 SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
685 stat->lastbranchvar = var;
687 stat->lastbranchvalue = boundchg->newbound;
688 break;
689
691 assert(boundchg->data.inferencedata.reason.cons != NULL);
692 SCIPsetDebugMsg(set, " -> constraint <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
693 SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
694 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
695 SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
696 boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
697 boundchg->data.inferencedata.info,
699 break;
700
702 SCIPsetDebugMsg(set, " -> propagator <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
703 boundchg->data.inferencedata.reason.prop != NULL
704 ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
705 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
706 SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
707 boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
708 boundchg->data.inferencedata.info,
710 break;
711
712 default:
713 SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
714 return SCIP_INVALIDDATA;
715 }
717 {
718 assert( var->exactdata->locdom.lbcertificateidx != -1 || SCIPsetIsInfinity(set, -var->locdom.lb) );
719 var->lbchginfos[var->nlbchginfos - 1].oldcertificateindex = var->exactdata->locdom.lbcertificateidx;
721 }
722 /* change local bound of variable */
723 SCIP_CALL( SCIPvarChgLbLocalExact(var, blkmem, set, stat, lp->lpexact, branchcand, eventqueue, boundchg->newboundexact) );
724 }
725 else
726 {
727 SCIPsetDebugMsg(set, " -> cutoff: new lower bound of <%s>[%g,%g]: %g\n",
728 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
729 *cutoff = TRUE;
730 boundchg->redundant = TRUE; /* bound change has not entered the lbchginfos array of the variable! */
731 }
732 }
733 else
734 {
735 /* mark bound change to be inactive */
736 SCIPsetDebugMsg(set, " -> inactive %s: new lower bound of <%s>[%g,%g]: %g\n",
737 (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
738 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
739 boundchg->redundant = TRUE;
740 }
741 break;
742
744 /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
746 {
748 {
749 /* add the bound change info to the variable's bound change info array */
750 switch( boundchg->boundchgtype )
751 {
753 SCIPsetDebugMsg(set, " -> branching: new upper bound of <%s>[%g,%g]: %g\n",
754 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
755 SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
757 stat->lastbranchvar = var;
759 stat->lastbranchvalue = boundchg->newbound;
760 break;
761
763 assert(boundchg->data.inferencedata.reason.cons != NULL);
764 SCIPsetDebugMsg(set, " -> constraint <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
765 SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
766 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
767 SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
768 boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
769 boundchg->data.inferencedata.info,
771 break;
772
774 SCIPsetDebugMsg(set, " -> propagator <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
775 boundchg->data.inferencedata.reason.prop != NULL
776 ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
777 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
778 SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
779 boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
780 boundchg->data.inferencedata.info,
782 break;
783
784 default:
785 SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
786 return SCIP_INVALIDDATA;
787 }
788
790 {
791 assert( var->exactdata->locdom.ubcertificateidx != -1 || SCIPsetIsInfinity(set, var->locdom.ub) );
792 var->ubchginfos[var->nubchginfos - 1].oldcertificateindex = var->exactdata->locdom.ubcertificateidx;
794 }
795 /* change local bound of variable */
796 SCIP_CALL( SCIPvarChgUbLocalExact(var, blkmem, set, stat, lp->lpexact, branchcand, eventqueue, boundchg->newboundexact) );
797 }
798 else
799 {
800 SCIPsetDebugMsg(set, " -> cutoff: new upper bound of <%s>[%g,%g]: %g\n",
801 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
802 *cutoff = TRUE;
803 boundchg->redundant = TRUE; /* bound change has not entered the ubchginfos array of the variable! */
804 }
805 }
806 else
807 {
808 /* mark bound change to be inactive */
809 SCIPsetDebugMsg(set, " -> inactive %s: new upper bound of <%s>[%g,%g]: %g\n",
810 (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
811 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
812 boundchg->redundant = TRUE;
813 }
814 break;
815
816 default:
817 SCIPerrorMessage("unknown bound type\n");
818 return SCIP_INVALIDDATA;
819 }
820
821 /* update the branching and inference history */
822 if( !boundchg->applied && !boundchg->redundant )
823 {
824 assert(var == boundchg->var);
825
827 {
828 SCIP_CALL( SCIPvarIncNBranchings(var, blkmem, set, stat,
831 }
832 else if( stat->lastbranchvar != NULL )
833 {
834 /**@todo if last branching variable is unknown, retrieve it from the nodes' boundchg arrays */
835 SCIP_CALL( SCIPvarIncInferenceSum(stat->lastbranchvar, blkmem, set, stat, stat->lastbranchdir, stat->lastbranchvalue, 1.0) );
836 }
837 boundchg->applied = TRUE;
838 }
839
840 return SCIP_OKAY;
841}
842
843
844/** applies single bound change */
846 SCIP_BOUNDCHG* boundchg, /**< bound change to apply */
847 BMS_BLKMEM* blkmem, /**< block memory */
848 SCIP_SET* set, /**< global SCIP settings */
849 SCIP_STAT* stat, /**< problem statistics */
850 SCIP_LP* lp, /**< current LP data */
851 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
852 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
853 int depth, /**< depth in the tree, where the bound change takes place */
854 int pos, /**< position of the bound change in its bound change array */
855 SCIP_Bool* cutoff /**< pointer to store whether an infeasible bound change was detected */
856 )
857{
858 SCIP_VAR* var;
859
860 assert(boundchg != NULL);
861 assert(stat != NULL);
862 assert(depth > 0);
863 assert(pos >= 0);
864 assert(cutoff != NULL);
865
866 *cutoff = FALSE;
867
868 /* ignore redundant bound changes */
869 if( boundchg->redundant )
870 return SCIP_OKAY;
871
872 if( boundchg->newboundexact != NULL)
873 return boundchgApplyExact(boundchg, blkmem, set, stat, lp, branchcand, eventqueue, depth, pos, cutoff);
874
875 var = boundchg->var;
876 assert(var != NULL);
879
880 /* apply bound change */
881 switch( boundchg->boundtype )
882 {
884 /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
885 if( SCIPsetIsGT(set, boundchg->newbound, var->locdom.lb) )
886 {
887 if( SCIPsetIsLE(set, boundchg->newbound, var->locdom.ub) )
888 {
889 /* add the bound change info to the variable's bound change info array */
890 switch( boundchg->boundchgtype )
891 {
893 SCIPsetDebugMsg(set, " -> branching: new lower bound of <%s>[%g,%g]: %g\n",
894 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
895 SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
897 stat->lastbranchvar = var;
899 stat->lastbranchvalue = boundchg->newbound;
900 break;
901
903 assert(boundchg->data.inferencedata.reason.cons != NULL);
904 SCIPsetDebugMsg(set, " -> constraint <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
905 SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
906 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
907 SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
908 boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
909 boundchg->data.inferencedata.info,
911 break;
912
914 SCIPsetDebugMsg(set, " -> propagator <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
915 boundchg->data.inferencedata.reason.prop != NULL
916 ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
917 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
918 SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
919 boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
920 boundchg->data.inferencedata.info,
922 break;
923
924 default:
925 SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
926 return SCIP_INVALIDDATA;
927 }
928
930 {
931 assert( var->exactdata->locdom.lbcertificateidx != -1 || SCIPsetIsInfinity(set, -var->locdom.lb) );
932 var->lbchginfos[var->nlbchginfos - 1].oldcertificateindex = var->exactdata->locdom.lbcertificateidx;
934 }
935
936 /* change local bound of variable */
937 SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, boundchg->newbound) );
938 }
939 else
940 {
941 SCIPsetDebugMsg(set, " -> cutoff: new lower bound of <%s>[%g,%g]: %g\n",
942 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
943 *cutoff = TRUE;
944 boundchg->redundant = TRUE; /* bound change has not entered the lbchginfos array of the variable! */
945 }
946 }
947 else
948 {
949 /* mark bound change to be inactive */
950 SCIPsetDebugMsg(set, " -> inactive %s: new lower bound of <%s>[%g,%g]: %g\n",
951 (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
952 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
953 boundchg->redundant = TRUE;
954 }
955 break;
956
958 /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
959 if( SCIPsetIsLT(set, boundchg->newbound, var->locdom.ub) )
960 {
961 if( SCIPsetIsGE(set, boundchg->newbound, var->locdom.lb) )
962 {
963 /* add the bound change info to the variable's bound change info array */
964 switch( boundchg->boundchgtype )
965 {
967 SCIPsetDebugMsg(set, " -> branching: new upper bound of <%s>[%g,%g]: %g\n",
968 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
969 SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
971 stat->lastbranchvar = var;
973 stat->lastbranchvalue = boundchg->newbound;
974 break;
975
977 assert(boundchg->data.inferencedata.reason.cons != NULL);
978 SCIPsetDebugMsg(set, " -> constraint <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
979 SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
980 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
981 SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
982 boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
983 boundchg->data.inferencedata.info,
985 break;
986
988 SCIPsetDebugMsg(set, " -> propagator <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
989 boundchg->data.inferencedata.reason.prop != NULL
990 ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
991 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
992 SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
993 boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
994 boundchg->data.inferencedata.info,
996 break;
997
998 default:
999 SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
1000 return SCIP_INVALIDDATA;
1001 }
1002
1004 {
1005 assert( var->exactdata->locdom.ubcertificateidx != -1 || SCIPsetIsInfinity(set, var->locdom.ub) );
1006 var->ubchginfos[var->nubchginfos - 1].oldcertificateindex = var->exactdata->locdom.ubcertificateidx;
1008 }
1009
1010 /* change local bound of variable */
1011 SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, boundchg->newbound) );
1012 }
1013 else
1014 {
1015 SCIPsetDebugMsg(set, " -> cutoff: new upper bound of <%s>[%g,%g]: %g\n",
1016 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
1017 *cutoff = TRUE;
1018 boundchg->redundant = TRUE; /* bound change has not entered the ubchginfos array of the variable! */
1019 }
1020 }
1021 else
1022 {
1023 /* mark bound change to be inactive */
1024 SCIPsetDebugMsg(set, " -> inactive %s: new upper bound of <%s>[%g,%g]: %g\n",
1025 (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
1026 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
1027 boundchg->redundant = TRUE;
1028 }
1029 break;
1030
1031 default:
1032 SCIPerrorMessage("unknown bound type\n");
1033 return SCIP_INVALIDDATA;
1034 }
1035
1036 /* update the branching and inference history */
1037 if( !boundchg->applied && !boundchg->redundant )
1038 {
1039 assert(var == boundchg->var);
1040
1042 {
1043 SCIP_CALL( SCIPvarIncNBranchings(var, blkmem, set, stat,
1046 }
1047 else if( stat->lastbranchvar != NULL )
1048 {
1049 /**@todo if last branching variable is unknown, retrieve it from the nodes' boundchg arrays */
1050 SCIP_CALL( SCIPvarIncInferenceSum(stat->lastbranchvar, blkmem, set, stat, stat->lastbranchdir, stat->lastbranchvalue, 1.0) );
1051 }
1052 boundchg->applied = TRUE;
1053 }
1054
1055 return SCIP_OKAY;
1056}
1057
1058/** undoes single bound change */
1060 SCIP_BOUNDCHG* boundchg, /**< bound change to remove */
1061 BMS_BLKMEM* blkmem, /**< block memory */
1062 SCIP_SET* set, /**< global SCIP settings */
1063 SCIP_STAT* stat, /**< problem statistics */
1064 SCIP_LP* lp, /**< current LP data */
1065 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1066 SCIP_EVENTQUEUE* eventqueue /**< event queue */
1067 )
1068{
1069 SCIP_VAR* var;
1070
1071 assert(boundchg != NULL);
1072 assert(stat != NULL);
1073
1074 /* ignore redundant bound changes */
1075 if( boundchg->redundant )
1076 return SCIP_OKAY;
1077
1078 var = boundchg->var;
1079 assert(var != NULL);
1081
1082 /* undo bound change: apply the previous bound change of variable */
1083 switch( boundchg->boundtype )
1084 {
1086 var->nlbchginfos--;
1087 assert(var->nlbchginfos >= 0);
1088 assert(var->lbchginfos != NULL);
1089 assert( SCIPsetIsFeasEQ(set, var->lbchginfos[var->nlbchginfos].newbound, var->locdom.lb) ); /*lint !e777*/
1090 assert( SCIPsetIsFeasLE(set, boundchg->newbound, var->locdom.lb) ); /* current lb might be larger to intermediate global bound change */
1091
1092 SCIPsetDebugMsg(set, "removed lower bound change info of var <%s>[%g,%g]: depth=%d, pos=%d, %g -> %g\n",
1093 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub,
1094 var->lbchginfos[var->nlbchginfos].bdchgidx.depth, var->lbchginfos[var->nlbchginfos].bdchgidx.pos,
1095 var->lbchginfos[var->nlbchginfos].oldbound, var->lbchginfos[var->nlbchginfos].newbound);
1096
1097 /* in case certificate is used, set back the certificate line index */
1099 && !SCIPsetIsInfinity(set, -var->lbchginfos[var->nlbchginfos].oldbound) )
1100 {
1102 var->lbchginfos[var->nlbchginfos].oldcertificateindex) );
1103 }
1104
1105 if( set->exact_enable && !SCIPrationalIsFpRepresentable(SCIPvarGetLbGlobalExact(boundchg->var))
1106 && SCIPsetIsEQ(set, var->lbchginfos[var->nlbchginfos].oldbound, SCIPvarGetLbGlobal(boundchg->var) ) )
1107 {
1108 /* reinstall the exact global bound, if necessary */
1109 SCIP_CALL( SCIPvarChgLbLocalExact(boundchg->var, blkmem, set, stat, lp->lpexact, branchcand, eventqueue,
1110 SCIPvarGetLbGlobalExact(boundchg->var)) );
1111 }
1112 else
1113 {
1114 /* reinstall the previous local bound */
1115 SCIP_CALL( SCIPvarChgLbLocal(boundchg->var, blkmem, set, stat, lp, branchcand, eventqueue,
1116 var->lbchginfos[var->nlbchginfos].oldbound) );
1117 }
1118
1119 /* in case all bound changes are removed the local bound should match the global bound */
1120 assert(var->nlbchginfos > 0 || SCIPsetIsFeasEQ(set, var->locdom.lb, var->glbdom.lb));
1121
1122 break;
1123
1125 var->nubchginfos--;
1126 assert(var->nubchginfos >= 0);
1127 assert(var->ubchginfos != NULL);
1128 assert( SCIPsetIsFeasEQ(set, var->ubchginfos[var->nubchginfos].newbound, var->locdom.ub) ); /*lint !e777*/
1129 assert( SCIPsetIsFeasGE(set, boundchg->newbound, var->locdom.ub) ); /* current ub might be smaller to intermediate global bound change */
1130
1131 SCIPsetDebugMsg(set, "removed upper bound change info of var <%s>[%g,%g]: depth=%d, pos=%d, %g -> %g\n",
1132 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub,
1133 var->ubchginfos[var->nubchginfos].bdchgidx.depth, var->ubchginfos[var->nubchginfos].bdchgidx.pos,
1134 var->ubchginfos[var->nubchginfos].oldbound, var->ubchginfos[var->nubchginfos].newbound);
1135
1137 && !SCIPsetIsInfinity(set, var->ubchginfos[var->nubchginfos].oldbound) )
1138 {
1140 var->ubchginfos[var->nubchginfos].oldcertificateindex) );
1141 }
1142
1143 if( set->exact_enable && !SCIPrationalIsFpRepresentable(SCIPvarGetUbGlobalExact(boundchg->var))
1144 && SCIPsetIsEQ(set, var->ubchginfos[var->nubchginfos].oldbound, SCIPvarGetUbGlobal(boundchg->var) ) )
1145 {
1146 /* reinstall the exact global bound, if necessary */
1147 SCIP_CALL( SCIPvarChgUbLocalExact(boundchg->var, blkmem, set, stat, lp->lpexact, branchcand, eventqueue,
1148 SCIPvarGetUbGlobalExact(boundchg->var)) );
1149 }
1150 else
1151 {
1152 /* reinstall the previous local bound */
1153 SCIP_CALL( SCIPvarChgUbLocal(boundchg->var, blkmem, set, stat, lp, branchcand, eventqueue,
1154 var->ubchginfos[var->nubchginfos].oldbound) );
1155 }
1156
1157 /* in case all bound changes are removed the local bound should match the global bound */
1158 assert(var->nubchginfos > 0 || SCIPsetIsFeasEQ(set, var->locdom.ub, var->glbdom.ub));
1159
1160 /* in case certificate is used, set back the certificate line index */
1161
1162 break;
1163
1164 default:
1165 SCIPerrorMessage("unknown bound type\n");
1166 return SCIP_INVALIDDATA;
1167 }
1168
1169 /* update last branching variable */
1171 {
1172 stat->lastbranchvar = NULL;
1174 }
1175
1176 return SCIP_OKAY;
1177}
1178
1179/** applies single bound change to the global problem by changing the global bound of the corresponding variable */
1180static
1182 SCIP_BOUNDCHG* boundchg, /**< bound change to apply */
1183 BMS_BLKMEM* blkmem, /**< block memory */
1184 SCIP_SET* set, /**< global SCIP settings */
1185 SCIP_STAT* stat, /**< problem statistics */
1186 SCIP_LP* lp, /**< current LP data */
1187 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1188 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1189 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1190 SCIP_Bool* cutoff /**< pointer to store whether an infeasible bound change was detected */
1191 )
1192{
1193 SCIP_VAR* var;
1194 SCIP_Real newbound;
1195 SCIP_BOUNDTYPE boundtype;
1196
1197 assert(boundchg != NULL);
1198 assert(cutoff != NULL);
1199
1200 *cutoff = FALSE;
1201
1202 /* ignore redundant bound changes */
1203 if( boundchg->redundant )
1204 return SCIP_OKAY;
1205
1206 var = SCIPboundchgGetVar(boundchg);
1207 newbound = SCIPboundchgGetNewbound(boundchg);
1208 boundtype = SCIPboundchgGetBoundtype(boundchg);
1209
1210 /* check if the bound change is redundant which can happen due to a (better) global bound change which was performed
1211 * after that bound change was applied
1212 *
1213 * @note a global bound change is not captured by the redundant member of the bound change data structure
1214 */
1215 if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasLE(set, newbound, SCIPvarGetLbGlobal(var)))
1216 || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasGE(set, newbound, SCIPvarGetUbGlobal(var))) )
1217 {
1218 return SCIP_OKAY;
1219 }
1220
1221 SCIPsetDebugMsg(set, "applying global bound change: <%s>[%g,%g] %s %g\n",
1223 boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", newbound);
1224
1225 /* check for cutoff */
1226 if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGT(set, newbound, SCIPvarGetUbGlobal(var)))
1227 || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLT(set, newbound, SCIPvarGetLbGlobal(var))) )
1228 {
1229 *cutoff = TRUE;
1230 return SCIP_OKAY;
1231 }
1232
1233 if( SCIPisCertified(set->scip) )
1234 {
1235 if( boundtype == SCIP_BOUNDTYPE_LOWER )
1236 {
1237 var->exactdata->glbdom.lbcertificateidx = boundchg->certificateindex;
1238 var->exactdata->locdom.lbcertificateidx = boundchg->certificateindex;
1239 }
1240 else if( boundtype == SCIP_BOUNDTYPE_UPPER )
1241 {
1242 var->exactdata->glbdom.ubcertificateidx = boundchg->certificateindex;
1243 var->exactdata->locdom.ubcertificateidx = boundchg->certificateindex;
1244 }
1245#ifndef NDEBUG
1247#endif
1248 }
1249
1250 /* apply bound change */
1251 SCIP_CALL( SCIPvarChgBdGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound, boundtype) );
1252
1253 return SCIP_OKAY;
1254}
1255
1256/** captures branching and inference data of bound change */
1257static
1259 SCIP_BOUNDCHG* boundchg /**< bound change to remove */
1260 )
1261{
1262 assert(boundchg != NULL);
1263
1264 /* capture variable associated with the bound change */
1265 assert(boundchg->var != NULL);
1266 SCIPvarCapture(boundchg->var);
1267
1268 switch( boundchg->boundchgtype )
1269 {
1272 break;
1273
1275 assert(boundchg->data.inferencedata.var != NULL);
1276 assert(boundchg->data.inferencedata.reason.cons != NULL);
1277 SCIPconsCapture(boundchg->data.inferencedata.reason.cons);
1278 break;
1279
1280 default:
1281 SCIPerrorMessage("invalid bound change type\n");
1282 return SCIP_INVALIDDATA;
1283 }
1284
1285 return SCIP_OKAY;
1286}
1287
1288/** releases branching and inference data of bound change */
1289static
1291 SCIP_BOUNDCHG* boundchg, /**< bound change to remove */
1292 BMS_BLKMEM* blkmem, /**< block memory */
1293 SCIP_SET* set, /**< global SCIP settings */
1294 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1295 SCIP_LP* lp /**< current LP data */
1296
1297 )
1298{
1299 assert(boundchg != NULL);
1300
1301 switch( boundchg->boundchgtype )
1302 {
1305 break;
1306
1308 assert(boundchg->data.inferencedata.var != NULL);
1309 assert(boundchg->data.inferencedata.reason.cons != NULL);
1310 SCIP_CALL( SCIPconsRelease(&boundchg->data.inferencedata.reason.cons, blkmem, set) );
1311 break;
1312
1313 default:
1314 SCIPerrorMessage("invalid bound change type\n");
1315 return SCIP_INVALIDDATA;
1316 }
1317
1318 /* release variable */
1319 assert(boundchg->var != NULL);
1320 SCIP_CALL( SCIPvarRelease(&boundchg->var, blkmem, set, eventqueue, lp) );
1321
1322 return SCIP_OKAY;
1323}
1324
1325/** creates empty domain change data with dynamic arrays */
1326static
1328 SCIP_DOMCHG** domchg, /**< pointer to domain change data */
1329 BMS_BLKMEM* blkmem /**< block memory */
1330 )
1331{
1332 assert(domchg != NULL);
1333 assert(blkmem != NULL);
1334
1335 SCIP_ALLOC( BMSallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN)) );
1336 (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1337 (*domchg)->domchgdyn.nboundchgs = 0;
1338 (*domchg)->domchgdyn.boundchgs = NULL;
1339 (*domchg)->domchgdyn.nholechgs = 0;
1340 (*domchg)->domchgdyn.holechgs = NULL;
1341 (*domchg)->domchgdyn.boundchgssize = 0;
1342 (*domchg)->domchgdyn.holechgssize = 0;
1343
1344 return SCIP_OKAY;
1345}
1346
1347/** frees domain change data */
1349 SCIP_DOMCHG** domchg, /**< pointer to domain change */
1350 BMS_BLKMEM* blkmem, /**< block memory */
1351 SCIP_SET* set, /**< global SCIP settings */
1352 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1353 SCIP_LP* lp /**< current LP data */
1354 )
1355{
1356 assert(domchg != NULL);
1357 assert(blkmem != NULL);
1358
1359 if( *domchg != NULL )
1360 {
1361 int i;
1362
1363 /* release variables, branching and inference data associated with the bound changes */
1364 for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1365 {
1366 SCIP_CALL( boundchgReleaseData(&(*domchg)->domchgbound.boundchgs[i], blkmem, set, eventqueue, lp) );
1367 if( (*domchg)->domchgbound.boundchgs[i].newboundexact != NULL )
1368 SCIPrationalFreeBlock(blkmem, &(*domchg)->domchgbound.boundchgs[i].newboundexact);
1369 }
1370
1371 /* free memory for bound and hole changes */
1372 switch( (*domchg)->domchgdyn.domchgtype )
1373 {
1375 BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgbound.boundchgs, (*domchg)->domchgbound.nboundchgs);
1376 BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOUND));
1377 break;
1379 BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgboth.boundchgs, (*domchg)->domchgboth.nboundchgs);
1380 BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgboth.holechgs, (*domchg)->domchgboth.nholechgs);
1381 BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH));
1382 break;
1384 BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.boundchgs, (*domchg)->domchgdyn.boundchgssize);
1385 BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.holechgs, (*domchg)->domchgdyn.holechgssize);
1386 BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN));
1387 break;
1388 default:
1389 SCIPerrorMessage("invalid domain change type\n");
1390 return SCIP_INVALIDDATA;
1391 }
1392 }
1393
1394 return SCIP_OKAY;
1395}
1396
1397/** converts a static domain change data into a dynamic one */
1398static
1400 SCIP_DOMCHG** domchg, /**< pointer to domain change data */
1401 BMS_BLKMEM* blkmem /**< block memory */
1402 )
1403{
1404 assert(domchg != NULL);
1405 assert(blkmem != NULL);
1406
1407 SCIPdebugMessage("making domain change data %p pointing to %p dynamic\n", (void*)domchg, (void*)*domchg);
1408
1409 if( *domchg == NULL )
1410 {
1411 SCIP_CALL( domchgCreate(domchg, blkmem) );
1412 }
1413 else
1414 {
1415 switch( (*domchg)->domchgdyn.domchgtype )
1416 {
1418 SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOUND), sizeof(SCIP_DOMCHGDYN)) );
1419 (*domchg)->domchgdyn.nholechgs = 0;
1420 (*domchg)->domchgdyn.holechgs = NULL;
1421 (*domchg)->domchgdyn.boundchgssize = (int) (*domchg)->domchgdyn.nboundchgs;
1422 (*domchg)->domchgdyn.holechgssize = 0;
1423 (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1424 break;
1426 SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH), sizeof(SCIP_DOMCHGDYN)) );
1427 (*domchg)->domchgdyn.boundchgssize = (int) (*domchg)->domchgdyn.nboundchgs;
1428 (*domchg)->domchgdyn.holechgssize = (*domchg)->domchgdyn.nholechgs;
1429 (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1430 break;
1432 break;
1433 default:
1434 SCIPerrorMessage("invalid domain change type\n");
1435 return SCIP_INVALIDDATA;
1436 }
1437 }
1438#ifndef NDEBUG
1439 {
1440 int i;
1441 for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1442 assert(!SCIPvarIsIntegral((*domchg)->domchgbound.boundchgs[i].var)
1443 || EPSISINT((*domchg)->domchgbound.boundchgs[i].newbound, 1e-06));
1444 }
1445#endif
1446
1447 return SCIP_OKAY;
1448}
1449
1450/** converts a dynamic domain change data into a static one, using less memory than for a dynamic one */
1452 SCIP_DOMCHG** domchg, /**< pointer to domain change data */
1453 BMS_BLKMEM* blkmem, /**< block memory */
1454 SCIP_SET* set, /**< global SCIP settings */
1455 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1456 SCIP_LP* lp /**< current LP data */
1457 )
1458{
1459 assert(domchg != NULL);
1460 assert(blkmem != NULL);
1461
1462 SCIPsetDebugMsg(set, "making domain change data %p pointing to %p static\n", (void*)domchg, (void*)*domchg);
1463
1464 if( *domchg != NULL )
1465 {
1466 switch( (*domchg)->domchgdyn.domchgtype )
1467 {
1469 if( (*domchg)->domchgbound.nboundchgs == 0 )
1470 {
1471 SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1472 }
1473 break;
1475 if( (*domchg)->domchgboth.nholechgs == 0 )
1476 {
1477 if( (*domchg)->domchgbound.nboundchgs == 0 )
1478 {
1479 SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1480 }
1481 else
1482 {
1483 SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH), sizeof(SCIP_DOMCHGBOUND)) );
1484 (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOUND; /*lint !e641*/
1485 }
1486 }
1487 break;
1489 if( (*domchg)->domchgboth.nholechgs == 0 )
1490 {
1491 if( (*domchg)->domchgbound.nboundchgs == 0 )
1492 {
1493 SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1494 }
1495 else
1496 {
1497 /* shrink dynamic size arrays to their minimal sizes */
1498 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.boundchgs, \
1499 (*domchg)->domchgdyn.boundchgssize, (*domchg)->domchgdyn.nboundchgs) ); /*lint !e571*/
1500 BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.holechgs, (*domchg)->domchgdyn.holechgssize);
1501
1502 /* convert into static domain change */
1503 SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN), sizeof(SCIP_DOMCHGBOUND)) );
1504 (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOUND; /*lint !e641*/
1505 }
1506 }
1507 else
1508 {
1509 /* shrink dynamic size arrays to their minimal sizes */
1510 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.boundchgs, \
1511 (*domchg)->domchgdyn.boundchgssize, (*domchg)->domchgdyn.nboundchgs) ); /*lint !e571*/
1512 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.holechgs, \
1513 (*domchg)->domchgdyn.holechgssize, (*domchg)->domchgdyn.nholechgs) );
1514
1515 /* convert into static domain change */
1516 SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN), sizeof(SCIP_DOMCHGBOTH)) );
1517 (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOTH; /*lint !e641*/
1518 }
1519 break;
1520 default:
1521 SCIPerrorMessage("invalid domain change type\n");
1522 return SCIP_INVALIDDATA;
1523 }
1524#ifndef NDEBUG
1525 if( *domchg != NULL )
1526 {
1527 int i;
1528 for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1529 assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1530 || SCIPsetIsFeasIntegral(set, (*domchg)->domchgbound.boundchgs[i].newbound));
1531 }
1532#endif
1533 }
1534
1535 return SCIP_OKAY;
1536}
1537
1538/** ensures, that boundchgs array can store at least num entries */
1539static
1541 SCIP_DOMCHG* domchg, /**< domain change data structure */
1542 BMS_BLKMEM* blkmem, /**< block memory */
1543 SCIP_SET* set, /**< global SCIP settings */
1544 int num /**< minimum number of entries to store */
1545 )
1546{
1547 assert(domchg != NULL);
1548 assert(domchg->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1549
1550 if( num > domchg->domchgdyn.boundchgssize )
1551 {
1552 int newsize;
1553
1554 newsize = SCIPsetCalcMemGrowSize(set, num);
1555 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &domchg->domchgdyn.boundchgs, domchg->domchgdyn.boundchgssize, newsize) );
1556 for( int i = domchg->domchgdyn.boundchgssize; i < newsize; ++i)
1558 domchg->domchgdyn.boundchgssize = newsize;
1559 }
1560 assert(num <= domchg->domchgdyn.boundchgssize);
1561
1562 return SCIP_OKAY;
1563}
1564
1565/** ensures, that holechgs array can store at least num additional entries */
1566static
1568 SCIP_DOMCHG* domchg, /**< domain change data structure */
1569 BMS_BLKMEM* blkmem, /**< block memory */
1570 SCIP_SET* set, /**< global SCIP settings */
1571 int num /**< minimum number of additional entries to store */
1572 )
1573{
1574 assert(domchg != NULL);
1575 assert(domchg->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1576
1577 if( num > domchg->domchgdyn.holechgssize )
1578 {
1579 int newsize;
1580
1581 newsize = SCIPsetCalcMemGrowSize(set, num);
1582 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &domchg->domchgdyn.holechgs, domchg->domchgdyn.holechgssize, newsize) );
1583 domchg->domchgdyn.holechgssize = newsize;
1584 }
1585 assert(num <= domchg->domchgdyn.holechgssize);
1586
1587 return SCIP_OKAY;
1588}
1589
1590/** applies domain change */
1592 SCIP_DOMCHG* domchg, /**< domain change to apply */
1593 BMS_BLKMEM* blkmem, /**< block memory */
1594 SCIP_SET* set, /**< global SCIP settings */
1595 SCIP_STAT* stat, /**< problem statistics */
1596 SCIP_LP* lp, /**< current LP data */
1597 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1598 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1599 int depth, /**< depth in the tree, where the domain change takes place */
1600 SCIP_Bool* cutoff /**< pointer to store whether an infeasible domain change was detected */
1601 )
1602{
1603 int i;
1604
1605 assert(cutoff != NULL);
1606
1607 *cutoff = FALSE;
1608
1609 SCIPsetDebugMsg(set, "applying domain changes at %p in depth %d\n", (void*)domchg, depth);
1610
1611 if( domchg == NULL )
1612 return SCIP_OKAY;
1613
1614 /* apply bound changes */
1615 for( i = 0; i < (int)domchg->domchgbound.nboundchgs; ++i )
1616 {
1617 SCIP_CALL( SCIPboundchgApply(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp,
1618 branchcand, eventqueue, depth, i, cutoff) );
1619 if( *cutoff )
1620 break;
1621 }
1622 SCIPsetDebugMsg(set, " -> %u bound changes (cutoff %u)\n", domchg->domchgbound.nboundchgs, *cutoff);
1623
1624 /* mark all bound changes after a cutoff redundant */
1625 for( ; i < (int)domchg->domchgbound.nboundchgs; ++i )
1627
1628 /* apply holelist changes */
1629 if( domchg->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_BOUND ) /*lint !e641*/
1630 {
1631 for( i = 0; i < domchg->domchgboth.nholechgs; ++i )
1632 *(domchg->domchgboth.holechgs[i].ptr) = domchg->domchgboth.holechgs[i].newlist;
1633 SCIPsetDebugMsg(set, " -> %d hole changes\n", domchg->domchgboth.nholechgs);
1634 }
1635
1636 return SCIP_OKAY;
1637}
1638
1639/** undoes domain change */
1641 SCIP_DOMCHG* domchg, /**< domain change to remove */
1642 BMS_BLKMEM* blkmem, /**< block memory */
1643 SCIP_SET* set, /**< global SCIP settings */
1644 SCIP_STAT* stat, /**< problem statistics */
1645 SCIP_LP* lp, /**< current LP data */
1646 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1647 SCIP_EVENTQUEUE* eventqueue /**< event queue */
1648 )
1649{
1650 int i;
1651
1652 SCIPsetDebugMsg(set, "undoing domain changes at %p\n", (void*)domchg);
1653 if( domchg == NULL )
1654 return SCIP_OKAY;
1655
1656 /* undo holelist changes */
1657 if( domchg->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_BOUND ) /*lint !e641*/
1658 {
1659 for( i = domchg->domchgboth.nholechgs-1; i >= 0; --i )
1660 *(domchg->domchgboth.holechgs[i].ptr) = domchg->domchgboth.holechgs[i].oldlist;
1661 SCIPsetDebugMsg(set, " -> %d hole changes\n", domchg->domchgboth.nholechgs);
1662 }
1663
1664 /* undo bound changes */
1665 for( i = domchg->domchgbound.nboundchgs-1; i >= 0; --i )
1666 {
1667 SCIP_CALL( SCIPboundchgUndo(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp, branchcand, eventqueue) );
1668 }
1669 SCIPsetDebugMsg(set, " -> %u bound changes\n", domchg->domchgbound.nboundchgs);
1670
1671 return SCIP_OKAY;
1672}
1673
1674/** applies domain change to the global problem */
1676 SCIP_DOMCHG* domchg, /**< domain change to apply */
1677 BMS_BLKMEM* blkmem, /**< block memory */
1678 SCIP_SET* set, /**< global SCIP settings */
1679 SCIP_STAT* stat, /**< problem statistics */
1680 SCIP_LP* lp, /**< current LP data */
1681 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1682 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1683 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1684 SCIP_Bool* cutoff /**< pointer to store whether an infeasible domain change was detected */
1685 )
1686{
1687 int i;
1688
1689 assert(cutoff != NULL);
1690
1691 *cutoff = FALSE;
1692
1693 if( domchg == NULL )
1694 return SCIP_OKAY;
1695
1696 SCIPsetDebugMsg(set, "applying domain changes at %p to the global problem\n", (void*)domchg);
1697
1698 /* apply bound changes */
1699 for( i = 0; i < (int)domchg->domchgbound.nboundchgs; ++i )
1700 {
1701 SCIP_CALL( boundchgApplyGlobal(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp,
1702 branchcand, eventqueue, cliquetable, cutoff) );
1703 if( *cutoff )
1704 break;
1705 }
1706 SCIPsetDebugMsg(set, " -> %u global bound changes\n", domchg->domchgbound.nboundchgs);
1707
1708 /**@todo globally apply holelist changes - how can this be done without confusing pointer updates? */
1709
1710 return SCIP_OKAY;
1711}
1712
1713/** adds certificate line number to domain changes */
1715 SCIP_DOMCHG* domchg, /**< pointer to domain change data structure */
1716 SCIP_CERTIFICATE* certificate /**< certificate information */
1717 )
1718{
1719 SCIP_BOUNDCHG* change;
1720
1721 if( !SCIPcertificateIsEnabled(certificate) )
1722 return;
1723
1724 change = &(domchg->domchgdyn.boundchgs[domchg->domchgdyn.nboundchgs - 1]);
1725
1726 #ifndef NDEBUG
1728 #endif
1729
1730 change->certificateindex = SCIPcertificateGetCurrentIndex(certificate) - 1;
1731}
1732
1733/** adds bound change to domain changes */
1735 SCIP_DOMCHG** domchg, /**< pointer to domain change data structure */
1736 BMS_BLKMEM* blkmem, /**< block memory */
1737 SCIP_SET* set, /**< global SCIP settings */
1738 SCIP_VAR* var, /**< variable to change the bounds for */
1739 SCIP_Real newbound, /**< new value for bound */
1740 SCIP_RATIONAL* newboundexact, /**< new value for exact bound, or NULL if not needed */
1741 SCIP_BOUNDTYPE boundtype, /**< type of bound for var: lower or upper bound */
1742 SCIP_BOUNDCHGTYPE boundchgtype, /**< type of bound change: branching decision or inference */
1743 SCIP_Real lpsolval, /**< solval of variable in last LP on path to node, or SCIP_INVALID if unknown */
1744 SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself), or NULL */
1745 SCIP_CONS* infercons, /**< constraint that deduced the bound change, or NULL */
1746 SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
1747 int inferinfo, /**< user information for inference to help resolving the conflict */
1748 SCIP_BOUNDTYPE inferboundtype /**< type of bound for inference var: lower or upper bound */
1749 )
1750{
1751 SCIP_BOUNDCHG* boundchg;
1752
1753 assert(domchg != NULL);
1754 assert(var != NULL);
1756 assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, boundtype == SCIP_BOUNDTYPE_LOWER ? 1.0 : 0.0));
1758 assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
1759 assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
1760 assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
1761
1762 SCIPsetDebugMsg(set, "adding %s bound change <%s: %g> of variable <%s> to domain change at %p pointing to %p\n",
1763 boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
1764 newbound, var->name, (void*)domchg, (void*)*domchg);
1765
1766 /* if domain change data doesn't exist, create it;
1767 * if domain change is static, convert it into dynamic change
1768 */
1769 if( *domchg == NULL )
1770 {
1771 SCIP_CALL( domchgCreate(domchg, blkmem) );
1772 }
1773 else if( (*domchg)->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_DYNAMIC ) /*lint !e641*/
1774 {
1775 SCIP_CALL( domchgMakeDynamic(domchg, blkmem) );
1776 }
1777 assert(*domchg != NULL && (*domchg)->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1778
1779 /* get memory for additional bound change */
1780 SCIP_CALL( domchgEnsureBoundchgsSize(*domchg, blkmem, set, (*domchg)->domchgdyn.nboundchgs+1) );
1781
1782 /* fill in the bound change data */
1783 boundchg = &(*domchg)->domchgdyn.boundchgs[(*domchg)->domchgdyn.nboundchgs];
1784 boundchg->var = var;
1785 switch( boundchgtype )
1786 {
1788 boundchg->data.branchingdata.lpsolval = lpsolval;
1789 break;
1791 assert(infercons != NULL);
1792 boundchg->data.inferencedata.var = infervar;
1793 boundchg->data.inferencedata.reason.cons = infercons;
1794 boundchg->data.inferencedata.info = inferinfo;
1795 break;
1797 boundchg->data.inferencedata.var = infervar;
1798 boundchg->data.inferencedata.reason.prop = inferprop;
1799 boundchg->data.inferencedata.info = inferinfo;
1800 break;
1801 default:
1802 SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
1803 return SCIP_INVALIDDATA;
1804 }
1805
1806 boundchg->newbound = newbound;
1807 boundchg->boundchgtype = boundchgtype; /*lint !e641*/
1808 boundchg->boundtype = boundtype; /*lint !e641*/
1809 boundchg->inferboundtype = inferboundtype; /*lint !e641*/
1810 boundchg->applied = FALSE;
1811 boundchg->redundant = FALSE;
1812 (*domchg)->domchgdyn.nboundchgs++;
1813 if( newboundexact != NULL )
1814 {
1815 if( boundchg->newboundexact == NULL )
1816 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &boundchg->newboundexact, newboundexact) );
1817 else
1818 SCIPrationalSetRational(boundchg->newboundexact, newboundexact);
1819 }
1820
1821 /* capture branching and inference data associated with the bound changes */
1822 SCIP_CALL( boundchgCaptureData(boundchg) );
1823
1824#ifdef SCIP_DISABLED_CODE /* expensive debug check */
1825#ifdef SCIP_MORE_DEBUG
1826 {
1827 int i;
1828 for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1829 assert(!SCIPvarIsIntegral((*domchg)->domchgbound.boundchgs[i].var)
1830 || SCIPsetIsFeasIntegral(set, (*domchg)->domchgbound.boundchgs[i].newbound));
1831 }
1832#endif
1833#endif
1834
1835 return SCIP_OKAY;
1836}
1837
1838/** adds hole change to domain changes */
1840 SCIP_DOMCHG** domchg, /**< pointer to domain change data structure */
1841 BMS_BLKMEM* blkmem, /**< block memory */
1842 SCIP_SET* set, /**< global SCIP settings */
1843 SCIP_HOLELIST** ptr, /**< changed list pointer */
1844 SCIP_HOLELIST* newlist, /**< new value of list pointer */
1845 SCIP_HOLELIST* oldlist /**< old value of list pointer */
1846 )
1847{
1848 SCIP_HOLECHG* holechg;
1849
1850 assert(domchg != NULL);
1851 assert(ptr != NULL);
1852
1853 /* if domain change data doesn't exist, create it;
1854 * if domain change is static, convert it into dynamic change
1855 */
1856 if( *domchg == NULL )
1857 {
1858 SCIP_CALL( domchgCreate(domchg, blkmem) );
1859 }
1860 else if( (*domchg)->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_DYNAMIC ) /*lint !e641*/
1861 {
1862 SCIP_CALL( domchgMakeDynamic(domchg, blkmem) );
1863 }
1864 assert(*domchg != NULL && (*domchg)->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1865
1866 /* get memory for additional hole change */
1867 SCIP_CALL( domchgEnsureHolechgsSize(*domchg, blkmem, set, (*domchg)->domchgdyn.nholechgs+1) );
1868
1869 /* fill in the hole change data */
1870 holechg = &(*domchg)->domchgdyn.holechgs[(*domchg)->domchgdyn.nholechgs];
1871 holechg->ptr = ptr;
1872 holechg->newlist = newlist;
1873 holechg->oldlist = oldlist;
1874 (*domchg)->domchgdyn.nholechgs++;
1875
1876 return SCIP_OKAY;
1877}
1878
1879
1880
1881
1882/*
1883 * methods for variables
1884 */
1885
1886/** returns adjusted lower bound value, which is rounded for integral variable types */
1887static
1889 SCIP_SET* set, /**< global SCIP settings */
1890 SCIP_Bool isintegral, /**< is variable integral? */
1891 SCIP_Real lb /**< lower bound to adjust */
1892 )
1893{
1894 if( lb < 0.0 && SCIPsetIsInfinity(set, -lb) )
1895 return -SCIPsetInfinity(set);
1896 else if( lb > 0.0 && SCIPsetIsInfinity(set, lb) )
1897 return SCIPsetInfinity(set);
1898 else if( isintegral )
1899 return SCIPsetFeasCeil(set, lb);
1900 else if( lb > 0.0 && lb < SCIPsetEpsilon(set) )
1901 return 0.0;
1902 else
1903 return lb;
1904}
1905
1906/** returns adjusted lower bound value, which is rounded for integral variable types */
1907static
1909 SCIP_Bool isintegral, /**< is variable integral? */
1910 SCIP_Real lb /**< lower bound to adjust */
1911 )
1912{
1913 if( isintegral )
1914 return ceil(lb);
1915 else
1916 return lb;
1917}
1918
1919/** returns adjusted lower bound value, which is rounded for integral variable types */
1920static
1922 SCIP_SET* set, /**< global SCIP settings */
1923 SCIP_Bool isintegral, /**< is variable integral? */
1924 SCIP_RATIONAL* lb /**< lower bound to adjust */
1925 )
1926{
1931 else if( isintegral )
1933}
1934
1935/** returns adjusted upper bound value, which is rounded for integral variable types */
1936static
1938 SCIP_SET* set, /**< global SCIP settings */
1939 SCIP_Bool isintegral, /**< is variable integral? */
1940 SCIP_Real ub /**< upper bound to adjust */
1941 )
1942{
1943 if( ub > 0.0 && SCIPsetIsInfinity(set, ub) )
1944 return SCIPsetInfinity(set);
1945 else if( ub < 0.0 && SCIPsetIsInfinity(set, -ub) )
1946 return -SCIPsetInfinity(set);
1947 else if( isintegral )
1948 return SCIPsetFeasFloor(set, ub);
1949 else if( ub < 0.0 && ub > -SCIPsetEpsilon(set) )
1950 return 0.0;
1951 else
1952 return ub;
1953}
1954
1955/** returns adjusted upperbound value, which is rounded for integral variable types */
1956static
1958 SCIP_Bool isintegral, /**< is variable integral? */
1959 SCIP_Real lb /**< lower bound to adjust */
1960 )
1961{
1962 if( isintegral )
1963 return floor(lb);
1964 else
1965 return lb;
1966}
1967
1968/** returns adjusted lower bound value, which is rounded for integral variable types */
1969static
1971 SCIP_SET* set, /**< global SCIP settings */
1972 SCIP_Bool isintegral, /**< is variable integral? */
1973 SCIP_RATIONAL* ub /**< lower bound to adjust */
1974 )
1975{
1980 else if( isintegral )
1982}
1983
1984/** writes the approximate exact multi-aggregate data in the floating-point structs */
1985static
1987 SCIP_SET* set, /**< global SCIP settings */
1988 SCIP_VAR* var /**< SCIP variable */
1989 )
1990{
1991 int i;
1992
1993 if( !set->exact_enable || SCIPvarGetStatus(var) != SCIP_VARSTATUS_MULTAGGR )
1994 return;
1995
1996 var->data.multaggr.constant = SCIPrationalGetReal(var->exactdata->multaggr.constant);
1997 for( i = 0; i < var->data.multaggr.nvars; i++ )
1998 {
1999 var->data.multaggr.scalars[i] = SCIPrationalGetReal(var->exactdata->multaggr.scalars[i]);
2000 }
2001}
2002
2003/** removes (redundant) cliques, implications and variable bounds of variable from all other variables' implications and variable
2004 * bounds arrays, and optionally removes them also from the variable itself
2005 */
2007 SCIP_VAR* var, /**< problem variable */
2008 BMS_BLKMEM* blkmem, /**< block memory */
2009 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
2010 SCIP_SET* set, /**< global SCIP settings */
2011 SCIP_Bool irrelevantvar, /**< has the variable become irrelevant? */
2012 SCIP_Bool onlyredundant, /**< should only the redundant implications and variable bounds be removed? */
2013 SCIP_Bool removefromvar /**< should the implications and variable bounds be removed from the var itself? */
2014 )
2015{
2016 SCIP_Real lb;
2017 SCIP_Real ub;
2018
2019 assert(var != NULL);
2022
2023 lb = SCIPvarGetLbGlobal(var);
2024 ub = SCIPvarGetUbGlobal(var);
2025
2026 SCIPsetDebugMsg(set, "removing %s implications and vbounds of %s<%s>[%g,%g]\n",
2027 onlyredundant ? "redundant" : "all", irrelevantvar ? "irrelevant " : "", SCIPvarGetName(var), lb, ub);
2028
2029 /* remove implications of (fixed) binary variable */
2030 if( var->implics != NULL && (!onlyredundant || lb > 0.5 || ub < 0.5) )
2031 {
2032 SCIP_Bool varfixing;
2033
2035
2036 varfixing = FALSE;
2037 do
2038 {
2039 SCIP_VAR** implvars;
2040 SCIP_BOUNDTYPE* impltypes;
2041 int nimpls;
2042 int i;
2043
2044 nimpls = SCIPimplicsGetNImpls(var->implics, varfixing);
2045 implvars = SCIPimplicsGetVars(var->implics, varfixing);
2046 impltypes = SCIPimplicsGetTypes(var->implics, varfixing);
2047
2048 for( i = 0; i < nimpls; i++ )
2049 {
2050 SCIP_VAR* implvar;
2051 SCIP_BOUNDTYPE impltype;
2052
2053 implvar = implvars[i];
2054 impltype = impltypes[i];
2055 assert(implvar != var);
2056
2057 /* remove for all implications z == 0 / 1 ==> x <= p / x >= p (x not binary)
2058 * the following variable bound from x's variable bounds
2059 * x <= b*z+d (z in vubs of x) , for z == 0 / 1 ==> x <= p
2060 * x >= b*z+d (z in vlbs of x) , for z == 0 / 1 ==> x >= p
2061 */
2062 if( impltype == SCIP_BOUNDTYPE_UPPER )
2063 {
2064 if( implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
2065 {
2066 SCIPsetDebugMsg(set, "deleting variable bound: <%s> == %u ==> <%s> <= %g\n",
2067 SCIPvarGetName(var), varfixing, SCIPvarGetName(implvar),
2068 SCIPimplicsGetBounds(var->implics, varfixing)[i]);
2069 SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, varfixing) );
2070 implvar->closestvblpcount = -1;
2071 var->closestvblpcount = -1;
2072 }
2073 }
2074 else
2075 {
2076 if( implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
2077 {
2078 SCIPsetDebugMsg(set, "deleting variable bound: <%s> == %u ==> <%s> >= %g\n",
2079 SCIPvarGetName(var), varfixing, SCIPvarGetName(implvar),
2080 SCIPimplicsGetBounds(var->implics, varfixing)[i]);
2081 SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, !varfixing) );
2082 implvar->closestvblpcount = -1;
2083 var->closestvblpcount = -1;
2084 }
2085 }
2086 }
2087 varfixing = !varfixing;
2088 }
2089 while( varfixing == TRUE );
2090
2091 if( removefromvar )
2092 {
2093 /* free the implications data structures */
2094 SCIPimplicsFree(&var->implics, blkmem);
2095 }
2096 }
2097
2098 /* remove the (redundant) variable lower bounds */
2099 if( var->vlbs != NULL )
2100 {
2101 SCIP_VAR** vars;
2102 SCIP_Real* coefs;
2103 SCIP_Real* constants;
2104 int nvbds;
2105 int newnvbds;
2106 int i;
2107
2108 nvbds = SCIPvboundsGetNVbds(var->vlbs);
2109 vars = SCIPvboundsGetVars(var->vlbs);
2110 coefs = SCIPvboundsGetCoefs(var->vlbs);
2111 constants = SCIPvboundsGetConstants(var->vlbs);
2112
2113 /* remove for all variable bounds x >= b*z+d the following implication from z's implications
2114 * z == ub ==> x >= b*ub + d , if b > 0
2115 * z == lb ==> x >= b*lb + d , if b < 0
2116 */
2117 newnvbds = 0;
2118 for( i = 0; i < nvbds; i++ )
2119 {
2120 SCIP_VAR* implvar;
2121 SCIP_Real coef;
2122
2123 assert(newnvbds <= i);
2124
2125 implvar = vars[i];
2126 assert(implvar != NULL);
2127
2128 coef = coefs[i];
2129 assert(!SCIPsetIsZero(set, coef));
2130
2131 /* check, if we want to remove the variable bound */
2132 if( onlyredundant )
2133 {
2134 SCIP_Real vbound;
2135
2136 vbound = MAX(coef * SCIPvarGetUbGlobal(implvar), coef * SCIPvarGetLbGlobal(implvar)) + constants[i]; /*lint !e666*/
2137 if( SCIPsetIsFeasGT(set, vbound, lb) )
2138 {
2139 /* the variable bound is not redundant: keep it */
2140 if( removefromvar )
2141 {
2142 if( newnvbds < i )
2143 {
2144 vars[newnvbds] = implvar;
2145 coefs[newnvbds] = coef;
2146 constants[newnvbds] = constants[i];
2147 }
2148 newnvbds++;
2149 }
2150 continue;
2151 }
2152 }
2153
2154 /* remove the corresponding implication */
2155 if( implvar->implics != NULL ) /* variable may have been aggregated in the mean time */
2156 {
2157 SCIPsetDebugMsg(set, "deleting implication: <%s> == %d ==> <%s> >= %g\n",
2158 SCIPvarGetName(implvar), (coef > 0.0), SCIPvarGetName(var), MAX(coef, 0.0) + constants[i]);
2159 SCIP_CALL( SCIPimplicsDel(&implvar->implics, blkmem, set, (coef > 0.0), var, SCIP_BOUNDTYPE_LOWER) );
2160 }
2161 if( coef > 0.0 && implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
2162 {
2163 SCIPsetDebugMsg(set, "deleting variable upper bound from <%s> involving variable %s\n",
2164 SCIPvarGetName(implvar), SCIPvarGetName(var));
2165 SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, FALSE) );
2166 implvar->closestvblpcount = -1;
2167 var->closestvblpcount = -1;
2168 }
2169 else if( coef < 0.0 && implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
2170 {
2171 SCIPsetDebugMsg(set, "deleting variable lower bound from <%s> involving variable %s\n",
2172 SCIPvarGetName(implvar), SCIPvarGetName(var));
2173 SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, TRUE) );
2174 implvar->closestvblpcount = -1;
2175 var->closestvblpcount = -1;
2176 }
2177 }
2178
2179 if( removefromvar )
2180 {
2181 /* update the number of variable bounds */
2182 SCIPvboundsShrink(&var->vlbs, blkmem, newnvbds);
2183 var->closestvblpcount = -1;
2184 }
2185 }
2186
2187 /**@todo in general, variable bounds like x >= b*z + d corresponding to an implication like z = ub ==> x >= b*ub + d
2188 * might be missing because we only add variable bounds with reasonably small value of b. thus, we currently
2189 * cannot remove such variables x from z's implications.
2190 */
2191
2192 /* remove the (redundant) variable upper bounds */
2193 if( var->vubs != NULL )
2194 {
2195 SCIP_VAR** vars;
2196 SCIP_Real* coefs;
2197 SCIP_Real* constants;
2198 int nvbds;
2199 int newnvbds;
2200 int i;
2201
2202 nvbds = SCIPvboundsGetNVbds(var->vubs);
2203 vars = SCIPvboundsGetVars(var->vubs);
2204 coefs = SCIPvboundsGetCoefs(var->vubs);
2205 constants = SCIPvboundsGetConstants(var->vubs);
2206
2207 /* remove for all variable bounds x <= b*z+d the following implication from z's implications
2208 * z == lb ==> x <= b*lb + d , if b > 0
2209 * z == ub ==> x <= b*ub + d , if b < 0
2210 */
2211 newnvbds = 0;
2212 for( i = 0; i < nvbds; i++ )
2213 {
2214 SCIP_VAR* implvar;
2215 SCIP_Real coef;
2216
2217 assert(newnvbds <= i);
2218
2219 implvar = vars[i];
2220 assert(implvar != NULL);
2221
2222 coef = coefs[i];
2223 assert(!SCIPsetIsZero(set, coef));
2224
2225 /* check, if we want to remove the variable bound */
2226 if( onlyredundant )
2227 {
2228 SCIP_Real vbound;
2229
2230 vbound = MIN(coef * SCIPvarGetUbGlobal(implvar), coef * SCIPvarGetLbGlobal(implvar)) + constants[i]; /*lint !e666*/
2231 if( SCIPsetIsFeasLT(set, vbound, ub) )
2232 {
2233 /* the variable bound is not redundant: keep it */
2234 if( removefromvar )
2235 {
2236 if( newnvbds < i )
2237 {
2238 vars[newnvbds] = implvar;
2239 coefs[newnvbds] = coefs[i];
2240 constants[newnvbds] = constants[i];
2241 }
2242 newnvbds++;
2243 }
2244 continue;
2245 }
2246 }
2247
2248 /* remove the corresponding implication */
2249 if( implvar->implics != NULL ) /* variable may have been aggregated in the mean time */
2250 {
2251 SCIPsetDebugMsg(set, "deleting implication: <%s> == %d ==> <%s> <= %g\n",
2252 SCIPvarGetName(implvar), (coef < 0.0), SCIPvarGetName(var), MIN(coef, 0.0) + constants[i]);
2253 SCIP_CALL( SCIPimplicsDel(&implvar->implics, blkmem, set, (coef < 0.0), var, SCIP_BOUNDTYPE_UPPER) );
2254 }
2255 if( coef < 0.0 && implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
2256 {
2257 SCIPsetDebugMsg(set, "deleting variable upper bound from <%s> involving variable %s\n",
2258 SCIPvarGetName(implvar), SCIPvarGetName(var));
2259 SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, TRUE) );
2260 implvar->closestvblpcount = -1;
2261 var->closestvblpcount = -1;
2262 }
2263 else if( coef > 0.0 && implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
2264 {
2265 SCIPsetDebugMsg(set, "deleting variable lower bound from <%s> involving variable %s\n",
2266 SCIPvarGetName(implvar), SCIPvarGetName(var));
2267 SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, FALSE) );
2268 implvar->closestvblpcount = -1;
2269 var->closestvblpcount = -1;
2270 }
2271 }
2272
2273 if( removefromvar )
2274 {
2275 /* update the number of variable bounds */
2276 SCIPvboundsShrink(&var->vubs, blkmem, newnvbds);
2277 var->closestvblpcount = -1;
2278 }
2279 }
2280
2281 /* remove the variable from all cliques */
2282 if( SCIPvarIsBinary(var) )
2283 SCIPcliquelistRemoveFromCliques(var->cliquelist, cliquetable, var, irrelevantvar);
2284
2285 /**@todo variable bounds like x <= b*z + d with z general integer are not removed from x's vbd arrays, because
2286 * z has no link (like in the binary case) to x
2287 */
2288
2289 return SCIP_OKAY;
2290}
2291
2292/** sets the variable name */
2293static
2295 SCIP_VAR* var, /**< problem variable */
2296 BMS_BLKMEM* blkmem, /**< block memory */
2297 SCIP_STAT* stat, /**< problem statistics, or NULL */
2298 const char* name /**< name of variable, or NULL for automatic name creation */
2299 )
2300{
2301 assert(blkmem != NULL);
2302 assert(var != NULL);
2303
2304 if( name == NULL )
2305 {
2306 char s[SCIP_MAXSTRLEN];
2307
2308 assert(stat != NULL);
2309
2310 (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "_var%d_", stat->nvaridx);
2311 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->name, s, strlen(s)+1) );
2312 }
2313 else
2314 {
2315 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->name, name, strlen(name)+1) );
2316 }
2317
2318 return SCIP_OKAY;
2319}
2320
2321/** creates variable; if variable is of integral type, fractional bounds are automatically rounded; an integer variable
2322 * with bounds zero and one is automatically converted into a binary variable
2323 */
2324static
2326 SCIP_VAR** var, /**< pointer to variable data */
2327 BMS_BLKMEM* blkmem, /**< block memory */
2328 SCIP_SET* set, /**< global SCIP settings */
2329 SCIP_STAT* stat, /**< problem statistics */
2330 const char* name, /**< name of variable, or NULL for automatic name creation */
2331 SCIP_Real lb, /**< lower bound of variable */
2332 SCIP_Real ub, /**< upper bound of variable */
2333 SCIP_Real obj, /**< objective function value */
2334 SCIP_VARTYPE vartype, /**< type of variable */
2335 SCIP_IMPLINTTYPE impltype, /**< implied integral type of the variable */
2336 SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2337 SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2338 SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2339 SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2340 SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2341 SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2342 SCIP_VARDATA* vardata /**< user data for this specific variable */
2343 )
2344{
2345 SCIP_Bool integral;
2346 int i;
2347
2348 assert(var != NULL);
2349 assert(blkmem != NULL);
2350 assert(stat != NULL);
2352
2353 /* forbid infinite objective values */
2355 {
2356 SCIPerrorMessage("invalid objective coefficient: value is infinite\n");
2357 return SCIP_INVALIDDATA;
2358 }
2359
2360 /* exact bounds may follow later */
2361 if( !set->exact_enable )
2362 {
2363 /* adjust bounds of variable */
2364 integral = vartype != SCIP_VARTYPE_CONTINUOUS || impltype != SCIP_IMPLINTTYPE_NONE;
2365 lb = adjustedLb(set, integral, lb);
2366 ub = adjustedUb(set, integral, ub);
2367
2368 /* convert [0,1]-integers into binary variables and check that binary variables have correct bounds */
2369 if( ( lb == 0.0 || lb == 1.0 ) && ( ub == 0.0 || ub == 1.0 ) ) /*lint !e777*/
2370 {
2371 if( vartype == SCIP_VARTYPE_INTEGER )
2372 vartype = SCIP_VARTYPE_BINARY;
2373 }
2374 else
2375 {
2376 if( vartype == SCIP_VARTYPE_BINARY )
2377 {
2378 SCIPerrorMessage("invalid bounds [%.2g,%.2g] for binary variable <%s>\n", lb, ub, name);
2379 return SCIP_INVALIDDATA;
2380 }
2381 }
2382
2383 assert(vartype != SCIP_VARTYPE_BINARY || lb == 0.0 || lb == 1.0); /*lint !e777*/
2384 assert(vartype != SCIP_VARTYPE_BINARY || ub == 0.0 || ub == 1.0); /*lint !e777*/
2386 }
2387
2389
2390 /* set variable's name */
2391 SCIP_CALL( varSetName(*var, blkmem, stat, name) );
2392
2393#ifndef NDEBUG
2394 (*var)->scip = set->scip;
2395#endif
2396 (*var)->obj = obj;
2397 (*var)->unchangedobj = obj;
2398 (*var)->branchfactor = 1.0;
2399 (*var)->rootsol = 0.0;
2400 (*var)->bestrootsol = 0.0;
2401 (*var)->bestrootredcost = 0.0;
2402 (*var)->bestrootlpobjval = SCIP_INVALID;
2403 (*var)->relaxsol = 0.0;
2404 (*var)->nlpsol = 0.0;
2405 (*var)->primsolavg = 0.5 * (lb + ub);
2406 (*var)->conflictlb = SCIP_REAL_MIN;
2407 (*var)->conflictub = SCIP_REAL_MAX;
2408 (*var)->conflictrelaxedlb = (*var)->conflictlb;
2409 (*var)->conflictrelaxedub = (*var)->conflictub;
2410 (*var)->lazylb = -SCIPsetInfinity(set);
2411 (*var)->lazyub = SCIPsetInfinity(set);
2412 (*var)->glbdom.holelist = NULL;
2413 (*var)->glbdom.lb = lb;
2414 (*var)->glbdom.ub = ub;
2415 (*var)->locdom.holelist = NULL;
2416 (*var)->locdom.lb = lb;
2417 (*var)->locdom.ub = ub;
2418 (*var)->varcopy = varcopy;
2419 (*var)->vardelorig = vardelorig;
2420 (*var)->vartrans = vartrans;
2421 (*var)->vardeltrans = vardeltrans;
2422 (*var)->vardata = vardata;
2423 (*var)->parentvars = NULL;
2424 (*var)->negatedvar = NULL;
2425 (*var)->vlbs = NULL;
2426 (*var)->vubs = NULL;
2427 (*var)->implics = NULL;
2428 (*var)->cliquelist = NULL;
2429 (*var)->eventfilter = NULL;
2430 (*var)->lbchginfos = NULL;
2431 (*var)->ubchginfos = NULL;
2432 (*var)->index = stat->nvaridx;
2433 (*var)->probindex = -1;
2434 (*var)->pseudocandindex = -1;
2435 (*var)->eventqueueindexobj = -1;
2436 (*var)->eventqueueindexlb = -1;
2437 (*var)->eventqueueindexub = -1;
2438 (*var)->parentvarssize = 0;
2439 (*var)->nparentvars = 0;
2440 (*var)->nuses = 0;
2441 (*var)->branchpriority = 0;
2442 (*var)->branchdirection = SCIP_BRANCHDIR_AUTO; /*lint !e641*/
2443 (*var)->lbchginfossize = 0;
2444 (*var)->nlbchginfos = 0;
2445 (*var)->ubchginfossize = 0;
2446 (*var)->nubchginfos = 0;
2447 (*var)->conflictlbcount = 0;
2448 (*var)->conflictubcount = 0;
2449 (*var)->closestvlbidx = -1;
2450 (*var)->closestvubidx = -1;
2451 (*var)->closestvblpcount = -1;
2452 (*var)->initial = initial;
2453 (*var)->removable = removable;
2454 (*var)->deleted = FALSE;
2455 (*var)->donotaggr = FALSE;
2456 (*var)->donotmultaggr = FALSE;
2457 (*var)->vartype = (unsigned int)vartype;
2458 (*var)->varimpltype = (unsigned int)impltype;
2459 (*var)->pseudocostflag = FALSE;
2460 (*var)->eventqueueimpl = FALSE;
2461 (*var)->deletable = FALSE;
2462 (*var)->delglobalstructs = FALSE;
2463 (*var)->exactdata = NULL;
2464 (*var)->relaxationonly = FALSE;
2465
2466 for( i = 0; i < NLOCKTYPES; i++ )
2467 {
2468 (*var)->nlocksdown[i] = 0;
2469 (*var)->nlocksup[i] = 0;
2470 }
2471
2472 stat->nvaridx++;
2473
2474 /* create branching and inference history entries */
2475 SCIP_CALL( SCIPhistoryCreate(&(*var)->history, blkmem) );
2476 SCIP_CALL( SCIPhistoryCreate(&(*var)->historycrun, blkmem) );
2477
2478 /* the value based history is only created on demand */
2479 (*var)->valuehistory = NULL;
2480
2481 return SCIP_OKAY;
2482}
2483
2484/** creates and captures an original problem variable; an integer variable with bounds
2485 * zero and one is automatically converted into a binary variable
2486 */
2488 SCIP_VAR** var, /**< pointer to variable data */
2489 BMS_BLKMEM* blkmem, /**< block memory */
2490 SCIP_SET* set, /**< global SCIP settings */
2491 SCIP_STAT* stat, /**< problem statistics */
2492 const char* name, /**< name of variable, or NULL for automatic name creation */
2493 SCIP_Real lb, /**< lower bound of variable */
2494 SCIP_Real ub, /**< upper bound of variable */
2495 SCIP_Real obj, /**< objective function value */
2496 SCIP_VARTYPE vartype, /**< type of variable */
2497 SCIP_IMPLINTTYPE impltype, /**< implied integral type of the variable */
2498 SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2499 SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2500 SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2501 SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2502 SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2503 SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2504 SCIP_VARDATA* vardata /**< user data for this specific variable */
2505 )
2506{
2507 assert(var != NULL);
2508 assert(blkmem != NULL);
2509 assert(stat != NULL);
2510
2511 /* create variable */
2512 SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, impltype, initial, removable,
2513 varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2514
2515 /* set variable status and data */
2516 (*var)->varstatus = SCIP_VARSTATUS_ORIGINAL; /*lint !e641*/
2517 (*var)->data.original.origdom.holelist = NULL;
2518 (*var)->data.original.origdom.lb = lb;
2519 (*var)->data.original.origdom.ub = ub;
2520 (*var)->data.original.transvar = NULL;
2521
2522 /* capture variable */
2524
2525 return SCIP_OKAY;
2526}
2527
2528/** creates and captures a loose variable belonging to the transformed problem; an integer variable with bounds
2529 * zero and one is automatically converted into a binary variable
2530 */
2532 SCIP_VAR** var, /**< pointer to variable data */
2533 BMS_BLKMEM* blkmem, /**< block memory */
2534 SCIP_SET* set, /**< global SCIP settings */
2535 SCIP_STAT* stat, /**< problem statistics */
2536 const char* name, /**< name of variable, or NULL for automatic name creation */
2537 SCIP_Real lb, /**< lower bound of variable */
2538 SCIP_Real ub, /**< upper bound of variable */
2539 SCIP_Real obj, /**< objective function value */
2540 SCIP_VARTYPE vartype, /**< type of variable */
2541 SCIP_IMPLINTTYPE impltype, /**< implied integral type of the variable */
2542 SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2543 SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2544 SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2545 SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2546 SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2547 SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2548 SCIP_VARDATA* vardata /**< user data for this specific variable */
2549 )
2550{
2551 assert(var != NULL);
2552 assert(blkmem != NULL);
2553
2554 /* create variable */
2555 SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, impltype, initial, removable,
2556 varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2557
2558 /* create event filter for transformed variable */
2559 SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
2560
2561 /* set variable status and data */
2562 (*var)->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
2563 (*var)->data.loose.minaggrcoef = 1.0;
2564 (*var)->data.loose.maxaggrcoef = 1.0;
2565
2566 /* capture variable */
2568
2569 return SCIP_OKAY;
2570}
2571
2572/** creates and sets the exact variable bounds and objective value (using floating-point data if value pointer is NULL)
2573 *
2574 * @note an inactive integer variable with bounds zero and one is automatically converted into a binary variable
2575 *
2576 * @note if exact data is provided, the corresponding floating-point data is overwritten
2577 */
2579 SCIP_VAR* var, /**< pointer to variable data */
2580 BMS_BLKMEM* blkmem, /**< block memory */
2581 SCIP_RATIONAL* lb, /**< lower bound of variable, or NULL to use floating-point data */
2582 SCIP_RATIONAL* ub, /**< upper bound of variable, or NULL to use floating-point data */
2583 SCIP_RATIONAL* obj /**< objective function value, or NULL to use floating-point data */
2584 )
2585{
2586 assert(var != NULL);
2587 assert(blkmem != NULL);
2588
2589 assert(var->exactdata == NULL);
2590 SCIP_ALLOC( BMSallocBlockMemory(blkmem, &(var->exactdata)) );
2591
2592 if( lb != NULL )
2593 {
2594 var->data.original.origdom.lb = SCIPrationalRoundReal(lb, SCIP_R_ROUND_DOWNWARDS);
2595 var->glbdom.lb = var->data.original.origdom.lb;
2596 var->locdom.lb = var->data.original.origdom.lb;
2597
2598 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &var->exactdata->origdom.lb, lb) );
2599 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &var->exactdata->glbdom.lb, lb) );
2600 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &var->exactdata->locdom.lb, lb) );
2601 }
2602 else
2603 {
2604 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &var->exactdata->origdom.lb) );
2605 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &var->exactdata->glbdom.lb) );
2606 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &var->exactdata->locdom.lb) );
2607
2608 SCIPrationalSetReal(var->exactdata->origdom.lb, var->data.original.origdom.lb);
2609 SCIPrationalSetReal(var->exactdata->glbdom.lb, var->glbdom.lb);
2610 SCIPrationalSetReal(var->exactdata->locdom.lb, var->locdom.lb);
2611 }
2612
2613 if( ub != NULL )
2614 {
2615 var->data.original.origdom.ub = SCIPrationalRoundReal(ub, SCIP_R_ROUND_UPWARDS);
2616 var->glbdom.ub = var->data.original.origdom.ub;
2617 var->locdom.ub = var->data.original.origdom.ub;
2618
2619 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &var->exactdata->origdom.ub, ub) );
2620 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &var->exactdata->glbdom.ub, ub) );
2621 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &var->exactdata->locdom.ub, ub) );
2622 }
2623 else
2624 {
2625 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &var->exactdata->origdom.ub) );
2626 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &var->exactdata->glbdom.ub) );
2627 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &var->exactdata->locdom.ub) );
2628
2629 SCIPrationalSetReal(var->exactdata->origdom.ub, var->data.original.origdom.ub);
2630 SCIPrationalSetReal(var->exactdata->glbdom.ub, var->glbdom.ub);
2631 SCIPrationalSetReal(var->exactdata->locdom.ub, var->locdom.ub);
2632 }
2633
2634 if( obj != NULL )
2635 {
2636 var->unchangedobj = SCIPrationalGetReal(obj);
2637 var->obj = var->unchangedobj;
2638
2639 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &var->exactdata->obj, obj) );
2640 SCIPintervalSetRational(&var->exactdata->objinterval, obj);
2641 }
2642 else
2643 {
2644 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &var->exactdata->obj) );
2645
2646 SCIPrationalSetReal(var->exactdata->obj, var->obj);
2647 SCIPintervalSet(&var->exactdata->objinterval, var->obj);
2648 }
2649
2650 var->exactdata->glbdom.lbcertificateidx = -1;
2651 var->exactdata->glbdom.ubcertificateidx = -1;
2652 var->exactdata->locdom.lbcertificateidx = -1;
2653 var->exactdata->locdom.ubcertificateidx = -1;
2654 var->exactdata->colexact = NULL;
2655 var->exactdata->varstatusexact = SCIPvarGetStatus(var);
2656 var->exactdata->certificateindex = -1;
2657 var->exactdata->multaggr.scalars = NULL;
2658 var->exactdata->multaggr.constant = NULL;
2659 var->exactdata->aggregate.constant = NULL;
2660 var->exactdata->aggregate.scalar = NULL;
2661 var->primsolavg = 0.5 * (var->data.original.origdom.lb + var->data.original.origdom.ub);
2662
2663 /* convert inactive [0,1]-integers into binary variables and check that binary variables have correct bounds */
2664 if( ( SCIPrationalIsZero(var->exactdata->origdom.lb) || SCIPrationalIsEQReal(var->exactdata->origdom.lb, 1.0) )
2665 && ( SCIPrationalIsZero(var->exactdata->origdom.ub) || SCIPrationalIsEQReal(var->exactdata->origdom.ub, 1.0) ) )
2666 {
2667 if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && var->probindex == -1 )
2668 var->vartype = (unsigned int)SCIP_VARTYPE_BINARY;
2669 }
2670 else
2671 {
2672 if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_BINARY )
2673 {
2674 SCIPerrorMessage("invalid bounds [%.2g,%.2g] for binary variable <%s>\n", var->data.original.origdom.lb, var->data.original.origdom.ub, var->name);
2675 return SCIP_INVALIDDATA;
2676 }
2677 }
2678
2679 return SCIP_OKAY;
2680}
2681
2682/** copies exact variable data from one variable to another
2683 *
2684 * @note This method cannot be integrated into SCIPvarCopy() because it is needed, e.g., when transforming vars.
2685 */
2687 BMS_BLKMEM* blkmem, /**< block memory */
2688 SCIP_VAR* targetvar, /**< variable that gets the exact data */
2689 SCIP_VAR* sourcevar, /**< variable the data gets copied from */
2690 SCIP_Bool negateobj /**< should the objective be negated */
2691 )
2692{
2693 assert(blkmem != NULL);
2694 assert(targetvar != NULL);
2695 assert(sourcevar != NULL);
2696
2697 if( sourcevar->exactdata == NULL )
2698 return SCIP_OKAY;
2699
2700 assert(sourcevar->exactdata != NULL);
2701
2702 SCIP_ALLOC( BMSallocBlockMemory(blkmem, &(targetvar->exactdata)) );
2703 targetvar->exactdata->glbdom = sourcevar->exactdata->glbdom;
2704 targetvar->exactdata->locdom = sourcevar->exactdata->locdom;
2705 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &targetvar->exactdata->glbdom.lb, sourcevar->exactdata->glbdom.lb) );
2706 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &targetvar->exactdata->glbdom.ub, sourcevar->exactdata->glbdom.ub) );
2707 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &targetvar->exactdata->locdom.lb, sourcevar->exactdata->locdom.lb) );
2708 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &targetvar->exactdata->locdom.ub, sourcevar->exactdata->locdom.ub) );
2709 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &targetvar->exactdata->origdom.lb, sourcevar->exactdata->origdom.lb) );
2710 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &targetvar->exactdata->origdom.ub, sourcevar->exactdata->origdom.ub) );
2711
2712 if( sourcevar->exactdata->aggregate.scalar != NULL )
2713 {
2714 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &targetvar->exactdata->aggregate.scalar, sourcevar->exactdata->aggregate.scalar) );
2716 }
2717 else
2718 {
2719 targetvar->exactdata->aggregate.constant = NULL;
2720 targetvar->exactdata->aggregate.scalar = NULL;
2721 }
2722
2723 if( sourcevar->exactdata->multaggr.scalars != NULL )
2724 {
2726 SCIP_CALL( SCIPrationalCopyBlockArray(blkmem, &targetvar->exactdata->multaggr.scalars, sourcevar->exactdata->multaggr.scalars, sourcevar->data.multaggr.nvars) );
2727 }
2728 else
2729 {
2730 targetvar->exactdata->multaggr.constant = NULL;
2731 targetvar->exactdata->multaggr.scalars = NULL;
2732 }
2733
2734 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &targetvar->exactdata->obj, sourcevar->exactdata->obj) );
2735 if( negateobj )
2736 {
2737 SCIPrationalNegate(targetvar->exactdata->obj, targetvar->exactdata->obj);
2738 }
2739 SCIPintervalSetRational(&(targetvar->exactdata->objinterval), targetvar->exactdata->obj);
2740 targetvar->exactdata->colexact = NULL;
2742 targetvar->exactdata->certificateindex = sourcevar->exactdata->certificateindex;
2743
2744 return SCIP_OKAY;
2745}
2746
2747/** copies and captures a variable from source to target SCIP; an integer variable with bounds zero and one is
2748 * automatically converted into a binary variable; in case the variable data cannot be copied the variable is not
2749 * copied at all
2750 */
2752 SCIP_VAR** var, /**< pointer to store the target variable */
2753 BMS_BLKMEM* blkmem, /**< block memory */
2754 SCIP_SET* set, /**< global SCIP settings */
2755 SCIP_STAT* stat, /**< problem statistics */
2756 SCIP* sourcescip, /**< source SCIP data structure */
2757 SCIP_VAR* sourcevar, /**< source variable */
2758 SCIP_HASHMAP* varmap, /**< a hashmap to store the mapping of source variables corresponding
2759 * target variables */
2760 SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
2761 * target constraints */
2762 SCIP_Bool global /**< should global or local bounds be used? */
2763 )
2764{
2765 SCIP_VARDATA* targetdata;
2767 SCIP_Real lb;
2768 SCIP_Real ub;
2769
2770 assert(set != NULL);
2771 assert(blkmem != NULL);
2772 assert(stat != NULL);
2773 assert(sourcescip != NULL);
2774 assert(sourcevar != NULL);
2775 assert(var != NULL);
2776 assert(set->stage == SCIP_STAGE_PROBLEM);
2777 assert(varmap != NULL);
2778 assert(consmap != NULL);
2779
2780 /** @todo copy hole lists */
2781 assert(global || SCIPvarGetHolelistLocal(sourcevar) == NULL);
2782 assert(!global || SCIPvarGetHolelistGlobal(sourcevar) == NULL);
2783
2785 targetdata = NULL;
2786
2787 if( SCIPvarGetStatus(sourcevar) == SCIP_VARSTATUS_ORIGINAL )
2788 {
2789 lb = SCIPvarGetLbOriginal(sourcevar);
2790 ub = SCIPvarGetUbOriginal(sourcevar);
2791 }
2792 else
2793 {
2794 lb = global ? SCIPvarGetLbGlobal(sourcevar) : SCIPvarGetLbLocal(sourcevar);
2795 ub = global ? SCIPvarGetUbGlobal(sourcevar) : SCIPvarGetUbLocal(sourcevar);
2796 }
2797
2798 /* creates and captures the variable in the target SCIP and initialize callback methods and variable data to NULL */
2799 SCIP_CALL( SCIPvarCreateOriginal(var, blkmem, set, stat, SCIPvarGetName(sourcevar),
2800 lb, ub, SCIPvarGetObj(sourcevar), SCIPvarGetType(sourcevar), SCIPvarGetImplType(sourcevar),
2801 SCIPvarIsInitial(sourcevar), SCIPvarIsRemovable(sourcevar),
2802 NULL, NULL, NULL, NULL, NULL) );
2803 assert(*var != NULL);
2804
2805 /* directly copy donot(mult)aggr flag */
2806 (*var)->donotaggr = sourcevar->donotaggr;
2807 (*var)->donotmultaggr = sourcevar->donotmultaggr;
2808
2809 /* insert variable into mapping between source SCIP and the target SCIP */
2810 assert(!SCIPhashmapExists(varmap, sourcevar));
2811 SCIP_CALL( SCIPhashmapInsert(varmap, sourcevar, *var) );
2812
2813 /* in case there exists variable data and the variable data copy callback, try to copy variable data */
2814 if( sourcevar->vardata != NULL )
2815 {
2816 if( sourcevar->varcopy != NULL )
2817 {
2818 SCIP_CALL( sourcevar->varcopy(set->scip, sourcescip, sourcevar, sourcevar->vardata,
2819 varmap, consmap, (*var), &targetdata, &result) );
2820
2821 /* evaluate result */
2823 {
2824 SCIPerrorMessage("variable data copying method returned invalid result <%d>\n", result);
2825 return SCIP_INVALIDRESULT;
2826 }
2827
2828 assert(targetdata == NULL || result == SCIP_SUCCESS);
2829
2830 /* if copying was successful, add the created variable data to the variable as well as all callback methods */
2831 if( result == SCIP_SUCCESS )
2832 {
2833 (*var)->varcopy = sourcevar->varcopy;
2834 (*var)->vardelorig = sourcevar->vardelorig;
2835 (*var)->vartrans = sourcevar->vartrans;
2836 (*var)->vardeltrans = sourcevar->vardeltrans;
2837 (*var)->vardata = targetdata;
2838 }
2839 }
2840 else
2841 {
2842 /* if there is no copy callback, just copy data pointers */
2843 (*var)->vardata = sourcevar->vardata;
2844 }
2845 }
2846
2847 /* we initialize histories of the variables by copying the source variable-information */
2848 if( set->history_allowtransfer )
2849 {
2850 SCIPvarMergeHistories((*var), sourcevar, stat);
2851 }
2852
2853 /* in case the copying was successfully, add the created variable data to the variable as well as all callback
2854 * methods
2855 */
2856 if( result == SCIP_SUCCESS )
2857 {
2858 (*var)->varcopy = sourcevar->varcopy;
2859 (*var)->vardelorig = sourcevar->vardelorig;
2860 (*var)->vartrans = sourcevar->vartrans;
2861 (*var)->vardeltrans = sourcevar->vardeltrans;
2862 (*var)->vardata = targetdata;
2863 }
2864
2865 SCIPsetDebugMsg(set, "created copy <%s> of variable <%s>\n", SCIPvarGetName(*var), SCIPvarGetName(sourcevar));
2866
2867 return SCIP_OKAY;
2868}
2869
2870/** parse given string for a value */
2871static
2873 SCIP_SET* set, /**< global SCIP settings */
2874 const char* str, /**< string to parse */
2875 SCIP_Real* value, /**< pointer to store the parsed value */
2876 SCIP_RATIONAL* valueexact /**< pointer to store the parsed exact value */
2877 )
2878{
2879 assert(value == NULL || valueexact == NULL);
2880
2881 /* parse exact value */
2882 if( valueexact != NULL )
2883 {
2884 /* check for rationality */
2885 if( SCIPrationalIsString(str) )
2886 {
2887 SCIPrationalSetString(valueexact, str);
2888 SCIPrationalCanonicalize(valueexact);
2889 }
2890 else
2891 {
2892 SCIPerrorMessage("expected exact value: %s\n", str);
2893 return SCIP_READERROR;
2894 }
2895
2896 SCIPrationalDebugMessage("parsed exact value: %q\n", valueexact);
2897 }
2898 /* parse real value */
2899 else if( value != NULL )
2900 {
2901 char* endptr;
2902
2903 /* check for infinity */
2904 if( strncmp(str, "+inf", 4) == 0 )
2905 {
2906 *value = SCIPsetInfinity(set);
2907 }
2908 else if( strncmp(str, "-inf", 4) == 0 )
2909 {
2910 *value = -SCIPsetInfinity(set);
2911 }
2912 else if( !SCIPstrToRealValue(str, value, &endptr) || *endptr != '\0' )
2913 {
2914 SCIPerrorMessage("expected real value: %s\n", str);
2915 return SCIP_READERROR;
2916 }
2917
2918 SCIPsetDebugMsg(set, "parsed real value: %g\n", *value);
2919 }
2920
2921 return SCIP_OKAY;
2922}
2923
2924/** parse the characters as bounds */
2925static
2927 SCIP_SET* set, /**< global SCIP settings */
2928 const char* str, /**< string to parse */
2929 char* type, /**< bound type (global, local, or lazy) */
2930 SCIP_Real* lb, /**< pointer to store the lower bound */
2931 SCIP_Real* ub, /**< pointer to store the upper bound */
2932 SCIP_RATIONAL* lbexact, /**< pointer to store the exact lower bound */
2933 SCIP_RATIONAL* ubexact, /**< pointer to store the exact upper bound */
2934 char** endptr /**< pointer to store the final string position if successfully parsed (or NULL if an error occurred) */
2935 )
2936{
2937 char token[SCIP_MAXSTRLEN];
2938
2939 SCIPsetDebugMsg(set, "parsing bounds: '%s'\n", str);
2940
2941 /* get bound type */
2942 SCIPstrCopySection(str, ' ', ' ', type, SCIP_MAXSTRLEN, endptr);
2943 if ( *endptr == str
2944 || ( strncmp(type, "original", 8) != 0 && strncmp(type, "global", 6) != 0 && strncmp(type, "local", 5) != 0 && strncmp(type, "lazy", 4) != 0 ) )
2945 {
2946 SCIPsetDebugMsg(set, "unkown bound type\n");
2947 *endptr = NULL;
2948 return SCIP_OKAY;
2949 }
2950
2951 SCIPsetDebugMsg(set, "parsed bound type <%s>\n", type);
2952
2953 /* get lower bound */
2954 SCIPstrCopySection(str, '[', ',', token, SCIP_MAXSTRLEN, endptr);
2955 SCIP_CALL( parseValue(set, token, lb, lbexact) );
2956
2957 str = *endptr - 1;
2958
2959 /* get upper bound */
2960 SCIPstrCopySection(str, ',', ']', token, SCIP_MAXSTRLEN, endptr);
2961 SCIP_CALL( parseValue(set, token, ub, ubexact) );
2962
2963 /* skip end of bounds */
2964 if( **endptr == ',' )
2965 ++(*endptr);
2966
2967 return SCIP_OKAY;
2968}
2969
2970/** parses a given string for a variable informations */
2971static
2973 SCIP_SET* set, /**< global SCIP settings */
2974 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2975 const char* str, /**< string to parse */
2976 char* name, /**< pointer to store the variable name */
2977 SCIP_Real* lb, /**< pointer to store the lower bound */
2978 SCIP_Real* ub, /**< pointer to store the upper bound */
2979 SCIP_Real* obj, /**< pointer to store the objective coefficient */
2980 SCIP_RATIONAL* lbexact, /**< pointer to store the exact lower bound */
2981 SCIP_RATIONAL* ubexact, /**< pointer to store the exact upper bound */
2982 SCIP_RATIONAL* objexact, /**< pointer to store the exact objective coefficient */
2983 SCIP_VARTYPE* vartype, /**< pointer to store the variable type */
2984 SCIP_IMPLINTTYPE* impltype, /**< pointer to store the implied integral type */
2985 SCIP_Real* lazylb, /**< pointer to store if the lower bound is lazy */
2986 SCIP_Real* lazyub, /**< pointer to store if the upper bound is lazy */
2987 SCIP_RATIONAL* lazylbexact, /**< pointer to store if the exact lower bound is lazy */
2988 SCIP_RATIONAL* lazyubexact, /**< pointer to store if the exact upper bound is lazy */
2989 SCIP_Bool local, /**< should the local bound be applied */
2990 char** endptr, /**< pointer to store the final string position if successfully */
2991 SCIP_Bool* success /**< pointer store if the paring process was successful */
2992 )
2993{
2994 SCIP_Bool lazyread = FALSE;
2995 char token[SCIP_MAXSTRLEN];
2996 char* strptr;
2997 int i;
2998
2999 assert(vartype != NULL);
3000 assert(success != NULL);
3001
3002 (*success) = TRUE;
3003
3004 /* copy variable type */
3005 SCIPstrCopySection(str, '[', ']', token, SCIP_MAXSTRLEN, endptr);
3006 assert(*endptr != str);
3007 SCIPsetDebugMsg(set, "parsed variable type <%s>\n", token);
3008
3009 (*impltype) = SCIP_IMPLINTTYPE_NONE;
3010 /* get variable type */
3011 if( strncmp(token, "binary", 3) == 0 )
3012 (*vartype) = SCIP_VARTYPE_BINARY;
3013 else if( strncmp(token, "integer", 3) == 0 )
3014 (*vartype) = SCIP_VARTYPE_INTEGER;
3015 else if( strncmp(token, "implicit", 3) == 0 )
3016 {
3017 (*vartype) = SCIP_VARTYPE_CONTINUOUS;
3018 (*impltype) = SCIP_IMPLINTTYPE_WEAK;
3019 }
3020 else if( strncmp(token, "continuous", 3) == 0 )
3021 (*vartype) = SCIP_VARTYPE_CONTINUOUS;
3022 else
3023 {
3024 SCIPmessagePrintWarning(messagehdlr, "unknown variable type\n");
3025 (*success) = FALSE;
3026 return SCIP_OKAY;
3027 }
3028
3029 /* move string pointer behind variable type */
3030 str = *endptr;
3031
3032 /* get variable name */
3033 SCIPstrCopySection(str, '<', '>', name, SCIP_MAXSTRLEN, endptr);
3034 assert(*endptr != str);
3035 SCIPsetDebugMsg(set, "parsed variable name <%s>\n", name);
3036
3037 /* move string pointer behind variable name */
3038 str = *endptr;
3039
3040 /* get objective coefficient */
3041 SCIPstrCopySection(str, '=', ',', token, SCIP_MAXSTRLEN, endptr);
3042 SCIP_CALL( parseValue(set, token, obj, objexact) );
3043
3044 /* move string pointer behind objective coefficient */
3045 str = *endptr;
3046
3047 /* parse global/original bounds */
3048 SCIP_CALL( parseBounds(set, str, token, lb, ub, lbexact, ubexact, endptr) );
3049 if( *endptr == NULL )
3050 {
3051 SCIPerrorMessage("Expected bound type: %s.\n", token);
3052 return SCIP_READERROR;
3053 }
3054 assert(strncmp(token, "global", 6) == 0 || strncmp(token, "original", 8) == 0);
3055
3056 /* store pointer */
3057 strptr = *endptr;
3058
3059 /* possibly parse optional local and lazy bounds */
3060 for( i = 0; i < 2 && *endptr != NULL && **endptr != '\0'; ++i )
3061 {
3062 /* start after previous bounds */
3063 strptr = *endptr;
3064
3065 /* parse variable bounds */
3066 SCIP_CALL( parseBounds(set, strptr, token, lazylb, lazyub, lazylbexact, lazyubexact, endptr) );
3067
3068 /* set local bounds */
3069 if( strncmp(token, "local", 5) == 0 )
3070 {
3071 if( local )
3072 {
3073 if( lb != NULL )
3074 {
3075 assert(lazylb != NULL);
3076 *lb = *lazylb;
3077 }
3078
3079 if( ub != NULL )
3080 {
3081 assert(lazyub != NULL);
3082 *ub = *lazyub;
3083 }
3084
3085 if( lbexact != NULL )
3086 {
3087 assert(lazylbexact != NULL);
3088 SCIPrationalSetRational(lbexact, lazylbexact);
3089 }
3090
3091 if( ubexact != NULL )
3092 {
3093 assert(lazyubexact != NULL);
3094 SCIPrationalSetRational(ubexact, lazyubexact);
3095 }
3096 }
3097 }
3098 /* set lazy bounds */
3099 else if( strncmp(token, "lazy", 4) == 0 )
3100 {
3101 lazyread = TRUE;
3102 break;
3103 }
3104
3105 /* stop if parsing of bounds failed */
3106 if( *endptr == NULL )
3107 break;
3108 }
3109
3110 /* reset lazy bounds */
3111 if( !lazyread )
3112 {
3113 if( lazylb != NULL )
3114 *lazylb = -SCIPsetInfinity(set);
3115
3116 if( lazyub != NULL )
3117 *lazyub = SCIPsetInfinity(set);
3118
3119 if( lazylbexact != NULL )
3120 SCIPrationalSetNegInfinity(lazylbexact);
3121
3122 if( lazyubexact != NULL )
3123 SCIPrationalSetInfinity(lazyubexact);
3124 }
3125
3126 /* check bounds for binary variables */
3127 if( (*vartype) == SCIP_VARTYPE_BINARY )
3128 {
3129 if( lb != NULL && *lb < 0.0 )
3130 {
3131 SCIPerrorMessage("Parsed invalid lower bound for binary variable <%s>: %f.\n", name, *lb);
3132 return SCIP_READERROR;
3133 }
3134
3135 if( ub != NULL && *ub > 1.0 )
3136 {
3137 SCIPerrorMessage("Parsed invalid upper bound for binary variable <%s>: %f.\n", name, *ub);
3138 return SCIP_READERROR;
3139 }
3140
3141 if( lbexact != NULL && SCIPrationalIsNegative(lbexact) )
3142 {
3143 SCIPerrorMessage("Parsed invalid exact lower bound for binary variable <%s>: %f.\n",
3145 return SCIP_READERROR;
3146 }
3147
3148 if( ubexact != NULL && SCIPrationalIsGTReal(ubexact, 1.0) )
3149 {
3150 SCIPerrorMessage("Parsed invalid exact upper bound for binary variable <%s>: %f.\n",
3152 return SCIP_READERROR;
3153 }
3154
3155 if( lazyread )
3156 {
3157 if( lazylb != NULL && *lazylb < 0.0 )
3158 {
3159 SCIPerrorMessage("Parsed invalid lazy lower bound for binary variable <%s>: %f.\n", name, *lazylb);
3160 return SCIP_READERROR;
3161 }
3162
3163 if( lazyub != NULL && *lazyub > 1.0 )
3164 {
3165 SCIPerrorMessage("Parsed invalid lazy upper bound for binary variable <%s>: %f.\n", name, *lazyub);
3166 return SCIP_READERROR;
3167 }
3168
3169 if( lazylbexact != NULL && SCIPrationalIsNegative(lazylbexact) )
3170 {
3171 SCIPerrorMessage("Parsed invalid exact lazy lower bound for binary variable <%s>: %f.\n",
3172 name, SCIPrationalRoundReal(lazylbexact, SCIP_R_ROUND_DOWNWARDS));
3173 return SCIP_READERROR;
3174 }
3175
3176 if( lazyubexact != NULL && SCIPrationalIsGTReal(lazyubexact, 1.0) )
3177 {
3178 SCIPerrorMessage("Parsed invalid exact lazy upper bound for binary variable <%s>: %f.\n",
3179 name, SCIPrationalRoundReal(lazyubexact, SCIP_R_ROUND_UPWARDS));
3180 return SCIP_READERROR;
3181 }
3182 }
3183 }
3184
3185 /* update string pointer */
3186 if( *endptr != NULL )
3187 strptr = *endptr;
3188
3189 /* detect implied declaration */
3190 SCIPstrCopySection(strptr, ' ', ':', token, SCIP_MAXSTRLEN, endptr);
3191
3192 /* no further declaration */
3193 if( *endptr == strptr )
3194 return SCIP_OKAY;
3195
3196 /* get implied type */
3197 if( strncmp(token, "implied", 7) == 0 )
3198 {
3199 strptr = *endptr;
3200 SCIP_CALL( SCIPskipSpace(&strptr) );
3201
3202 if( strncmp(strptr, "strong", 6) == 0 )
3203 {
3204 (*impltype) = SCIP_IMPLINTTYPE_STRONG;
3205 *endptr = strptr + 6;
3206 }
3207 else if( strncmp(strptr, "weak", 4) == 0 )
3208 {
3209 (*impltype) = SCIP_IMPLINTTYPE_WEAK;
3210 *endptr = strptr + 4;
3211 }
3212 else if( strncmp(strptr, "none", 4) == 0 )
3213 {
3214 (*impltype) = SCIP_IMPLINTTYPE_NONE;
3215 *endptr = strptr + 4;
3216 }
3217 else
3218 {
3219 SCIPerrorMessage("Expected implied integral type 'none', 'weak', or 'strong', got: '%s'.\n", strptr);
3220 return SCIP_READERROR;
3221 }
3222 }
3223 /* keep other declarations */
3224 else
3225 *endptr = strptr;
3226
3227 return SCIP_OKAY;
3228}
3229
3230/** parses variable information (in cip format) out of a string; if the parsing process was successful an original
3231 * variable is created and captured; if variable is of integral type, fractional bounds are automatically rounded; an
3232 * integer variable with bounds zero and one is automatically converted into a binary variable
3233 */
3235 SCIP_VAR** var, /**< pointer to variable data */
3236 BMS_BLKMEM* blkmem, /**< block memory */
3237 SCIP_SET* set, /**< global SCIP settings */
3238 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3239 SCIP_STAT* stat, /**< problem statistics */
3240 const char* str, /**< string to parse */
3241 SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
3242 SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
3243 SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
3244 SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable */
3245 SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data */
3246 SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable */
3247 SCIP_VARDATA* vardata, /**< user data for this specific variable */
3248 char** endptr, /**< pointer to store the final string position if successfully */
3249 SCIP_Bool* success /**< pointer store if the paring process was successful */
3250 )
3251{
3252 char name[SCIP_MAXSTRLEN];
3253 SCIP_VARTYPE vartype;
3254 SCIP_IMPLINTTYPE impltype;
3255
3256 assert(var != NULL);
3257 assert(blkmem != NULL);
3258 assert(stat != NULL);
3259 assert(endptr != NULL);
3260 assert(success != NULL);
3261
3262 /* parse exact variable */
3263 if( set->exact_enable )
3264 {
3265 SCIP_RATIONAL* lb;
3266 SCIP_RATIONAL* ub;
3268 SCIP_RATIONAL* lazylb;
3269 SCIP_RATIONAL* lazyub;
3270
3271 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &lb) );
3272 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &ub) );
3274 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &lazylb) );
3275 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &lazyub) );
3276
3277 /* parse string in cip format for exact variable information */
3278 SCIP_CALL( varParse(set, messagehdlr, str, name, NULL, NULL, NULL, lb, ub, obj, &vartype, &impltype,
3279 NULL, NULL, lazylb, lazyub, FALSE, endptr, success) );
3280
3281 if( *success ) /*lint !e774*/
3282 {
3283 /* create variable */
3284 SCIP_CALL( varCreate(var, blkmem, set, stat, name, 0.0, 0.0, 0.0, vartype, impltype, initial, removable,
3285 varcopy, vardelorig, vartrans, vardeltrans, vardata) );
3286
3287 /* set variable status */
3290 (*var)->varstatus = (unsigned int)SCIP_VARSTATUS_ORIGINAL;
3291 (*var)->data.original.origdom.holelist = NULL;
3292 (*var)->data.original.transvar = NULL;
3293
3294 /* add exact data */
3295 SCIP_CALL( SCIPvarAddExactData(*var, blkmem, lb, ub, obj) );
3296
3297 /**@todo implement lazy bounds in exact solving mode (and adjust values before setting them) */
3298 if( !SCIPrationalIsNegInfinity(lazylb) || !SCIPrationalIsInfinity(lazyub) )
3299 {
3300 SCIPerrorMessage("exact lazy bounds not supported yet\n");
3301 return SCIP_READERROR;
3302 }
3303
3304 /* capture variable */
3306 }
3307
3308 SCIPrationalFreeBlock(blkmem, &lazyub);
3309 SCIPrationalFreeBlock(blkmem, &lazylb);
3310 SCIPrationalFreeBlock(blkmem, &obj);
3311 SCIPrationalFreeBlock(blkmem, &ub);
3312 SCIPrationalFreeBlock(blkmem, &lb);
3313 }
3314 else
3315 {
3316 SCIP_Real lb;
3317 SCIP_Real ub;
3318 SCIP_Real obj;
3319 SCIP_Real lazylb;
3320 SCIP_Real lazyub;
3321
3322 /* parse string in cip format for variable information */
3323 SCIP_CALL( varParse(set, messagehdlr, str, name, &lb, &ub, &obj, NULL, NULL, NULL, &vartype, &impltype,
3324 &lazylb, &lazyub, NULL, NULL, FALSE, endptr, success) );
3325
3326 if( *success ) /*lint !e774*/
3327 {
3328 /* create variable */
3329 SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, impltype, initial, removable,
3330 varcopy, vardelorig, vartrans, vardeltrans, vardata) );
3331
3332 /* set variable status */
3333 assert(*var != NULL);
3334 (*var)->varstatus = (unsigned int)SCIP_VARSTATUS_ORIGINAL;
3335 (*var)->data.original.origdom.holelist = NULL;
3336 (*var)->data.original.origdom.lb = (*var)->glbdom.lb;
3337 (*var)->data.original.origdom.ub = (*var)->glbdom.ub;
3338 (*var)->data.original.transvar = NULL;
3339 SCIPvarAdjustLb(*var, set, &lazylb);
3340 SCIPvarAdjustUb(*var, set, &lazyub);
3341 (*var)->lazylb = lazylb;
3342 (*var)->lazyub = lazyub;
3343
3344 /* capture variable */
3346 }
3347 }
3348
3349 return SCIP_OKAY;
3350}
3351
3352/** parses variable information (in cip format) out of a string; if the parsing process was successful a loose variable
3353 * belonging to the transformed problem is created and captured; if variable is of integral type, fractional bounds are
3354 * automatically rounded; an integer variable with bounds zero and one is automatically converted into a binary
3355 * variable
3356 */
3358 SCIP_VAR** var, /**< pointer to variable data */
3359 BMS_BLKMEM* blkmem, /**< block memory */
3360 SCIP_SET* set, /**< global SCIP settings */
3361 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3362 SCIP_STAT* stat, /**< problem statistics */
3363 const char* str, /**< string to parse */
3364 SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
3365 SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
3366 SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
3367 SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable */
3368 SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data */
3369 SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable */
3370 SCIP_VARDATA* vardata, /**< user data for this specific variable */
3371 char** endptr, /**< pointer to store the final string position if successfully */
3372 SCIP_Bool* success /**< pointer store if the paring process was successful */
3373 )
3374{
3375 char name[SCIP_MAXSTRLEN];
3376 SCIP_VARTYPE vartype;
3377 SCIP_IMPLINTTYPE impltype;
3378
3379 assert(var != NULL);
3380 assert(blkmem != NULL);
3381 assert(endptr != NULL);
3382 assert(success != NULL);
3383
3384 /* parse exact variable */
3385 if( set->exact_enable )
3386 {
3387 SCIP_RATIONAL* lb;
3388 SCIP_RATIONAL* ub;
3390 SCIP_RATIONAL* lazylb;
3391 SCIP_RATIONAL* lazyub;
3392
3393 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &lb) );
3394 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &ub) );
3396 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &lazylb) );
3397 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &lazyub) );
3398
3399 /* parse string in cip format for exact variable information */
3400 SCIP_CALL( varParse(set, messagehdlr, str, name, NULL, NULL, NULL, lb, ub, obj, &vartype, &impltype,
3401 NULL, NULL, lazylb, lazyub, TRUE, endptr, success) );
3402
3403 if( *success ) /*lint !e774*/
3404 {
3405 /* create variable */
3406 SCIP_CALL( varCreate(var, blkmem, set, stat, name, 0.0, 0.0, 0.0, vartype, impltype, initial, removable,
3407 varcopy, vardelorig, vartrans, vardeltrans, vardata) );
3408
3409 /* set variable status */
3412 (*var)->varstatus = (unsigned int)SCIP_VARSTATUS_LOOSE;
3413 (*var)->data.loose.minaggrcoef = 1.0;
3414 (*var)->data.loose.maxaggrcoef = 1.0;
3415
3416 /* add exact data */
3417 SCIP_CALL( SCIPvarAddExactData(*var, blkmem, lb, ub, obj) );
3418
3419 /**@todo implement lazy bounds in exact solving mode */
3420 if( !SCIPrationalIsNegInfinity(lazylb) || !SCIPrationalIsInfinity(lazyub) )
3421 {
3422 SCIPerrorMessage("exact lazy bounds not supported yet\n");
3423 return SCIP_READERROR;
3424 }
3425
3426 /* create event filter for transformed variable */
3427 SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
3428
3429 /* capture variable */
3431 }
3432
3433 SCIPrationalFreeBlock(blkmem, &lazyub);
3434 SCIPrationalFreeBlock(blkmem, &lazylb);
3435 SCIPrationalFreeBlock(blkmem, &obj);
3436 SCIPrationalFreeBlock(blkmem, &ub);
3437 SCIPrationalFreeBlock(blkmem, &lb);
3438 }
3439 /* parse real variable */
3440 else
3441 {
3442 SCIP_Real lb;
3443 SCIP_Real ub;
3444 SCIP_Real obj;
3445 SCIP_Real lazylb;
3446 SCIP_Real lazyub;
3447
3448 /* parse string in cip format for variable information */
3449 SCIP_CALL( varParse(set, messagehdlr, str, name, &lb, &ub, &obj, NULL, NULL, NULL, &vartype, &impltype,
3450 &lazylb, &lazyub, NULL, NULL, TRUE, endptr, success) );
3451
3452 if( *success ) /*lint !e774*/
3453 {
3454 /* create variable */
3455 SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, impltype, initial, removable,
3456 varcopy, vardelorig, vartrans, vardeltrans, vardata) );
3457
3458 /* set variable status */
3459 assert(*var != NULL);
3460 (*var)->varstatus = (unsigned int)SCIP_VARSTATUS_LOOSE;
3461 (*var)->data.loose.minaggrcoef = 1.0;
3462 (*var)->data.loose.maxaggrcoef = 1.0;
3463 (*var)->lazylb = lazylb;
3464 (*var)->lazyub = lazyub;
3465
3466 /* create event filter for transformed variable */
3467 SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
3468
3469 /* capture variable */
3471 }
3472 }
3473
3474 return SCIP_OKAY;
3475}
3476
3477/** ensures, that parentvars array of var can store at least num entries */
3478static
3480 SCIP_VAR* var, /**< problem variable */
3481 BMS_BLKMEM* blkmem, /**< block memory */
3482 SCIP_SET* set, /**< global SCIP settings */
3483 int num /**< minimum number of entries to store */
3484 )
3485{
3486 assert(var->nparentvars <= var->parentvarssize);
3487
3488 if( num > var->parentvarssize )
3489 {
3490 int newsize;
3491
3492 newsize = SCIPsetCalcMemGrowSize(set, num);
3493 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->parentvars, var->parentvarssize, newsize) );
3494 var->parentvarssize = newsize;
3495 }
3496 assert(num <= var->parentvarssize);
3497
3498 return SCIP_OKAY;
3499}
3500
3501/** adds variable to parent list of a variable and captures parent variable */
3502static
3504 SCIP_VAR* var, /**< variable to add parent to */
3505 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3506 SCIP_SET* set, /**< global SCIP settings */
3507 SCIP_VAR* parentvar /**< parent variable to add */
3508 )
3509{
3510 assert(var != NULL);
3511 assert(parentvar != NULL);
3512
3513 /* the direct original counterpart must be stored as first parent */
3514 assert(var->nparentvars == 0 || SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL);
3515
3516 SCIPsetDebugMsg(set, "adding parent <%s>[%p] to variable <%s>[%p] in slot %d\n",
3517 parentvar->name, (void*)parentvar, var->name, (void*)var, var->nparentvars);
3518
3519 SCIP_CALL( varEnsureParentvarsSize(var, blkmem, set, var->nparentvars+1) );
3520
3521 var->parentvars[var->nparentvars] = parentvar;
3522 var->nparentvars++;
3523
3524 SCIPvarCapture(parentvar);
3525
3526 return SCIP_OKAY;
3527}
3528
3529/** deletes and releases all variables from the parent list of a variable, frees the memory of parents array */
3530static
3532 SCIP_VAR** var, /**< pointer to variable */
3533 BMS_BLKMEM* blkmem, /**< block memory */
3534 SCIP_SET* set, /**< global SCIP settings */
3535 SCIP_EVENTQUEUE* eventqueue, /**< event queue (or NULL, if it's an original variable) */
3536 SCIP_LP* lp /**< current LP data (or NULL, if it's an original variable) */
3537 )
3538{
3539 SCIP_VAR* parentvar;
3540 int i;
3541
3542 SCIPsetDebugMsg(set, "free parents of <%s>\n", (*var)->name);
3543
3544 /* release the parent variables and remove the link from the parent variable to the child */
3545 for( i = 0; i < (*var)->nparentvars; ++i )
3546 {
3547 assert((*var)->parentvars != NULL);
3548 parentvar = (*var)->parentvars[i];
3549 assert(parentvar != NULL);
3550
3551 switch( SCIPvarGetStatus(parentvar) )
3552 {
3554 assert(parentvar->data.original.transvar == *var);
3555 assert(&parentvar->data.original.transvar != var);
3556 parentvar->data.original.transvar = NULL;
3557 break;
3558
3560 assert(parentvar->data.aggregate.var == *var);
3561 assert(&parentvar->data.aggregate.var != var);
3562 parentvar->data.aggregate.var = NULL;
3563 break;
3564
3565#ifdef SCIP_DISABLED_CODE
3566 /* The following code is unclear: should the current variable be removed from its parents? */
3568 assert(parentvar->data.multaggr.vars != NULL);
3569 for( v = 0; v < parentvar->data.multaggr.nvars && parentvar->data.multaggr.vars[v] != *var; ++v )
3570 {}
3571 assert(v < parentvar->data.multaggr.nvars && parentvar->data.multaggr.vars[v] == *var);
3572 if( v < parentvar->data.multaggr.nvars-1 )
3573 {
3574 parentvar->data.multaggr.vars[v] = parentvar->data.multaggr.vars[parentvar->data.multaggr.nvars-1];
3575 parentvar->data.multaggr.scalars[v] = parentvar->data.multaggr.scalars[parentvar->data.multaggr.nvars-1];
3576 }
3577 parentvar->data.multaggr.nvars--;
3578 break;
3579#endif
3580
3582 assert(parentvar->negatedvar == *var);
3583 assert((*var)->negatedvar == parentvar);
3584 parentvar->negatedvar = NULL;
3585 (*var)->negatedvar = NULL;
3586 break;
3587
3588 default:
3589 SCIPerrorMessage("parent variable is neither ORIGINAL, AGGREGATED nor NEGATED\n");
3590 return SCIP_INVALIDDATA;
3591 } /*lint !e788*/
3592
3593 SCIP_CALL( SCIPvarRelease(&(*var)->parentvars[i], blkmem, set, eventqueue, lp) );
3594 }
3595
3596 /* free parentvars array */
3597 BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->parentvars, (*var)->parentvarssize);
3598
3599 return SCIP_OKAY;
3600}
3601
3602/** free exact variable data, if it exists */
3603static
3605 SCIP_VAR* var, /**< variable */
3606 BMS_BLKMEM* blkmem, /**< block memory */
3607 SCIP_SET* set /**< global SCIP settings */
3608 )
3609{
3610 assert(blkmem != NULL);
3611 assert(var != NULL);
3612
3613 if( !set->exact_enable )
3614 {
3615 assert( var->exactdata == NULL );
3616 return SCIP_OKAY;
3617 }
3618
3619 /* free exact variable data if it was created */
3620 if( var->exactdata != NULL )
3621 {
3623 {
3624 SCIP_CALL( SCIPcolExactFree(&(var->exactdata->colexact), blkmem) );
3625 }
3626
3627 if( var->exactdata->aggregate.scalar != NULL )
3628 {
3629 SCIPrationalFreeBlock(blkmem, &(var)->exactdata->aggregate.constant);
3630 SCIPrationalFreeBlock(blkmem, &(var)->exactdata->aggregate.scalar);
3631 }
3632
3633 if( var->exactdata->multaggr.scalars != NULL )
3634 {
3635 SCIPrationalFreeBlock(blkmem, &(var)->exactdata->multaggr.constant);
3636 SCIPrationalFreeBlockArray(blkmem, &(var)->exactdata->multaggr.scalars, var->data.multaggr.varssize);
3637 }
3638
3639 SCIPrationalFreeBlock(blkmem, &(var)->exactdata->glbdom.lb);
3640 SCIPrationalFreeBlock(blkmem, &(var)->exactdata->glbdom.ub);
3641 SCIPrationalFreeBlock(blkmem, &(var)->exactdata->locdom.lb);
3642 SCIPrationalFreeBlock(blkmem, &(var)->exactdata->locdom.ub);
3643 SCIPrationalFreeBlock(blkmem, &(var)->exactdata->origdom.lb);
3644 SCIPrationalFreeBlock(blkmem, &(var)->exactdata->origdom.ub);
3645 SCIPrationalFreeBlock(blkmem, &(var)->exactdata->obj );
3646
3647 BMSfreeBlockMemory(blkmem, &(var)->exactdata);
3648 assert((var)->exactdata == NULL);
3649 }
3650
3651 return SCIP_OKAY;
3652}
3653
3654/** frees a variable */
3655static
3657 SCIP_VAR** var, /**< pointer to variable */
3658 BMS_BLKMEM* blkmem, /**< block memory */
3659 SCIP_SET* set, /**< global SCIP settings */
3660 SCIP_EVENTQUEUE* eventqueue, /**< event queue (may be NULL, if it's not a column variable) */
3661 SCIP_LP* lp /**< current LP data (may be NULL, if it's not a column variable) */
3662 )
3663{
3664 assert(var != NULL);
3665 assert(*var != NULL);
3666 assert(SCIPvarGetStatus(*var) != SCIP_VARSTATUS_COLUMN || &(*var)->data.col->var != var);
3667 assert((*var)->nuses == 0);
3668 assert((*var)->probindex == -1);
3669 assert((*var)->nlocksup[SCIP_LOCKTYPE_MODEL] == 0);
3670 assert((*var)->nlocksdown[SCIP_LOCKTYPE_MODEL] == 0);
3671
3672 SCIPsetDebugMsg(set, "free variable <%s> with status=%d\n", (*var)->name, SCIPvarGetStatus(*var));
3673
3674 switch( SCIPvarGetStatus(*var) )
3675 {
3677 assert((*var)->data.original.transvar == NULL); /* cannot free variable, if transformed variable is still existing */
3678 holelistFree(&(*var)->data.original.origdom.holelist, blkmem);
3679 assert((*var)->data.original.origdom.holelist == NULL);
3680 break;
3682 break;
3684 SCIP_CALL( SCIPcolFree(&(*var)->data.col, blkmem, set, eventqueue, lp) ); /* free corresponding LP column */
3685 break;
3688 break;
3690 BMSfreeBlockMemoryArray(blkmem, &(*var)->data.multaggr.vars, (*var)->data.multaggr.varssize);
3691 BMSfreeBlockMemoryArray(blkmem, &(*var)->data.multaggr.scalars, (*var)->data.multaggr.varssize);
3692 break;
3694 break;
3695 default:
3696 SCIPerrorMessage("unknown variable status\n");
3697 return SCIP_INVALIDDATA;
3698 }
3699
3700 /* release all parent variables and free the parentvars array */
3701 SCIP_CALL( varFreeParents(var, blkmem, set, eventqueue, lp) );
3702
3703 /* free user data */
3705 {
3706 if( (*var)->vardelorig != NULL )
3707 {
3708 SCIP_CALL( (*var)->vardelorig(set->scip, *var, &(*var)->vardata) );
3709 }
3710 }
3711 else
3712 {
3713 if( (*var)->vardeltrans != NULL )
3714 {
3715 SCIP_CALL( (*var)->vardeltrans(set->scip, *var, &(*var)->vardata) );
3716 }
3717 }
3718
3719 /* free event filter */
3720 if( (*var)->eventfilter != NULL )
3721 {
3722 SCIP_CALL( SCIPeventfilterFree(&(*var)->eventfilter, blkmem, set) );
3723 }
3724 assert((*var)->eventfilter == NULL);
3725
3726 /* free hole lists */
3727 holelistFree(&(*var)->glbdom.holelist, blkmem);
3728 holelistFree(&(*var)->locdom.holelist, blkmem);
3729 assert((*var)->glbdom.holelist == NULL);
3730 assert((*var)->locdom.holelist == NULL);
3731
3732 /* free variable bounds data structures */
3733 SCIPvboundsFree(&(*var)->vlbs, blkmem);
3734 SCIPvboundsFree(&(*var)->vubs, blkmem);
3735
3736 /* free implications data structures */
3737 SCIPimplicsFree(&(*var)->implics, blkmem);
3738
3739 /* free clique list data structures */
3740 SCIPcliquelistFree(&(*var)->cliquelist, blkmem);
3741
3742 /* free bound change information arrays */
3743 BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->lbchginfos, (*var)->lbchginfossize);
3744 BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->ubchginfos, (*var)->ubchginfossize);
3745
3746 /* free branching and inference history entries */
3747 SCIPhistoryFree(&(*var)->history, blkmem);
3748 SCIPhistoryFree(&(*var)->historycrun, blkmem);
3749 SCIPvaluehistoryFree(&(*var)->valuehistory, blkmem);
3750
3751 /* free exact data if it exists */
3752 SCIP_CALL( varFreeExactData(*var, blkmem, set) );
3753
3754 /* free variable data structure */
3755 BMSfreeBlockMemoryArray(blkmem, &(*var)->name, strlen((*var)->name)+1);
3756 BMSfreeBlockMemory(blkmem, var);
3757
3758 return SCIP_OKAY;
3759}
3760
3761/** increases usage counter of variable */
3763 SCIP_VAR* var /**< variable */
3764 )
3765{
3766 assert(var != NULL);
3767 assert(var->nuses >= 0);
3768
3769 SCIPdebugMessage("capture variable <%s> with nuses=%d\n", var->name, var->nuses);
3770 var->nuses++;
3771
3772#ifdef DEBUGUSES_VARNAME
3773 if( strcmp(var->name, DEBUGUSES_VARNAME) == 0
3774#ifdef DEBUGUSES_PROBNAME
3775 && ((var->scip->transprob != NULL && strcmp(SCIPprobGetName(var->scip->transprob), DEBUGUSES_PROBNAME) == 0) ||
3776 strcmp(SCIPprobGetName(var->scip->origprob), DEBUGUSES_PROBNAME) == 0)
3777#endif
3778 )
3779 {
3780 printf("Captured variable " DEBUGUSES_VARNAME " in SCIP %p, now %d uses; captured at\n", (void*)var->scip, var->nuses);
3781 print_backtrace();
3782 }
3783#endif
3784}
3785
3786/** decreases usage counter of variable, and frees memory if necessary */
3788 SCIP_VAR** var, /**< pointer to variable */
3789 BMS_BLKMEM* blkmem, /**< block memory */
3790 SCIP_SET* set, /**< global SCIP settings */
3791 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3792 SCIP_LP* lp /**< current LP data (or NULL, if it's an original variable) */
3793 )
3794{
3795 assert(var != NULL);
3796 assert(*var != NULL);
3797 assert((*var)->nuses >= 1);
3798 assert(blkmem != NULL);
3799 assert((*var)->scip == set->scip);
3800
3801 SCIPsetDebugMsg(set, "release variable <%s> with nuses=%d\n", (*var)->name, (*var)->nuses);
3802 (*var)->nuses--;
3803
3804#ifdef DEBUGUSES_VARNAME
3805 if( strcmp((*var)->name, DEBUGUSES_VARNAME) == 0
3806#ifdef DEBUGUSES_PROBNAME
3807 && (((*var)->scip->transprob != NULL && strcmp(SCIPprobGetName((*var)->scip->transprob), DEBUGUSES_PROBNAME) == 0) ||
3808 strcmp(SCIPprobGetName((*var)->scip->origprob), DEBUGUSES_PROBNAME) == 0)
3809#endif
3810 )
3811 {
3812 printf("Released variable " DEBUGUSES_VARNAME " in SCIP %p, now %d uses; released at\n", (void*)(*var)->scip, (*var)->nuses);
3813 print_backtrace();
3814 }
3815#endif
3816
3817 if( (*var)->nuses == 0 )
3818 {
3819 SCIP_CALL( varFree(var, blkmem, set, eventqueue, lp) );
3820 }
3821
3822 *var = NULL;
3823
3824 return SCIP_OKAY;
3825}
3826
3827/** change variable name */
3829 SCIP_VAR* var, /**< problem variable */
3830 BMS_BLKMEM* blkmem, /**< block memory */
3831 const char* name /**< name of variable */
3832 )
3833{
3834 assert(name != NULL);
3835
3836 /* remove old variable name */
3837 BMSfreeBlockMemoryArray(blkmem, &var->name, strlen(var->name)+1);
3838
3839 /* set new variable name */
3840 SCIP_CALL( varSetName(var, blkmem, NULL, name) );
3841
3842 return SCIP_OKAY;
3843}
3844
3845/** initializes variable data structure for solving */
3847 SCIP_VAR* var /**< problem variable */
3848 )
3849{
3850 assert(var != NULL);
3851
3852 SCIPhistoryReset(var->historycrun);
3853 var->conflictlbcount = 0;
3854 var->conflictubcount = 0;
3855}
3856
3857/** outputs the given bounds into the file stream */
3858static
3860 SCIP_SET* set, /**< global SCIP settings */
3861 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3862 FILE* file, /**< output file (or NULL for standard output) */
3863 SCIP_Real lb, /**< lower bound */
3864 SCIP_Real ub, /**< upper bound */
3865 const char* name /**< bound type name */
3866 )
3867{
3868 assert(set != NULL);
3869
3870 SCIPmessageFPrintInfo(messagehdlr, file, ", %s=[", name);
3871 if( SCIPsetIsInfinity(set, lb) )
3872 SCIPmessageFPrintInfo(messagehdlr, file, "+inf");
3873 else if( SCIPsetIsInfinity(set, -lb) )
3874 SCIPmessageFPrintInfo(messagehdlr, file, "-inf");
3875 else
3876 SCIPmessageFPrintInfo(messagehdlr, file, "%.15g", lb);
3877 SCIPmessageFPrintInfo(messagehdlr, file, ",");
3878 if( SCIPsetIsInfinity(set, ub) )
3879 SCIPmessageFPrintInfo(messagehdlr, file, "+inf");
3880 else if( SCIPsetIsInfinity(set, -ub) )
3881 SCIPmessageFPrintInfo(messagehdlr, file, "-inf");
3882 else
3883 SCIPmessageFPrintInfo(messagehdlr, file, "%.15g", ub);
3884 SCIPmessageFPrintInfo(messagehdlr, file, "]");
3885}
3886
3887/** outputs the given exact bounds into the file stream */
3888static
3890 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3891 FILE* file, /**< output file (or NULL for standard output) */
3892 SCIP_RATIONAL* lb, /**< exact lower bound */
3893 SCIP_RATIONAL* ub, /**< exact upper bound */
3894 const char* name /**< bound type name */
3895 )
3896{
3897 assert(lb != NULL);
3898 assert(ub != NULL);
3899
3900 SCIPmessageFPrintInfo(messagehdlr, file, ", %s=[", name);
3901 if( SCIPrationalIsInfinity(lb) )
3902 SCIPmessageFPrintInfo(messagehdlr, file, "+inf");
3903 else if( SCIPrationalIsNegInfinity(lb) )
3904 SCIPmessageFPrintInfo(messagehdlr, file, "-inf");
3905 else
3906 SCIPrationalMessage(messagehdlr, file, lb);
3907 SCIPmessageFPrintInfo(messagehdlr, file, ",");
3908 if( SCIPrationalIsInfinity(ub) )
3909 SCIPmessageFPrintInfo(messagehdlr, file, "+inf");
3910 else if( SCIPrationalIsNegInfinity(ub) )
3911 SCIPmessageFPrintInfo(messagehdlr, file, "-inf");
3912 else
3913 SCIPrationalMessage(messagehdlr, file, ub);
3914 SCIPmessageFPrintInfo(messagehdlr, file, "]");
3915}
3916
3917/** prints hole list to file stream */
3918static
3920 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3921 FILE* file, /**< output file (or NULL for standard output) */
3922 SCIP_HOLELIST* holelist, /**< hole list pointer to hole of interest */
3923 const char* name /**< hole type name */
3924 )
3925{ /*lint --e{715}*/
3926 SCIP_Real left;
3927 SCIP_Real right;
3928
3929 if( holelist == NULL )
3930 return;
3931
3932 left = SCIPholelistGetLeft(holelist);
3933 right = SCIPholelistGetRight(holelist);
3934
3935 /* display first hole */
3936 SCIPmessageFPrintInfo(messagehdlr, file, ", %s=(%g,%g)", name, left, right);
3937 holelist = SCIPholelistGetNext(holelist);
3938
3939 while(holelist != NULL )
3940 {
3941 left = SCIPholelistGetLeft(holelist);
3942 right = SCIPholelistGetRight(holelist);
3943
3944 /* display hole */
3945 SCIPmessageFPrintInfo(messagehdlr, file, "(%g,%g)", left, right);
3946
3947 /* get next hole */
3948 holelist = SCIPholelistGetNext(holelist);
3949 }
3950}
3951
3952/** outputs variable information into file stream */
3954 SCIP_VAR* var, /**< problem variable */
3955 SCIP_SET* set, /**< global SCIP settings */
3956 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3957 FILE* file /**< output file (or NULL for standard output) */
3958 )
3959{
3960 assert(var != NULL);
3961 assert(var->scip == set->scip);
3962 assert(set != NULL);
3963 assert(set->write_implintlevel >= -2);
3964 assert(set->write_implintlevel <= 2);
3965
3966 SCIP_VARTYPE vartype = SCIPvarGetType(var);
3968 int i;
3969
3970 /* change integrality constraints of implied integral variables based on the writing settings */
3971 if( vartype == SCIP_VARTYPE_CONTINUOUS )
3972 {
3973 if( (int)impltype > 2 - set->write_implintlevel )
3974 vartype = SCIP_VARTYPE_INTEGER;
3975 }
3976 else
3977 {
3978 if( (int)impltype > 2 + set->write_implintlevel )
3979 vartype = SCIP_VARTYPE_CONTINUOUS;
3980 }
3981
3982 /* type of variable */
3983 switch( vartype )
3984 {
3986 SCIPmessageFPrintInfo(messagehdlr, file, " [binary]");
3987 break;
3989 SCIPmessageFPrintInfo(messagehdlr, file, " [integer]");
3990 break;
3992 SCIPmessageFPrintInfo(messagehdlr, file, " [continuous]");
3993 break;
3995 default:
3996 SCIPerrorMessage("unknown variable type\n");
3997 return SCIP_INVALIDDATA;
3998 } /*lint !e788*/
3999
4000 /* name */
4001 SCIPmessageFPrintInfo(messagehdlr, file, " <%s>:", var->name);
4002
4003 if( var->exactdata != NULL )
4004 {
4005 assert(set->exact_enable);
4006
4007 SCIP_RATIONAL* lb;
4008 SCIP_RATIONAL* ub;
4009
4010 /* exact objective value */
4011 assert(var->exactdata->obj != NULL);
4012 SCIPmessageFPrintInfo(messagehdlr, file, " obj=");
4013 SCIPrationalMessage(messagehdlr, file, var->exactdata->obj);
4014
4015 /* exact bounds (global bounds for transformed variables, original bounds for original variables) */
4017 {
4018 /* output exact original bounds */
4021 printBoundsExact(messagehdlr, file, lb, ub, "original bounds");
4022
4023 /**@todo get exact lazy bounds */
4024 /**@todo output exact lazy bounds */
4026 {
4027 SCIPerrorMessage("exact lazy bounds not supported yet\n");
4028 return SCIP_INVALIDDATA;
4029 }
4030
4032 }
4033 else
4034 {
4035 /* output exact global bounds */
4038 printBoundsExact(messagehdlr, file, lb, ub, "global bounds");
4039
4040 /* output exact local bounds */
4043 printBoundsExact(messagehdlr, file, lb, ub, "local bounds");
4044
4045 /**@todo get exact lazy bounds */
4046 /**@todo output exact lazy bounds */
4048 {
4049 SCIPerrorMessage("exact lazy bounds not supported yet\n");
4050 return SCIP_INVALIDDATA;
4051 }
4052
4055 }
4056 }
4057 else
4058 {
4059 assert(!set->exact_enable);
4060
4061 SCIP_Real lb;
4062 SCIP_Real ub;
4063
4064 /* objective value */
4065 SCIPmessageFPrintInfo(messagehdlr, file, " obj=%.15g", var->obj);
4066
4067 /* bounds (global bounds for transformed variables, original bounds for original variables) */
4069 {
4070 /* output original bounds */
4073 printBounds(set, messagehdlr, file, lb, ub, "original bounds");
4074
4075 /* output lazy bounds */
4076 lb = SCIPvarGetLbLazy(var);
4077 ub = SCIPvarGetUbLazy(var);
4078
4079 /* only display the lazy bounds if they are different from [-infinity,infinity] */
4080 if( !SCIPsetIsInfinity(set, -lb) || !SCIPsetIsInfinity(set, ub) )
4081 printBounds(set, messagehdlr, file, lb, ub, "lazy bounds");
4082
4083 /* original hole list */
4084 printHolelist(messagehdlr, file, SCIPvarGetHolelistOriginal(var), "original holes");
4085 }
4086 else
4087 {
4088 /* output global bounds */
4089 lb = SCIPvarGetLbGlobal(var);
4090 ub = SCIPvarGetUbGlobal(var);
4091 printBounds(set, messagehdlr, file, lb, ub, "global bounds");
4092
4093 /* output local bounds */
4094 lb = SCIPvarGetLbLocal(var);
4095 ub = SCIPvarGetUbLocal(var);
4096 printBounds(set, messagehdlr, file, lb, ub, "local bounds");
4097
4098 /* output lazy bounds */
4099 lb = SCIPvarGetLbLazy(var);
4100 ub = SCIPvarGetUbLazy(var);
4101
4102 /* only display the lazy bounds if they are different from [-infinity,infinity] */
4103 if( !SCIPsetIsInfinity(set, -lb) || !SCIPsetIsInfinity(set, ub) )
4104 printBounds(set, messagehdlr, file, lb, ub, "lazy bounds");
4105
4106 /* global hole list */
4107 printHolelist(messagehdlr, file, SCIPvarGetHolelistGlobal(var), "global holes");
4108
4109 /* local hole list */
4110 printHolelist(messagehdlr, file, SCIPvarGetHolelistLocal(var), "local holes");
4111 }
4112 }
4113
4114 /* implication of variable */
4115 switch( impltype )
4116 {
4118 break;
4120 SCIPmessageFPrintInfo(messagehdlr, file, ", implied: weak");
4121 break;
4123 SCIPmessageFPrintInfo(messagehdlr, file, ", implied: strong");
4124 break;
4125 default:
4126 SCIPerrorMessage("unknown implied type\n");
4127 return SCIP_INVALIDDATA;
4128 }
4129
4130 /* fixings and aggregations */
4131 switch( SCIPvarGetStatus(var) )
4132 {
4136 break;
4137
4139 SCIPmessageFPrintInfo(messagehdlr, file, ", fixed:");
4140 if( SCIPsetIsInfinity(set, var->glbdom.lb) )
4141 SCIPmessageFPrintInfo(messagehdlr, file, "+inf");
4142 else if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
4143 SCIPmessageFPrintInfo(messagehdlr, file, "-inf");
4144 else
4145 SCIPmessageFPrintInfo(messagehdlr, file, "%.15g", var->glbdom.lb);
4146 break;
4147
4149 SCIPmessageFPrintInfo(messagehdlr, file, ", aggregated:");
4150 if( !SCIPsetIsZero(set, var->data.aggregate.constant) )
4151 SCIPmessageFPrintInfo(messagehdlr, file, " %.15g", var->data.aggregate.constant);
4152 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g<%s>", var->data.aggregate.scalar, SCIPvarGetName(var->data.aggregate.var));
4153 break;
4154
4156 SCIPmessageFPrintInfo(messagehdlr, file, ", aggregated:");
4157 if( var->data.multaggr.nvars == 0 || !SCIPsetIsZero(set, var->data.multaggr.constant) )
4158 SCIPmessageFPrintInfo(messagehdlr, file, " %.15g", var->data.multaggr.constant);
4159 for( i = 0; i < var->data.multaggr.nvars; ++i )
4160 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g<%s>", var->data.multaggr.scalars[i], SCIPvarGetName(var->data.multaggr.vars[i]));
4161 break;
4162
4164 SCIPmessageFPrintInfo(messagehdlr, file, ", negated: %.15g - <%s>", var->data.negate.constant, SCIPvarGetName(var->negatedvar));
4165 break;
4166
4167 default:
4168 SCIPerrorMessage("unknown variable status\n");
4169 return SCIP_INVALIDDATA;
4170 }
4171
4172 SCIPmessageFPrintInfo(messagehdlr, file, "\n");
4173
4174 return SCIP_OKAY;
4175}
4176
4177/** issues a VARUNLOCKED event on the given variable */
4178static
4180 SCIP_VAR* var, /**< problem variable to change */
4181 BMS_BLKMEM* blkmem, /**< block memory */
4182 SCIP_SET* set, /**< global SCIP settings */
4183 SCIP_EVENTQUEUE* eventqueue /**< event queue */
4184 )
4185{
4186 SCIP_EVENT* event;
4187
4188 assert(var != NULL);
4189 assert(var->nlocksdown[SCIP_LOCKTYPE_MODEL] <= 1 && var->nlocksup[SCIP_LOCKTYPE_MODEL] <= 1);
4190 assert(var->scip == set->scip);
4191
4192 /* issue VARUNLOCKED event on variable */
4193 SCIP_CALL( SCIPeventCreateVarUnlocked(&event, blkmem, var) );
4194 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
4195
4196 return SCIP_OKAY;
4197}
4198
4199/** modifies lock numbers for rounding */
4201 SCIP_VAR* var, /**< problem variable */
4202 BMS_BLKMEM* blkmem, /**< block memory */
4203 SCIP_SET* set, /**< global SCIP settings */
4204 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4205 SCIP_LOCKTYPE locktype, /**< type of the variable locks */
4206 int addnlocksdown, /**< increase in number of rounding down locks */
4207 int addnlocksup /**< increase in number of rounding up locks */
4208 )
4209{
4210 SCIP_VAR* lockvar;
4211
4212 assert(var != NULL);
4213 assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
4214 assert(var->nlocksup[locktype] >= 0);
4215 assert(var->nlocksdown[locktype] >= 0);
4216 assert(var->scip == set->scip);
4217
4218 if( addnlocksdown == 0 && addnlocksup == 0 )
4219 return SCIP_OKAY;
4220
4221#ifdef SCIP_DEBUG
4222 SCIPsetDebugMsg(set, "add rounding locks %d/%d to variable <%s> (locks=%d/%d, type=%u)\n",
4223 addnlocksdown, addnlocksup, var->name, var->nlocksdown[locktype], var->nlocksup[locktype], locktype);
4224#endif
4225
4226 lockvar = var;
4227
4228 while( TRUE ) /*lint !e716 */
4229 {
4230 assert(lockvar != NULL);
4231
4232 switch( SCIPvarGetStatus(lockvar) )
4233 {
4235 if( lockvar->data.original.transvar != NULL )
4236 {
4237 lockvar = lockvar->data.original.transvar;
4238 break;
4239 }
4240 else
4241 {
4242 lockvar->nlocksdown[locktype] += addnlocksdown;
4243 lockvar->nlocksup[locktype] += addnlocksup;
4244
4245 assert(lockvar->nlocksdown[locktype] >= 0);
4246 assert(lockvar->nlocksup[locktype] >= 0);
4247
4248 return SCIP_OKAY;
4249 }
4253 lockvar->nlocksdown[locktype] += addnlocksdown;
4254 lockvar->nlocksup[locktype] += addnlocksup;
4255
4256 assert(lockvar->nlocksdown[locktype] >= 0);
4257 assert(lockvar->nlocksup[locktype] >= 0);
4258
4259 if( locktype == SCIP_LOCKTYPE_MODEL && lockvar->nlocksdown[locktype] <= 1
4260 && lockvar->nlocksup[locktype] <= 1 )
4261 {
4262 SCIP_CALL( varEventVarUnlocked(lockvar, blkmem, set, eventqueue) );
4263 }
4264
4265 return SCIP_OKAY;
4267 assert(!lockvar->donotaggr);
4268
4269 if( lockvar->data.aggregate.scalar < 0.0 )
4270 {
4271 int tmp = addnlocksup;
4272
4273 addnlocksup = addnlocksdown;
4274 addnlocksdown = tmp;
4275 }
4276
4277 lockvar = lockvar->data.aggregate.var;
4278 break;
4280 {
4281 int v;
4282
4283 assert(!lockvar->donotmultaggr);
4284
4285 lockvar->nlocksdown[locktype] += addnlocksdown;
4286 lockvar->nlocksup[locktype] += addnlocksup;
4287
4288 assert(lockvar->nlocksdown[locktype] >= 0);
4289 assert(lockvar->nlocksup[locktype] >= 0);
4290
4291 for( v = lockvar->data.multaggr.nvars - 1; v >= 0; --v )
4292 {
4293 if( lockvar->data.multaggr.scalars[v] > 0.0 )
4294 {
4295 SCIP_CALL( SCIPvarAddLocks(lockvar->data.multaggr.vars[v], blkmem, set, eventqueue, locktype, addnlocksdown,
4296 addnlocksup) );
4297 }
4298 else
4299 {
4300 SCIP_CALL( SCIPvarAddLocks(lockvar->data.multaggr.vars[v], blkmem, set, eventqueue, locktype, addnlocksup,
4301 addnlocksdown) );
4302 }
4303 }
4304 return SCIP_OKAY;
4305 }
4307 {
4308 int tmp = addnlocksup;
4309
4310 assert(lockvar->negatedvar != NULL);
4312 assert(lockvar->negatedvar->negatedvar == lockvar);
4313
4314 addnlocksup = addnlocksdown;
4315 addnlocksdown = tmp;
4316
4317 lockvar = lockvar->negatedvar;
4318 break;
4319 }
4320 default:
4321 SCIPerrorMessage("unknown variable status\n");
4322 return SCIP_INVALIDDATA;
4323 }
4324 }
4325}
4326
4327/** gets number of locks for rounding down of a special type */
4329 SCIP_VAR* var, /**< problem variable */
4330 SCIP_LOCKTYPE locktype /**< type of variable locks */
4331 )
4332{
4333 int nlocks;
4334 int i;
4335
4336 assert(var != NULL);
4337 assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
4338 assert(var->nlocksdown[locktype] >= 0);
4339
4340 switch( SCIPvarGetStatus(var) )
4341 {
4343 if( var->data.original.transvar != NULL )
4344 return SCIPvarGetNLocksDownType(var->data.original.transvar, locktype);
4345 else
4346 return var->nlocksdown[locktype];
4347
4351 return var->nlocksdown[locktype];
4352
4354 assert(!var->donotaggr);
4355 if( var->data.aggregate.scalar > 0.0 )
4356 return SCIPvarGetNLocksDownType(var->data.aggregate.var, locktype);
4357 else
4358 return SCIPvarGetNLocksUpType(var->data.aggregate.var, locktype);
4359
4361 assert(!var->donotmultaggr);
4362 nlocks = 0;
4363 for( i = 0; i < var->data.multaggr.nvars; ++i )
4364 {
4365 if( var->data.multaggr.scalars[i] > 0.0 )
4366 nlocks += SCIPvarGetNLocksDownType(var->data.multaggr.vars[i], locktype);
4367 else
4368 nlocks += SCIPvarGetNLocksUpType(var->data.multaggr.vars[i], locktype);
4369 }
4370 return nlocks;
4371
4373 assert(var->negatedvar != NULL);
4375 assert(var->negatedvar->negatedvar == var);
4376 return SCIPvarGetNLocksUpType(var->negatedvar, locktype);
4377
4378 default:
4379 SCIPerrorMessage("unknown variable status\n");
4380 SCIPABORT();
4381 return INT_MAX; /*lint !e527*/
4382 }
4383}
4384
4385/** gets number of locks for rounding up of a special type */
4387 SCIP_VAR* var, /**< problem variable */
4388 SCIP_LOCKTYPE locktype /**< type of variable locks */
4389 )
4390{
4391 int nlocks;
4392 int i;
4393
4394 assert(var != NULL);
4395 assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
4396 assert(var->nlocksup[locktype] >= 0);
4397
4398 switch( SCIPvarGetStatus(var) )
4399 {
4401 if( var->data.original.transvar != NULL )
4402 return SCIPvarGetNLocksUpType(var->data.original.transvar, locktype);
4403 else
4404 return var->nlocksup[locktype];
4405
4409 return var->nlocksup[locktype];
4410
4412 assert(!var->donotaggr);
4413 if( var->data.aggregate.scalar > 0.0 )
4414 return SCIPvarGetNLocksUpType(var->data.aggregate.var, locktype);
4415 else
4416 return SCIPvarGetNLocksDownType(var->data.aggregate.var, locktype);
4417
4419 assert(!var->donotmultaggr);
4420 nlocks = 0;
4421 for( i = 0; i < var->data.multaggr.nvars; ++i )
4422 {
4423 if( var->data.multaggr.scalars[i] > 0.0 )
4424 nlocks += SCIPvarGetNLocksUpType(var->data.multaggr.vars[i], locktype);
4425 else
4426 nlocks += SCIPvarGetNLocksDownType(var->data.multaggr.vars[i], locktype);
4427 }
4428 return nlocks;
4429
4431 assert(var->negatedvar != NULL);
4433 assert(var->negatedvar->negatedvar == var);
4434 return SCIPvarGetNLocksDownType(var->negatedvar, locktype);
4435
4436 default:
4437 SCIPerrorMessage("unknown variable status\n");
4438 SCIPABORT();
4439 return INT_MAX; /*lint !e527*/
4440 }
4441}
4442
4443/** gets number of locks for rounding down
4444 *
4445 * @note This method will always return variable locks of type model
4446 *
4447 * @note It is recommented to use SCIPvarGetNLocksDownType()
4448 */
4450 SCIP_VAR* var /**< problem variable */
4451 )
4452{
4454}
4455
4456/** gets number of locks for rounding up
4457 *
4458 * @note This method will always return variable locks of type model
4459 *
4460 * @note It is recommented to use SCIPvarGetNLocksUpType()
4461 */
4463 SCIP_VAR* var /**< problem variable */
4464 )
4465{
4467}
4468
4469/** is it possible, to round variable down and stay feasible?
4470 *
4471 * @note This method will always check w.r.t variable locks of type model
4472 */
4474 SCIP_VAR* var /**< problem variable */
4475 )
4476{
4478}
4479
4480/** is it possible, to round variable up and stay feasible?
4481 *
4482 * @note This method will always check w.r.t. variable locks of type model
4483 */
4485 SCIP_VAR* var /**< problem variable */
4486 )
4487{
4489}
4490
4491/** gets and captures transformed variable of a given variable; if the variable is not yet transformed,
4492 * a new transformed variable for this variable is created
4493 */
4495 SCIP_VAR* origvar, /**< original problem variable */
4496 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
4497 SCIP_SET* set, /**< global SCIP settings */
4498 SCIP_STAT* stat, /**< problem statistics */
4499 SCIP_OBJSENSE objsense, /**< objective sense of original problem; transformed is always MINIMIZE */
4500 SCIP_VAR** transvar /**< pointer to store the transformed variable */
4501 )
4502{
4503 char name[SCIP_MAXSTRLEN];
4504
4505 assert(origvar != NULL);
4506 assert(origvar->scip == set->scip);
4508 assert(SCIPsetIsEQ(set, origvar->glbdom.lb, origvar->locdom.lb));
4509 assert(SCIPsetIsEQ(set, origvar->glbdom.ub, origvar->locdom.ub));
4510 assert(origvar->vlbs == NULL);
4511 assert(origvar->vubs == NULL);
4512 assert(transvar != NULL);
4513
4514 /* check if variable is already transformed */
4515 if( origvar->data.original.transvar != NULL )
4516 {
4517 *transvar = origvar->data.original.transvar;
4518 SCIPvarCapture(*transvar);
4519 }
4520 else
4521 {
4522 int i;
4523
4524 /* create transformed variable */
4525 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "t_%s", origvar->name);
4526 SCIP_CALL( SCIPvarCreateTransformed(transvar, blkmem, set, stat, name,
4527 origvar->glbdom.lb, origvar->glbdom.ub, (SCIP_Real)objsense * origvar->obj,
4528 SCIPvarGetType(origvar), SCIPvarGetImplType(origvar), origvar->initial, origvar->removable,
4529 origvar->vardelorig, origvar->vartrans, origvar->vardeltrans, origvar->varcopy, NULL) );
4530
4531 /* copy the branch factor and priority */
4532 (*transvar)->branchfactor = origvar->branchfactor;
4533 (*transvar)->branchpriority = origvar->branchpriority;
4534 (*transvar)->branchdirection = origvar->branchdirection; /*lint !e732*/
4535
4536 /* duplicate hole lists */
4537 SCIP_CALL( holelistDuplicate(&(*transvar)->glbdom.holelist, blkmem, set, origvar->glbdom.holelist) );
4538 SCIP_CALL( holelistDuplicate(&(*transvar)->locdom.holelist, blkmem, set, origvar->locdom.holelist) );
4539
4540 /* link original and transformed variable */
4541 origvar->data.original.transvar = *transvar;
4542 SCIP_CALL( varAddParent(*transvar, blkmem, set, origvar) );
4543
4544 /* copy rounding locks */
4545 for( i = 0; i < NLOCKTYPES; i++ )
4546 {
4547 (*transvar)->nlocksdown[i] = origvar->nlocksdown[i];
4548 (*transvar)->nlocksup[i] = origvar->nlocksup[i];
4549 assert((*transvar)->nlocksdown[i] >= 0);
4550 assert((*transvar)->nlocksup[i] >= 0);
4551 }
4552
4553 /* copy donot(mult)aggr status */
4554 (*transvar)->donotaggr = origvar->donotaggr;
4555 (*transvar)->donotmultaggr = origvar->donotmultaggr;
4556
4557 /* copy lazy bounds */
4558 (*transvar)->lazylb = origvar->lazylb;
4559 (*transvar)->lazyub = origvar->lazyub;
4560
4561 /* transfer eventual variable statistics; do not update global statistics, because this has been done
4562 * when original variable was created
4563 */
4564 SCIPhistoryUnite((*transvar)->history, origvar->history, FALSE);
4565
4566 /* transform user data */
4567 if( origvar->vartrans != NULL )
4568 {
4569 SCIP_CALL( origvar->vartrans(set->scip, origvar, origvar->vardata, *transvar, &(*transvar)->vardata) );
4570 }
4571 else
4572 (*transvar)->vardata = origvar->vardata;
4573 }
4574
4575 SCIPsetDebugMsg(set, "transformed variable: <%s>[%p] -> <%s>[%p]\n", origvar->name, (void*)origvar, (*transvar)->name, (void*)*transvar);
4576
4577 return SCIP_OKAY;
4578}
4579
4580/** gets corresponding transformed variable of an original or negated original variable */
4582 SCIP_VAR* origvar, /**< original problem variable */
4583 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
4584 SCIP_SET* set, /**< global SCIP settings */
4585 SCIP_STAT* stat, /**< problem statistics */
4586 SCIP_VAR** transvar /**< pointer to store the transformed variable, or NULL if not existing yet */
4587 )
4588{
4589 assert(origvar != NULL);
4591 assert(origvar->scip == set->scip);
4592
4594 {
4595 assert(origvar->negatedvar != NULL);
4597
4598 if( origvar->negatedvar->data.original.transvar == NULL )
4599 *transvar = NULL;
4600 else
4601 {
4602 SCIP_CALL( SCIPvarNegate(origvar->negatedvar->data.original.transvar, blkmem, set, stat, transvar) );
4603 }
4604 }
4605 else
4606 *transvar = origvar->data.original.transvar;
4607
4608 return SCIP_OKAY;
4609}
4610
4611/** converts loose transformed variable into column variable, creates LP column */
4613 SCIP_VAR* var, /**< problem variable */
4614 BMS_BLKMEM* blkmem, /**< block memory */
4615 SCIP_SET* set, /**< global SCIP settings */
4616 SCIP_STAT* stat, /**< problem statistics */
4617 SCIP_PROB* prob, /**< problem data */
4618 SCIP_LP* lp /**< current LP data */
4619 )
4620{
4621 assert(var != NULL);
4623 assert(var->scip == set->scip);
4624
4625 SCIPsetDebugMsg(set, "creating column for variable <%s>\n", var->name);
4626
4627 /* switch variable status */
4628 var->varstatus = SCIP_VARSTATUS_COLUMN; /*lint !e641*/
4629
4630 /* create column of variable */
4631 SCIP_CALL( SCIPcolCreate(&var->data.col, blkmem, set, stat, var, 0, NULL, NULL, var->removable) );
4632
4633 if( var->probindex != -1 )
4634 {
4635 /* inform problem about the variable's status change */
4636 SCIP_CALL( SCIPprobVarChangedStatus(prob, blkmem, set, NULL, NULL, var) );
4637
4638 /* inform LP, that problem variable is now a column variable and no longer loose */
4640 }
4641
4642 return SCIP_OKAY;
4643}
4644
4645/** converts loose transformed variable into column variable, creates LP column */
4647 SCIP_VAR* var, /**< problem variable */
4648 BMS_BLKMEM* blkmem, /**< block memory */
4649 SCIP_SET* set, /**< global SCIP settings */
4650 SCIP_STAT* stat, /**< problem statistics */
4651 SCIP_LPEXACT* lp /**< current LP data */
4652 )
4653{
4654 if( !set->exact_enable )
4655 return SCIP_OKAY;
4656
4657 assert(var != NULL);
4658 assert(var->exactdata->colexact == NULL);
4659 assert(var->scip == set->scip);
4660 assert(var->exactdata != NULL);
4661
4662 SCIPsetDebugMsg(set, "creating exact column for variable <%s>\n", var->name);
4663
4664 /* switch variable status */
4665 var->exactdata->varstatusexact = SCIP_VARSTATUS_COLUMN; /*lint !e641*/
4666
4667 /* create column of variable */
4668 SCIP_CALL( SCIPcolExactCreate(&(var->exactdata->colexact), SCIPvarGetCol(var), blkmem, set, stat, var, 0, NULL, NULL, var->removable) );
4669
4670 if( var->probindex != -1 )
4671 {
4672 /* inform LP, that problem variable is now a column variable and no longer loose */
4674 }
4675
4676 return SCIP_OKAY;
4677}
4678
4679/** converts column transformed variable back into loose variable, frees LP column */
4681 SCIP_VAR* var, /**< problem variable */
4682 BMS_BLKMEM* blkmem, /**< block memory */
4683 SCIP_SET* set, /**< global SCIP settings */
4684 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4685 SCIP_PROB* prob, /**< problem data */
4686 SCIP_LP* lp /**< current LP data */
4687 )
4688{
4689 assert(var != NULL);
4691 assert(var->scip == set->scip);
4692 assert(var->data.col != NULL);
4693 assert(var->data.col->lppos == -1);
4694 assert(var->data.col->lpipos == -1);
4695
4696 SCIPsetDebugMsg(set, "deleting column for variable <%s>\n", var->name);
4697
4698 /* free column of variable */
4699 SCIP_CALL( SCIPcolFree(&var->data.col, blkmem, set, eventqueue, lp) );
4700
4701 /* switch variable status */
4702 var->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
4703
4704 if( var->probindex != -1 )
4705 {
4706 /* inform problem about the variable's status change */
4707 SCIP_CALL( SCIPprobVarChangedStatus(prob, blkmem, set, NULL, NULL, var) );
4708
4709 /* inform LP, that problem variable is now a loose variable and no longer a column */
4711 }
4712
4713 /* initialize variable data */
4714 var->data.loose.minaggrcoef = 1.0;
4715 var->data.loose.maxaggrcoef = 1.0;
4716
4717 return SCIP_OKAY;
4718}
4719
4720/** issues a VARFIXED event on the given variable and all its parents (except ORIGINAL parents);
4721 * the event issuing on the parents is necessary, because unlike with bound changes, the parent variables
4722 * are not informed about a fixing of an active variable they are pointing to
4723 */
4724static
4726 SCIP_VAR* var, /**< problem variable to change */
4727 BMS_BLKMEM* blkmem, /**< block memory */
4728 SCIP_SET* set, /**< global SCIP settings */
4729 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4730 int fixeventtype /**< is this event a fixation(0), an aggregation(1), or a
4731 * multi-aggregation(2)
4732 */
4733 )
4734{
4735 SCIP_EVENT* event;
4736 SCIP_VARSTATUS varstatus;
4737 int i;
4738
4739 assert(var != NULL);
4740 assert(var->scip == set->scip);
4741 assert(0 <= fixeventtype && fixeventtype <= 2);
4742
4743 /* issue VARFIXED event on variable */
4744 SCIP_CALL( SCIPeventCreateVarFixed(&event, blkmem, var) );
4745 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
4746
4747#ifndef NDEBUG
4748 for( i = var->nparentvars -1; i >= 0; --i )
4749 {
4751 }
4752#endif
4753
4754 switch( fixeventtype )
4755 {
4756 case 0:
4757 /* process all parents of a fixed variable */
4758 for( i = var->nparentvars - 1; i >= 0; --i )
4759 {
4760 varstatus = SCIPvarGetStatus(var->parentvars[i]);
4761
4762 assert(varstatus != SCIP_VARSTATUS_FIXED);
4763
4764 /* issue event on all not yet fixed parent variables, (that should already issued this event) except the original
4765 * one
4766 */
4767 if( varstatus != SCIP_VARSTATUS_ORIGINAL )
4768 {
4769 SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
4770 }
4771 }
4772 break;
4773 case 1:
4774 /* process all parents of a aggregated variable */
4775 for( i = var->nparentvars - 1; i >= 0; --i )
4776 {
4777 varstatus = SCIPvarGetStatus(var->parentvars[i]);
4778
4779 assert(varstatus != SCIP_VARSTATUS_FIXED);
4780
4781 /* issue event for not aggregated parent variable, because for these and its parents the var event was already
4782 * issued(, except the original one)
4783 *
4784 * @note that even before an aggregated parent variable, there might be variables, for which the vent was not
4785 * yet issued
4786 */
4787 if( varstatus == SCIP_VARSTATUS_AGGREGATED )
4788 continue;
4789
4790 if( varstatus != SCIP_VARSTATUS_ORIGINAL )
4791 {
4792 SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
4793 }
4794 }
4795 break;
4796 case 2:
4797 /* process all parents of a aggregated variable */
4798 for( i = var->nparentvars - 1; i >= 0; --i )
4799 {
4800 varstatus = SCIPvarGetStatus(var->parentvars[i]);
4801
4802 assert(varstatus != SCIP_VARSTATUS_FIXED);
4803
4804 /* issue event on all parent variables except the original one */
4805 if( varstatus != SCIP_VARSTATUS_ORIGINAL )
4806 {
4807 SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
4808 }
4809 }
4810 break;
4811 default:
4812 SCIPerrorMessage("unknown variable fixation event origin\n");
4813 return SCIP_INVALIDDATA;
4814 }
4815
4816 return SCIP_OKAY;
4817}
4818
4819/** converts variable into fixed variable */
4821 SCIP_VAR* var, /**< problem variable */
4822 BMS_BLKMEM* blkmem, /**< block memory */
4823 SCIP_SET* set, /**< global SCIP settings */
4824 SCIP_STAT* stat, /**< problem statistics */
4825 SCIP_PROB* transprob, /**< tranformed problem data */
4826 SCIP_PROB* origprob, /**< original problem data */
4827 SCIP_PRIMAL* primal, /**< primal data */
4828 SCIP_TREE* tree, /**< branch and bound tree */
4829 SCIP_REOPT* reopt, /**< reoptimization data structure */
4830 SCIP_LP* lp, /**< current LP data */
4831 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4832 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4833 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
4834 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4835 SCIP_Real fixedval, /**< value to fix variable at */
4836 SCIP_Bool* infeasible, /**< pointer to store whether the fixing is infeasible */
4837 SCIP_Bool* fixed /**< pointer to store whether the fixing was performed (variable was unfixed) */
4838 )
4839{
4840 SCIP_Real obj;
4841 SCIP_Real childfixedval;
4842
4843 assert(var != NULL);
4844 assert(var->scip == set->scip);
4845 assert(SCIPsetIsEQ(set, var->glbdom.lb, var->locdom.lb));
4846 assert(SCIPsetIsEQ(set, var->glbdom.ub, var->locdom.ub));
4847 assert(!SCIPsetIsInfinity(set, REALABS(fixedval)));
4848 assert(infeasible != NULL);
4849 assert(fixed != NULL);
4850
4851 SCIPsetDebugMsg(set, "fix variable <%s>[%g,%g] to %g\n", var->name, var->glbdom.lb, var->glbdom.ub, fixedval);
4852
4853 *infeasible = FALSE;
4854 *fixed = FALSE;
4855
4857 {
4858 *infeasible = !SCIPsetIsFeasEQ(set, fixedval, var->locdom.lb);
4859 SCIPsetDebugMsg(set, " -> variable already fixed to %g (fixedval=%g): infeasible=%u\n", var->locdom.lb, fixedval, *infeasible);
4860 return SCIP_OKAY;
4861 }
4862 else if( ( SCIPvarIsIntegral(var) && !SCIPsetIsFeasIntegral(set, fixedval) )
4863 || SCIPsetIsFeasLT(set, fixedval, var->locdom.lb)
4864 || SCIPsetIsFeasGT(set, fixedval, var->locdom.ub) )
4865 {
4866 SCIPsetDebugMsg(set, " -> fixing infeasible: locdom=[%g,%g], fixedval=%g\n", var->locdom.lb, var->locdom.ub, fixedval);
4867 *infeasible = TRUE;
4868 return SCIP_OKAY;
4869 }
4870
4871 switch( SCIPvarGetStatus(var) )
4872 {
4874 if( var->data.original.transvar == NULL )
4875 {
4876 SCIPerrorMessage("cannot fix an untransformed original variable\n");
4877 return SCIP_INVALIDDATA;
4878 }
4879 SCIP_CALL( SCIPvarFix(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
4880 lp, branchcand, eventqueue, eventfilter, cliquetable, fixedval, infeasible, fixed) );
4881 break;
4882
4884 assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
4885
4886 /* set the fixed variable's objective value to 0.0 */
4887 obj = var->obj;
4888 SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
4889
4890 /* since we change the variable type form loose to fixed, we have to adjust the number of loose
4891 * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
4892 * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
4893 * objective of this variable is set to zero
4894 */
4896
4897 /* free hole lists */
4898 holelistFree(&var->glbdom.holelist, blkmem);
4899 holelistFree(&var->locdom.holelist, blkmem);
4900
4901 /* adjust fixed value */
4902 if( SCIPvarIsIntegral(var) )
4903 fixedval = SCIPsetRound(set, fixedval);
4904
4905 /* change variable bounds to fixed value */
4906 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, fixedval) );
4907 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, fixedval) );
4908
4909 /* explicitly set variable's bounds if the fixed value was in epsilon range of the old bound (so above call didn't set bound) */
4910 var->glbdom.lb = fixedval;
4911 var->glbdom.ub = fixedval;
4912
4913 /* ensure local domain is fixed to same value as global domain */
4914 var->locdom.lb = fixedval;
4915 var->locdom.ub = fixedval;
4916
4917 /* delete implications and variable bounds information */
4918 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
4919 assert(var->vlbs == NULL);
4920 assert(var->vubs == NULL);
4921 assert(var->implics == NULL);
4922
4923 /* clear the history of the variable */
4924 SCIPhistoryReset(var->history);
4925 SCIPhistoryReset(var->historycrun);
4926
4927 /* convert variable into fixed variable */
4928 var->varstatus = SCIP_VARSTATUS_FIXED; /*lint !e641*/
4929
4930 /* inform problem about the variable's status change */
4931 if( var->probindex != -1 )
4932 {
4933 SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
4934 }
4935
4936 /* reset the objective value of the fixed variable, thus adjusting the problem's objective offset */
4937 SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventqueue, eventfilter, obj) );
4938
4939 /* issue VARFIXED event */
4940 SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 0) );
4941
4942 *fixed = TRUE;
4943 break;
4944
4946 SCIPerrorMessage("cannot fix a column variable\n");
4947 return SCIP_INVALIDDATA;
4948
4950 SCIPerrorMessage("cannot fix a fixed variable again\n"); /*lint !e527*/
4951 SCIPABORT(); /* case is already handled in earlier if condition */
4952 return SCIP_INVALIDDATA; /*lint !e527*/
4953
4955 /* fix aggregation variable y in x = a*y + c, instead of fixing x directly */
4956 assert(SCIPsetIsZero(set, var->obj));
4957 assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
4958 childfixedval = (fixedval - var->data.aggregate.constant) / var->data.aggregate.scalar;
4959 SCIP_CALL( SCIPvarFix(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
4960 branchcand, eventqueue, eventfilter, cliquetable, childfixedval, infeasible, fixed) );
4961 break;
4962
4964 SCIPerrorMessage("cannot fix a multiple aggregated variable\n");
4965 SCIPABORT();
4966 return SCIP_INVALIDDATA; /*lint !e527*/
4967
4969 /* fix negation variable x in x' = offset - x, instead of fixing x' directly */
4970 assert(SCIPsetIsZero(set, var->obj));
4971 assert(var->negatedvar != NULL);
4973 assert(var->negatedvar->negatedvar == var);
4974 SCIP_CALL( SCIPvarFix(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
4975 branchcand, eventqueue, eventfilter, cliquetable, var->data.negate.constant - fixedval, infeasible, fixed) );
4976 break;
4977
4978 default:
4979 SCIPerrorMessage("unknown variable status\n");
4980 return SCIP_INVALIDDATA;
4981 }
4982
4983 return SCIP_OKAY;
4984}
4985
4986/** converts variable into fixed variable */
4988 SCIP_VAR* var, /**< problem variable */
4989 BMS_BLKMEM* blkmem, /**< block memory */
4990 SCIP_SET* set, /**< global SCIP settings */
4991 SCIP_STAT* stat, /**< problem statistics */
4992 SCIP_PROB* transprob, /**< tranformed problem data */
4993 SCIP_PROB* origprob, /**< original problem data */
4994 SCIP_PRIMAL* primal, /**< primal data */
4995 SCIP_TREE* tree, /**< branch and bound tree */
4996 SCIP_REOPT* reopt, /**< reoptimization data structure */
4997 SCIP_LP* lp, /**< current LP data */
4998 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4999 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5000 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
5001 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5002 SCIP_RATIONAL* fixedval, /**< value to fix variable at */
5003 SCIP_Bool* infeasible, /**< pointer to store whether the fixing is infeasible */
5004 SCIP_Bool* fixed /**< pointer to store whether the fixing was performed (variable was unfixed) */
5005 )
5006{
5008 SCIP_RATIONAL* childfixedval;
5009 SCIP_RATIONAL* tmpval;
5010
5011 assert(var != NULL);
5012 assert(var->scip == set->scip);
5013 assert(set->exact_enable);
5014
5015 *infeasible = FALSE;
5016 *fixed = FALSE;
5017
5018 if( !set->exact_enable )
5019 return SCIP_OKAY;
5020
5021 assert(SCIPrationalIsEQ(var->exactdata->glbdom.lb, var->exactdata->locdom.lb));
5022 assert(SCIPrationalIsEQ(var->exactdata->glbdom.ub, var->exactdata->locdom.ub));
5023 assert(infeasible != NULL);
5024 assert(fixed != NULL);
5025
5026 SCIPrationalDebugMessage("fix variable <%s>[%g,%g] to %q\n", var->name, var->glbdom.lb, var->glbdom.ub, fixedval);
5027
5029 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &childfixedval) );
5030 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmpval) );
5031
5033
5035 {
5036 *infeasible = !SCIPrationalIsEQ(fixedval, var->exactdata->locdom.lb);
5037 SCIPrationalDebugMessage(" -> variable already fixed to %q (fixedval=%q): infeasible=%u\n", var->exactdata->locdom.lb, fixedval, *infeasible);
5038 goto terminate;
5039 }
5040 else if( (SCIPvarIsIntegral(var) && !SCIPrationalIsIntegral(fixedval))
5041 || SCIPrationalIsLT(fixedval, var->exactdata->locdom.lb)
5042 || SCIPrationalIsGT(fixedval, var->exactdata->locdom.ub) )
5043 {
5044 SCIPrationalDebugMessage(" -> fixing infeasible: locdom=[%q,%q], fixedval=%q\n", var->exactdata->locdom.lb, var->exactdata->locdom.ub, fixedval);
5045 *infeasible = TRUE;
5046 goto terminate;
5047 }
5048
5049 switch( SCIPvarGetStatusExact(var) )
5050 {
5052 if( var->data.original.transvar == NULL )
5053 {
5054 SCIPerrorMessage("cannot fix an untransformed original variable\n");
5055 return SCIP_INVALIDDATA;
5056 }
5057 SCIP_CALL( SCIPvarFixExact(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
5058 lp, branchcand, eventqueue, eventfilter, cliquetable, fixedval, infeasible, fixed) );
5059 break;
5060
5062 assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
5063
5064 /* set the fixed variable's objective value to 0.0 */
5065 SCIPrationalSetRational(obj, var->exactdata->obj);
5066 SCIP_CALL( SCIPvarChgObjExact(var, blkmem, set, transprob, primal, lp->lpexact, eventqueue, tmpval) );
5067
5068 /* since we change the variable type form loose to fixed, we have to adjust the number of loose
5069 * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
5070 * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
5071 * objective of this variable is set to zero
5072 */
5074
5075 /* free fole lists */
5076 holelistFree(&var->glbdom.holelist, blkmem);
5077 holelistFree(&var->locdom.holelist, blkmem);
5078
5079 /* no need to adjust fixed value as in floating-point code */
5081
5082 /* change variable bounds to fixed value */
5083 SCIP_CALL( SCIPvarChgLbGlobalExact(var, blkmem, set, stat, lp->lpexact, branchcand, eventqueue, cliquetable, fixedval) );
5084 SCIP_CALL( SCIPvarChgUbGlobalExact(var, blkmem, set, stat, lp->lpexact, branchcand, eventqueue, cliquetable, fixedval) );
5085
5086 /* delete implications and variable bounds information */
5087 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
5088 assert(var->vlbs == NULL);
5089 assert(var->vubs == NULL);
5090 assert(var->implics == NULL);
5091 assert(var->cliquelist == NULL);
5092
5093 /* clear the history of the variable */
5094 SCIPhistoryReset(var->history);
5095 SCIPhistoryReset(var->historycrun);
5096
5097 /* convert variable into fixed variable */
5098 var->varstatus = SCIP_VARSTATUS_FIXED; /*lint !e641*/
5099 var->exactdata->varstatusexact = SCIP_VARSTATUS_FIXED; /*lint !e641*/
5100
5101 /* inform problem about the variable's status change */
5102 if( var->probindex != -1 )
5103 {
5104 SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
5105 }
5106
5107 /* reset the objective value of the fixed variable, thus adjusting the problem's objective offset */
5108 SCIP_CALL( SCIPvarAddObjExact(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventqueue, eventfilter, obj) );
5109
5110 /* issue VARFIXED event */
5111 SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 0) );
5112
5113 *fixed = TRUE;
5114 break;
5115
5117 SCIPerrorMessage("cannot fix a column variable\n");
5118 return SCIP_INVALIDDATA;
5119
5121 SCIPerrorMessage("cannot fix a fixed variable again\n"); /*lint !e527*/
5122 SCIPABORT(); /* case is already handled in earlier if condition */
5123 return SCIP_INVALIDDATA; /*lint !e527*/
5124
5126 /* fix aggregation variable y in x = a*y + c, instead of fixing x directly */
5127 assert(SCIPsetIsZero(set, var->obj));
5128 assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
5129 if( SCIPrationalIsInfinity(fixedval) || SCIPrationalIsNegInfinity(fixedval) )
5130 SCIPrationalIsNegative(var->exactdata->aggregate.scalar) ? SCIPrationalNegate(childfixedval, fixedval) : SCIPrationalSetRational(childfixedval, fixedval);
5131 else
5132 {
5133 SCIPrationalDiff(tmpval, fixedval, var->exactdata->aggregate.constant);
5134 SCIPrationalDiv(childfixedval, tmpval, var->exactdata->aggregate.scalar);
5135 }
5136 SCIP_CALL( SCIPvarFixExact(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5137 branchcand, eventqueue, eventfilter, cliquetable, childfixedval, infeasible, fixed) );
5138 break;
5139
5141 SCIPerrorMessage("cannot fix a multiple aggregated variable\n");
5142 SCIPABORT();
5143 return SCIP_INVALIDDATA; /*lint !e527*/
5144
5146 /* fix negation variable x in x' = offset - x, instead of fixing x' directly */
5147 assert(SCIPrationalIsZero(var->exactdata->obj));
5148 assert(var->negatedvar != NULL);
5150 assert(var->negatedvar->negatedvar == var);
5151 SCIPrationalDiffReal(fixedval, fixedval, var->data.negate.constant);
5152 SCIPrationalNegate(fixedval, fixedval);
5153 SCIP_CALL( SCIPvarFixExact(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5154 branchcand, eventqueue, eventfilter, cliquetable, fixedval, infeasible, fixed) );
5155 break;
5156
5157 default:
5158 SCIPerrorMessage("unknown variable status\n");
5159 return SCIP_INVALIDDATA;
5160 }
5161
5162terminate:
5163 SCIPrationalFreeBuffer(set->buffer, &tmpval);
5164 SCIPrationalFreeBuffer(set->buffer, &childfixedval);
5165 SCIPrationalFreeBuffer(set->buffer, &obj);
5166
5167 return SCIP_OKAY;
5168}
5169
5170/** transforms given variables, scalars and constant to the corresponding active variables, scalars and constant
5171 *
5172 * If the number of needed active variables is greater than the available slots in the variable array, nothing happens
5173 * except that an upper bound on the required size is stored in the variable requiredsize; otherwise, the active
5174 * variable representation is stored in the arrays.
5175 *
5176 * The reason for this approach is that we cannot reallocate memory, since we do not know how the memory has been
5177 * allocated (e.g., by a C++ 'new' or SCIP functions). Note that requiredsize is an upper bound due to possible
5178 * cancelations.
5179 */
5181 SCIP_SET* set, /**< global SCIP settings */
5182 SCIP_VAR** vars, /**< variable array to get active variables */
5183 SCIP_Real* scalars, /**< scalars a_1, ..., a_n in linear sum a_1*x_1 + ... + a_n*x_n + c */
5184 int* nvars, /**< pointer to number of variables and values in vars and scalars array */
5185 int varssize, /**< available slots in vars and scalars array */
5186 SCIP_Real* constant, /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c */
5187 int* requiredsize /**< pointer to store an uppper bound on the required size for the active variables */
5188 )
5189{
5190 SCIP_VAR** activevars;
5191 SCIP_Real activeconstant;
5192 SCIP_Bool activeconstantinf;
5193 int activevarssize;
5194 int nactivevars;
5195
5196 SCIP_VAR* var;
5197 SCIP_Real scalar;
5198 int v;
5199
5200 SCIP_VAR** tmpvars;
5201 SCIP_VAR** multvars;
5202 SCIP_Real* tmpscalars;
5203 SCIP_Real* multscalars;
5204 int tmpvarssize;
5205 int ntmpvars;
5206 int nmultvars;
5207
5208 SCIP_VAR* multvar;
5209 SCIP_Real multscalar;
5210 SCIP_Real multconstant;
5211 SCIP_VARSTATUS varstatus;
5212 int ntotalvars;
5213
5214 assert(set != NULL);
5215 assert(nvars != NULL);
5216 assert(constant != NULL);
5217 assert(requiredsize != NULL);
5218 assert(*nvars <= varssize);
5219
5220 *requiredsize = 0;
5221
5222 if( *nvars == 0 )
5223 return SCIP_OKAY;
5224
5225 assert(vars != NULL);
5226 assert(scalars != NULL);
5227
5228 /* handle the "easy" case of just one variable and avoid memory allocation if the variable is already active */
5229 if( *nvars == 1 && (vars[0]->varstatus == ((int) SCIP_VARSTATUS_COLUMN) || vars[0]->varstatus == ((int) SCIP_VARSTATUS_LOOSE)) )
5230 {
5231 *requiredsize = 1;
5232
5233 return SCIP_OKAY;
5234 }
5235
5236 /* allocate temporary list of variables */
5237 tmpvarssize = *nvars;
5238 SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpvars, tmpvarssize) );
5239
5240 /* allocate memory for list of active variables */
5241 activevarssize = MAX(10, 2 * (*nvars)); /* take the maximum to avoid small reallocations */
5242 SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
5243
5244 /* allocate dense array for storing scalars (to avoid checking for duplicate variables) */
5245 ntotalvars = SCIPgetNTotalVars(set->scip);
5246 SCIP_CALL( SCIPsetAllocCleanBufferArray(set, &tmpscalars, ntotalvars) );
5247
5248 /* perform one round of replacing variables by their active, fixed or multi-aggregated counterparts */
5249 activeconstant = 0.0;
5250 nactivevars = 0;
5251 ntmpvars = 0;
5252 for( v = 0; v < *nvars; ++v )
5253 {
5254 var = vars[v];
5255 assert(var != NULL);
5256 scalar = scalars[v];
5257
5258 /* Transforms variable, scalar and constant to corresponding active, fixed, or multi-aggregated variable, scalar
5259 * and constant; activeconstant collects the sum of all constants (even for variables with scalar == 0.0). */
5260 SCIP_CALL( SCIPvarGetProbvarSum(&var, set, &scalar, &activeconstant) );
5261 assert(var != NULL);
5262
5263 assert(SCIPsetIsInfinity(set, activeconstant) == (activeconstant == SCIPsetInfinity(set))); /*lint !e777*/
5264 assert(SCIPsetIsInfinity(set, -activeconstant) == (activeconstant == -SCIPsetInfinity(set))); /*lint !e777*/
5265
5266 varstatus = SCIPvarGetStatus(var);
5267 assert( varstatus == SCIP_VARSTATUS_LOOSE || varstatus == SCIP_VARSTATUS_COLUMN
5268 || varstatus == SCIP_VARSTATUS_MULTAGGR || varstatus == SCIP_VARSTATUS_FIXED);
5269
5270 /* enter nonzero scalars into dense array and list */
5271 if( scalar != 0.0 )
5272 {
5273 assert(0 <= var->index && var->index < ntotalvars);
5274 if( tmpscalars[var->index] == 0.0 )
5275 {
5276 if( varstatus == SCIP_VARSTATUS_LOOSE || varstatus == SCIP_VARSTATUS_COLUMN )
5277 activevars[nactivevars++] = var; /* store active variables */
5278 else if( varstatus == SCIP_VARSTATUS_MULTAGGR )
5279 tmpvars[ntmpvars++] = var; /* enter mutli-aggregated variables in list to be processed below */
5280 }
5281 tmpscalars[var->index] += scalar;
5282 }
5283 }
5284 assert(ntmpvars <= *nvars);
5285 assert(nactivevars <= *nvars);
5286
5287 /* store whether the constant is infinite */
5288 activeconstantinf = SCIPsetIsInfinity(set, activeconstant) || SCIPsetIsInfinity(set, -activeconstant);
5289
5290 /* collect for each variable the representation in active variables */
5291 while( ntmpvars >= 1 )
5292 {
5293 --ntmpvars;
5294
5295 var = tmpvars[ntmpvars];
5296 assert(var != NULL);
5297 assert(0 <= var->index && var->index < ntotalvars);
5299
5300 scalar = tmpscalars[var->index];
5301 /* the scalar can be 0 if the variable has been treated before and is zeroed below */
5302 if( scalar == 0.0 )
5303 continue;
5304
5305 /* x = a_1*y_1 + ... + a_n*y_n + c */
5306 nmultvars = var->data.multaggr.nvars;
5307 multvars = var->data.multaggr.vars;
5308 multscalars = var->data.multaggr.scalars;
5309
5310 /* mark variable as treated */
5311 tmpscalars[var->index] = 0.0;
5312
5313 /* loop through variables of multi-aggregation */
5314 for( v = 0; v < nmultvars; ++v )
5315 {
5316 multvar = multvars[v];
5317 multscalar = multscalars[v];
5318 multconstant = 0.0;
5319
5320 assert(multvar != NULL);
5321 SCIP_CALL( SCIPvarGetProbvarSum(&multvar, set, &multscalar, &multconstant) );
5322 assert(multvar != NULL);
5323
5324 /* handle constant */
5325 if( !activeconstantinf )
5326 {
5327 assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
5328
5329 if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) )
5330 {
5331 assert(scalar != 0.0);
5332 if( scalar * multconstant > 0.0 )
5333 {
5334 activeconstant = SCIPsetInfinity(set);
5335 activeconstantinf = TRUE;
5336 }
5337 else
5338 {
5339 activeconstant = -SCIPsetInfinity(set);
5340 activeconstantinf = TRUE;
5341 }
5342 }
5343 else
5344 activeconstant += scalar * multconstant;
5345 }
5346#ifndef NDEBUG
5347 else
5348 {
5349 assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
5350 (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
5351 assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
5352 (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
5353 }
5354#endif
5355
5356 /* Note that the variable can have a nonzero constant but 0 scalar. */
5357 if( multscalar == 0.0 )
5358 continue;
5359
5360 /* enter variable into list if not already present */
5361 assert(0 <= multvar->index && multvar->index < ntotalvars);
5362 if( tmpscalars[multvar->index] == 0.0 )
5363 {
5364 varstatus = SCIPvarGetStatus(multvar);
5365 if( varstatus == SCIP_VARSTATUS_LOOSE || varstatus == SCIP_VARSTATUS_COLUMN )
5366 {
5367 /* store active variables */
5368 if( nactivevars >= activevarssize )
5369 {
5370 activevarssize *= 2;
5371 SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
5372 assert(nactivevars < activevarssize);
5373 }
5374 activevars[nactivevars++] = multvar;
5375 }
5376 else if( varstatus == SCIP_VARSTATUS_MULTAGGR )
5377 {
5378 /* ensure storage */
5379 if( ntmpvars >= tmpvarssize )
5380 {
5381 tmpvarssize *= 2;
5382 SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
5383 assert(ntmpvars <= tmpvarssize);
5384 }
5385 tmpvars[ntmpvars++] = multvar;
5386 }
5387 }
5388
5389 /* transfer new scalar to dense array in any case */
5390 tmpscalars[multvar->index] += scalar * multscalar;
5391 assert(scalar * multscalar != 0.0);
5392 }
5393
5394 /* handle constant of multi-aggregation */
5395 if( !activeconstantinf )
5396 {
5397 assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
5398
5399 multconstant = SCIPvarGetMultaggrConstant(var);
5400
5401 if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) )
5402 {
5403 assert(scalar != 0.0);
5404 if( scalar * multconstant > 0.0 )
5405 {
5406 activeconstant = SCIPsetInfinity(set);
5407 activeconstantinf = TRUE;
5408 }
5409 else
5410 {
5411 activeconstant = -SCIPsetInfinity(set);
5412 activeconstantinf = TRUE;
5413 }
5414 }
5415 else
5416 activeconstant += scalar * multconstant;
5417 }
5418#ifndef NDEBUG
5419 else
5420 {
5421 multconstant = SCIPvarGetMultaggrConstant(var);
5422 assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
5423 (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
5424 assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
5425 (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
5426 }
5427#endif
5428 }
5429
5430 /* Here, nactivevars is an upper bound on the required size, because of possible cancellation. We could compute the
5431 * actual size, but this would need another loop through the active variables. We therefore take the upper bound. */
5432
5433 /* return results */
5434 if( varssize >= nactivevars )
5435 {
5436 assert(vars != NULL);
5437
5438 if( !SCIPsetIsInfinity(set, *constant) && !SCIPsetIsInfinity(set, -(*constant)) )
5439 {
5440 /* if activeconstant is infinite, the constant pointer gets the same value, otherwise add the value */
5441 if( activeconstantinf )
5442 *constant = activeconstant;
5443 else
5444 *constant += activeconstant;
5445 }
5446#ifndef NDEBUG
5447 else
5448 {
5449 assert(!SCIPsetIsInfinity(set, (*constant)) || !SCIPsetIsInfinity(set, -activeconstant));
5450 assert(!SCIPsetIsInfinity(set, -(*constant)) || !SCIPsetIsInfinity(set, activeconstant));
5451 }
5452#endif
5453
5454 /* copy active variable and scalar array to the given arrays */
5455 *nvars = 0;
5456 for( v = 0; v < nactivevars; ++v )
5457 {
5458 var = activevars[v];
5459
5461 assert(0 <= var->index && var->index < ntotalvars);
5462
5463 /* due to cancelation, the scalar could become 0 */
5464 if( ! SCIPsetIsZero(set, tmpscalars[var->index]) )
5465 {
5466 vars[*nvars] = var;
5467 scalars[*nvars] = tmpscalars[var->index];
5468 assert(scalars[*nvars] != 0.0);
5469 ++(*nvars);
5470 }
5471
5472 /* clean buffer again */
5473 tmpscalars[var->index] = 0.0;
5474 }
5475 /* set requiredsize to space actually needed */
5476 *requiredsize = *nvars;
5477 }
5478 else
5479 {
5480 /* clean buffer again */
5481 for( v = 0; v < nactivevars; ++v )
5482 {
5483 var = activevars[v];
5484 assert( 0 <= var->index && var->index < ntotalvars );
5485 tmpscalars[var->index] = 0.0;
5486 }
5487 *requiredsize = nactivevars;
5488 }
5489
5490 assert(SCIPsetIsInfinity(set, *constant) == ((*constant) == SCIPsetInfinity(set))); /*lint !e777*/
5491 assert(SCIPsetIsInfinity(set, -(*constant)) == ((*constant) == -SCIPsetInfinity(set))); /*lint !e777*/
5492
5493 SCIPsetFreeCleanBufferArray(set, &tmpscalars);
5494 SCIPsetFreeBufferArray(set, &activevars);
5495 SCIPsetFreeBufferArray(set, &tmpvars);
5496
5497 return SCIP_OKAY;
5498}
5499
5500/** transforms given variables, scalars and constant to the corresponding active variables, scalars and constant
5501 *
5502 * If the number of needed active variables is greater than the available slots in the variable array, nothing happens except
5503 * that the required size is stored in the corresponding variable; hence, if afterwards the required size is greater than the
5504 * available slots (varssize), nothing happens; otherwise, the active variable representation is stored in the arrays.
5505 *
5506 * The reason for this approach is that we cannot reallocate memory, since we do not know how the
5507 * memory has been allocated (e.g., by a C++ 'new' or SCIP functions).
5508 *
5509 * @todo Reimplement this method as was done with SCIPvarGetActiveRepresentatives() using a clean buffer array for rationals.
5510 */
5512 SCIP_SET* set, /**< global SCIP settings */
5513 SCIP_VAR** vars, /**< variable array to get active variables */
5514 SCIP_RATIONAL** scalars, /**< scalars a_1, ..., a_n in linear sum a_1*x_1 + ... + a_n*x_n + c */
5515 int* nvars, /**< pointer to number of variables and values in vars and vals array */
5516 int varssize, /**< available slots in vars and scalars array */
5517 SCIP_RATIONAL* constant, /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c */
5518 int* requiredsize, /**< pointer to store the required array size for the active variables */
5519 SCIP_Bool mergemultiples /**< should multiple occurrences of a var be replaced by a single coeff? */
5520 )
5521{
5522 SCIP_VAR** activevars;
5523 SCIP_RATIONAL** activescalars;
5524 int nactivevars;
5525 SCIP_RATIONAL* activeconstant;
5526 SCIP_Bool activeconstantinf;
5527 int activevarssize;
5528
5529 SCIP_VAR* var;
5530 SCIP_RATIONAL* scalar;
5531 int v;
5532 int k;
5533
5534 SCIP_VAR** tmpvars;
5535 SCIP_VAR** multvars;
5536 SCIP_RATIONAL** tmpscalars;
5537 SCIP_RATIONAL** multscalars;
5538 int tmpvarssize;
5539 int ntmpvars;
5540 int nmultvars;
5541 int ntmpvarsnew;
5542
5543 SCIP_VAR* multvar;
5544 SCIP_RATIONAL* multscalar;
5545 SCIP_RATIONAL* multconstant;
5546 int pos;
5547
5548 int noldtmpvars;
5549
5550 SCIP_VAR** tmpvars2;
5551 SCIP_RATIONAL** tmpscalars2;
5552 int tmpvarssize2;
5553 int ntmpvars2;
5554
5555 SCIP_Bool sortagain = FALSE;
5556
5557 assert(set != NULL);
5558 assert(nvars != NULL);
5559 assert(scalars != NULL || *nvars == 0);
5560 assert(constant != NULL);
5561 assert(requiredsize != NULL);
5562 assert(*nvars <= varssize);
5563
5564 *requiredsize = 0;
5565
5566 if( *nvars == 0 )
5567 return SCIP_OKAY;
5568
5569 assert(vars != NULL);
5570
5571 /* handle the "easy" case of just one variable and avoid memory allocation if the variable is already active */
5572 if( *nvars == 1 && (vars[0]->varstatus == ((int) SCIP_VARSTATUS_COLUMN) || vars[0]->varstatus == ((int) SCIP_VARSTATUS_LOOSE)) )
5573 {
5574 *requiredsize = 1;
5575
5576 return SCIP_OKAY;
5577 }
5578
5579 nactivevars = 0;
5580 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &scalar) );
5581 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &activeconstant) );
5582 activeconstantinf = FALSE;
5583 activevarssize = (*nvars) * 2;
5584 ntmpvars = *nvars;
5585 tmpvarssize = *nvars;
5586
5587 tmpvarssize2 = 1;
5588
5589 /* allocate temporary memory */
5590 SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpvars2, tmpvarssize2) );
5591 SCIP_CALL( SCIPrationalCreateBufferArray(set->buffer, &tmpscalars2, tmpvarssize2) );
5592 SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
5593 SCIP_CALL( SCIPrationalCreateBufferArray(set->buffer, &activescalars, activevarssize) );
5594 SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
5595 SCIP_CALL( SCIPrationalCopyBufferArray(set->buffer, &tmpscalars, scalars, *nvars) );
5596
5597 /* to avoid unnecessary expanding of variable arrays while disaggregating several variables multiple times combine same variables
5598 * first, first get all corresponding variables with status loose, column, multaggr or fixed
5599 */
5600 for( v = ntmpvars - 1; v >= 0; --v )
5601 {
5602 var = tmpvars[v];
5603 SCIPrationalSetRational(scalar, tmpscalars[v]);
5604
5605 assert(var != NULL);
5606 /* transforms given variable, scalar and constant to the corresponding active, fixed, or
5607 * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed
5608 * variable, "scalar" will be 0.0 and the value of the sum will be stored in "constant".
5609 */
5610 SCIP_CALL( SCIPvarGetProbvarSumExact(&var, scalar, activeconstant) );
5611 assert(var != NULL);
5612
5613 activeconstantinf = SCIPrationalIsInfinity(activeconstant) || SCIPrationalIsNegInfinity(activeconstant);
5614
5619
5620 tmpvars[v] = var;
5621 SCIPrationalSetRational(tmpscalars[v], scalar);
5622 }
5623 noldtmpvars = ntmpvars;
5624
5625 /* sort all variables to combine equal variables easily */
5626 SCIPsortPtrPtr((void**)tmpvars, (void**)tmpscalars, SCIPvarComp, noldtmpvars);
5627 ntmpvars = 0;
5628 for( v = 1; v < noldtmpvars; ++v )
5629 {
5630 /* combine same variables */
5631 if( SCIPvarCompare(tmpvars[v], tmpvars[ntmpvars]) == 0 )
5632 {
5633 SCIPrationalAdd(tmpscalars[ntmpvars], tmpscalars[ntmpvars], tmpscalars[v]);
5634 }
5635 else
5636 {
5637 ++ntmpvars;
5638 if( v > ntmpvars )
5639 {
5640 SCIPrationalSetRational(tmpscalars[ntmpvars], tmpscalars[v]);
5641 tmpvars[ntmpvars] = tmpvars[v];
5642 }
5643 }
5644 }
5645 ++ntmpvars;
5646
5647#ifdef SCIP_MORE_DEBUG
5648 for( v = 1; v < ntmpvars; ++v )
5649 assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
5650#endif
5651
5652 /* collect for each variable the representation in active variables */
5653 while( ntmpvars >= 1 )
5654 {
5655 --ntmpvars;
5656 ntmpvars2 = 0;
5657 var = tmpvars[ntmpvars];
5658 SCIPrationalSetRational(scalar, tmpscalars[ntmpvars]);
5659
5660 assert(var != NULL);
5661
5662 /* TODO: maybe we should test here on SCIPsetIsZero() instead of 0.0 */
5663 if( SCIPrationalIsZero(scalar) )
5664 continue;
5665
5670
5671 switch( SCIPvarGetStatus(var) )
5672 {
5675 /* x = a*y + c */
5676 if( nactivevars >= activevarssize )
5677 {
5678 int newactivevarssize = activevarssize * 2;
5679 SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, newactivevarssize) );
5680 SCIP_CALL( SCIPrationalReallocBufferArray(set->buffer, &activescalars, activevarssize, newactivevarssize) );
5681 activevarssize = newactivevarssize;
5682 assert(nactivevars < activevarssize);
5683 }
5684 activevars[nactivevars] = var;
5685 SCIPrationalSetRational(activescalars[nactivevars], scalar);
5686 nactivevars++;
5687 break;
5688
5690 /* x = a_1*y_1 + ... + a_n*y_n + c */
5691 nmultvars = var->data.multaggr.nvars;
5692 multvars = var->data.multaggr.vars;
5693 multscalars = var->exactdata->multaggr.scalars;
5694 sortagain = TRUE;
5695
5696 if( nmultvars + ntmpvars > tmpvarssize )
5697 {
5698 ntmpvarsnew = tmpvarssize;
5699 while( nmultvars + ntmpvars > ntmpvarsnew )
5700 ntmpvarsnew *= 2;
5701 SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, ntmpvarsnew) );
5702 SCIP_CALL( SCIPrationalReallocBufferArray(set->buffer, &tmpscalars, tmpvarssize, ntmpvarsnew) );
5703 assert(nmultvars + ntmpvars <= ntmpvarsnew);
5704 tmpvarssize = ntmpvarsnew;
5705 }
5706
5707 if( nmultvars > tmpvarssize2 )
5708 {
5709 ntmpvarsnew = tmpvarssize2;
5710 while( nmultvars > ntmpvarsnew )
5711 ntmpvarsnew *= 2;
5712 SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars2, ntmpvarsnew) );
5713 SCIP_CALL( SCIPrationalReallocBufferArray(set->buffer, &tmpscalars2, tmpvarssize2, ntmpvarsnew) );
5714 assert(nmultvars <= ntmpvarsnew);
5715 tmpvarssize2 = ntmpvarsnew;
5716 }
5717
5718 --nmultvars;
5719
5720 for( ; nmultvars >= 0; --nmultvars )
5721 {
5722 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &multconstant) );
5723 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &multscalar) );
5724
5725 multvar = multvars[nmultvars];
5726 SCIPrationalSetRational(multscalar, multscalars[nmultvars]);
5727
5728 assert(multvar != NULL);
5729 SCIP_CALL( SCIPvarGetProbvarSumExact(&multvar, multscalar, multconstant) );
5730 assert(multvar != NULL);
5731
5736
5737 if( !activeconstantinf )
5738 {
5740
5741 if( SCIPrationalIsAbsInfinity(multconstant) )
5742 {
5743 assert(!SCIPrationalIsZero(scalar));
5744 if( SCIPrationalGetSign(scalar) == SCIPrationalGetSign(multconstant) && !SCIPrationalIsZero(scalar) )
5745 {
5746 SCIPrationalSetInfinity(activeconstant);
5747 activeconstantinf = TRUE;
5748 }
5749 else
5750 {
5751 SCIPrationalSetNegInfinity(activeconstant);
5752 activeconstantinf = TRUE;
5753 }
5754 }
5755 else
5756 SCIPrationalAddProd(activeconstant, scalar, multconstant);
5757 }
5758
5759 if( SCIPsortedvecFindPtr((void**)tmpvars, SCIPvarComp, multvar, ntmpvars, &pos) )
5760 {
5761 assert(SCIPvarCompare(tmpvars[pos], multvar) == 0);
5762 SCIPrationalAddProd(tmpscalars[pos], scalar, multscalar);
5763 }
5764 else
5765 {
5766 tmpvars2[ntmpvars2] = multvar;
5767 SCIPrationalMult(tmpscalars2[ntmpvars2], scalar, multscalar);
5768 ++(ntmpvars2);
5769 assert(ntmpvars2 <= tmpvarssize2);
5770 }
5771
5772 SCIPrationalFreeBuffer(set->buffer, &multscalar);
5773 SCIPrationalFreeBuffer(set->buffer, &multconstant);
5774 }
5775
5776 if( ntmpvars2 > 0 )
5777 {
5778 /* sort all variables to combine equal variables easily */
5779 SCIPsortPtrPtr((void**)tmpvars2, (void**)tmpscalars2, SCIPvarComp, ntmpvars2);
5780 pos = 0;
5781 for( v = 1; v < ntmpvars2; ++v )
5782 {
5783 /* combine same variables */
5784 if( SCIPvarCompare(tmpvars2[v], tmpvars2[pos]) == 0 )
5785 {
5786 SCIPrationalAdd(tmpscalars2[pos], tmpscalars2[pos], tmpscalars2[v]);
5787 }
5788 else
5789 {
5790 ++pos;
5791 if( v > pos )
5792 {
5793 SCIPrationalSetRational(tmpscalars2[pos], tmpscalars2[v]);
5794 tmpvars2[pos] = tmpvars2[v];
5795 }
5796 }
5797 }
5798 ntmpvars2 = pos + 1;
5799#ifdef SCIP_MORE_DEBUG
5800 for( v = 1; v < ntmpvars2; ++v )
5801 {
5802 assert(SCIPvarCompare(tmpvars2[v], tmpvars2[v-1]) > 0);
5803 }
5804 for( v = 1; v < ntmpvars; ++v )
5805 {
5806 assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
5807 }
5808#endif
5809 v = ntmpvars - 1;
5810 k = ntmpvars2 - 1;
5811 pos = ntmpvars + ntmpvars2 - 1;
5812 ntmpvars += ntmpvars2;
5813
5814 while( v >= 0 && k >= 0 )
5815 {
5816 assert(pos >= 0);
5817 assert(SCIPvarCompare(tmpvars[v], tmpvars2[k]) != 0);
5818 if( SCIPvarCompare(tmpvars[v], tmpvars2[k]) >= 0 )
5819 {
5820 tmpvars[pos] = tmpvars[v];
5821 SCIPrationalSetRational(tmpscalars[pos], tmpscalars[v]);
5822 --v;
5823 }
5824 else
5825 {
5826 tmpvars[pos] = tmpvars2[k];
5827 SCIPrationalSetRational(tmpscalars[pos], tmpscalars2[k]);
5828 --k;
5829 }
5830 --pos;
5831 assert(pos >= 0);
5832 }
5833 while( v >= 0 )
5834 {
5835 assert(pos >= 0);
5836 tmpvars[pos] = tmpvars[v];
5837 SCIPrationalSetRational(tmpscalars[pos], tmpscalars[v]);
5838 --v;
5839 --pos;
5840 }
5841 while( k >= 0 )
5842 {
5843 assert(pos >= 0);
5844 tmpvars[pos] = tmpvars2[k];
5845 SCIPrationalSetRational(tmpscalars[pos], tmpscalars2[k]);
5846 --k;
5847 --pos;
5848 }
5849 }
5850#ifdef SCIP_MORE_DEBUG
5851 for( v = 1; v < ntmpvars; ++v )
5852 {
5853 assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
5854 }
5855#endif
5856
5857 if( !activeconstantinf )
5858 {
5860
5861 multconstant = SCIPvarGetMultaggrConstantExact(var);
5862
5863 if( SCIPrationalIsAbsInfinity(multconstant) )
5864 {
5865 assert(!SCIPrationalIsZero(scalar));
5866 if( SCIPrationalGetSign(scalar) == SCIPrationalGetSign(multconstant) && !SCIPrationalIsZero(scalar) )
5867 {
5868 SCIPrationalSetInfinity(activeconstant);
5869 activeconstantinf = TRUE;
5870 }
5871 else
5872 {
5873 SCIPrationalSetNegInfinity(activeconstant);
5874 activeconstantinf = TRUE;
5875 }
5876 }
5877 else
5878 SCIPrationalAddProd(activeconstant, scalar, multconstant);
5879 }
5880
5881 break;
5882
5887 default:
5888 /* case x = c, but actually we should not be here, since SCIPvarGetProbvarSum() returns a scalar of 0.0 for
5889 * fixed variables and is handled already
5890 */
5892 assert(SCIPsetIsZero(set, var->glbdom.lb) && SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub));
5893 }
5894 }
5895
5896 if( mergemultiples )
5897 {
5898 if( sortagain )
5899 {
5900 /* sort variable and scalar array by variable index */
5901 SCIPsortPtrPtr((void**)activevars, (void**)activescalars, SCIPvarComp, nactivevars);
5902
5903 /* eliminate duplicates and count required size */
5904 v = nactivevars - 1;
5905 while( v > 0 )
5906 {
5907 /* combine both variable since they are the same */
5908 if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
5909 {
5910 SCIPrationalNegate(scalar, activescalars[v]);
5911 if( !SCIPrationalIsEQ(activescalars[v - 1], scalar) )
5912 {
5913 SCIPrationalAdd(activescalars[v - 1], activescalars[v - 1], activescalars[v]);
5914 --nactivevars;
5915 activevars[v] = activevars[nactivevars];
5916 SCIPrationalSetRational(activescalars[v], activescalars[nactivevars]);
5917 }
5918 else
5919 {
5920 --nactivevars;
5921 activevars[v] = activevars[nactivevars];
5922 SCIPrationalSetRational(activescalars[v], activescalars[nactivevars]);
5923 --nactivevars;
5924 --v;
5925 activevars[v] = activevars[nactivevars];
5926 SCIPrationalSetRational(activescalars[v], activescalars[nactivevars]);
5927 }
5928 }
5929 --v;
5930 }
5931 }
5932 /* the variables were added in reverse order, we revert the order now;
5933 * this should not be necessary, but not doing this changes the behavior sometimes
5934 */
5935 else
5936 {
5937 SCIP_VAR* tmpvar;
5938
5939 for( v = 0; v < nactivevars / 2; ++v )
5940 {
5941 tmpvar = activevars[v];
5942 SCIPrationalSetRational(scalar, activescalars[v]);
5943 activevars[v] = activevars[nactivevars - 1 - v];
5944 SCIPrationalSetRational(activescalars[v], activescalars[nactivevars - 1 - v]);
5945 activevars[nactivevars - 1 - v] = tmpvar;
5946 SCIPrationalSetRational(activescalars[nactivevars - 1 - v], scalar);
5947 }
5948 }
5949 }
5950 *requiredsize = nactivevars;
5951
5952 if( varssize >= *requiredsize )
5953 {
5954 assert(vars != NULL);
5955
5956 *nvars = *requiredsize;
5957
5958 if( !SCIPrationalIsAbsInfinity(constant) )
5959 {
5960 /* if the activeconstant is infinite, the constant pointer gets the same value, otherwise add the value */
5961 if( activeconstantinf )
5962 SCIPrationalSetRational(constant, activeconstant);
5963 else
5964 SCIPrationalAdd(constant, constant, activeconstant);
5965 }
5966
5967 /* copy active variable and scalar array to the given arrays */
5968 for( v = 0; v < *nvars; ++v )
5969 {
5970 vars[v] = activevars[v];
5971 SCIPrationalSetRational(scalars[v], activescalars[v]); /*lint !e613*/
5972 }
5973 }
5974
5975 SCIPrationalFreeBufferArray(set->buffer, &tmpscalars, tmpvarssize);
5976 SCIPsetFreeBufferArray(set, &tmpvars);
5977 SCIPrationalFreeBufferArray(set->buffer, &activescalars, activevarssize);
5978 SCIPsetFreeBufferArray(set, &activevars);
5979 SCIPrationalFreeBufferArray(set->buffer, &tmpscalars2, tmpvarssize2);
5980 SCIPsetFreeBufferArray(set, &tmpvars2);
5981
5982 SCIPrationalFreeBuffer(set->buffer, &activeconstant);
5983 SCIPrationalFreeBuffer(set->buffer, &scalar);
5984
5985 return SCIP_OKAY;
5986}
5987
5988/** flattens aggregation graph of multi-aggregated variable in order to avoid exponential recursion later on */
5990 SCIP_VAR* var, /**< problem variable */
5991 BMS_BLKMEM* blkmem, /**< block memory */
5992 SCIP_SET* set, /**< global SCIP settings */
5993 SCIP_EVENTQUEUE* eventqueue /**< event queue */
5994 )
5995{
5996 int nlocksup[NLOCKTYPES];
5997 int nlocksdown[NLOCKTYPES];
5998 SCIP_Real multconstant;
5999 int multvarssize;
6000 int nmultvars;
6001 int multrequiredsize;
6002 int i;
6003
6004 assert( var != NULL );
6006 assert(var->scip == set->scip);
6007
6008 /* in order to update the locks on the active representation of the multi-aggregated variable, we remove all locks
6009 * on the current representation now and re-add the locks once the variable graph has been flattened, which
6010 * may lead to duplicate occurences of the same variable being merged
6011 *
6012 * Here is an example. Assume we have the multi-aggregation z = x + y.
6013 * z occures with positive coefficient in a <= constraint c1, so it has an uplock from there.
6014 * When the multi-aggregation is performed, all locks are added to the active representation,
6015 * so x and y both get an uplock from c1. However, z was not yet replaced by x + y in c1.
6016 * Next, a negation y = 1 - x is identified. Again, locks are moved, so that the uplock of y originating
6017 * from c1 is added to x as a downlock. Thus, x has both an up- and downlock from c1.
6018 * The multi-aggregation changes to z = x + 1 - x, which corresponds to the locks.
6019 * However, before z is replaced by that sum, SCIPvarFlattenAggregationGraph() is called
6020 * which changes z = x + y = x + 1 - x = 1, since it merges multiple occurences of the same variable.
6021 * The up- and downlock of x, however, is not removed when replacing z in c1 by its active representation,
6022 * because it is just 1 now. Therefore, we need to update locks when flattening the aggregation graph.
6023 * For this, the multi-aggregated variable knows its locks in addition to adding them to the active
6024 * representation, which corresponds to the locks from constraints where the variable was not replaced yet.
6025 * By removing the locks here, based on the old representation and adding them again after flattening,
6026 * we ensure that the locks are correct afterwards if coefficients were merged.
6027 */
6028 for( i = 0; i < NLOCKTYPES; ++i )
6029 {
6030 nlocksup[i] = var->nlocksup[i];
6031 nlocksdown[i] = var->nlocksdown[i];
6032
6033 SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, -nlocksdown[i], -nlocksup[i]) );
6034 }
6035
6036 multconstant = var->data.multaggr.constant;
6037 nmultvars = var->data.multaggr.nvars;
6038 multvarssize = var->data.multaggr.varssize;
6039
6040 if( !set->exact_enable )
6041 {
6042 SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize) );
6043
6044 if( multrequiredsize > multvarssize )
6045 {
6046 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.vars), multvarssize, multrequiredsize) );
6047 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.scalars), multvarssize, multrequiredsize) );
6048 multvarssize = multrequiredsize;
6049 SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize) );
6050
6051 assert( multrequiredsize <= multvarssize );
6052 }
6053
6054 /**@note After the flattening the multi aggregation might resolve to be in fact an aggregation (or even a fixing?).
6055 * This issue is not resolved right now, since var->data.multaggr.nvars < 2 should not cause troubles. However, one
6056 * may loose performance hereby, since aggregated variables are easier to handle.
6057 *
6058 * Note, that there are two cases where SCIPvarFlattenAggregationGraph() is called: The easier one is that it is
6059 * called while installing the multi-aggregation. in principle, the described issue could be handled straightforward
6060 * in this case by aggregating or fixing the variable instead. The more complicated case is the one, when the
6061 * multi-aggregation is used, e.g., in linear presolving (and the variable is already declared to be multi-aggregated).
6062 *
6063 * By now, it is not allowed to fix or aggregate multi-aggregated variables which would be necessary in this case.
6064 *
6065 * The same issue appears in the SCIPvarGetProbvar...() methods.
6066 */
6067
6068 var->data.multaggr.constant = multconstant;
6069 }
6070 else
6071 {
6072 SCIP_CALL( SCIPvarGetActiveRepresentativesExact(set, var->data.multaggr.vars, var->exactdata->multaggr.scalars,
6073 &nmultvars, multvarssize, var->exactdata->multaggr.constant, &multrequiredsize, TRUE) );
6074
6075 var->data.multaggr.nvars = nmultvars;
6076 var->data.multaggr.varssize = multvarssize;
6078
6079 if( multrequiredsize > multvarssize )
6080 {
6081 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.vars), multvarssize, multrequiredsize) );
6082 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.scalars), multvarssize, multrequiredsize) );
6083 SCIP_CALL( SCIPrationalReallocBlockArray(blkmem, &(var->exactdata->multaggr.scalars), multvarssize, multrequiredsize) );
6084 multvarssize = multrequiredsize;
6085 SCIP_CALL( SCIPvarGetActiveRepresentativesExact(set, var->data.multaggr.vars, var->exactdata->multaggr.scalars,
6086 &nmultvars, multvarssize, var->exactdata->multaggr.constant, &multrequiredsize, TRUE) );
6087
6088 var->data.multaggr.nvars = nmultvars;
6089 var->data.multaggr.varssize = multvarssize;
6090
6092
6093 assert( multrequiredsize <= multvarssize );
6094 }
6095 }
6096
6097 var->data.multaggr.nvars = nmultvars;
6098 var->data.multaggr.varssize = multvarssize;
6099
6100 for( i = 0; i < NLOCKTYPES; ++i )
6101 {
6102 SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
6103 }
6104
6105 return SCIP_OKAY;
6106}
6107
6108/** merge two variable histories together; a typical use case is that \p othervar is an image of the target variable
6109 * in a SCIP copy. Method should be applied with care, especially because no internal checks are performed whether
6110 * the history merge is reasonable
6111 *
6112 * @note Do not use this method if the two variables originate from two SCIP's with different objective functions, since
6113 * this corrupts the variable pseudo costs
6114 * @note Apply with care; no internal checks are performed if the two variables should be merged
6115 */
6117 SCIP_VAR* targetvar, /**< the variable that should contain both histories afterwards */
6118 SCIP_VAR* othervar, /**< the variable whose history is to be merged with that of the target variable */
6119 SCIP_STAT* stat /**< problem statistics */
6120 )
6121{
6122 /* merge only the history of the current run into the target history */
6123 SCIPhistoryUnite(targetvar->history, othervar->historycrun, FALSE);
6124
6125 /* apply the changes also to the global history */
6126 SCIPhistoryUnite(stat->glbhistory, othervar->historycrun, FALSE);
6127}
6128
6129/** sets the history of a variable; this method is typically used within reoptimization to keep and update the variable
6130 * history over several iterations
6131 */
6133 SCIP_VAR* var, /**< variable */
6134 SCIP_HISTORY* history, /**< the history which is to set */
6135 SCIP_STAT* stat /**< problem statistics */
6136 )
6137{
6138 /* merge only the history of the current run into the target history */
6139 SCIPhistoryUnite(var->history, history, FALSE);
6140
6141 /* apply the changes also to the global history */
6142 SCIPhistoryUnite(stat->glbhistory, history, FALSE);
6143}
6144
6145/** update min/maxaggrcoef of a loose variable */
6146static
6148 SCIP_VAR* var, /**< problem variable that is used in aggregation */
6149 SCIP_VAR* aggvar, /**< variable that is aggregated */
6150 SCIP_Real aggscalar /**< coefficient that is used for var in the aggregation of aggvar */
6151 )
6152{
6153 SCIP_Real minscalar;
6154 SCIP_Real maxscalar;
6155
6156 assert(var != NULL);
6158 assert(aggvar != NULL);
6160 assert(aggscalar != 0.0); /*lint !e777*/
6161
6162 maxscalar = minscalar = REALABS(aggscalar);
6163 minscalar *= aggvar->data.loose.minaggrcoef;
6164 maxscalar *= aggvar->data.loose.maxaggrcoef;
6165 if( var->data.loose.minaggrcoef > minscalar )
6166 var->data.loose.minaggrcoef = minscalar;
6167 if( var->data.loose.maxaggrcoef < maxscalar )
6168 var->data.loose.maxaggrcoef = maxscalar;
6169}
6170
6171
6172/** tightens the bounds of both variables in aggregation x = a*y + c */
6173static
6175 SCIP_VAR* var, /**< problem variable */
6176 BMS_BLKMEM* blkmem, /**< block memory */
6177 SCIP_SET* set, /**< global SCIP settings */
6178 SCIP_STAT* stat, /**< problem statistics */
6179 SCIP_PROB* transprob, /**< tranformed problem data */
6180 SCIP_PROB* origprob, /**< original problem data */
6181 SCIP_PRIMAL* primal, /**< primal data */
6182 SCIP_TREE* tree, /**< branch and bound tree */
6183 SCIP_REOPT* reopt, /**< reoptimization data structure */
6184 SCIP_LP* lp, /**< current LP data */
6185 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6186 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6187 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
6188 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6189 SCIP_VAR* aggvar, /**< variable y in aggregation x = a*y + c */
6190 SCIP_Real scalar, /**< multiplier a in aggregation x = a*y + c */
6191 SCIP_Real constant, /**< constant shift c in aggregation x = a*y + c */
6192 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
6193 SCIP_Bool* fixed /**< pointer to store whether the variables were fixed */
6194 )
6195{
6196 SCIP_Real varlb;
6197 SCIP_Real varub;
6198 SCIP_Real aggvarlb;
6199 SCIP_Real aggvarub;
6200 SCIP_Bool aggvarbdschanged;
6201
6202 assert(var != NULL);
6203 assert(var->scip == set->scip);
6204 assert(aggvar != NULL);
6205 assert(!SCIPsetIsZero(set, scalar));
6206 assert(infeasible != NULL);
6207 assert(fixed != NULL);
6208
6209 *infeasible = FALSE;
6210 *fixed = FALSE;
6211
6212 SCIPsetDebugMsg(set, "updating bounds of variables in aggregation <%s> == %g*<%s> %+g\n", var->name, scalar, aggvar->name, constant);
6213 SCIPsetDebugMsg(set, " old bounds: <%s> [%g,%g] <%s> [%g,%g]\n",
6214 var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
6215
6216 /* loop as long additional changes may be found */
6217 do
6218 {
6219 aggvarbdschanged = FALSE;
6220
6221 /* update the bounds of the aggregated variable x in x = a*y + c */
6222 if( scalar > 0.0 )
6223 {
6224 if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
6225 varlb = -SCIPsetInfinity(set);
6226 else
6227 varlb = aggvar->glbdom.lb * scalar + constant;
6228 if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
6229 varub = SCIPsetInfinity(set);
6230 else
6231 varub = aggvar->glbdom.ub * scalar + constant;
6232 }
6233 else
6234 {
6235 if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
6236 varub = SCIPsetInfinity(set);
6237 else
6238 varub = aggvar->glbdom.lb * scalar + constant;
6239 if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
6240 varlb = -SCIPsetInfinity(set);
6241 else
6242 varlb = aggvar->glbdom.ub * scalar + constant;
6243 }
6244 varlb = MAX(varlb, var->glbdom.lb);
6245 varub = MIN(varub, var->glbdom.ub);
6246 SCIPvarAdjustLb(var, set, &varlb);
6247 SCIPvarAdjustUb(var, set, &varub);
6248
6249 /* check the new bounds */
6250 if( SCIPsetIsGT(set, varlb, varub) )
6251 {
6252 /* the aggregation is infeasible */
6253 *infeasible = TRUE;
6254 return SCIP_OKAY;
6255 }
6256 else if( SCIPsetIsEQ(set, varlb, varub) )
6257 {
6258 /* the aggregated variable is fixed -> fix both variables */
6259 SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
6260 eventqueue, eventfilter, cliquetable, varlb, infeasible, fixed) );
6261 if( !(*infeasible) )
6262 {
6263 SCIP_Bool aggfixed;
6264
6265 SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
6266 eventqueue, eventfilter, cliquetable, (varlb-constant)/scalar, infeasible, &aggfixed) );
6267 assert(*fixed == aggfixed);
6268 }
6269 return SCIP_OKAY;
6270 }
6271 else
6272 {
6273 if( SCIPsetIsGT(set, varlb, var->glbdom.lb) )
6274 {
6275 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, varlb) );
6276 }
6277 if( SCIPsetIsLT(set, varub, var->glbdom.ub) )
6278 {
6279 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, varub) );
6280 }
6281
6282 /* update the hole list of the aggregation variable */
6283 /**@todo update hole list of aggregation variable */
6284 }
6285
6286 /* update the bounds of the aggregation variable y in x = a*y + c -> y = (x-c)/a */
6287 if( scalar > 0.0 )
6288 {
6289 if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
6290 aggvarlb = -SCIPsetInfinity(set);
6291 else
6292 aggvarlb = (var->glbdom.lb - constant) / scalar;
6293 if( SCIPsetIsInfinity(set, var->glbdom.ub) )
6294 aggvarub = SCIPsetInfinity(set);
6295 else
6296 aggvarub = (var->glbdom.ub - constant) / scalar;
6297 }
6298 else
6299 {
6300 if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
6301 aggvarub = SCIPsetInfinity(set);
6302 else
6303 aggvarub = (var->glbdom.lb - constant) / scalar;
6304 if( SCIPsetIsInfinity(set, var->glbdom.ub) )
6305 aggvarlb = -SCIPsetInfinity(set);
6306 else
6307 aggvarlb = (var->glbdom.ub - constant) / scalar;
6308 }
6309 aggvarlb = MAX(aggvarlb, aggvar->glbdom.lb);
6310 aggvarub = MIN(aggvarub, aggvar->glbdom.ub);
6311 SCIPvarAdjustLb(aggvar, set, &aggvarlb);
6312 SCIPvarAdjustUb(aggvar, set, &aggvarub);
6313
6314 /* check the new bounds */
6315 if( SCIPsetIsGT(set, aggvarlb, aggvarub) )
6316 {
6317 /* the aggregation is infeasible */
6318 *infeasible = TRUE;
6319 return SCIP_OKAY;
6320 }
6321 else if( SCIPsetIsEQ(set, aggvarlb, aggvarub) )
6322 {
6323 /* the aggregation variable is fixed -> fix both variables */
6324 SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
6325 eventqueue, eventfilter, cliquetable, aggvarlb, infeasible, fixed) );
6326 if( !(*infeasible) )
6327 {
6328 SCIP_Bool varfixed;
6329
6330 SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
6331 eventqueue, eventfilter, cliquetable, aggvarlb * scalar + constant, infeasible, &varfixed) );
6332 assert(*fixed == varfixed);
6333 }
6334 return SCIP_OKAY;
6335 }
6336 else
6337 {
6338 SCIP_Real oldbd;
6339 if( SCIPsetIsGT(set, aggvarlb, aggvar->glbdom.lb) )
6340 {
6341 oldbd = aggvar->glbdom.lb;
6342 SCIP_CALL( SCIPvarChgLbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, aggvarlb) );
6343 aggvarbdschanged = !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.lb);
6344 }
6345 if( SCIPsetIsLT(set, aggvarub, aggvar->glbdom.ub) )
6346 {
6347 oldbd = aggvar->glbdom.ub;
6348 SCIP_CALL( SCIPvarChgUbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, aggvarub) );
6349 aggvarbdschanged = aggvarbdschanged || !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.ub);
6350 }
6351
6352 /* update the hole list of the aggregation variable */
6353 /**@todo update hole list of aggregation variable */
6354 }
6355 }
6356 while( aggvarbdschanged );
6357
6358 SCIPsetDebugMsg(set, " new bounds: <%s> [%g,%g] <%s> [%g,%g]\n",
6359 var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
6360
6361 return SCIP_OKAY;
6362}
6363
6364/** tightens the bounds of both variables in aggregation x = a*y + c */
6365static
6367 SCIP_VAR* var, /**< problem variable */
6368 BMS_BLKMEM* blkmem, /**< block memory */
6369 SCIP_SET* set, /**< global SCIP settings */
6370 SCIP_STAT* stat, /**< problem statistics */
6371 SCIP_PROB* transprob, /**< tranformed problem data */
6372 SCIP_PROB* origprob, /**< original problem data */
6373 SCIP_PRIMAL* primal, /**< primal data */
6374 SCIP_TREE* tree, /**< branch and bound tree */
6375 SCIP_REOPT* reopt, /**< reoptimization data structure */
6376 SCIP_LP* lp, /**< current LP data */
6377 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6378 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6379 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
6380 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6381 SCIP_VAR* aggvar, /**< variable y in aggregation x = a*y + c */
6382 SCIP_RATIONAL* scalar, /**< multiplier a in aggregation x = a*y + c */
6383 SCIP_RATIONAL* constant, /**< constant shift c in aggregation x = a*y + c */
6384 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
6385 SCIP_Bool* fixed /**< pointer to store whether the variables were fixed */
6386 )
6387{
6388 SCIP_RATIONAL* varlb;
6389 SCIP_RATIONAL* varub;
6390 SCIP_RATIONAL* aggvarlb;
6391 SCIP_RATIONAL* aggvarub;
6392 SCIP_Bool aggvarbdschanged;
6393
6394 assert(var != NULL);
6395 assert(var->scip == set->scip);
6396 assert(aggvar != NULL);
6397 assert(!SCIPrationalIsZero(scalar));
6398 assert(infeasible != NULL);
6399 assert(fixed != NULL);
6400
6401 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &varlb) );
6402 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &varub) );
6403 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &aggvarlb) );
6404 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &aggvarub) );
6405
6406 *infeasible = FALSE;
6407 *fixed = FALSE;
6408
6409 SCIPrationalDebugMessage("updating bounds of variables in aggregation <%s> == %q*<%s> %+q\n", var->name, scalar, aggvar->name, constant);
6410 SCIPrationalDebugMessage(" old bounds: <%s> [%q,%q] <%s> [%q,%q]\n",
6411 var->name, var->exactdata->glbdom.lb, var->exactdata->glbdom.ub, aggvar->name, aggvar->exactdata->glbdom.lb, aggvar->exactdata->glbdom.ub);
6412
6413 /* loop as long additional changes may be found */
6414 do
6415 {
6416 aggvarbdschanged = FALSE;
6417
6418 /* update the bounds of the aggregated variable x in x = a*y + c */
6419 if( SCIPrationalIsPositive(scalar) )
6420 {
6423 else
6424 {
6425 SCIPrationalMult(varlb, aggvar->exactdata->glbdom.lb, scalar);
6426 SCIPrationalAdd(varlb, varlb, constant);
6427 }
6430 else
6431 {
6432 SCIPrationalMult(varub, aggvar->exactdata->glbdom.ub, scalar);
6433 SCIPrationalAdd(varub, varub, constant);
6434 }
6435 }
6436 else
6437 {
6440 else
6441 {
6442 SCIPrationalMult(varub, aggvar->exactdata->glbdom.lb, scalar);
6443 SCIPrationalAdd(varub, varub, constant);
6444 }
6447 else
6448 {
6449 SCIPrationalMult(varlb, aggvar->exactdata->glbdom.ub, scalar);
6450 SCIPrationalAdd(varlb, varlb, constant);
6451 }
6452 }
6453 SCIPrationalMax(varlb, varlb, var->exactdata->glbdom.lb);
6454 SCIPrationalMin(varub, varub, var->exactdata->glbdom.ub);
6455 SCIPvarAdjustLbExact(var, set, varlb);
6456 SCIPvarAdjustUbExact(var, set, varub);
6457
6458 /* check the new bounds */
6459 if( SCIPrationalIsGT(varlb, varub) )
6460 {
6461 /* the aggregation is infeasible */
6462 *infeasible = TRUE;
6463 break;
6464 }
6465 else if( SCIPrationalIsEQ(varlb, varub) )
6466 {
6467 /* the aggregated variable is fixed -> fix both variables */
6468 SCIP_CALL( SCIPvarFixExact(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
6469 eventqueue, eventfilter, cliquetable, varlb, infeasible, fixed) );
6470
6471 if( !(*infeasible) )
6472 {
6473 SCIP_Bool aggfixed;
6474
6475 SCIPrationalDiff(varlb, varlb, constant);
6476 SCIPrationalDiv(varlb, varlb, scalar);
6477
6478 SCIP_CALL( SCIPvarFixExact(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
6479 eventqueue, eventfilter, cliquetable, varlb, infeasible, &aggfixed) );
6480 assert(*fixed == aggfixed);
6481 }
6482 break;
6483 }
6484 else
6485 {
6486 if( SCIPrationalIsGT(varlb, var->exactdata->glbdom.lb) )
6487 {
6488 SCIP_CALL( SCIPvarChgLbGlobalExact(var, blkmem, set, stat, lp->lpexact, branchcand, eventqueue, cliquetable, varlb) );
6489 }
6490 if( SCIPrationalIsLT(varub, var->exactdata->glbdom.ub) )
6491 {
6492 SCIP_CALL( SCIPvarChgUbGlobalExact(var, blkmem, set, stat, lp->lpexact, branchcand, eventqueue, cliquetable, varub) );
6493 }
6494
6495 /* update the hole list of the aggregation variable */
6496 /**@todo update hole list of aggregation variable */
6497 }
6498
6499 /* update the bounds of the aggregation variable y in x = a*y + c -> y = (x-c)/a */
6500 if( SCIPrationalIsPositive(scalar) )
6501 {
6502 if( SCIPrationalIsNegInfinity(var->exactdata->glbdom.lb) )
6504 else
6505 {
6506 SCIPrationalDiff(aggvarlb, var->exactdata->glbdom.lb, constant);
6507 SCIPrationalDiv(aggvarlb, aggvarlb, scalar);
6508 }
6509 if( SCIPrationalIsInfinity(var->exactdata->glbdom.ub) )
6510 SCIPrationalSetInfinity(aggvarub);
6511 else
6512 {
6513 SCIPrationalDiff(aggvarub, var->exactdata->glbdom.ub, constant);
6514 SCIPrationalDiv(aggvarub, aggvarub, scalar);
6515 }
6516 }
6517 else
6518 {
6519 if( SCIPrationalIsNegInfinity(var->exactdata->glbdom.lb) )
6520 SCIPrationalSetInfinity(aggvarub);
6521 else
6522 {
6523 SCIPrationalDiff(aggvarub, var->exactdata->glbdom.lb, constant);
6524 SCIPrationalDiv(aggvarub, aggvarub, scalar);
6525 }
6526 if( SCIPrationalIsInfinity(var->exactdata->glbdom.ub) )
6528 else
6529 {
6530 SCIPrationalDiff(aggvarlb, var->exactdata->glbdom.ub, constant);
6531 SCIPrationalDiv(aggvarlb, aggvarlb, scalar);
6532 }
6533 }
6534 SCIPrationalMax(aggvarlb, aggvarlb, aggvar->exactdata->glbdom.lb);
6535 SCIPrationalMin(aggvarub, aggvarub, aggvar->exactdata->glbdom.ub);
6536 SCIPvarAdjustLbExact(aggvar, set, aggvarlb);
6537 SCIPvarAdjustUbExact(aggvar, set, aggvarub);
6538
6539 /* check the new bounds */
6540 if( SCIPrationalIsGT(aggvarlb, aggvarub) )
6541 {
6542 /* the aggregation is infeasible */
6543 *infeasible = TRUE;
6544 break;
6545 }
6546 else if( SCIPrationalIsEQ(aggvarlb, aggvarub) )
6547 {
6548 /* the aggregation variable is fixed -> fix both variables */
6549 SCIP_CALL( SCIPvarFixExact(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
6550 eventqueue, eventfilter, cliquetable, aggvarlb, infeasible, fixed) );
6551
6552 if( !(*infeasible) )
6553 {
6554 SCIP_Bool varfixed;
6555
6556 SCIPrationalMult(aggvarlb, aggvarlb, scalar);
6557 SCIPrationalAdd(aggvarlb, aggvarlb, constant);
6558
6559 SCIP_CALL( SCIPvarFixExact(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
6560 eventqueue, eventfilter, cliquetable, aggvarlb, infeasible, &varfixed) );
6561 assert(*fixed == varfixed);
6562 }
6563 break;
6564 }
6565 else
6566 {
6567 if( SCIPrationalIsGT(aggvarlb, aggvar->exactdata->glbdom.lb) )
6568 {
6569 SCIPrationalSetRational(varlb, aggvar->exactdata->glbdom.lb);
6570 SCIP_CALL( SCIPvarChgLbGlobalExact(aggvar, blkmem, set, stat, lp->lpexact, branchcand, eventqueue, cliquetable, aggvarlb) );
6571 aggvarbdschanged = !SCIPrationalIsEQ(varlb, aggvar->exactdata->glbdom.lb);
6572 }
6573
6574 if( SCIPrationalIsLT(aggvarub, aggvar->exactdata->glbdom.ub) )
6575 {
6576 SCIPrationalSetRational(varub, aggvar->exactdata->glbdom.ub);
6577 SCIP_CALL( SCIPvarChgUbGlobalExact(aggvar, blkmem, set, stat, lp->lpexact, branchcand, eventqueue, cliquetable, aggvarub) );
6578 aggvarbdschanged = aggvarbdschanged || !SCIPrationalIsEQ(varub, aggvar->exactdata->glbdom.ub);
6579 }
6580
6581 /* update the hole list of the aggregation variable */
6582 /**@todo update hole list of aggregation variable */
6583 }
6584 }
6585 while( aggvarbdschanged );
6586
6587 SCIPrationalDebugMessage(" new bounds: <%s> [%q,%q] <%s> [%q,%q]\n",
6588 var->name, var->exactdata->glbdom.lb, var->exactdata->glbdom.ub, aggvar->name, aggvar->exactdata->glbdom.lb, aggvar->exactdata->glbdom.ub);
6589
6590 SCIPrationalFreeBuffer(set->buffer, &aggvarub);
6591 SCIPrationalFreeBuffer(set->buffer, &aggvarlb);
6592 SCIPrationalFreeBuffer(set->buffer, &varub);
6593 SCIPrationalFreeBuffer(set->buffer, &varlb);
6594
6595 return SCIP_OKAY;
6596}
6597
6598/** converts loose variable into aggregated variable */
6600 SCIP_VAR* var, /**< loose problem variable */
6601 BMS_BLKMEM* blkmem, /**< block memory */
6602 SCIP_SET* set, /**< global SCIP settings */
6603 SCIP_STAT* stat, /**< problem statistics */
6604 SCIP_PROB* transprob, /**< tranformed problem data */
6605 SCIP_PROB* origprob, /**< original problem data */
6606 SCIP_PRIMAL* primal, /**< primal data */
6607 SCIP_TREE* tree, /**< branch and bound tree */
6608 SCIP_REOPT* reopt, /**< reoptimization data structure */
6609 SCIP_LP* lp, /**< current LP data */
6610 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6611 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6612 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6613 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
6614 SCIP_VAR* aggvar, /**< loose variable y in aggregation x = a*y + c */
6615 SCIP_Real scalar, /**< multiplier a in aggregation x = a*y + c */
6616 SCIP_Real constant, /**< constant shift c in aggregation x = a*y + c */
6617 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
6618 SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
6619 )
6620{
6621 SCIP_VAR** vars;
6622 SCIP_Real* coefs;
6623 SCIP_Real* constants;
6624 SCIP_Real obj;
6625 SCIP_Real branchfactor;
6626 SCIP_Bool fixed;
6627 int branchpriority;
6628 int nlocksdown[NLOCKTYPES];
6629 int nlocksup[NLOCKTYPES];
6630 int nvbds;
6631 int i;
6632 int j;
6633
6634 assert(var != NULL);
6635 assert(aggvar != NULL);
6636 assert(var->scip == set->scip);
6637 assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
6638 assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
6640 assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
6641 assert(infeasible != NULL);
6642 assert(aggregated != NULL);
6643
6644 *infeasible = FALSE;
6645 *aggregated = FALSE;
6646
6647 /* get active problem variable of aggregation variable */
6648 SCIP_CALL( SCIPvarGetProbvarSum(&aggvar, set, &scalar, &constant) );
6649
6650 /* aggregation is a fixing, if the scalar is zero */
6651 if( SCIPsetIsZero(set, scalar) )
6652 {
6653 SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue,
6654 eventfilter, cliquetable, constant, infeasible, aggregated) );
6655 goto TERMINATE;
6656 }
6657
6658 /* don't perform the aggregation if the aggregation variable is multi-aggregated itself */
6660 return SCIP_OKAY;
6661
6662 /**@todo currently we don't perform the aggregation if the aggregation variable has a non-empty hole list; this
6663 * should be changed in the future
6664 */
6666 return SCIP_OKAY;
6667
6668 /* if the variable is not allowed to be aggregated */
6669 if( SCIPvarDoNotAggr(var) )
6670 {
6671 SCIPsetDebugMsg(set, "variable is not allowed to be aggregated.\n");
6672 return SCIP_OKAY;
6673 }
6674
6675 assert(aggvar->glbdom.lb == aggvar->locdom.lb); /*lint !e777*/
6676 assert(aggvar->glbdom.ub == aggvar->locdom.ub); /*lint !e777*/
6678
6679 SCIPsetDebugMsg(set, "aggregate variable <%s>[%g,%g] == %g*<%s>[%g,%g] %+g\n", var->name, var->glbdom.lb, var->glbdom.ub,
6680 scalar, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub, constant);
6681
6682 /* if variable and aggregation variable are equal, the variable can be fixed: x == a*x + c => x == c/(1-a) */
6683 if( var == aggvar )
6684 {
6685 if( SCIPsetIsEQ(set, scalar, 1.0) )
6686 *infeasible = !SCIPsetIsZero(set, constant);
6687 else
6688 {
6689 SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
6690 eventqueue, eventfilter, cliquetable, constant/(1.0-scalar), infeasible, aggregated) );
6691 }
6692 goto TERMINATE;
6693 }
6694
6695 /* tighten the bounds of aggregated and aggregation variable */
6696 SCIP_CALL( varUpdateAggregationBounds(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
6697 branchcand, eventqueue, eventfilter, cliquetable, aggvar, scalar, constant, infeasible, &fixed) );
6698 if( *infeasible || fixed )
6699 {
6700 *aggregated = fixed;
6701 goto TERMINATE;
6702 }
6703
6704 /* delete implications and variable bounds of the aggregated variable from other variables, but keep them in the
6705 * aggregated variable
6706 */
6707 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, FALSE) );
6708
6709 /* set the aggregated variable's objective value to 0.0 */
6710 obj = var->obj;
6711 SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
6712
6713 /* unlock all locks */
6714 for( i = 0; i < NLOCKTYPES; i++ )
6715 {
6716 nlocksdown[i] = var->nlocksdown[i];
6717 nlocksup[i] = var->nlocksup[i];
6718
6719 var->nlocksdown[i] = 0;
6720 var->nlocksup[i] = 0;
6721 }
6722
6723 /* update aggregation bounds (argument names of varUpdateMinMaxAggrCoef are swapped) */
6724 varUpdateMinMaxAggrCoef(aggvar, var, scalar);
6725
6726 /* check, if variable should be used as NEGATED variable of the aggregation variable */
6727 if( SCIPvarIsBinary(var) && SCIPvarIsBinary(aggvar)
6728 && var->negatedvar == NULL && aggvar->negatedvar == NULL
6729 && SCIPsetIsEQ(set, scalar, -1.0) && SCIPsetIsEQ(set, constant, 1.0) )
6730 {
6731 /* link both variables as negation pair */
6732 var->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
6733 var->data.negate.constant = 1.0;
6734 var->negatedvar = aggvar;
6735 aggvar->negatedvar = var;
6736
6737 /* copy donot(mult)aggr status */
6738 aggvar->donotaggr |= var->donotaggr;
6739 aggvar->donotmultaggr |= var->donotmultaggr;
6740
6741 /* mark both variables to be non-deletable */
6744 }
6745 else
6746 {
6747 /* convert variable into aggregated variable */
6748 var->varstatus = SCIP_VARSTATUS_AGGREGATED; /*lint !e641*/
6749 var->data.aggregate.var = aggvar;
6750 var->data.aggregate.scalar = scalar;
6751 var->data.aggregate.constant = constant;
6752
6753 /* copy donot(mult)aggr status */
6754 aggvar->donotaggr |= var->donotaggr;
6755 aggvar->donotmultaggr |= var->donotmultaggr;
6756
6757 /* mark both variables to be non-deletable */
6760 }
6761
6762 /* make aggregated variable a parent of the aggregation variable */
6763 SCIP_CALL( varAddParent(aggvar, blkmem, set, var) );
6764
6765 /* relock the variable, thus increasing the locks of the aggregation variable */
6766 for( i = 0; i < NLOCKTYPES; i++ )
6767 {
6768 SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
6769 }
6770
6771 /* move the variable bounds to the aggregation variable:
6772 * - add all variable bounds again to the variable, thus adding it to the aggregation variable
6773 * - free the variable bounds data structures
6774 */
6775 if( var->vlbs != NULL )
6776 {
6777 nvbds = SCIPvboundsGetNVbds(var->vlbs);
6778 vars = SCIPvboundsGetVars(var->vlbs);
6779 coefs = SCIPvboundsGetCoefs(var->vlbs);
6780 constants = SCIPvboundsGetConstants(var->vlbs);
6781 for( i = 0; i < nvbds && !(*infeasible); ++i )
6782 {
6783 SCIP_CALL( SCIPvarAddVlb(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
6784 eventqueue, eventfilter, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
6785 }
6786 }
6787 if( var->vubs != NULL )
6788 {
6789 nvbds = SCIPvboundsGetNVbds(var->vubs);
6790 vars = SCIPvboundsGetVars(var->vubs);
6791 coefs = SCIPvboundsGetCoefs(var->vubs);
6792 constants = SCIPvboundsGetConstants(var->vubs);
6793 for( i = 0; i < nvbds && !(*infeasible); ++i )
6794 {
6795 SCIP_CALL( SCIPvarAddVub(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
6796 eventqueue, eventfilter, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
6797 }
6798 }
6799 SCIPvboundsFree(&var->vlbs, blkmem);
6800 SCIPvboundsFree(&var->vubs, blkmem);
6801
6802 /* move the implications to the aggregation variable:
6803 * - add all implications again to the variable, thus adding it to the aggregation variable
6804 * - free the implications data structures
6805 */
6806 if( var->implics != NULL && SCIPvarGetType(aggvar) == SCIP_VARTYPE_BINARY && !SCIPvarIsImpliedIntegral(aggvar) )
6807 {
6809 for( i = 0; i < 2; ++i )
6810 {
6811 SCIP_VAR** implvars;
6812 SCIP_BOUNDTYPE* impltypes;
6813 SCIP_Real* implbounds;
6814 int nimpls;
6815
6816 nimpls = SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i);
6817 implvars = SCIPimplicsGetVars(var->implics, (SCIP_Bool)i);
6818 impltypes = SCIPimplicsGetTypes(var->implics, (SCIP_Bool)i);
6819 implbounds = SCIPimplicsGetBounds(var->implics, (SCIP_Bool)i);
6820
6821 for( j = 0; j < nimpls && !(*infeasible); ++j )
6822 {
6823 /* @todo can't we omit transitive closure, because it should already have been done when adding the
6824 * implication to the aggregated variable?
6825 */
6826 SCIP_CALL( SCIPvarAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
6827 branchcand, eventqueue, eventfilter, (SCIP_Bool)i, implvars[j], impltypes[j], implbounds[j], FALSE,
6828 infeasible, NULL) );
6829 assert(nimpls == SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i));
6830 }
6831 }
6832 }
6833 SCIPimplicsFree(&var->implics, blkmem);
6834
6835 /* add the history entries to the aggregation variable and clear the history of the aggregated variable */
6836 SCIPhistoryUnite(aggvar->history, var->history, scalar < 0.0);
6837 SCIPhistoryUnite(aggvar->historycrun, var->historycrun, scalar < 0.0);
6838 SCIPhistoryReset(var->history);
6839 SCIPhistoryReset(var->historycrun);
6840
6841 /* update flags of aggregation variable */
6842 aggvar->removable &= var->removable;
6843
6844 /* update branching factors and priorities of both variables to be the maximum of both variables */
6845 branchfactor = MAX(aggvar->branchfactor, var->branchfactor);
6846 branchpriority = MAX(aggvar->branchpriority, var->branchpriority);
6847 SCIP_CALL( SCIPvarChgBranchFactor(aggvar, set, branchfactor) );
6848 SCIP_CALL( SCIPvarChgBranchPriority(aggvar, branchpriority) );
6849 SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
6850 SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
6851
6852 /* update branching direction of both variables to agree to a single direction */
6853 if( scalar >= 0.0 )
6854 {
6855 if( (SCIP_BRANCHDIR)var->branchdirection == SCIP_BRANCHDIR_AUTO )
6856 {
6858 }
6860 {
6861 SCIP_CALL( SCIPvarChgBranchDirection(aggvar, (SCIP_BRANCHDIR)var->branchdirection) );
6862 }
6863 else if( var->branchdirection != aggvar->branchdirection )
6864 {
6866 }
6867 }
6868 else
6869 {
6870 if( (SCIP_BRANCHDIR)var->branchdirection == SCIP_BRANCHDIR_AUTO )
6871 {
6873 }
6875 {
6877 }
6878 else if( var->branchdirection != aggvar->branchdirection )
6879 {
6881 }
6882 }
6883
6884 if( var->probindex != -1 )
6885 {
6886 /* inform problem about the variable's status change */
6887 SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
6888 }
6889
6890 /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
6891 * variable and the problem's objective offset
6892 */
6893 SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventqueue, eventfilter, obj) );
6894
6895 /* issue VARFIXED event */
6896 SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 1) );
6897
6898 *aggregated = TRUE;
6899
6900TERMINATE:
6901 /* check aggregation on debugging solution */
6902 if( *infeasible || *aggregated )
6903 SCIP_CALL( SCIPdebugCheckAggregation(set, var, &aggvar, &scalar, constant, 1) ); /*lint !e506 !e774*/
6904
6905 return SCIP_OKAY;
6906}
6907
6908/** converts loose variable into aggregated variable */
6910 SCIP_VAR* var, /**< loose problem variable */
6911 BMS_BLKMEM* blkmem, /**< block memory */
6912 SCIP_SET* set, /**< global SCIP settings */
6913 SCIP_STAT* stat, /**< problem statistics */
6914 SCIP_PROB* transprob, /**< tranformed problem data */
6915 SCIP_PROB* origprob, /**< original problem data */
6916 SCIP_PRIMAL* primal, /**< primal data */
6917 SCIP_TREE* tree, /**< branch and bound tree */
6918 SCIP_REOPT* reopt, /**< reoptimization data structure */
6919 SCIP_LP* lp, /**< current LP data */
6920 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6921 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6922 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6923 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
6924 SCIP_VAR* aggvar, /**< loose variable y in aggregation x = a*y + c */
6925 SCIP_RATIONAL* scalar, /**< multiplier a in aggregation x = a*y + c */
6926 SCIP_RATIONAL* constant, /**< constant shift c in aggregation x = a*y + c */
6927 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
6928 SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
6929 )
6930{
6932 SCIP_RATIONAL* tmpval;
6933 SCIP_Real branchfactor;
6934 SCIP_Bool fixed;
6935 int branchpriority;
6936 int nlocksdown[NLOCKTYPES];
6937 int nlocksup[NLOCKTYPES];
6938 int i;
6939
6940 assert(var != NULL);
6941 assert(aggvar != NULL);
6942 assert(var->scip == set->scip);
6943 assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
6944 assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
6946 assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
6947 assert(infeasible != NULL);
6948 assert(aggregated != NULL);
6949
6950 *infeasible = FALSE;
6951 *aggregated = FALSE;
6952
6953 /* get active problem variable of aggregation variable */
6954 SCIP_CALL( SCIPvarGetProbvarSumExact(&aggvar, scalar, constant) );
6955
6956 /* aggregation is a fixing, if the scalar is zero */
6957 if( SCIPrationalIsZero(scalar) )
6958 {
6959 SCIP_CALL( SCIPvarFixExact(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
6960 eventqueue, eventfilter, cliquetable, constant, infeasible, aggregated) );
6961 return SCIP_OKAY;
6962 }
6963
6964 /* don't perform the aggregation if the aggregation variable is multi-aggregated itself */
6966 return SCIP_OKAY;
6967
6968 /**@todo currently we don't perform the aggregation if the aggregation variable has a non-empty hole list; this
6969 * should be changed in the future
6970 */
6972 return SCIP_OKAY;
6973
6974 /* if the variable is not allowed to be aggregated */
6975 if( SCIPvarDoNotAggr(var) )
6976 {
6977 SCIPsetDebugMsg(set, "variable is not allowed to be aggregated.\n");
6978 return SCIP_OKAY;
6979 }
6980
6981 assert(aggvar->glbdom.lb == aggvar->locdom.lb); /*lint !e777*/
6982 assert(aggvar->glbdom.ub == aggvar->locdom.ub); /*lint !e777*/
6984
6985 SCIPrationalDebugMessage("aggregate variable <%s>[%q,%q] == %q*<%s>[%q,%q] +%q\n", var->name, var->exactdata->glbdom.lb, var->exactdata->glbdom.ub,
6986 scalar, aggvar->name, aggvar->exactdata->glbdom.lb, aggvar->exactdata->glbdom.ub, constant);
6987
6988 /* if variable and aggregation variable are equal, the variable can be fixed: x == a*x + c => x == c/(1-a) */
6989 if( var == aggvar )
6990 {
6991 if( SCIPrationalIsEQReal(scalar, 1.0) )
6992 *infeasible = !SCIPrationalIsZero(constant);
6993 else
6994 {
6995 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmpval) );
6996 /* fix to constant/(1-scalar) */
6997 SCIPrationalDiffReal(tmpval, scalar, 1.0);
6998 SCIPrationalNegate(tmpval, tmpval);
6999 SCIPrationalDiv(tmpval, constant, tmpval);
7000 SCIP_CALL( SCIPvarFixExact(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
7001 eventqueue, eventfilter, cliquetable, tmpval, infeasible, aggregated) );
7002
7003 SCIPrationalFreeBuffer(set->buffer, &tmpval);
7004 }
7005 return SCIP_OKAY;
7006 }
7007
7008 /* tighten the bounds of aggregated and aggregation variable */
7009 SCIP_CALL( varUpdateAggregationBoundsExact(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
7010 branchcand, eventqueue, eventfilter, cliquetable, aggvar, scalar, constant, infeasible, &fixed) );
7011 if( *infeasible || fixed )
7012 {
7013 *aggregated = fixed;
7014 return SCIP_OKAY;
7015 }
7016
7017 /* delete implications and variable bounds of the aggregated variable from other variables, but keep them in the
7018 * aggregated variable
7019 */
7020 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, FALSE) );
7021 assert(var->cliquelist == NULL);
7022
7024 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmpval) );
7025
7026 /* set the aggregated variable's objective value to 0.0 */
7027 SCIPrationalSetRational(obj, var->exactdata->obj);
7028 SCIPrationalSetReal(tmpval, 0.0);
7029 SCIP_CALL( SCIPvarChgObjExact(var, blkmem, set, transprob, primal, lp->lpexact, eventqueue, tmpval) );
7030
7031 SCIPrationalFreeBuffer(set->buffer, &tmpval);
7032
7033 /* unlock all locks */
7034 for( i = 0; i < NLOCKTYPES; i++ )
7035 {
7036 nlocksdown[i] = var->nlocksdown[i];
7037 nlocksup[i] = var->nlocksup[i];
7038
7039 var->nlocksdown[i] = 0;
7040 var->nlocksup[i] = 0;
7041 }
7042
7043 /* check, if variable should be used as NEGATED variable of the aggregation variable */
7044 if( SCIPvarIsBinary(var) && SCIPvarIsBinary(aggvar)
7045 && var->negatedvar == NULL && aggvar->negatedvar == NULL
7046 && SCIPrationalIsEQReal(scalar, -1.0) && SCIPrationalIsEQReal(constant, 1.0) )
7047 {
7048 /* link both variables as negation pair */
7049 var->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
7050 var->exactdata->varstatusexact = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
7051 var->data.negate.constant = 1.0;
7052 var->negatedvar = aggvar;
7053 aggvar->negatedvar = var;
7054
7055 /* copy doNotMultiaggr status */
7056 aggvar->donotmultaggr |= var->donotmultaggr;
7057
7058 /* mark both variables to be non-deletable */
7061 }
7062 else
7063 {
7064 /* convert variable into aggregated variable */
7065 var->varstatus = SCIP_VARSTATUS_AGGREGATED; /*lint !e641*/
7066 var->exactdata->varstatusexact = SCIP_VARSTATUS_AGGREGATED; /*lint !e641*/
7067 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &var->exactdata->aggregate.scalar) );
7068 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &var->exactdata->aggregate.constant) );
7069
7070 var->data.aggregate.var = aggvar;
7071 SCIPrationalSetRational(var->exactdata->aggregate.scalar, scalar);
7072 SCIPrationalSetRational(var->exactdata->aggregate.constant, constant);
7073 var->data.aggregate.scalar = SCIPrationalGetReal(scalar);
7074 var->data.aggregate.constant = SCIPrationalGetReal(constant);
7075
7076 /* copy doNotMultiaggr status */
7077 aggvar->donotmultaggr |= var->donotmultaggr;
7078
7079 /* mark both variables to be non-deletable */
7082 }
7083
7084 /* make aggregated variable a parent of the aggregation variable */
7085 SCIP_CALL( varAddParent(aggvar, blkmem, set, var) );
7086
7087 /* relock the variable, thus increasing the locks of the aggregation variable */
7088 for( i = 0; i < NLOCKTYPES; i++ )
7089 {
7090 SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
7091 }
7092
7093 /* move the variable bounds to the aggregation variable:
7094 * - add all variable bounds again to the variable, thus adding it to the aggregation variable
7095 * - free the variable bounds data structures
7096 */
7097 assert(var->vlbs == NULL);
7098 assert(var->vubs == NULL);
7099
7100 /* move the implications to the aggregation variable:
7101 * - add all implications again to the variable, thus adding it to the aggregation variable
7102 * - free the implications data structures
7103 */
7104 assert(var->implics == NULL);
7105
7106 /* add the history entries to the aggregation variable and clear the history of the aggregated variable */
7107 SCIPhistoryUnite(aggvar->history, var->history, SCIPrationalIsNegative(scalar));
7108 SCIPhistoryUnite(aggvar->historycrun, var->historycrun, SCIPrationalIsNegative(scalar));
7109 SCIPhistoryReset(var->history);
7110 SCIPhistoryReset(var->historycrun);
7111
7112 /* update flags of aggregation variable */
7113 aggvar->removable &= var->removable;
7114
7115 /* update branching factors and priorities of both variables to be the maximum of both variables */
7116 branchfactor = MAX(aggvar->branchfactor, var->branchfactor);
7117 branchpriority = MAX(aggvar->branchpriority, var->branchpriority);
7118 SCIP_CALL( SCIPvarChgBranchFactor(aggvar, set, branchfactor) );
7119 SCIP_CALL( SCIPvarChgBranchPriority(aggvar, branchpriority) );
7120 SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
7121 SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
7122
7123 /* update branching direction of both variables to agree to a single direction */
7124 if( !SCIPrationalIsNegative(scalar) )
7125 {
7126 if( (SCIP_BRANCHDIR)var->branchdirection == SCIP_BRANCHDIR_AUTO )
7127 {
7129 }
7131 {
7132 SCIP_CALL( SCIPvarChgBranchDirection(aggvar, (SCIP_BRANCHDIR)var->branchdirection) );
7133 }
7134 else if( var->branchdirection != aggvar->branchdirection )
7135 {
7137 }
7138 }
7139 else
7140 {
7141 if( (SCIP_BRANCHDIR)var->branchdirection == SCIP_BRANCHDIR_AUTO )
7142 {
7144 }
7146 {
7148 }
7149 else if( var->branchdirection != aggvar->branchdirection )
7150 {
7152 }
7153 }
7154
7155 if( var->probindex != -1 )
7156 {
7157 /* inform problem about the variable's status change */
7158 SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
7159 }
7160
7161 /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
7162 * variable and the problem's objective offset
7163 */
7164 SCIP_CALL( SCIPvarAddObjExact(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventqueue, eventfilter, obj) );
7165
7166 /* issue VARFIXED event */
7167 SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 1) );
7168
7169 SCIPrationalFreeBuffer(set->buffer, &obj);
7170
7171 *aggregated = TRUE;
7172
7173 return SCIP_OKAY;
7174}
7175
7176/** Tries to aggregate an equality a*x + b*y == c consisting of two (implicit) integral active problem variables x and
7177 * y. An integer aggregation (i.e. integral coefficients a' and b', such that a'*x + b'*y == c') is searched.
7178 *
7179 * This can lead to the detection of infeasibility (e.g. if c' is fractional), or to a rejection of the aggregation
7180 * (denoted by aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
7181 */
7182static
7184 SCIP_SET* set, /**< global SCIP settings */
7185 BMS_BLKMEM* blkmem, /**< block memory */
7186 SCIP_STAT* stat, /**< problem statistics */
7187 SCIP_PROB* transprob, /**< tranformed problem data */
7188 SCIP_PROB* origprob, /**< original problem data */
7189 SCIP_PRIMAL* primal, /**< primal data */
7190 SCIP_TREE* tree, /**< branch and bound tree */
7191 SCIP_REOPT* reopt, /**< reoptimization data structure */
7192 SCIP_LP* lp, /**< current LP data */
7193 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7194 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7195 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7196 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
7197 SCIP_VAR* varx, /**< integral variable x in equality a*x + b*y == c */
7198 SCIP_VAR* vary, /**< integral variable y in equality a*x + b*y == c */
7199 SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
7200 SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
7201 SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
7202 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
7203 SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
7204 )
7205{
7206 SCIP_VAR* aggvar;
7207 char aggvarname[SCIP_MAXSTRLEN];
7208 SCIP_Longint scalarxn = 0;
7209 SCIP_Longint scalarxd = 0;
7210 SCIP_Longint scalaryn = 0;
7211 SCIP_Longint scalaryd = 0;
7215 SCIP_Longint scm;
7216 SCIP_Longint gcd;
7217 SCIP_Longint currentclass;
7218 SCIP_Longint classstep;
7219 SCIP_Longint xsol;
7220 SCIP_Longint ysol;
7221 SCIP_Bool success;
7222 SCIP_VARTYPE vartype;
7223 SCIP_IMPLINTTYPE impltypex;
7224 SCIP_IMPLINTTYPE impltypey;
7225 SCIP_IMPLINTTYPE impltype;
7226
7227#define MAXDNOM 1000000LL
7228
7229 assert(set != NULL);
7230 assert(blkmem != NULL);
7231 assert(stat != NULL);
7232 assert(transprob != NULL);
7233 assert(origprob != NULL);
7234 assert(tree != NULL);
7235 assert(lp != NULL);
7236 assert(cliquetable != NULL);
7237 assert(branchcand != NULL);
7238 assert(eventqueue != NULL);
7239 assert(varx != NULL);
7240 assert(vary != NULL);
7241 assert(varx != vary);
7242 assert(infeasible != NULL);
7243 assert(aggregated != NULL);
7249 assert(!SCIPsetIsZero(set, scalarx));
7250 assert(!SCIPsetIsZero(set, scalary));
7251
7252 *infeasible = FALSE;
7253 *aggregated = FALSE;
7254
7255 /* if the variable is not allowed to be aggregated */
7256 if( SCIPvarDoNotAggr(varx) )
7257 {
7258 SCIPsetDebugMsg(set, "variable is not allowed to be aggregated.\n");
7259 return SCIP_OKAY;
7260 }
7261
7262 /* get rational representation of coefficients */
7263 success = SCIPrealToRational(scalarx, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalarxn, &scalarxd);
7264 if( success )
7265 success = SCIPrealToRational(scalary, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalaryn, &scalaryd);
7266 if( !success )
7267 return SCIP_OKAY;
7268 assert(scalarxd >= 1);
7269 assert(scalaryd >= 1);
7270
7271 /* multiply equality with smallest common denominator */
7272 scm = SCIPcalcSmaComMul(scalarxd, scalaryd);
7273 a = (scm/scalarxd)*scalarxn;
7274 b = (scm/scalaryd)*scalaryn;
7275 rhs *= scm;
7276
7277 /* divide equality by the greatest common divisor of a and b */
7278 gcd = SCIPcalcGreComDiv(ABS(a), ABS(b));
7279 a /= gcd;
7280 b /= gcd;
7281 rhs /= gcd;
7282 assert(a != 0);
7283 assert(b != 0);
7284
7285 /* check, if right hand side is integral */
7286 if( !SCIPsetIsFeasIntegral(set, rhs) )
7287 {
7288 *infeasible = TRUE;
7289 return SCIP_OKAY;
7290 }
7292
7293 /* check that the scalar and constant in the aggregation are not too large to avoid numerical problems */
7294 if( REALABS((SCIP_Real)(c/a)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) /*lint !e653*/
7295 || REALABS((SCIP_Real)(b)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) /*lint !e653*/
7296 || REALABS((SCIP_Real)(a)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
7297 {
7298 return SCIP_OKAY;
7299 }
7300
7301 /* check, if we are in an easy case with either |a| = 1 or |b| = 1 */
7302 if( ( a == 1 || a == -1 ) && !SCIPvarIsImpliedIntegral(vary) )
7303 {
7304 /* aggregate x = - b/a*y + c/a */
7305 /*lint --e{653}*/
7306 SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
7307 branchcand, eventqueue, eventfilter, vary, (SCIP_Real)(-b/a), (SCIP_Real)(c/a), infeasible, aggregated) );
7308 assert(*aggregated);
7309 return SCIP_OKAY;
7310 }
7311 if( ( b == 1 || b == -1 ) && !SCIPvarIsImpliedIntegral(varx) )
7312 {
7313 /* aggregate y = - a/b*x + c/b */
7314 /*lint --e{653}*/
7315 SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
7316 branchcand, eventqueue, eventfilter, varx, (SCIP_Real)(-a/b), (SCIP_Real)(c/b), infeasible, aggregated) );
7317 assert(*aggregated);
7318 return SCIP_OKAY;
7319 }
7320
7321 /* Both variables are integers, their coefficients are not multiples of each other, and they don't have any
7322 * common divisor. Let (x',y') be a solution of the equality
7323 * a*x + b*y == c -> a*x == c - b*y
7324 * Then x = -b*z + x', y = a*z + y' with z integral gives all solutions to the equality.
7325 */
7326
7327 /* find initial solution (x',y'):
7328 * - find y' such that c - b*y' is a multiple of a
7329 * - start in equivalence class c%a
7330 * - step through classes, where each step increases class number by (-b)%a, until class 0 is visited
7331 * - if equivalence class 0 is visited, we are done: y' equals the number of steps taken
7332 * - 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
7333 * - calculate x' with x' = (c - b*y')/a (which must be integral)
7334 *
7335 * Algorithm works for a > 0 only.
7336 */
7337 if( a < 0 )
7338 {
7339 a = -a;
7340 b = -b;
7341 c = -c;
7342 }
7343 assert(a > 0);
7344
7345 /* search upwards from ysol = 0 */
7346 ysol = 0;
7347 currentclass = c % a;
7348 if( currentclass < 0 )
7349 currentclass += a;
7350 assert(0 <= currentclass && currentclass < a);
7351
7352 classstep = (-b) % a;
7353
7354 if( classstep < 0 )
7355 classstep += a;
7356 assert(0 <= classstep && classstep < a);
7357
7358 while( currentclass != 0 )
7359 {
7360 assert(0 <= currentclass && currentclass < a);
7361 currentclass += classstep;
7362 if( currentclass >= a )
7363 currentclass -= a;
7364 ysol++;
7365 }
7366 assert(ysol < a);
7367 assert(((c - b*ysol) % a) == 0);
7368
7369 xsol = (c - b*ysol)/a;
7370
7371 /* determine variable type for new artificial variable:
7372 *
7373 * if both variables are implicit integer the new variable can be implicit too, because the integer implication on
7374 * these both variables should be enforced by some other variables, otherwise the new variable needs to be of
7375 * integral type
7376 */
7379 impltypex = SCIPvarGetImplType(varx);
7380 impltypey = SCIPvarGetImplType(vary);
7381 impltype = MIN(impltypex, impltypey);
7382
7383 /* feasible solutions are (x,y) = (x',y') + z * (-b,a)
7384 * - create new integer variable z with infinite bounds
7385 * - aggregate variable x = -b*z + x'
7386 * - aggregate variable y = a*z + y'
7387 * - the bounds of z are calculated automatically during aggregation
7388 */
7389 (void) SCIPsnprintf(aggvarname, SCIP_MAXSTRLEN, "agg%d", stat->nvaridx);
7390 SCIP_CALL( SCIPvarCreateTransformed(&aggvar, blkmem, set, stat,
7391 aggvarname, -SCIPsetInfinity(set), SCIPsetInfinity(set), 0.0, vartype, impltype,
7393 NULL, NULL, NULL, NULL, NULL) );
7394
7395 SCIP_CALL( SCIPprobAddVar(transprob, blkmem, set, lp, branchcand, eventqueue, eventfilter, aggvar) );
7396
7397 SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
7398 branchcand, eventqueue, eventfilter, aggvar, (SCIP_Real)(-b), (SCIP_Real)xsol, infeasible, aggregated) );
7399 assert(*aggregated || *infeasible);
7400
7401 if( !(*infeasible) )
7402 {
7403 SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
7404 branchcand, eventqueue, eventfilter, aggvar, (SCIP_Real)a, (SCIP_Real)ysol, infeasible, aggregated) );
7405 assert(*aggregated || *infeasible);
7406 }
7407
7408 /* release z */
7409 SCIP_CALL( SCIPvarRelease(&aggvar, blkmem, set, eventqueue, lp) );
7410
7411 return SCIP_OKAY; /*lint !e438*/
7412}
7413
7414/** Tries to aggregate an equality a*x + b*y == c consisting of two (implicit) integral active problem variables x and
7415 * y. An integer aggregation (i.e. integral coefficients a' and b', such that a'*x + b'*y == c') is searched.
7416 *
7417 * This can lead to the detection of infeasibility (e.g. if c' is fractional), or to a rejection of the aggregation
7418 * (denoted by aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
7419 */
7420static
7422 SCIP_SET* set, /**< global SCIP settings */
7423 BMS_BLKMEM* blkmem, /**< block memory */
7424 SCIP_STAT* stat, /**< problem statistics */
7425 SCIP_PROB* transprob, /**< tranformed problem data */
7426 SCIP_PROB* origprob, /**< original problem data */
7427 SCIP_PRIMAL* primal, /**< primal data */
7428 SCIP_TREE* tree, /**< branch and bound tree */
7429 SCIP_REOPT* reopt, /**< reoptimization data structure */
7430 SCIP_LP* lp, /**< current LP data */
7431 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7432 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7433 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7434 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
7435 SCIP_VAR* varx, /**< integral variable x in equality a*x + b*y == c */
7436 SCIP_VAR* vary, /**< integral variable y in equality a*x + b*y == c */
7437 SCIP_RATIONAL* scalarx, /**< multiplier a in equality a*x + b*y == c */
7438 SCIP_RATIONAL* scalary, /**< multiplier b in equality a*x + b*y == c */
7439 SCIP_RATIONAL* rhs, /**< right hand side c in equality a*x + b*y == c */
7440 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
7441 SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
7442 )
7443{
7444 SCIP_VAR* aggvar;
7445 SCIP_RATIONAL* tmprat1;
7446 SCIP_RATIONAL* tmprat2;
7447 SCIP_RATIONAL* tmprat3;
7448 char aggvarname[SCIP_MAXSTRLEN];
7449 SCIP_Longint scalarxn;
7450 SCIP_Longint scalarxd;
7451 SCIP_Longint scalaryn;
7452 SCIP_Longint scalaryd;
7456 SCIP_Longint scm;
7457 SCIP_Longint gcd;
7458 SCIP_Longint currentclass;
7459 SCIP_Longint classstep;
7460 SCIP_Longint xsol;
7461 SCIP_Longint ysol;
7462 SCIP_VARTYPE vartype;
7463 SCIP_IMPLINTTYPE impltypex;
7464 SCIP_IMPLINTTYPE impltypey;
7465 SCIP_IMPLINTTYPE impltype;
7466
7467 assert(set != NULL);
7468 assert(blkmem != NULL);
7469 assert(stat != NULL);
7470 assert(transprob != NULL);
7471 assert(origprob != NULL);
7472 assert(tree != NULL);
7473 assert(lp != NULL);
7474 assert(cliquetable != NULL);
7475 assert(branchcand != NULL);
7476 assert(eventqueue != NULL);
7477 assert(varx != NULL);
7478 assert(vary != NULL);
7479 assert(varx != vary);
7480 assert(infeasible != NULL);
7481 assert(aggregated != NULL);
7487 assert(!SCIPrationalIsZero(scalarx));
7488 assert(!SCIPrationalIsZero(scalary));
7489
7490 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmprat1) );
7491 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmprat2) );
7492 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmprat3) );
7493
7494 *infeasible = FALSE;
7495 *aggregated = FALSE;
7496
7497 SCIPrationalCanonicalize(scalary);
7498 SCIPrationalCanonicalize(scalarx);
7499
7500 scalarxd = SCIPrationalDenominator(scalarx);
7501 scalaryd = SCIPrationalDenominator(scalary);
7502 scalarxn = SCIPrationalNumerator(scalarx);
7503 scalaryn = SCIPrationalNumerator(scalary);
7504
7505 /* multiply equality with smallest common denominator */
7506 scm = SCIPcalcSmaComMul(scalarxd, scalaryd);
7507 a = (scm/scalarxd)*scalarxn;
7508 b = (scm/scalaryd)*scalaryn;
7509
7510 /* divide equality by the greatest common divisor of a and b */
7511 gcd = SCIPcalcGreComDiv(ABS(a), ABS(b));
7512 a /= gcd;
7513 b /= gcd;
7514 SCIPrationalSetFraction(tmprat1, scm, gcd);
7515 SCIPrationalMult(rhs, rhs, tmprat1);
7516 assert(a != 0);
7517 assert(b != 0);
7518
7519 /* check, if right hand side is integral */
7520 if( !SCIPrationalIsIntegral(rhs) )
7521 {
7522 *infeasible = TRUE;
7523 goto FREE;
7524 }
7525
7526 /* we know rhs is integral, so check if it is in integer range */
7528 {
7529 *infeasible = TRUE;
7530 goto FREE;
7531 }
7532
7533 /* check that the scalar and constant in the aggregation are not too large to avoid numerical problems */
7534 if( REALABS((SCIP_Real)(c/a)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) /*lint !e653*/
7535 || REALABS((SCIP_Real)(b)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) /*lint !e653*/
7536 || REALABS((SCIP_Real)(a)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
7537 {
7538 goto FREE;
7539 }
7540
7541 /* check, if we are in an easy case with either |a| = 1 or |b| = 1 */
7542 if( ( a == 1 || a == -1 ) && !SCIPvarIsImpliedIntegral(vary) )
7543 {
7544 /* aggregate x = - b/a*y + c/a */
7545 /*lint --e{653}*/
7546 SCIPrationalSetFraction(tmprat1, -b, a);
7547 SCIPrationalSetFraction(tmprat2, c, a);
7548 SCIP_CALL( SCIPvarAggregateExact(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
7549 branchcand, eventqueue, eventfilter, vary, tmprat1, tmprat2, infeasible, aggregated) );
7550 assert(*aggregated);
7551 goto FREE;
7552 }
7553 if( ( b == 1 || b == -1 ) && !SCIPvarIsImpliedIntegral(varx) )
7554 {
7555 /* aggregate y = - a/b*x + c/b */
7556 /*lint --e{653}*/
7557 SCIPrationalSetFraction(tmprat1, -a, b);
7558 SCIPrationalSetFraction(tmprat2, c, b);
7559 SCIP_CALL( SCIPvarAggregateExact(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
7560 branchcand, eventqueue, eventfilter, varx, tmprat1, tmprat2, infeasible, aggregated) );
7561 assert(*aggregated);
7562 goto FREE;
7563 }
7564
7565 /* Both variables are integers, their coefficients are not multiples of each other, and they don't have any
7566 * common divisor. Let (x',y') be a solution of the equality
7567 * a*x + b*y == c -> a*x == c - b*y
7568 * Then x = -b*z + x', y = a*z + y' with z integral gives all solutions to the equality.
7569 */
7570
7571 /* find initial solution (x',y'):
7572 * - find y' such that c - b*y' is a multiple of a
7573 * - start in equivalence class c%a
7574 * - step through classes, where each step increases class number by (-b)%a, until class 0 is visited
7575 * - if equivalence class 0 is visited, we are done: y' equals the number of steps taken
7576 * - 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
7577 * - calculate x' with x' = (c - b*y')/a (which must be integral)
7578 *
7579 * Algorithm works for a > 0 only.
7580 */
7581 if( a < 0 )
7582 {
7583 a = -a;
7584 b = -b;
7585 c = -c;
7586 }
7587 assert(a > 0);
7588
7589 /* search upwards from ysol = 0 */
7590 ysol = 0;
7591 currentclass = c % a;
7592 if( currentclass < 0 )
7593 currentclass += a;
7594 assert(0 <= currentclass && currentclass < a);
7595
7596 classstep = (-b) % a;
7597
7598 if( classstep < 0 )
7599 classstep += a;
7600 assert(0 <= classstep && classstep < a);
7601
7602 while( currentclass != 0 )
7603 {
7604 assert(0 <= currentclass && currentclass < a);
7605 currentclass += classstep;
7606 if( currentclass >= a )
7607 currentclass -= a;
7608 ysol++;
7609 }
7610 assert(ysol < a);
7611 assert(((c - b*ysol) % a) == 0);
7612
7613 xsol = (c - b*ysol)/a;
7614
7615 /* determine variable type for new artificial variable:
7616 *
7617 * if both variables are implicit integer the new variable can be implicit too, because the integer implication on
7618 * these both variables should be enforced by some other variables, otherwise the new variable needs to be of
7619 * integral type
7620 */
7623 impltypex = SCIPvarGetImplType(varx);
7624 impltypey = SCIPvarGetImplType(vary);
7625 impltype = MIN(impltypex, impltypey);
7626
7627 /* feasible solutions are (x,y) = (x',y') + z * (-b,a)
7628 * - create new integer variable z with infinite bounds
7629 * - aggregate variable x = -b*z + x'
7630 * - aggregate variable y = a*z + y'
7631 * - the bounds of z are calculated automatically during aggregation
7632 */
7633 (void) SCIPsnprintf(aggvarname, SCIP_MAXSTRLEN, "agg%d", stat->nvaridx);
7634 SCIP_CALL( SCIPvarCreateTransformed(&aggvar, blkmem, set, stat,
7635 aggvarname, -SCIPsetInfinity(set), SCIPsetInfinity(set), 0.0, vartype, impltype,
7637 NULL, NULL, NULL, NULL, NULL) );
7638
7640 SCIPrationalSetInfinity(tmprat2);
7641 SCIPrationalSetFraction(tmprat3, 0LL, 0LL);
7642
7643 SCIP_CALL( SCIPvarAddExactData(aggvar, blkmem, tmprat1, tmprat2, tmprat3) );
7644
7645 SCIP_CALL( SCIPprobAddVar(transprob, blkmem, set, lp, branchcand, eventqueue, eventfilter, aggvar) );
7646
7647 SCIPrationalSetFraction(tmprat1, -b, 1LL);
7648 SCIPrationalSetFraction(tmprat2, xsol, 1LL);
7649
7650 SCIP_CALL( SCIPvarAggregateExact(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
7651 branchcand, eventqueue, eventfilter, aggvar, tmprat1, tmprat2, infeasible, aggregated) );
7652 assert(*aggregated || *infeasible);
7653
7654 if( !(*infeasible) )
7655 {
7656 SCIPrationalSetFraction(tmprat1, a, 1LL);
7657 SCIPrationalSetFraction(tmprat2, ysol, 1LL);
7658
7659 SCIP_CALL( SCIPvarAggregateExact(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
7660 branchcand, eventqueue, eventfilter, aggvar, tmprat1, tmprat2, infeasible, aggregated) );
7661 assert(*aggregated || *infeasible);
7662 }
7663
7664 /* release z */
7665 SCIP_CALL( SCIPvarRelease(&aggvar, blkmem, set, eventqueue, lp) );
7666
7667FREE:
7668 SCIPrationalFreeBuffer(set->buffer, &tmprat3);
7669 SCIPrationalFreeBuffer(set->buffer, &tmprat2);
7670 SCIPrationalFreeBuffer(set->buffer, &tmprat1);
7671
7672 return SCIP_OKAY; /*lint !e438*/
7673}
7674
7675/** performs second step of SCIPaggregateVars():
7676 * the variable to be aggregated is chosen among active problem variables x' and y', preferring a less strict variable
7677 * type as aggregation variable (i.e. continuous variables are preferred over implicit integers, implicit integers
7678 * or integers over binaries). If none of the variables is continuous, it is tried to find an integer
7679 * aggregation (i.e. integral coefficients a'' and b'', such that a''*x' + b''*y' == c''). This can lead to
7680 * the detection of infeasibility (e.g. if c'' is fractional), or to a rejection of the aggregation (denoted by
7681 * aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
7682 *
7683 * @todo check for fixings, infeasibility, bound changes, or domain holes:
7684 * a) if there is no easy aggregation and we have one binary variable and another integer/implicit/binary variable
7685 * b) for implicit integer variables with fractional aggregation scalar (we cannot (for technical reasons) and do
7686 * not want to aggregate implicit integer variables, since we loose the corresponding divisibility property)
7687 */
7689 SCIP_SET* set, /**< global SCIP settings */
7690 BMS_BLKMEM* blkmem, /**< block memory */
7691 SCIP_STAT* stat, /**< problem statistics */
7692 SCIP_PROB* transprob, /**< tranformed problem data */
7693 SCIP_PROB* origprob, /**< original problem data */
7694 SCIP_PRIMAL* primal, /**< primal data */
7695 SCIP_TREE* tree, /**< branch and bound tree */
7696 SCIP_REOPT* reopt, /**< reoptimization data structure */
7697 SCIP_LP* lp, /**< current LP data */
7698 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7699 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7700 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7701 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
7702 SCIP_VAR* varx, /**< variable x in equality a*x + b*y == c */
7703 SCIP_VAR* vary, /**< variable y in equality a*x + b*y == c */
7704 SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
7705 SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
7706 SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
7707 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
7708 SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
7709 )
7710{
7711 SCIP_Real scalar;
7712 SCIP_Real constant;
7713 SCIP_Bool easyaggr;
7714 SCIP_VARTYPE typex;
7715 SCIP_VARTYPE typey;
7716
7717 assert(set != NULL);
7718 assert(blkmem != NULL);
7719 assert(stat != NULL);
7720 assert(transprob != NULL);
7721 assert(origprob != NULL);
7722 assert(tree != NULL);
7723 assert(lp != NULL);
7724 assert(cliquetable != NULL);
7725 assert(branchcand != NULL);
7726 assert(eventqueue != NULL);
7727 assert(varx != NULL);
7728 assert(vary != NULL);
7729 assert(varx != vary);
7730 assert(infeasible != NULL);
7731 assert(aggregated != NULL);
7735 assert(scalarx != 0.0); /*lint !e777*/
7736 assert(scalary != 0.0); /*lint !e777*/
7738
7739 *infeasible = FALSE;
7740 *aggregated = FALSE;
7741
7742 /**@todo simplify the following code once SCIP_DEPRECATED_VARTYPE_IMPLINT is removed */
7745
7746 /* prefer aggregating the variable of more general type (preferred aggregation variable is varx) */
7747 if( typex < typey ||
7748 ( typex == typey && SCIPvarIsBinary(varx) && !SCIPvarIsBinary(vary)) )
7749 {
7750 SCIP_VAR* var;
7751 SCIP_VARTYPE type;
7752
7753 /* switch the variables, such that varx is the variable of more general type (cont > implint > int > bin) */
7754 var = vary;
7755 vary = varx;
7756 varx = var;
7757 scalar = scalary;
7758 scalary = scalarx;
7759 scalarx = scalar;
7760 type = typey;
7761 typey = typex;
7762 typex = type;
7763 }
7764
7765 /* don't aggregate if the aggregation would lead to a binary variable aggregated to a non-binary variable */
7766 if( SCIPvarIsBinary(varx) && !SCIPvarIsBinary(vary) )
7767 return SCIP_OKAY;
7768
7769 assert(typex >= typey);
7770
7771 easyaggr = FALSE;
7772
7773 /* calculate aggregation scalar and constant: a*x + b*y == c => x == -b/a * y + c/a */
7774 scalar = -scalary / scalarx;
7775 constant = rhs / scalarx;
7776
7777 /* check if it is an easy aggregation */
7778 if( typex == SCIP_VARTYPE_CONTINUOUS )
7779 {
7780 easyaggr = TRUE;
7781 }
7782 else if( SCIPsetIsIntegral(set, scalar) )
7783 {
7784 if( SCIPsetIsFeasIntegral(set, constant) )
7785 constant = SCIPsetRound(set, constant);
7786 else
7787 {
7788 *infeasible = TRUE;
7789 return SCIP_OKAY;
7790 }
7791
7792 scalar = SCIPsetRound(set, scalar);
7793 easyaggr = TRUE;
7794 }
7795 else if( typex == typey && SCIPsetIsIntegral(set, scalarx / scalary) )
7796 {
7797 /* swap the variables, such that varx is the aggregated variable */
7798 SCIP_VAR* var;
7799
7800 constant = rhs / scalary;
7801
7802 if( SCIPsetIsFeasIntegral(set, constant) )
7803 constant = SCIPsetRound(set, constant);
7804 else
7805 {
7806 *infeasible = TRUE;
7807 return SCIP_OKAY;
7808 }
7809
7810 scalar = SCIPsetRound(set, -scalarx / scalary);
7811 var = varx;
7812 varx = vary;
7813 vary = var;
7814 easyaggr = TRUE;
7815 }
7816
7817 /* terminate if a bound on resolved aggregation scalar becomes too small or large so that numerical cancellation may be caused */
7818 if( !SCIPvarIsAggrCoefAcceptable(set, varx, scalar) )
7819 return SCIP_OKAY;
7820
7821 /* did we find an "easy" aggregation? */
7822 if( easyaggr )
7823 {
7824 assert(typex >= typey);
7825
7826 if( REALABS(constant) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
7827 return SCIP_OKAY;
7828
7829 /* if the aggregation scalar is fractional, we cannot aggregate integral variables,
7830 * since then we would loose the corresponding divisibility property
7831 */
7833
7834 /* aggregate the variable */
7835 SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
7836 branchcand, eventqueue, eventfilter, vary, scalar, constant, infeasible, aggregated) );
7837 assert(*aggregated || *infeasible || SCIPvarDoNotAggr(varx));
7838 }
7839 else if( ( typex == SCIP_VARTYPE_INTEGER || typex == SCIP_DEPRECATED_VARTYPE_IMPLINT )
7840 && ( typey == SCIP_VARTYPE_INTEGER || typey == SCIP_DEPRECATED_VARTYPE_IMPLINT ) )
7841 {
7842 /* the variables are both integral: we have to try to find an integer aggregation */
7843 SCIP_CALL( tryAggregateIntVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
7844 branchcand, eventqueue, eventfilter, varx, vary, scalarx, scalary, rhs, infeasible, aggregated) );
7845 }
7846
7847 return SCIP_OKAY;
7848}
7849
7850/** performs second step of SCIPaggregateVarsExact()
7851 *
7852 * The variable to be aggregated is chosen among active problem variables x' and y', preferring a less strict variable
7853 * type as aggregation variable (i.e. continuous variables are preferred over implicit integers, implicit integers
7854 * or integers over binaries). If none of the variables is continuous, it is tried to find an integer
7855 * aggregation (i.e. integral coefficients a'' and b'', such that a''*x' + b''*y' == c''). This can lead to
7856 * the detection of infeasibility (e.g. if c'' is fractional), or to a rejection of the aggregation (denoted by
7857 * aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
7858 *
7859 * @todo check for fixings, infeasibility, bound changes, or domain holes:
7860 * a) if there is no easy aggregation and we have one binary variable and another integer/implicit/binary variable
7861 * b) for implicit integer variables with fractional aggregation scalar (we cannot (for technical reasons) and do
7862 * not want to aggregate implicit integer variables, since we loose the corresponding divisibility property)
7863 */
7865 SCIP_SET* set, /**< global SCIP settings */
7866 BMS_BLKMEM* blkmem, /**< block memory */
7867 SCIP_STAT* stat, /**< problem statistics */
7868 SCIP_PROB* transprob, /**< tranformed problem data */
7869 SCIP_PROB* origprob, /**< original problem data */
7870 SCIP_PRIMAL* primal, /**< primal data */
7871 SCIP_TREE* tree, /**< branch and bound tree */
7872 SCIP_REOPT* reopt, /**< reoptimization data structure */
7873 SCIP_LP* lp, /**< current LP data */
7874 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7875 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7876 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7877 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
7878 SCIP_VAR* varx, /**< variable x in equality a*x + b*y == c */
7879 SCIP_VAR* vary, /**< variable y in equality a*x + b*y == c */
7880 SCIP_RATIONAL* scalarx, /**< multiplier a in equality a*x + b*y == c */
7881 SCIP_RATIONAL* scalary, /**< multiplier b in equality a*x + b*y == c */
7882 SCIP_RATIONAL* rhs, /**< right hand side c in equality a*x + b*y == c */
7883 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
7884 SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
7885 )
7886{
7887 SCIP_Bool easyaggr;
7888 SCIP_RATIONAL* quotxy;
7889 SCIP_RATIONAL* quotyx;
7890 SCIP_Real absquot;
7891 SCIP_Real maxscalar;
7892 SCIP_VARTYPE typex;
7893 SCIP_VARTYPE typey;
7894
7895 assert(set != NULL);
7896 assert(blkmem != NULL);
7897 assert(stat != NULL);
7898 assert(transprob != NULL);
7899 assert(origprob != NULL);
7900 assert(tree != NULL);
7901 assert(lp != NULL);
7902 assert(cliquetable != NULL);
7903 assert(branchcand != NULL);
7904 assert(eventqueue != NULL);
7905 assert(varx != NULL);
7906 assert(vary != NULL);
7907 assert(varx != vary);
7908 assert(infeasible != NULL);
7909 assert(aggregated != NULL);
7913 assert(!SCIPrationalIsZero(scalarx));
7914 assert(!SCIPrationalIsZero(scalary));
7915
7916 *infeasible = FALSE;
7917 *aggregated = FALSE;
7918
7919 absquot = REALABS(SCIPrationalGetReal(scalarx) / SCIPrationalGetReal(scalary));
7920 maxscalar = SCIPsetFeastol(set) / SCIPsetEpsilon(set);
7921 maxscalar = MAX(maxscalar, 1.0);
7922
7923 if( absquot > maxscalar || absquot < 1 / maxscalar )
7924 return SCIP_OKAY;
7925
7926 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &quotxy) );
7927 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &quotyx) );
7928
7929 SCIPrationalDiv(quotxy, scalarx, scalary);
7930 SCIPrationalInvert(quotyx, quotxy);
7931
7932 /**@todo simplify the following code once SCIP_DEPRECATED_VARTYPE_IMPLINT is removed */
7935
7936 /* prefer aggregating the variable of more general type (preferred aggregation variable is varx) */
7937 if( typex < typey ||
7938 ( typex == typey && SCIPvarIsBinary(varx) && !SCIPvarIsBinary(vary)) )
7939 {
7940 SCIP_VAR* var;
7941 SCIP_RATIONAL* scalar;
7942 SCIP_VARTYPE type;
7943
7944 /* switch the variables, such that varx is the variable of more general type (cont > implint > int > bin) */
7945 var = vary;
7946 vary = varx;
7947 varx = var;
7948 scalar = scalary;
7949 scalary = scalarx;
7950 scalarx = scalar;
7951 type = typey;
7952 typey = typex;
7953 typex = type;
7954 SCIPrationalInvert(quotyx, quotyx);
7955 SCIPrationalInvert(quotxy, quotxy);
7956 }
7957
7958 /* don't aggregate if the aggregation would lead to a binary variable aggregated to a non-binary variable */
7959 if( SCIPvarIsBinary(varx) && !SCIPvarIsBinary(vary) )
7960 return SCIP_OKAY;
7961
7962 assert(typex >= typey);
7963
7964 /* figure out, which variable should be aggregated */
7965 easyaggr = FALSE;
7966
7967 /* check if it is an easy aggregation that means:
7968 *
7969 * a*x + b*y == c -> x == -b/a * y + c/a iff |b/a| > feastol and |a/b| > feastol
7970 */
7972 {
7973 if( typex == SCIP_VARTYPE_CONTINUOUS && typey != SCIP_VARTYPE_CONTINUOUS )
7974 {
7975 easyaggr = TRUE;
7976 }
7977 else if( SCIPrationalIsIntegral(quotyx) )
7978 {
7979 easyaggr = TRUE;
7980 }
7981 else if( typex == typey && SCIPrationalIsIntegral(quotxy) )
7982 {
7983 /* we have an easy aggregation if we flip the variables x and y */
7984 SCIP_VAR* var;
7985 SCIP_RATIONAL* scalar;
7986
7987 /* switch the variables, such that varx is the aggregated variable */
7988 var = vary;
7989 vary = varx;
7990 varx = var;
7991 scalar = scalary;
7992 scalary = scalarx;
7993 scalarx = scalar;
7994 easyaggr = TRUE;
7995 SCIPrationalInvert(quotyx, quotyx);
7996 }
7997 else if( typex == SCIP_VARTYPE_CONTINUOUS )
7998 {
7999 /* the aggregation is still easy if both variables are continuous */
8000 assert(typey == SCIP_VARTYPE_CONTINUOUS); /* otherwise we are in the first case */
8001 easyaggr = TRUE;
8002 }
8003 }
8004
8005 /* did we find an "easy" aggregation? */
8006 if( easyaggr )
8007 {
8008 SCIP_RATIONAL* constant;
8009
8010 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &constant) );
8011
8012 assert(typex >= typey);
8013
8014 /* calculate aggregation scalar and constant: a*x + b*y == c => x == -b/a * y + c/a */
8015 SCIPrationalNegate(quotyx, quotyx);
8016 SCIPrationalDiv(constant, rhs, scalarx);
8017
8018 if( REALABS(SCIPrationalGetReal(constant)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
8019 goto FREE;
8020
8021 /* check aggregation for integer feasibility */
8022 if( typex != SCIP_VARTYPE_CONTINUOUS && typey != SCIP_VARTYPE_CONTINUOUS
8023 && SCIPrationalIsIntegral(quotyx) && !SCIPrationalIsIntegral(constant) )
8024 {
8025 *infeasible = TRUE;
8026 goto FREE;
8027 }
8028
8029 /* if the aggregation scalar is fractional, we cannot (for technical reasons) and do not want to aggregate implicit integer variables,
8030 * since then we would loose the corresponding divisibility property
8031 */
8033
8034 /* aggregate the variable */
8035 SCIP_CALL( SCIPvarAggregateExact(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
8036 branchcand, eventqueue, eventfilter, vary, quotyx, constant, infeasible, aggregated) );
8037 assert(*aggregated || *infeasible || SCIPvarDoNotAggr(varx));
8038FREE:
8039 SCIPrationalFreeBuffer(set->buffer, &constant);
8040 }
8041 else if( (typex == SCIP_VARTYPE_INTEGER || typex == SCIP_DEPRECATED_VARTYPE_IMPLINT)
8042 && (typey == SCIP_VARTYPE_INTEGER || typey == SCIP_DEPRECATED_VARTYPE_IMPLINT) )
8043 {
8044 /* the variables are both integral: we have to try to find an integer aggregation */
8045 SCIP_CALL( tryAggregateIntVarsExact(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
8046 branchcand, eventqueue, eventfilter, varx, vary, scalarx, scalary, rhs, infeasible, aggregated) );
8047 }
8048
8049 SCIPrationalFreeBuffer(set->buffer, &quotyx);
8050 SCIPrationalFreeBuffer(set->buffer, &quotxy);
8051
8052 return SCIP_OKAY;
8053}
8054
8055/** converts variable into multi-aggregated variable */
8057 SCIP_VAR* var, /**< problem variable */
8058 BMS_BLKMEM* blkmem, /**< block memory */
8059 SCIP_SET* set, /**< global SCIP settings */
8060 SCIP_STAT* stat, /**< problem statistics */
8061 SCIP_PROB* transprob, /**< tranformed problem data */
8062 SCIP_PROB* origprob, /**< original problem data */
8063 SCIP_PRIMAL* primal, /**< primal data */
8064 SCIP_TREE* tree, /**< branch and bound tree */
8065 SCIP_REOPT* reopt, /**< reoptimization data structure */
8066 SCIP_LP* lp, /**< current LP data */
8067 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
8068 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
8069 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
8070 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
8071 int naggvars, /**< number n of variables in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
8072 SCIP_VAR** aggvars, /**< variables y_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
8073 SCIP_Real* scalars, /**< multipliers a_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
8074 SCIP_Real constant, /**< constant shift c in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
8075 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
8076 SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
8077 )
8078{
8079 SCIP_VAR** tmpvars;
8080 SCIP_Real* tmpscalars;
8081 SCIP_Real obj;
8082 SCIP_Real branchfactor;
8083 int branchpriority;
8084 SCIP_BRANCHDIR branchdirection;
8085 int nlocksdown[NLOCKTYPES];
8086 int nlocksup[NLOCKTYPES];
8087 int v;
8088 SCIP_Real tmpconstant;
8089 SCIP_Real tmpscalar;
8090 int ntmpvars;
8091 int tmpvarssize;
8092 int tmprequiredsize;
8093 int i;
8094
8095 assert(var != NULL);
8096 assert(var->scip == set->scip);
8097 assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
8098 assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
8099 assert(!SCIPsetIsInfinity(set, REALABS(constant)));
8100 assert(naggvars == 0 || aggvars != NULL);
8101 assert(naggvars == 0 || scalars != NULL);
8102 assert(infeasible != NULL);
8103 assert(aggregated != NULL);
8104
8105 SCIPsetDebugMsg(set, "trying multi-aggregating variable <%s> == ...%d vars... %+g\n", var->name, naggvars, constant);
8106
8107 *infeasible = FALSE;
8108 *aggregated = FALSE;
8109
8110 switch( SCIPvarGetStatus(var) )
8111 {
8113 if( var->data.original.transvar == NULL )
8114 {
8115 SCIPerrorMessage("cannot multi-aggregate an untransformed original variable\n");
8116 return SCIP_INVALIDDATA;
8117 }
8118 SCIP_CALL( SCIPvarMultiaggregate(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
8119 reopt, lp, cliquetable, branchcand, eventqueue, eventfilter, naggvars, aggvars, scalars, constant, infeasible, aggregated) );
8120 break;
8121
8123 assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
8124
8125 /* check if we would create a self-reference */
8126 ntmpvars = naggvars;
8127 tmpvarssize = naggvars;
8128 tmpconstant = constant;
8129 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpvars, aggvars, ntmpvars) );
8130 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpscalars, scalars, ntmpvars) );
8131
8132 /* get all active variables for multi-aggregation */
8133 SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize) );
8134 if( tmprequiredsize > tmpvarssize )
8135 {
8136 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpvars, tmpvarssize, tmprequiredsize) );
8137 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize, tmprequiredsize) );
8138 tmpvarssize = tmprequiredsize;
8139 SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize) );
8140 assert( tmprequiredsize <= tmpvarssize );
8141 }
8142
8143 tmpscalar = 0.0;
8144
8145 /* iterate over all active variables of the multi-aggregation and filter all variables which are equal to the
8146 * possible multi-aggregated variable
8147 */
8148 for( v = ntmpvars - 1; v >= 0; --v )
8149 {
8150 assert(tmpvars[v] != NULL);
8152
8153 if( tmpvars[v]->index == var->index )
8154 {
8155 tmpscalar += tmpscalars[v];
8156 tmpvars[v] = tmpvars[ntmpvars - 1];
8157 tmpscalars[v] = tmpscalars[ntmpvars - 1];
8158 --ntmpvars;
8159 }
8160 }
8161
8162 /* this means that x = x + a_1*y_1 + ... + a_n*y_n + c */
8163 if( SCIPsetIsEQ(set, tmpscalar, 1.0) )
8164 {
8165 if( ntmpvars == 0 )
8166 {
8167 if( SCIPsetIsFeasZero(set, tmpconstant) ) /* x = x */
8168 {
8169 SCIPsetDebugMsg(set, "Possible multi-aggregation was completely resolved and detected to be redundant.\n");
8170 goto TERMINATE;
8171 }
8172 else /* 0 = c and c != 0 */
8173 {
8174 SCIPsetDebugMsg(set, "Multi-aggregation was completely resolved and led to infeasibility.\n");
8175 *infeasible = TRUE;
8176 goto TERMINATE;
8177 }
8178 }
8179 else if( ntmpvars == 1 ) /* 0 = a*y + c => y = -c/a */
8180 {
8181 assert(tmpscalars[0] != 0.0);
8182 assert(tmpvars[0] != NULL);
8183
8184 SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(tmpvars[0]), -constant/tmpscalars[0]);
8185 SCIP_CALL( SCIPvarFix(tmpvars[0], blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
8186 branchcand, eventqueue, eventfilter, cliquetable, -constant/tmpscalars[0], infeasible, aggregated) );
8187 goto TERMINATE;
8188 }
8189 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 */
8190 {
8191 /* both variables are different active problem variables, and both scalars are non-zero: try to aggregate them */
8192 SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
8193 SCIPvarGetName(tmpvars[0]), SCIPvarGetName(tmpvars[1]), tmpscalars[0], tmpscalars[1], -tmpconstant);
8194
8195 SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
8196 cliquetable, branchcand, eventqueue, eventfilter, tmpvars[0], tmpvars[1], tmpscalars[0],
8197 tmpscalars[1], -tmpconstant, infeasible, aggregated) );
8198
8199 goto TERMINATE;
8200 }
8201 else
8202 /* @todo: it is possible to multi-aggregate another variable, does it make sense?,
8203 * rest looks like 0 = a_1*y_1 + ... + a_n*y_n + c and has at least three variables
8204 */
8205 goto TERMINATE;
8206 }
8207 /* this means that x = b*x + a_1*y_1 + ... + a_n*y_n + c */
8208 else if( tmpscalar != 0.0 ) /*lint !e777*/
8209 {
8210 tmpscalar = 1 - tmpscalar;
8211 tmpconstant /= tmpscalar;
8212 for( v = 0; v < ntmpvars; ++v )
8213 tmpscalars[v] /= tmpscalar;
8214 }
8215
8216 /* check, if we are in one of the simple cases */
8217 if( ntmpvars == 0 )
8218 {
8219 SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(var), tmpconstant);
8220 SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
8221 eventqueue, eventfilter, cliquetable, tmpconstant, infeasible, aggregated) );
8222 goto TERMINATE;
8223 }
8224
8225 /* if only one aggregation variable is left, we perform a normal aggregation instead of a multi-aggregation */
8226 if( ntmpvars == 1 )
8227 {
8228 SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
8229 SCIPvarGetName(var), SCIPvarGetName(tmpvars[0]), 1.0, -tmpscalars[0], tmpconstant);
8230
8231 SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
8232 cliquetable, branchcand, eventqueue, eventfilter, var, tmpvars[0], 1.0, -tmpscalars[0], tmpconstant,
8233 infeasible, aggregated) );
8234
8235 goto TERMINATE;
8236 }
8237
8238 /**@todo currently we don't perform the multi aggregation if the multi aggregation variable has a non
8239 * empty hole list; this should be changed in the future */
8241 goto TERMINATE;
8242
8243 /* if the variable is not allowed to be multi-aggregated */
8245 {
8246 SCIPsetDebugMsg(set, "variable is not allowed to be multi-aggregated.\n");
8247 goto TERMINATE;
8248 }
8249
8250 /* terminate if scalars may lead to numerical trouble */
8251 for( v = 0; v < ntmpvars; ++v )
8252 if( !SCIPvarIsAggrCoefAcceptable(set, var, tmpscalars[v]) )
8253 goto TERMINATE;
8254
8255 /* if the variable to be multi-aggregated has implications or variable bounds (i.e. is the implied variable or
8256 * variable bound variable of another variable), we have to remove it from the other variables implications or
8257 * variable bounds
8258 */
8259 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
8260 assert(var->vlbs == NULL);
8261 assert(var->vubs == NULL);
8262 assert(var->implics == NULL);
8263
8264 /* set the aggregated variable's objective value to 0.0 */
8265 obj = var->obj;
8266 SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
8267
8268 /* since we change the variable type form loose to multi aggregated, we have to adjust the number of loose
8269 * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
8270 * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
8271 * objective of this variable is set to zero
8272 */
8274
8275 /* unlock all rounding locks */
8276 for( i = 0; i < NLOCKTYPES; i++ )
8277 {
8278 nlocksdown[i] = var->nlocksdown[i];
8279 nlocksup[i] = var->nlocksup[i];
8280
8281 var->nlocksdown[i] = 0;
8282 var->nlocksup[i] = 0;
8283 }
8284
8285 /* update aggregation bounds */
8286 for( v = 0; v < ntmpvars; ++v )
8287 varUpdateMinMaxAggrCoef(tmpvars[v], var, tmpscalars[v]);
8288
8289 /* convert variable into multi-aggregated variable */
8290 var->varstatus = SCIP_VARSTATUS_MULTAGGR; /*lint !e641*/
8291 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.vars, tmpvars, ntmpvars) );
8292 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.scalars, tmpscalars, ntmpvars) );
8293 var->data.multaggr.constant = tmpconstant;
8294 var->data.multaggr.nvars = ntmpvars;
8295 var->data.multaggr.varssize = ntmpvars;
8296
8297 /* mark variable to be non-deletable */
8299
8300 /* relock the variable, thus increasing the locks of the aggregation variables */
8301 for( i = 0; i < NLOCKTYPES; i++ )
8302 {
8303 SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
8304 }
8305
8306 /* update flags and branching factors and priorities of aggregation variables;
8307 * update preferred branching direction of all aggregation variables that don't have a preferred direction yet
8308 */
8309 branchfactor = var->branchfactor;
8310 branchpriority = var->branchpriority;
8311 branchdirection = (SCIP_BRANCHDIR)var->branchdirection;
8312
8313 for( v = 0; v < ntmpvars; ++v )
8314 {
8315 assert(tmpvars[v] != NULL);
8316 tmpvars[v]->removable &= var->removable;
8317 branchfactor = MAX(tmpvars[v]->branchfactor, branchfactor);
8318 branchpriority = MAX(tmpvars[v]->branchpriority, branchpriority);
8319
8320 /* mark variable to be non-deletable */
8321 SCIPvarMarkNotDeletable(tmpvars[v]);
8322 }
8323 for( v = 0; v < ntmpvars; ++v )
8324 {
8325 SCIP_CALL( SCIPvarChgBranchFactor(tmpvars[v], set, branchfactor) );
8326 SCIP_CALL( SCIPvarChgBranchPriority(tmpvars[v], branchpriority) );
8327 if( (SCIP_BRANCHDIR)tmpvars[v]->branchdirection == SCIP_BRANCHDIR_AUTO )
8328 {
8329 if( tmpscalars[v] >= 0.0 )
8330 {
8331 SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], branchdirection) );
8332 }
8333 else
8334 {
8335 SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], SCIPbranchdirOpposite(branchdirection)) );
8336 }
8337 }
8338 }
8339 SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
8340 SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
8341
8342 if( var->probindex != -1 )
8343 {
8344 /* inform problem about the variable's status change */
8345 SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
8346 }
8347
8348 /* issue VARFIXED event */
8349 SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 2) );
8350
8351 /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
8352 * variables and the problem's objective offset
8353 */
8354 SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventqueue, eventfilter, obj) );
8355
8356 *aggregated = TRUE;
8357
8358 TERMINATE:
8359 BMSfreeBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize);
8360 BMSfreeBlockMemoryArray(blkmem, &tmpvars, tmpvarssize);
8361
8362 break;
8363
8365 SCIPerrorMessage("cannot multi-aggregate a column variable\n");
8366 return SCIP_INVALIDDATA;
8367
8369 SCIPerrorMessage("cannot multi-aggregate a fixed variable\n");
8370 return SCIP_INVALIDDATA;
8371
8373 SCIPerrorMessage("cannot multi-aggregate an aggregated variable\n");
8374 return SCIP_INVALIDDATA;
8375
8377 SCIPerrorMessage("cannot multi-aggregate a multiple aggregated variable again\n");
8378 return SCIP_INVALIDDATA;
8379
8381 /* aggregate negation variable x in x' = offset - x, instead of aggregating x' directly:
8382 * x' = a_1*y_1 + ... + a_n*y_n + c -> x = offset - x' = offset - a_1*y_1 - ... - a_n*y_n - c
8383 */
8384 assert(SCIPsetIsZero(set, var->obj));
8385 assert(var->negatedvar != NULL);
8387 assert(var->negatedvar->negatedvar == var);
8388
8389 /* switch the signs of the aggregation scalars */
8390 for( v = 0; v < naggvars; ++v )
8391 scalars[v] *= -1.0;
8392
8393 /* perform the multi aggregation on the negation variable */
8394 SCIP_CALL( SCIPvarMultiaggregate(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
8395 cliquetable, branchcand, eventqueue, eventfilter, naggvars, aggvars, scalars,
8396 var->data.negate.constant - constant, infeasible, aggregated) );
8397
8398 /* switch the signs of the aggregation scalars again, to reset them to their original values */
8399 for( v = 0; v < naggvars; ++v )
8400 scalars[v] *= -1.0;
8401 break;
8402
8403 default:
8404 SCIPerrorMessage("unknown variable status\n");
8405 return SCIP_INVALIDDATA;
8406 }
8407
8408 /* check multi-aggregation on debugging solution */
8409 if( *infeasible || *aggregated )
8410 SCIP_CALL( SCIPdebugCheckAggregation(set, var, aggvars, scalars, constant, naggvars) ); /*lint !e506 !e774*/
8411
8412 return SCIP_OKAY;
8413}
8414
8415/** converts variable into multi-aggregated variable */
8417 SCIP_VAR* var, /**< problem variable */
8418 BMS_BLKMEM* blkmem, /**< block memory */
8419 SCIP_SET* set, /**< global SCIP settings */
8420 SCIP_STAT* stat, /**< problem statistics */
8421 SCIP_PROB* transprob, /**< tranformed problem data */
8422 SCIP_PROB* origprob, /**< original problem data */
8423 SCIP_PRIMAL* primal, /**< primal data */
8424 SCIP_TREE* tree, /**< branch and bound tree */
8425 SCIP_REOPT* reopt, /**< reoptimization data structure */
8426 SCIP_LPEXACT* lpexact, /**< current LP data */
8427 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
8428 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
8429 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
8430 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
8431 int naggvars, /**< number n of variables in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
8432 SCIP_VAR** aggvars, /**< variables y_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
8433 SCIP_RATIONAL** scalars, /**< multipliers a_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
8434 SCIP_RATIONAL* constant, /**< constant shift c in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
8435 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
8436 SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
8437 )
8438{
8439 SCIP_VAR** tmpvars;
8440 SCIP_RATIONAL** tmpscalars;
8442 SCIP_RATIONAL* tmpconstant;
8443 SCIP_RATIONAL* tmpscalar;
8444 SCIP_RATIONAL* tmpval;
8445 SCIP_Real branchfactor;
8446 int branchpriority;
8447 SCIP_BRANCHDIR branchdirection;
8448 int nlocksdown[NLOCKTYPES];
8449 int nlocksup[NLOCKTYPES];
8450 int v;
8451 int ntmpvars;
8452 int tmpvarssize;
8453 int tmprequiredsize;
8454 int i;
8455
8456 assert(var != NULL);
8457 assert(var->scip == set->scip);
8458 assert(set->exact_enable);
8459 assert(SCIPrationalIsEQ(var->exactdata->glbdom.lb, var->exactdata->locdom.lb)); /*lint !e777*/
8460 assert(SCIPrationalIsEQ(var->exactdata->glbdom.ub, var->exactdata->locdom.ub)); /*lint !e777*/
8461 assert(naggvars == 0 || aggvars != NULL);
8462 assert(naggvars == 0 || scalars != NULL);
8463 assert(infeasible != NULL);
8464 assert(aggregated != NULL);
8465
8466 SCIPrationalDebugMessage("trying exact multi-aggregating variable <%s> == ...%d vars... %+q\n", var->name, naggvars, constant);
8467
8468 *infeasible = FALSE;
8469 *aggregated = FALSE;
8470
8471 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmpconstant) );
8472 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmpscalar) );
8474 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmpval) );
8475
8476 switch( SCIPvarGetStatusExact(var) )
8477 {
8479 if( var->data.original.transvar == NULL )
8480 {
8481 SCIPerrorMessage("cannot multi-aggregate an untransformed original variable\n");
8482 return SCIP_INVALIDDATA;
8483 }
8484 SCIP_CALL( SCIPvarMultiaggregateExact(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
8485 reopt, lpexact, cliquetable, branchcand, eventqueue, eventfilter, naggvars, aggvars, scalars, constant, infeasible, aggregated) );
8486 break;
8487
8489 assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
8490
8491 /* check if we would create a self-reference */
8492 ntmpvars = naggvars;
8493 tmpvarssize = naggvars;
8494 SCIPrationalSetRational(tmpconstant, constant);
8495 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpvars, aggvars, ntmpvars) );
8496 SCIP_CALL( SCIPrationalCopyBlockArray(blkmem, &tmpscalars, scalars, ntmpvars) );
8497
8498 /* get all active variables for multi-aggregation */
8499 SCIP_CALL( SCIPvarGetActiveRepresentativesExact(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, tmpconstant, &tmprequiredsize, FALSE) );
8500 if( tmprequiredsize > tmpvarssize )
8501 {
8502 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpvars, tmpvarssize, tmprequiredsize) );
8503 SCIP_CALL( SCIPrationalReallocBlockArray(blkmem, &tmpscalars, tmpvarssize, tmprequiredsize) );
8504 tmpvarssize = tmprequiredsize;
8505 SCIP_CALL( SCIPvarGetActiveRepresentativesExact(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, tmpconstant, &tmprequiredsize, FALSE) );
8506 assert( tmprequiredsize <= tmpvarssize );
8507 }
8508
8509 SCIPrationalSetReal(tmpscalar, 0.0);
8510
8511 /* iterate over all active variables of the multi-aggregation and filter all variables which are equal to the
8512 * possible multi-aggregated variable
8513 */
8514 for( v = ntmpvars - 1; v >= 0; --v )
8515 {
8516 assert(tmpvars[v] != NULL);
8518
8519 if( tmpvars[v]->index == var->index )
8520 {
8521 SCIPrationalAdd(tmpscalar, tmpscalar, tmpscalars[v]);
8522 tmpvars[v] = tmpvars[ntmpvars - 1];
8523 SCIPrationalSetRational(tmpscalars[v], tmpscalars[ntmpvars - 1]);
8524 --ntmpvars;
8525 }
8526 }
8527
8528 /* this means that x = x + a_1*y_1 + ... + a_n*y_n + c */
8529 if( SCIPrationalIsEQReal(tmpscalar, 1.0) )
8530 {
8531 if( ntmpvars == 0 )
8532 {
8533 if( SCIPrationalIsZero(tmpconstant) ) /* x = x */
8534 {
8535 SCIPsetDebugMsg(set, "Possible multi-aggregation was completely resolved and detected to be redundant.\n");
8536 goto TERMINATE;
8537 }
8538 else /* 0 = c and c != 0 */
8539 {
8540 SCIPsetDebugMsg(set, "Multi-aggregation was completely resolved and led to infeasibility.\n");
8541 *infeasible = TRUE;
8542 goto TERMINATE;
8543 }
8544 }
8545 else if( ntmpvars == 1 ) /* 0 = a*y + c => y = -c/a */
8546 {
8547 assert(!SCIPrationalIsZero(tmpscalars[0]));
8548 assert(tmpvars[0] != NULL);
8549
8550 SCIPrationalDiv(tmpval, constant, tmpscalars[0]);
8551 SCIPrationalNegate(tmpval, tmpval);
8552
8553 SCIPrationalDebugMessage("Possible multi-aggregation led to fixing of variable <%s> to %q.\n", SCIPvarGetName(tmpvars[0]), tmpval);
8554 SCIP_CALL( SCIPvarFixExact(tmpvars[0], blkmem, set, stat, transprob, origprob, primal, tree, reopt, lpexact->fplp,
8555 branchcand, eventqueue, eventfilter, cliquetable, tmpval, infeasible, aggregated) );
8556 goto TERMINATE;
8557 }
8558 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 */
8559 {
8560 /* both variables are different active problem variables, and both scalars are non-zero: try to aggregate them */
8561
8562 SCIPrationalNegate(tmpconstant, tmpconstant);
8563 SCIPrationalDebugMessage("Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %q and %q and constant %q.\n",
8564 SCIPvarGetName(tmpvars[0]), SCIPvarGetName(tmpvars[1]), tmpscalars[0], tmpscalars[1], tmpconstant);
8565
8566 SCIP_CALL( SCIPvarTryAggregateVarsExact(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lpexact->fplp,
8567 cliquetable, branchcand, eventqueue, eventfilter, tmpvars[0], tmpvars[1], tmpscalars[0],
8568 tmpscalars[1], tmpconstant, infeasible, aggregated) );
8569
8570 goto TERMINATE;
8571 }
8572 else
8573 /** @todo: it is possible to multi-aggregate another variable, does it make sense?,
8574 * rest looks like 0 = a_1*y_1 + ... + a_n*y_n + c and has at least three variables
8575 */
8576 goto TERMINATE;
8577 }
8578 /* this means that x = b*x + a_1*y_1 + ... + a_n*y_n + c */
8579 else if( !SCIPrationalIsZero(tmpscalar) )
8580 {
8581 SCIPrationalDiffReal(tmpscalar, tmpscalar, 1.0);
8582 SCIPrationalNegate(tmpscalar, tmpscalar);
8583 SCIPrationalDiv(tmpconstant, tmpconstant, tmpscalar);
8584 for( v = ntmpvars - 1; v >= 0; --v )
8585 SCIPrationalDiv(tmpscalars[v], tmpscalars[v], tmpscalar);
8586 }
8587
8588 /* check, if we are in one of the simple cases */
8589 if( ntmpvars == 0 )
8590 {
8591 SCIPrationalDebugMessage("Possible multi-aggregation led to fixing of variable <%s> to %q.\n", SCIPvarGetName(var), tmpconstant);
8592 SCIP_CALL( SCIPvarFixExact(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lpexact->fplp, branchcand,
8593 eventqueue, eventfilter, cliquetable, tmpconstant, infeasible, aggregated) );
8594 goto TERMINATE;
8595 }
8596
8597 /* if only one aggregation variable is left, we perform a normal aggregation instead of a multi-aggregation */
8598 if( ntmpvars == 1 )
8599 {
8600 SCIPrationalNegate(tmpscalars[0], tmpscalars[0]);
8601 SCIPrationalSetReal(tmpval, 1.0);
8602 SCIPrationalDebugMessage("Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %f and %q and constant %q.\n",
8603 SCIPvarGetName(var), SCIPvarGetName(tmpvars[0]), 1.0, tmpscalars[0], tmpconstant);
8604
8605 SCIP_CALL( SCIPvarTryAggregateVarsExact(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lpexact->fplp,
8606 cliquetable, branchcand, eventqueue, eventfilter, var, tmpvars[0], tmpval, tmpscalars[0], tmpconstant,
8607 infeasible, aggregated) );
8608
8609 goto TERMINATE;
8610 }
8611
8612 /**@todo currently we don't perform the multi aggregation if the multi aggregation variable has a non
8613 * empty hole list; this should be changed in the future */
8615 goto TERMINATE;
8616
8617 /* if the variable is not allowed to be multi-aggregated */
8619 {
8620 SCIPsetDebugMsg(set, "variable is not allowed to be multi-aggregated.\n");
8621 goto TERMINATE;
8622 }
8623
8624 /* if the variable to be multi-aggregated has implications or variable bounds (i.e. is the implied variable or
8625 * variable bound variable of another variable), we have to remove it from the other variables implications or
8626 * variable bounds
8627 */
8628 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
8629 assert(var->vlbs == NULL);
8630 assert(var->vubs == NULL);
8631 assert(var->implics == NULL);
8632 assert(var->cliquelist == NULL);
8633
8634 /* set the aggregated variable's objective value to 0.0 */
8635 SCIPrationalSetRational(obj, var->exactdata->obj);
8636 SCIPrationalSetReal(tmpval, 0.0);
8637 SCIP_CALL( SCIPvarChgObjExact(var, blkmem, set, transprob, primal, lpexact, eventqueue, tmpval) );
8638
8639 /* since we change the variable type form loose to multi aggregated, we have to adjust the number of loose
8640 * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
8641 * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
8642 * objective of this variable is set to zero
8643 */
8644 SCIPlpDecNLoosevars(lpexact->fplp);
8645 SCIPlpExactDecNLoosevars(lpexact);
8646
8647 /* unlock all rounding locks */
8648 for( i = 0; i < NLOCKTYPES; i++ )
8649 {
8650 nlocksdown[i] = var->nlocksdown[i];
8651 nlocksup[i] = var->nlocksup[i];
8652
8653 var->nlocksdown[i] = 0;
8654 var->nlocksup[i] = 0;
8655 }
8656
8657 /* convert variable into multi-aggregated variable */
8658 var->varstatus = SCIP_VARSTATUS_MULTAGGR; /*lint !e641*/
8659 var->exactdata->varstatusexact = SCIP_VARSTATUS_MULTAGGR; /*lint !e641*/
8660 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.vars, tmpvars, ntmpvars) );
8661 SCIP_CALL( SCIPrationalCopyBlockArray(blkmem, &(var->exactdata->multaggr.scalars), tmpscalars, ntmpvars) );
8662 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &var->data.multaggr.scalars, ntmpvars) );
8663 for( i = 0; i < ntmpvars; ++i )
8664 var->data.multaggr.scalars[i] = SCIPrationalGetReal(tmpscalars[i]);
8665 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &(var->exactdata->multaggr.constant), tmpconstant) );
8666 var->data.multaggr.constant = SCIPrationalGetReal(tmpconstant);
8667 var->data.multaggr.nvars = ntmpvars;
8668 var->data.multaggr.varssize = ntmpvars;
8669
8670 /* mark variable to be non-deletable */
8672
8673 /* relock the variable, thus increasing the locks of the aggregation variables */
8674 for( i = 0; i < NLOCKTYPES; i++ )
8675 {
8676 SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
8677 }
8678
8679 /* update flags and branching factors and priorities of aggregation variables;
8680 * update preferred branching direction of all aggregation variables that don't have a preferred direction yet
8681 */
8682 branchfactor = var->branchfactor;
8683 branchpriority = var->branchpriority;
8684 branchdirection = (SCIP_BRANCHDIR)var->branchdirection;
8685
8686 for( v = 0; v < ntmpvars; ++v )
8687 {
8688 assert(tmpvars[v] != NULL);
8689 tmpvars[v]->removable &= var->removable;
8690 branchfactor = MAX(tmpvars[v]->branchfactor, branchfactor);
8691 branchpriority = MAX(tmpvars[v]->branchpriority, branchpriority);
8692
8693 /* mark variable to be non-deletable */
8694 SCIPvarMarkNotDeletable(tmpvars[v]);
8695 }
8696 for( v = 0; v < ntmpvars; ++v )
8697 {
8698 SCIP_CALL( SCIPvarChgBranchFactor(tmpvars[v], set, branchfactor) );
8699 SCIP_CALL( SCIPvarChgBranchPriority(tmpvars[v], branchpriority) );
8700 if( (SCIP_BRANCHDIR)tmpvars[v]->branchdirection == SCIP_BRANCHDIR_AUTO )
8701 {
8702 if( !SCIPrationalIsNegative(tmpscalars[v]) )
8703 {
8704 SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], branchdirection) );
8705 }
8706 else
8707 {
8708 SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], SCIPbranchdirOpposite(branchdirection)) );
8709 }
8710 }
8711 }
8712 SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
8713 SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
8714
8715 if( var->probindex != -1 )
8716 {
8717 /* inform problem about the variable's status change */
8718 SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
8719 }
8720
8721 /* issue VARFIXED event */
8722 SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 2) );
8723
8724 /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
8725 * variables and the problem's objective offset
8726 */
8727 SCIP_CALL( SCIPvarAddObjExact(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lpexact->fplp, eventqueue, eventfilter, obj) );
8728
8729 *aggregated = TRUE;
8730
8731 TERMINATE:
8732 SCIPrationalFreeBlockArray(blkmem, &tmpscalars, tmpvarssize);
8733 BMSfreeBlockMemoryArray(blkmem, &tmpvars, tmpvarssize);
8734 break;
8735
8737 SCIPerrorMessage("cannot multi-aggregate a column variable\n");
8738 return SCIP_INVALIDDATA;
8739
8741 SCIPerrorMessage("cannot multi-aggregate a fixed variable\n");
8742 return SCIP_INVALIDDATA;
8743
8745 SCIPerrorMessage("cannot multi-aggregate an aggregated variable\n");
8746 return SCIP_INVALIDDATA;
8747
8749 SCIPerrorMessage("cannot multi-aggregate a multiple aggregated variable again\n");
8750 return SCIP_INVALIDDATA;
8751
8753 /* aggregate negation variable x in x' = offset - x, instead of aggregating x' directly:
8754 * x' = a_1*y_1 + ... + a_n*y_n + c -> x = offset - x' = offset - a_1*y_1 - ... - a_n*y_n - c
8755 */
8756 assert(SCIPrationalIsZero(var->exactdata->obj));
8757 assert(var->negatedvar != NULL);
8759 assert(var->negatedvar->negatedvar == var);
8760
8761 /* switch the signs of the aggregation scalars */
8762 for( v = 0; v < naggvars; ++v )
8764
8765 SCIPrationalDiffReal(tmpval, constant, var->data.negate.constant);
8766 SCIPrationalNegate(tmpval, tmpval);
8767 /* perform the multi aggregation on the negation variable */
8768 SCIP_CALL( SCIPvarMultiaggregateExact(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lpexact,
8769 cliquetable, branchcand, eventqueue, eventfilter, naggvars, aggvars, scalars,
8770 tmpval, infeasible, aggregated) );
8771
8772 /* switch the signs of the aggregation scalars again, to reset them to their original values */
8773 for( v = 0; v < naggvars; ++v )
8775
8776 break;
8777
8778 default:
8779 SCIPerrorMessage("unknown variable status\n");
8780 return SCIP_INVALIDDATA;
8781 }
8782
8783 SCIPrationalFreeBuffer(set->buffer, &tmpval);
8784 SCIPrationalFreeBuffer(set->buffer, &obj);
8785 SCIPrationalFreeBuffer(set->buffer, &tmpscalar);
8786 SCIPrationalFreeBuffer(set->buffer, &tmpconstant);
8787
8788 return SCIP_OKAY;
8789}
8790
8791/** transformed variables are resolved to their active, fixed, or multi-aggregated problem variable of a variable,
8792 * or for original variables the same variable is returned
8793 */
8794static
8796 SCIP_VAR* var /**< problem variable */
8797 )
8798{
8799 SCIP_VAR* retvar;
8800
8801 assert(var != NULL);
8802
8803 retvar = var;
8804
8805 SCIPdebugMessage("get active variable of <%s>\n", var->name);
8806
8807 while( TRUE ) /*lint !e716 */
8808 {
8809 assert(retvar != NULL);
8810
8811 switch( SCIPvarGetStatus(retvar) )
8812 {
8817 return retvar;
8818
8820 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
8821 if ( retvar->data.multaggr.nvars == 1 )
8822 retvar = retvar->data.multaggr.vars[0];
8823 else
8824 return retvar;
8825 break;
8826
8828 retvar = retvar->data.aggregate.var;
8829 break;
8830
8832 retvar = retvar->negatedvar;
8833 break;
8834
8835 default:
8836 SCIPerrorMessage("unknown variable status\n");
8837 SCIPABORT();
8838 return NULL; /*lint !e527*/
8839 }
8840 }
8841}
8842
8843/** returns whether variable is not allowed to be aggregated */
8845 SCIP_VAR* var /**< problem variable */
8846 )
8847{
8848 SCIP_VAR* retvar;
8849
8850 assert(var != NULL);
8851
8852 retvar = varGetActiveVar(var);
8853 assert(retvar != NULL);
8854
8855 switch( SCIPvarGetStatus(retvar) )
8856 {
8861 return retvar->donotaggr;
8862
8864 return FALSE;
8865
8868 default:
8869 /* aggregated and negated variables should be resolved by varGetActiveVar() */
8870 SCIPerrorMessage("wrong variable status\n");
8871 SCIPABORT();
8872 return FALSE; /*lint !e527 */
8873 }
8874}
8875
8876/** returns whether variable is not allowed to be multi-aggregated */
8878 SCIP_VAR* var /**< problem variable */
8879 )
8880{
8881 SCIP_VAR* retvar;
8882
8883 assert(var != NULL);
8884
8885 retvar = varGetActiveVar(var);
8886 assert(retvar != NULL);
8887
8888 switch( SCIPvarGetStatus(retvar) )
8889 {
8894 return retvar->donotmultaggr;
8895
8897 return FALSE;
8898
8901 default:
8902 /* aggregated and negated variables should be resolved by varGetActiveVar() */
8903 SCIPerrorMessage("wrong variable status\n");
8904 SCIPABORT();
8905 return FALSE; /*lint !e527 */
8906 }
8907}
8908
8909/** checks whether a loose variable can be used in a new aggregation with given coefficient */
8911 SCIP_SET* set, /**< global SCIP settings */
8912 SCIP_VAR* var, /**< problem variable */
8913 SCIP_Real scalar /**< aggregation scalar */
8914 )
8915{
8916 assert(set != NULL);
8917 assert(var != NULL);
8918 assert(scalar != 0.0); /*lint !e777*/
8922
8924 return FALSE;
8925
8926 if( SCIPsetIsSumZero(set, 1.0 / (SCIPvarGetMaxAggrCoef(var) * scalar)) )
8927 return FALSE;
8928
8929 return TRUE;
8930}
8931
8932/** adds correct bound-data to negated variable */
8933static
8935 SCIP_VAR* negvar, /**< the negated variable */
8936 SCIP_VAR* origvar, /**< the original variable */
8937 BMS_BLKMEM* blkmem /**< block memory of transformed problem */
8938 )
8939{
8940 SCIP_Real constant;
8941
8942 if( origvar->exactdata == NULL )
8943 return SCIP_OKAY;
8944
8945 assert(negvar != NULL);
8946 assert(origvar != NULL);
8947 assert(origvar->exactdata != NULL);
8948 assert(negvar->exactdata == NULL);
8949
8950 constant = negvar->data.negate.constant;
8951
8952 SCIP_CALL( SCIPvarCopyExactData(blkmem, negvar, origvar, FALSE) );
8953
8954 SCIPrationalDiffReal(negvar->exactdata->glbdom.ub, origvar->exactdata->glbdom.lb, constant);
8956
8957 SCIPrationalDiffReal(negvar->exactdata->glbdom.lb, origvar->exactdata->glbdom.ub, constant);
8959
8960 SCIPrationalDiffReal(negvar->exactdata->locdom.ub, origvar->exactdata->locdom.lb, constant);
8962
8963 SCIPrationalDiffReal(negvar->exactdata->locdom.lb, origvar->exactdata->locdom.ub, constant);
8965
8967
8972
8973 return SCIP_OKAY;
8974}
8975
8976/** gets negated variable x' = offset - x of problem variable x; the negated variable is created if not yet existing;
8977 * the negation offset of binary variables is always 1, the offset of other variables is fixed to lb + ub when the
8978 * negated variable is created
8979 */
8981 SCIP_VAR* var, /**< problem variable to negate */
8982 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
8983 SCIP_SET* set, /**< global SCIP settings */
8984 SCIP_STAT* stat, /**< problem statistics */
8985 SCIP_VAR** negvar /**< pointer to store the negated variable */
8986 )
8987{
8988 assert(var != NULL);
8989 assert(var->scip == set->scip);
8990 assert(negvar != NULL);
8991
8992 /* check, if we already created the negated variable */
8993 if( var->negatedvar == NULL )
8994 {
8995 char negvarname[SCIP_MAXSTRLEN];
8996
8998
8999 SCIPsetDebugMsg(set, "creating negated variable of <%s>\n", var->name);
9000
9001 /* negation is only possible for bounded variables */
9002 if( SCIPsetIsInfinity(set, -var->glbdom.lb) || SCIPsetIsInfinity(set, var->glbdom.ub) )
9003 {
9004 SCIPerrorMessage("cannot negate unbounded variable\n");
9005 return SCIP_INVALIDDATA;
9006 }
9007
9008 (void) SCIPsnprintf(negvarname, SCIP_MAXSTRLEN, "%s_neg", var->name);
9009
9010 /* create negated variable */
9011 SCIP_CALL( varCreate(negvar, blkmem, set, stat, negvarname, var->glbdom.lb, var->glbdom.ub, 0.0,
9012 SCIPvarGetType(var), SCIPvarGetImplType(var), var->initial, var->removable, NULL, NULL, NULL, NULL, NULL) );
9013 (*negvar)->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
9014 if( SCIPvarIsBinary(var) )
9015 (*negvar)->data.negate.constant = 1.0;
9016 else
9017 (*negvar)->data.negate.constant = var->glbdom.lb + var->glbdom.ub;
9018
9019 /* create event filter for transformed variable */
9021 {
9022 SCIP_CALL( SCIPeventfilterCreate(&(*negvar)->eventfilter, blkmem) );
9023 }
9024
9025 /* set the bounds corresponding to the negation variable */
9026 (*negvar)->glbdom.lb = (*negvar)->data.negate.constant - var->glbdom.ub;
9027 (*negvar)->glbdom.ub = (*negvar)->data.negate.constant - var->glbdom.lb;
9028 (*negvar)->locdom.lb = (*negvar)->data.negate.constant - var->locdom.ub;
9029 (*negvar)->locdom.ub = (*negvar)->data.negate.constant - var->locdom.lb;
9030
9031 SCIP_CALL( varNegateExactData(*negvar, var, blkmem) );
9032 /**@todo create holes in the negated variable corresponding to the holes of the negation variable */
9033
9034 /* link the variables together */
9035 var->negatedvar = *negvar;
9036 (*negvar)->negatedvar = var;
9037
9038 /* mark both variables to be non-deletable */
9040 SCIPvarMarkNotDeletable(*negvar);
9041
9042 /* copy the branch factor and priority, and use the negative preferred branching direction */
9043 (*negvar)->branchfactor = var->branchfactor;
9044 (*negvar)->branchpriority = var->branchpriority;
9045 (*negvar)->branchdirection = SCIPbranchdirOpposite((SCIP_BRANCHDIR)var->branchdirection); /*lint !e641*/
9046
9047 /* copy donot(mult)aggr status */
9048 (*negvar)->donotaggr = var->donotaggr;
9049 (*negvar)->donotmultaggr = var->donotmultaggr;
9050
9051 /* copy lazy bounds (they have to be flipped) */
9052 (*negvar)->lazylb = (*negvar)->data.negate.constant - var->lazyub;
9053 (*negvar)->lazyub = (*negvar)->data.negate.constant - var->lazylb;
9054
9055 /* make negated variable a parent of the negation variable (negated variable is captured as a parent) */
9056 SCIP_CALL( varAddParent(var, blkmem, set, *negvar) );
9057 assert((*negvar)->nuses == 1);
9058 }
9059 assert(var->negatedvar != NULL);
9060
9061 /* return the negated variable */
9062 *negvar = var->negatedvar;
9063
9064 /* exactly one variable of the negation pair has to be marked as negated variable */
9066
9067 return SCIP_OKAY;
9068}
9069
9070/** informs variable that its position in problem's vars array changed */
9071static
9073 SCIP_VAR* var, /**< problem variable */
9074 int probindex /**< new problem index of variable (-1 for removal) */
9075 )
9076{
9077 assert(var != NULL);
9078
9079 var->probindex = probindex;
9081 {
9082 assert(var->data.col != NULL);
9083 var->data.col->var_probindex = probindex;
9084 }
9085}
9086
9087/** informs variable that its position in problem's vars array changed */
9089 SCIP_VAR* var, /**< problem variable */
9090 int probindex /**< new problem index of variable */
9091 )
9092{
9093 assert(var != NULL);
9094 assert(probindex >= 0);
9095
9096 varSetProbindex(var, probindex);
9097}
9098
9099/** gives the variable a new name
9100 *
9101 * @note the old pointer is overwritten, which might result in a memory leakage
9102 */
9104 SCIP_VAR* var, /**< problem variable */
9105 const char* name /**< new name of variable */
9106 )
9107{
9108 assert(var != NULL);
9109 assert(name != NULL);
9110
9111 var->name = (char*)name;
9112}
9113
9114/** informs variable that it will be removed from the problem; adjusts probindex and removes variable from the
9115 * implication graph;
9116 * If 'final' is TRUE, the thorough implication graph removal is not performed. Instead, only the
9117 * variable bounds and implication data structures of the variable are freed. Since in the final removal
9118 * of all variables from the transformed problem, this deletes the implication graph completely and is faster
9119 * than removing the variables one by one, each time updating all lists of the other variables.
9120 * If 'keepimplics' is TRUE, the implications, variable bounds and cliques are kept. This should be used when the
9121 * variable type is upgraded, i.e. when it gains (implied) integrality, so that existing implications are not lost.
9122 */
9124 SCIP_VAR* var, /**< problem variable */
9125 BMS_BLKMEM* blkmem, /**< block memory buffer */
9126 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9127 SCIP_SET* set, /**< global SCIP settings */
9128 SCIP_Bool final, /**< is this the final removal of all problem variables? */
9129 SCIP_Bool keepimplics /**< should the implications be kept? */
9130 )
9131{
9133 assert(var->scip == set->scip);
9134
9135 /* if the variable is active in the transformed problem, remove it from the implication graph */
9138 {
9139 if( final )
9140 {
9141 /* just destroy the data structures */
9142 SCIPvboundsFree(&var->vlbs, blkmem);
9143 SCIPvboundsFree(&var->vubs, blkmem);
9144 SCIPimplicsFree(&var->implics, blkmem);
9145 }
9146 else if( !keepimplics )
9147 {
9148 /* unlink the variable from all other variables' lists and free the data structures */
9149 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
9150 }
9151 }
9152
9153 /* mark the variable to be no longer a member of the problem */
9154 varSetProbindex(var, -1);
9155
9156 return SCIP_OKAY;
9157}
9158
9159/** marks the variable to be deleted from the problem */
9161 SCIP_VAR* var /**< problem variable */
9162 )
9163{
9164 assert(var != NULL);
9165 assert(var->probindex != -1);
9166
9167 var->deleted = TRUE;
9168}
9169
9170/** marks the variable to not to be aggregated */
9172 SCIP_VAR* var /**< problem variable */
9173 )
9174{
9175 SCIP_VAR* retvar;
9176
9177 assert(var != NULL);
9178
9179 retvar = varGetActiveVar(var);
9180 assert(retvar != NULL);
9181
9182 switch( SCIPvarGetStatus(retvar) )
9183 {
9188 retvar->donotaggr = TRUE;
9189 break;
9190
9192 SCIPerrorMessage("cannot mark a multi-aggregated variable to not be aggregated.\n");
9193 return SCIP_INVALIDDATA;
9194
9197 default:
9198 /* aggregated and negated variables should be resolved by varGetActiveVar() */
9199 SCIPerrorMessage("wrong variable status\n");
9200 return SCIP_INVALIDDATA;
9201 }
9202
9203 return SCIP_OKAY;
9204}
9205
9206/** marks the variable to not to be multi-aggregated */
9208 SCIP_VAR* var /**< problem variable */
9209 )
9210{
9211 SCIP_VAR* retvar;
9212
9213 assert(var != NULL);
9214
9215 retvar = varGetActiveVar(var);
9216 assert(retvar != NULL);
9217
9218 switch( SCIPvarGetStatus(retvar) )
9219 {
9224 retvar->donotmultaggr = TRUE;
9225 break;
9226
9228 SCIPerrorMessage("cannot mark a multi-aggregated variable to not be multi-aggregated.\n");
9229 return SCIP_INVALIDDATA;
9230
9233 default:
9234 /* aggregated and negated variables should be resolved by varGetActiveVar() */
9235 SCIPerrorMessage("wrong variable status\n");
9236 return SCIP_INVALIDDATA;
9237 }
9238
9239 return SCIP_OKAY;
9240}
9241
9242/** changes type of variable; cannot be called, if var belongs to a problem */
9244 SCIP_VAR* var, /**< variable to change */
9245 BMS_BLKMEM* blkmem, /**< block memory */
9246 SCIP_SET* set, /**< global SCIP settings */
9247 SCIP_PRIMAL* primal, /**< primal data */
9248 SCIP_LP* lp, /**< current LP data */
9249 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9250 SCIP_VARTYPE vartype /**< new type of variable */
9251 )
9252{
9253 SCIP_EVENT* event;
9254 SCIP_VARTYPE oldtype;
9255
9256 assert(var != NULL);
9257
9258 SCIPdebugMessage("change type of <%s> from %d to %d\n", var->name, SCIPvarGetType(var), vartype);
9259
9260 if( var->probindex >= 0 )
9261 {
9262 SCIPerrorMessage("cannot change type of variable already in the problem\n");
9263 return SCIP_INVALIDDATA;
9264 }
9265
9266 if( vartype == SCIP_DEPRECATED_VARTYPE_IMPLINT )
9267 {
9269 {
9270 SCIP_CALL( SCIPvarChgImplType(var, blkmem, set, primal, lp, eventqueue, SCIP_IMPLINTTYPE_WEAK) );
9271 }
9272 return SCIP_OKAY;
9273 }
9274
9275 oldtype = (SCIP_VARTYPE)var->vartype;
9276 var->vartype = vartype; /*lint !e641*/
9277
9279 {
9280 SCIP_CALL( SCIPeventCreateTypeChanged(&event, blkmem, var, oldtype, vartype) );
9281 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
9282 }
9283
9284 if( var->negatedvar != NULL )
9285 {
9286 assert(oldtype == (SCIP_VARTYPE)var->negatedvar->vartype
9287 || SCIPvarIsBinary(var) == SCIPvarIsBinary(var->negatedvar));
9288
9289 var->negatedvar->vartype = vartype; /*lint !e641*/
9290
9292 {
9293 SCIP_CALL( SCIPeventCreateTypeChanged(&event, blkmem, var->negatedvar, oldtype, vartype) );
9294 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
9295 }
9296 }
9297
9298 return SCIP_OKAY;
9299}
9300
9301/** changes implied integral type of variable; cannot be called, if var belongs to a problem */
9303 SCIP_VAR* var, /**< variable to change */
9304 BMS_BLKMEM* blkmem, /**< block memory */
9305 SCIP_SET* set, /**< global SCIP settings */
9306 SCIP_PRIMAL* primal, /**< primal data */
9307 SCIP_LP* lp, /**< current LP data */
9308 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9309 SCIP_IMPLINTTYPE impltype /**< new implied integral type of variable */
9310 )
9311{
9312 SCIP_EVENT* event;
9313 SCIP_IMPLINTTYPE oldtype;
9314
9315 assert(var != NULL);
9316
9317 SCIPdebugMessage("change implied integral type of <%s> from %d to %d\n", var->name, SCIPvarGetImplType(var), impltype);
9318
9319 if( var->probindex >= 0 )
9320 {
9321 SCIPerrorMessage("cannot change type of variable already in the problem\n");
9322 return SCIP_INVALIDDATA;
9323 }
9324
9325 oldtype = (SCIP_IMPLINTTYPE) var->varimpltype;
9326 var->varimpltype = impltype; /*lint !e641*/
9327
9329 {
9330 SCIP_CALL( SCIPeventCreateImplTypeChanged(&event, blkmem, var, oldtype, impltype) );
9331 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
9332 }
9333
9334 if( var->negatedvar != NULL )
9335 {
9336 var->negatedvar->varimpltype = impltype; /*lint !e641*/
9337
9339 {
9340 SCIP_CALL( SCIPeventCreateImplTypeChanged(&event, blkmem, var->negatedvar, oldtype, impltype) );
9341 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
9342 }
9343 }
9344
9345 return SCIP_OKAY;
9346}
9347
9348/** appends OBJCHANGED event to the event queue */
9349static
9351 SCIP_VAR* var, /**< problem variable to change */
9352 BMS_BLKMEM* blkmem, /**< block memory */
9353 SCIP_SET* set, /**< global SCIP settings */
9354 SCIP_PRIMAL* primal, /**< primal data */
9355 SCIP_LP* lp, /**< current LP data */
9356 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9357 SCIP_Real oldobj, /**< old objective value for variable */
9358 SCIP_Real newobj /**< new objective value for variable */
9359 )
9360{
9361 SCIP_EVENT* event;
9362
9363 assert(var != NULL);
9364 assert(var->scip == set->scip);
9365 assert(var->eventfilter != NULL);
9368
9369 /* In the case where the objcetive value of a variable is very close to epsilon, and it is aggregated
9370 * into a variable with a big objective value, round-off errors might make the assert oldobj != newobj fail.
9371 * Hence, we relax it by letting it pass if the variables are percieved the same and we use very large values
9372 * that make comparison with values close to epsilon inaccurate.
9373 */
9376 (set->exact_enable && oldobj != newobj)); /*lint !e777*/
9377
9378 SCIP_CALL( SCIPeventCreateObjChanged(&event, blkmem, var, oldobj, newobj) );
9379 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
9380
9381 return SCIP_OKAY;
9382}
9383
9384/** appends OBJCHANGED event to the event queue */
9385static
9387 SCIP_VAR* var, /**< problem variable to change */
9388 BMS_BLKMEM* blkmem, /**< block memory */
9389 SCIP_SET* set, /**< global SCIP settings */
9390 SCIP_PRIMAL* primal, /**< primal data */
9391 SCIP_LP* lp, /**< current LP data */
9392 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9393 SCIP_RATIONAL* oldobj, /**< old objective value for variable */
9394 SCIP_RATIONAL* newobj /**< new objective value for variable */
9395 )
9396{
9397 SCIP_EVENT* event;
9398
9399 assert(var != NULL);
9400 assert(var->scip == set->scip);
9401 assert(var->eventfilter != NULL);
9404
9405 /* In the case where the objcetive value of a variable is very close to epsilon, and it is aggregated
9406 * into a variable with a big objective value, round-off errors might make the assert oldobj != newobj fail.
9407 * Hence, we relax it by letting it pass if the variables are percieved the same and we use very large values
9408 * that make comparison with values close to epsilon inaccurate.
9409 */
9411
9413 SCIP_CALL( SCIPeventAddExactObjChg(event, blkmem, oldobj, newobj) );
9414 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
9415
9416 return SCIP_OKAY;
9417}
9418
9419/** changes objective value of variable */
9421 SCIP_VAR* var, /**< variable to change */
9422 BMS_BLKMEM* blkmem, /**< block memory */
9423 SCIP_SET* set, /**< global SCIP settings */
9424 SCIP_PROB* prob, /**< problem data */
9425 SCIP_PRIMAL* primal, /**< primal data */
9426 SCIP_LP* lp, /**< current LP data */
9427 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9428 SCIP_Real newobj /**< new objective value for variable */
9429 )
9430{
9432
9433 assert(var != NULL);
9434 assert(set != NULL);
9435 assert(var->scip == set->scip);
9436
9437 SCIPsetDebugMsg(set, "changing objective value of <%s> from %g to %g\n", var->name, var->obj, newobj);
9438
9439 if( !SCIPsetIsEQ(set, var->obj, newobj) )
9440 {
9441 switch( SCIPvarGetStatus(var) )
9442 {
9444 if( var->data.original.transvar != NULL )
9445 {
9447
9448 SCIP_CALL( SCIPvarChgObj(var->data.original.transvar, blkmem, set, prob, primal, lp, eventqueue,
9449 (SCIP_Real) prob->objsense * newobj/prob->objscale) );
9450 }
9451 else
9452 assert(set->stage == SCIP_STAGE_PROBLEM);
9453
9454 var->obj = newobj;
9455 var->unchangedobj = newobj;
9456
9457 break;
9458
9461 oldobj = var->obj;
9462 var->obj = newobj;
9463
9464 /* update unchanged objective value of variable */
9465 if( !lp->divingobjchg )
9466 var->unchangedobj = newobj;
9467
9468 /* update the number of variables with non-zero objective coefficient;
9469 * we only want to do the update, if the variable is added to the problem;
9470 * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
9471 */
9472 if( SCIPvarIsActive(var) )
9473 SCIPprobUpdateNObjVars(prob, set, oldobj, var->obj);
9474
9475 SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
9476 break;
9477
9482 SCIPerrorMessage("cannot change objective value of a fixed, aggregated, multi-aggregated, or negated variable\n");
9483 return SCIP_INVALIDDATA;
9484
9485 default:
9486 SCIPerrorMessage("unknown variable status\n");
9487 return SCIP_INVALIDDATA;
9488 }
9489 }
9490
9491 return SCIP_OKAY;
9492}
9493
9494/** changes rational objective value of variable */
9496 SCIP_VAR* var, /**< variable to change */
9497 BMS_BLKMEM* blkmem, /**< block memory */
9498 SCIP_SET* set, /**< global SCIP settings */
9499 SCIP_PROB* prob, /**< problem data */
9500 SCIP_PRIMAL* primal, /**< primal data */
9501 SCIP_LPEXACT* lp, /**< current LP data */
9502 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9503 SCIP_RATIONAL* newobj /**< new objective value for variable */
9504 )
9505{
9506 SCIP_Real newobjreal;
9508 SCIP_RATIONAL* tmp;
9509
9510 assert(var != NULL);
9511 assert(set != NULL);
9512
9513 if( !set->exact_enable )
9514 return SCIP_OKAY;
9515
9516 assert(var->exactdata != NULL);
9517 assert(var->scip == set->scip);
9518
9519 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmp) );
9521 newobjreal = SCIPrationalGetReal(newobj);
9522
9523 SCIPrationalDebugMessage("changing exact objective value of <%s> from %q to %q\n", var->name, var->exactdata->obj, newobj);
9524
9525 if( !SCIPrationalIsEQ(var->exactdata->obj, newobj) )
9526 {
9527 switch( SCIPvarGetStatusExact(var) )
9528 {
9530 if( var->data.original.transvar != NULL )
9531 {
9533
9535
9536 SCIP_CALL( SCIPvarChgObjExact(var->data.original.transvar, blkmem, set, prob, primal, lp, eventqueue,
9537 tmp) );
9538 }
9539 else
9540 assert(set->stage == SCIP_STAGE_PROBLEM);
9541
9542 SCIPrationalSetRational(var->exactdata->obj, newobj);
9543 SCIPintervalSetRational(&(var->exactdata->objinterval), newobj);
9544 var->obj = newobjreal;
9545 var->unchangedobj = newobjreal;
9546 break;
9547
9550 SCIPrationalSetRational(oldobj, var->exactdata->obj);
9551 SCIPrationalSetRational(var->exactdata->obj, newobj);
9552 SCIPintervalSetRational(&(var->exactdata->objinterval), newobj);
9553 var->obj = newobjreal;
9554
9555 /* update unchanged objective value of variable */
9556 if( !lp->fplp->divingobjchg )
9557 var->unchangedobj = newobjreal;
9558
9559 /* update the number of variables with non-zero objective coefficient;
9560 * we only want to do the update, if the variable is added to the problem;
9561 * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
9562 */
9563 if( SCIPvarIsActive(var) )
9565
9566 SCIP_CALL( varEventObjChangedExact(var, blkmem, set, primal, lp->fplp, eventqueue, oldobj, var->exactdata->obj) );
9567
9568 break;
9569
9574 SCIPerrorMessage("cannot change objective value of a fixed, aggregated, multi-aggregated, or negated variable\n");
9575 return SCIP_INVALIDDATA;
9576
9577 default:
9578 SCIPerrorMessage("unknown variable status\n");
9579 return SCIP_INVALIDDATA;
9580 }
9581 }
9582
9584 SCIPrationalFreeBuffer(set->buffer, &tmp);
9585
9586 return SCIP_OKAY;
9587}
9588
9589/** adds value to objective value of variable */
9591 SCIP_VAR* var, /**< variable to change */
9592 BMS_BLKMEM* blkmem, /**< block memory */
9593 SCIP_SET* set, /**< global SCIP settings */
9594 SCIP_STAT* stat, /**< problem statistics */
9595 SCIP_PROB* transprob, /**< transformed problem data */
9596 SCIP_PROB* origprob, /**< original problem data */
9597 SCIP_PRIMAL* primal, /**< primal data */
9598 SCIP_TREE* tree, /**< branch and bound tree */
9599 SCIP_REOPT* reopt, /**< reoptimization data structure */
9600 SCIP_LP* lp, /**< current LP data */
9601 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9602 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
9603 SCIP_Real addobj /**< additional objective value for variable */
9604 )
9605{
9606 assert(var != NULL);
9607 assert(set != NULL);
9608 assert(var->scip == set->scip);
9610
9611 SCIPsetDebugMsg(set, "adding %g to objective value %g of <%s>\n", addobj, var->obj, var->name);
9612
9613 if( !SCIPsetIsZero(set, addobj) )
9614 {
9616 int i;
9617
9618 switch( SCIPvarGetStatus(var) )
9619 {
9621 if( var->data.original.transvar != NULL )
9622 {
9623 SCIP_CALL( SCIPvarAddObj(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
9624 reopt, lp, eventqueue, eventfilter, (SCIP_Real) transprob->objsense * addobj/transprob->objscale) );
9625 }
9626 else
9627 assert(set->stage == SCIP_STAGE_PROBLEM);
9628
9629 var->obj += addobj;
9630 var->unchangedobj += addobj;
9631 assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
9632
9633 break;
9634
9637 oldobj = var->obj;
9638 var->obj += addobj;
9639
9640 /* update unchanged objective value of variable */
9641 if( !lp->divingobjchg )
9642 {
9643 var->unchangedobj += addobj;
9644 assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
9645 }
9646
9647 /* update the number of variables with non-zero objective coefficient;
9648 * we only want to do the update, if the variable is added to the problem;
9649 * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
9650 */
9651 if( SCIPvarIsActive(var) )
9652 SCIPprobUpdateNObjVars(transprob, set, oldobj, var->obj);
9653
9654 SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
9655 break;
9656
9658 assert(SCIPsetIsEQ(set, var->locdom.lb, var->locdom.ub));
9659 SCIPprobAddObjoffset(transprob, var->locdom.lb * addobj);
9660 SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, eventfilter, transprob, origprob, tree, reopt, lp) );
9661 break;
9662
9664 assert(!var->donotaggr);
9665 /* x = a*y + c -> add a*addobj to obj. val. of y, and c*addobj to obj. offset of problem */
9666 SCIPprobAddObjoffset(transprob, var->data.aggregate.constant * addobj);
9667 SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, eventfilter, transprob, origprob, tree, reopt, lp) );
9668 SCIP_CALL( SCIPvarAddObj(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
9669 lp, eventqueue, eventfilter, var->data.aggregate.scalar * addobj) );
9670 break;
9671
9673 assert(!var->donotmultaggr);
9674 /* 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 */
9675 SCIPprobAddObjoffset(transprob, var->data.multaggr.constant * addobj);
9676 SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, eventfilter, transprob, origprob, tree, reopt, lp) );
9677 for( i = 0; i < var->data.multaggr.nvars; ++i )
9678 {
9679 SCIP_CALL( SCIPvarAddObj(var->data.multaggr.vars[i], blkmem, set, stat, transprob, origprob, primal, tree,
9680 reopt, lp, eventqueue, eventfilter, var->data.multaggr.scalars[i] * addobj) );
9681 }
9682 break;
9683
9685 /* x' = offset - x -> add -addobj to obj. val. of x and offset*addobj to obj. offset of problem */
9686 assert(var->negatedvar != NULL);
9688 assert(var->negatedvar->negatedvar == var);
9689 SCIPprobAddObjoffset(transprob, var->data.negate.constant * addobj);
9690 SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, eventfilter, transprob, origprob, tree, reopt, lp) );
9691 SCIP_CALL( SCIPvarAddObj(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
9692 eventqueue, eventfilter, -addobj) );
9693 break;
9694
9695 default:
9696 SCIPerrorMessage("unknown variable status\n");
9697 return SCIP_INVALIDDATA;
9698 }
9699 }
9700
9701 return SCIP_OKAY;
9702}
9703
9704/** adds exact value to objective value of variable */
9706 SCIP_VAR* var, /**< variable to change */
9707 BMS_BLKMEM* blkmem, /**< block memory */
9708 SCIP_SET* set, /**< global SCIP settings */
9709 SCIP_STAT* stat, /**< problem statistics */
9710 SCIP_PROB* transprob, /**< transformed problem data */
9711 SCIP_PROB* origprob, /**< original problem data */
9712 SCIP_PRIMAL* primal, /**< primal data */
9713 SCIP_TREE* tree, /**< branch and bound tree */
9714 SCIP_REOPT* reopt, /**< reoptimization data structure */
9715 SCIP_LP* lp, /**< current LP data */
9716 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9717 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
9718 SCIP_RATIONAL* addobj /**< additional objective value for variable */
9719 )
9720{
9721 SCIP_RATIONAL* tmpobj;
9723 SCIP_RATIONAL* multaggrobj;
9724 SCIP_Real oldobjreal;
9725
9726 assert(var != NULL);
9727 assert(set != NULL);
9728 assert(var->scip == set->scip);
9730
9731 SCIPrationalDebugMessage("adding %q to objective value %q of <%s>\n", addobj, var->exactdata->obj, var->name);
9732
9734 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmpobj) );
9735
9736 if( !SCIPrationalIsZero(addobj) )
9737 {
9738 int i;
9739
9740 switch( SCIPvarGetStatusExact(var) )
9741 {
9743 if( var->data.original.transvar != NULL )
9744 {
9745 SCIPrationalMultReal(tmpobj, addobj, (SCIP_Real)transprob->objsense/transprob->objscale);
9746 SCIP_CALL( SCIPvarAddObjExact(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
9747 reopt, lp, eventqueue, eventfilter, tmpobj) );
9748 }
9749 else
9750 assert(set->stage == SCIP_STAGE_PROBLEM);
9751
9752 SCIPrationalAdd(var->exactdata->obj, var->exactdata->obj, addobj);
9753 SCIPintervalSetRational(&(var->exactdata->objinterval), var->exactdata->obj);
9754 var->obj = SCIPrationalGetReal(var->exactdata->obj);
9755 var->unchangedobj = var->obj;
9756
9757 break;
9758
9761 SCIPrationalSetRational(oldobj, var->exactdata->obj);
9762 oldobjreal = var->obj;
9763 SCIPrationalAdd(var->exactdata->obj, var->exactdata->obj, addobj);
9764 SCIPintervalSetRational(&(var->exactdata->objinterval), var->exactdata->obj);
9765 var->obj = SCIPrationalGetReal(var->exactdata->obj);
9766
9767 /* update unchanged objective value of variable */
9768 if( !lp->divingobjchg )
9769 {
9770 var->unchangedobj = var->obj;
9771 }
9772
9773 /* update the number of variables with non-zero objective coefficient;
9774 * we only want to do the update, if the variable is added to the problem;
9775 * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
9776 */
9777 if( SCIPvarIsActive(var) )
9778 SCIPprobUpdateNObjVars(transprob, set, oldobjreal, var->obj);
9779
9780 SCIP_CALL( varEventObjChangedExact(var, blkmem, set, primal, lp, eventqueue, oldobj, var->exactdata->obj) );
9781 break;
9782
9784 assert(SCIPsetIsEQ(set, var->locdom.lb, var->locdom.ub));
9785 SCIPrationalMult(tmpobj, var->exactdata->locdom.lb, addobj);
9786 SCIPprobAddObjoffsetExact(transprob, tmpobj);
9787 SCIP_CALL( SCIPprimalUpdateObjoffsetExact(primal, blkmem, set, stat, eventqueue, eventfilter, transprob, origprob, tree, reopt, lp) );
9788 break;
9789
9791 /* x = a*y + c -> add a*addobj to obj. val. of y, and c*addobj to obj. offset of problem */
9792 SCIPrationalMult(tmpobj, var->exactdata->aggregate.constant, addobj);
9793 SCIPprobAddObjoffsetExact(transprob, tmpobj);
9794 SCIP_CALL( SCIPprimalUpdateObjoffsetExact(primal, blkmem, set, stat, eventqueue, eventfilter, transprob, origprob, tree, reopt, lp) );
9795
9796 SCIPrationalMult(tmpobj, var->exactdata->aggregate.scalar, addobj);
9797
9798 SCIP_CALL( SCIPvarAddObjExact(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
9799 lp, eventqueue, eventfilter, tmpobj) );
9800 break;
9801
9803 assert(!var->donotmultaggr);
9804 /* 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 */
9805 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &multaggrobj) );
9806
9807 SCIPrationalMult(tmpobj, var->exactdata->multaggr.constant, addobj);
9808 SCIPprobAddObjoffsetExact(transprob, tmpobj);
9809 SCIP_CALL( SCIPprimalUpdateObjoffsetExact(primal, blkmem, set, stat, eventqueue, eventfilter, transprob, origprob, tree, reopt, lp) );
9810
9811 for( i = 0; i < var->data.multaggr.nvars; ++i )
9812 {
9813 SCIPrationalMult(multaggrobj, addobj, var->exactdata->multaggr.scalars[i]);
9814 SCIP_CALL( SCIPvarAddObjExact(var->data.multaggr.vars[i], blkmem, set, stat, transprob, origprob, primal, tree,
9815 reopt, lp, eventqueue, eventfilter, multaggrobj) );
9816 }
9817 SCIPrationalFreeBuffer(set->buffer, &multaggrobj);
9818 break;
9819
9821 /* x' = offset - x -> add -addobj to obj. val. of x and offset*addobj to obj. offset of problem */
9822 assert(var->negatedvar != NULL);
9824 assert(var->negatedvar->negatedvar == var);
9825
9826 SCIPrationalMultReal(tmpobj, addobj, var->data.negate.constant);
9827 SCIPprobAddObjoffsetExact(transprob, tmpobj);
9828 SCIP_CALL( SCIPprimalUpdateObjoffsetExact(primal, blkmem, set, stat, eventqueue, eventfilter, transprob, origprob, tree, reopt, lp) );
9829
9830 SCIPrationalNegate(tmpobj, addobj);
9831 SCIP_CALL( SCIPvarAddObjExact(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
9832 eventqueue, eventfilter, tmpobj) );
9833 break;
9834
9835 default:
9836 SCIPerrorMessage("unknown variable status\n");
9837 return SCIP_INVALIDDATA;
9838 }
9839 }
9840
9841 SCIPrationalFreeBuffer(set->buffer, &tmpobj);
9843
9844 return SCIP_OKAY;
9845}
9846
9847/** changes objective value of variable in current dive */
9849 SCIP_VAR* var, /**< problem variable to change */
9850 SCIP_SET* set, /**< global SCIP settings */
9851 SCIP_LP* lp, /**< current LP data */
9852 SCIP_Real newobj /**< new objective value for variable */
9853 )
9854{
9855 assert(var != NULL);
9856 assert(set != NULL);
9857 assert(var->scip == set->scip);
9858 assert(lp != NULL);
9859
9860 SCIPsetDebugMsg(set, "changing objective of <%s> to %g in current dive\n", var->name, newobj);
9861
9862 if( SCIPsetIsZero(set, newobj) )
9863 newobj = 0.0;
9864
9865 /* change objective value of attached variables */
9866 switch( SCIPvarGetStatus(var) )
9867 {
9869 assert(var->data.original.transvar != NULL);
9870 SCIP_CALL( SCIPvarChgObjDive(var->data.original.transvar, set, lp, newobj) );
9871 break;
9872
9874 assert(var->data.col != NULL);
9875 SCIP_CALL( SCIPcolChgObj(var->data.col, set, lp, newobj) );
9876 break;
9877
9880 /* nothing to do here: only the constant shift in objective function would change */
9881 break;
9882
9883 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
9884 assert(var->data.aggregate.var != NULL);
9885 assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
9886 SCIP_CALL( SCIPvarChgObjDive(var->data.aggregate.var, set, lp, newobj / var->data.aggregate.scalar) );
9887 /* the constant can be ignored, because it would only affect the objective shift */
9888 break;
9889
9891 SCIPerrorMessage("cannot change diving objective value of a multi-aggregated variable\n");
9892 return SCIP_INVALIDDATA;
9893
9894 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
9895 assert(var->negatedvar != NULL);
9897 assert(var->negatedvar->negatedvar == var);
9898 SCIP_CALL( SCIPvarChgObjDive(var->negatedvar, set, lp, -newobj) );
9899 /* the offset can be ignored, because it would only affect the objective shift */
9900 break;
9901
9902 default:
9903 SCIPerrorMessage("unknown variable status\n");
9904 return SCIP_INVALIDDATA;
9905 }
9906
9907 return SCIP_OKAY;
9908}
9909
9910/** adjust lower bound to integral value, if variable is integral */
9912 SCIP_VAR* var, /**< problem variable */
9913 SCIP_SET* set, /**< global SCIP settings */
9914 SCIP_Real* lb /**< pointer to lower bound to adjust */
9915 )
9916{
9917 assert(var != NULL);
9918 assert(set != NULL);
9919 assert(var->scip == set->scip);
9920 assert(lb != NULL);
9921
9922 SCIPsetDebugMsg(set, "adjust lower bound %g of <%s>\n", *lb, var->name);
9923
9924 *lb = adjustedLb(set, SCIPvarIsIntegral(var), *lb);
9925}
9926
9927/** adjust lower bound to integral value, if variable is integral */
9929 SCIP_VAR* var, /**< problem variable */
9930 SCIP_SET* set, /**< global SCIP settings */
9931 SCIP_RATIONAL* lb /**< pointer to lower bound to adjust */
9932 )
9933{
9934 assert(var != NULL);
9935 assert(set != NULL);
9936 assert(var->scip == set->scip);
9937 assert(lb != NULL);
9938
9939 SCIPrationalDebugMessage("adjust lower bound %q of <%s>\n", lb, var->name);
9940
9942}
9943
9944/** adjust lower bound to integral value, if variable is integral */
9946 SCIP_VAR* var, /**< problem variable */
9947 SCIP_SET* set, /**< global SCIP settings */
9948 SCIP_Real* lb /**< pointer to lower bound to adjust */
9949 )
9950{
9951 assert(var != NULL);
9952 assert(set != NULL);
9953 assert(var->scip == set->scip);
9954 assert(lb != NULL);
9955
9956 SCIPsetDebugMsg(set, "adjust lower bound %g of <%s>\n", *lb, var->name);
9957
9959}
9960
9961/** adjust upper bound to integral value, if variable is integral */
9963 SCIP_VAR* var, /**< problem variable */
9964 SCIP_SET* set, /**< global SCIP settings */
9965 SCIP_Real* ub /**< pointer to upper bound to adjust */
9966 )
9967{
9968 assert(var != NULL);
9969 assert(set != NULL);
9970 assert(var->scip == set->scip);
9971 assert(ub != NULL);
9972
9973 SCIPsetDebugMsg(set, "adjust upper bound %g of <%s>\n", *ub, var->name);
9974
9975 *ub = adjustedUb(set, SCIPvarIsIntegral(var), *ub);
9976}
9977
9978/** adjust lower bound to integral value, if variable is integral */
9980 SCIP_VAR* var, /**< problem variable */
9981 SCIP_SET* set, /**< global SCIP settings */
9982 SCIP_RATIONAL* ub /**< pointer to lower bound to adjust */
9983 )
9984{
9985 assert(var != NULL);
9986 assert(set != NULL);
9987 assert(var->scip == set->scip);
9988 assert(ub != NULL);
9989
9990 SCIPrationalDebugMessage("adjust upper bound %q of <%s>\n", ub, var->name);
9991
9993}
9994
9995/** adjust lower bound to integral value, if variable is integral */
9997 SCIP_VAR* var, /**< problem variable */
9998 SCIP_SET* set, /**< global SCIP settings */
9999 SCIP_Real* ub /**< pointer to lower bound to adjust */
10000 )
10001{
10002 assert(var != NULL);
10003 assert(set != NULL);
10004 assert(var->scip == set->scip);
10005 assert(ub != NULL);
10006
10007 SCIPsetDebugMsg(set, "adjust upper bound %g of <%s>\n", *ub, var->name);
10008
10010}
10011
10012/** adjust lower or upper bound to integral value, if variable is integral */
10014 SCIP_VAR* var, /**< problem variable */
10015 SCIP_SET* set, /**< global SCIP settings */
10016 SCIP_BOUNDTYPE boundtype, /**< type of bound to adjust */
10017 SCIP_Real* bd /**< pointer to bound to adjust */
10018 )
10019{
10020 assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
10021
10022 if( boundtype == SCIP_BOUNDTYPE_LOWER )
10023 SCIPvarAdjustLb(var, set, bd);
10024 else
10025 SCIPvarAdjustUb(var, set, bd);
10026}
10027
10028/** changes lower bound of original variable in original problem */
10030 SCIP_VAR* var, /**< problem variable to change */
10031 SCIP_SET* set, /**< global SCIP settings */
10032 SCIP_Real newbound /**< new bound for variable */
10033 )
10034{
10035 int i;
10036
10037 assert(var != NULL);
10040 assert(set != NULL);
10041 assert(var->scip == set->scip);
10042 assert(set->stage == SCIP_STAGE_PROBLEM);
10043
10044 /* check that the bound is feasible */
10046 /* adjust bound to integral value if variable is of integral type */
10047 newbound = adjustedLb(set, SCIPvarIsIntegral(var), newbound);
10048
10049 if( SCIPsetIsZero(set, newbound) )
10050 newbound = 0.0;
10051
10052 /* original domains are only stored for ORIGINAL variables, not for NEGATED */
10054 {
10055 SCIPsetDebugMsg(set, "changing original lower bound of <%s> from %g to %g\n",
10056 var->name, var->data.original.origdom.lb, newbound);
10057
10058 if( SCIPsetIsEQ(set, var->data.original.origdom.lb, newbound) )
10059 return SCIP_OKAY;
10060
10061 /* change the bound */
10062 var->data.original.origdom.lb = newbound;
10063 }
10065 {
10066 assert( var->negatedvar != NULL );
10067 SCIP_CALL( SCIPvarChgUbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
10068 }
10069
10070 /* process parent variables */
10071 for( i = 0; i < var->nparentvars; ++i )
10072 {
10073 SCIP_VAR* parentvar;
10074
10075 parentvar = var->parentvars[i];
10076 assert(parentvar != NULL);
10078 assert(parentvar->negatedvar == var);
10079 assert(var->negatedvar == parentvar);
10080
10081 SCIP_CALL( SCIPvarChgUbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
10082 }
10083
10084 return SCIP_OKAY;
10085}
10086
10087/** changes exact lower bound of original variable in original problem */
10089 SCIP_VAR* var, /**< problem variable to change */
10090 SCIP_SET* set, /**< global SCIP settings */
10091 SCIP_RATIONAL* newbound /**< new bound for variable */
10092 )
10093{
10094 SCIP_RATIONAL* tmpval;
10095 int i;
10096
10097 assert(var != NULL);
10100 assert(set != NULL);
10101 assert(var->scip == set->scip);
10102 assert(set->stage == SCIP_STAGE_PROBLEM);
10103
10104 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmpval) );
10105 SCIPrationalSetRational(tmpval, newbound);
10106
10107 /* check that the bound is feasible */
10109
10110 /* adjust bound to integral value if variable is of integral type */
10112
10113 /* original domains are only stored for ORIGINAL variables, not for NEGATED */
10115 {
10116 SCIPrationalDebugMessage("changing original lower bound of <%s> from %q to %q\n",
10117 var->name, var->exactdata->origdom.lb, newbound);
10118
10119 if( SCIPrationalIsEQ(var->exactdata->origdom.lb, newbound) )
10120 {
10121 SCIPrationalFreeBuffer(set->buffer, &tmpval);
10122 return SCIP_OKAY;
10123 }
10124
10125 /* change the bound */
10126 SCIPrationalSetRational(var->exactdata->origdom.lb, newbound);
10127 var->data.original.origdom.lb = SCIPrationalRoundReal(newbound, SCIP_R_ROUND_DOWNWARDS);
10128 }
10130 {
10131 assert( var->negatedvar != NULL );
10132
10133 SCIPrationalSetReal(tmpval, var->data.negate.constant);
10134 SCIPrationalDiff(tmpval, tmpval, newbound);
10135
10136 SCIP_CALL( SCIPvarChgUbOriginalExact(var->negatedvar, set, tmpval) );
10137 }
10138
10139 /* process parent variables */
10140 for( i = 0; i < var->nparentvars; ++i )
10141 {
10142 SCIP_VAR* parentvar;
10143
10144 parentvar = var->parentvars[i];
10145 assert(parentvar != NULL);
10147 assert(parentvar->negatedvar == var);
10148 assert(var->negatedvar == parentvar);
10149
10150 SCIPrationalSetReal(tmpval, parentvar->data.negate.constant);
10151 SCIPrationalDiff(tmpval, tmpval, newbound);
10152
10153 SCIP_CALL( SCIPvarChgUbOriginalExact(parentvar, set, tmpval) );
10154 }
10155
10156 SCIPrationalFreeBuffer(set->buffer, &tmpval);
10157
10158 return SCIP_OKAY;
10159}
10160
10161/** changes upper bound of original variable in original problem */
10163 SCIP_VAR* var, /**< problem variable to change */
10164 SCIP_SET* set, /**< global SCIP settings */
10165 SCIP_Real newbound /**< new bound for variable */
10166 )
10167{
10168 int i;
10169
10170 assert(var != NULL);
10173 assert(set != NULL);
10174 assert(var->scip == set->scip);
10175 assert(set->stage == SCIP_STAGE_PROBLEM);
10176
10177 /* check that the bound is feasible */
10179 /* adjust bound to integral value if variable is of integral type */
10180 newbound = adjustedUb(set, SCIPvarIsIntegral(var), newbound);
10181
10182 if( SCIPsetIsZero(set, newbound) )
10183 newbound = 0.0;
10184
10185 /* original domains are only stored for ORIGINAL variables, not for NEGATED */
10187 {
10188 SCIPsetDebugMsg(set, "changing original upper bound of <%s> from %g to %g\n",
10189 var->name, var->data.original.origdom.ub, newbound);
10190
10191 if( SCIPsetIsEQ(set, var->data.original.origdom.ub, newbound) )
10192 return SCIP_OKAY;
10193
10194 /* change the bound */
10195 var->data.original.origdom.ub = newbound;
10196 }
10198 {
10199 assert( var->negatedvar != NULL );
10200 SCIP_CALL( SCIPvarChgLbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
10201 }
10202
10203 /* process parent variables */
10204 for( i = 0; i < var->nparentvars; ++i )
10205 {
10206 SCIP_VAR* parentvar;
10207
10208 parentvar = var->parentvars[i];
10209 assert(parentvar != NULL);
10211 assert(parentvar->negatedvar == var);
10212 assert(var->negatedvar == parentvar);
10213
10214 SCIP_CALL( SCIPvarChgLbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
10215 }
10216
10217 return SCIP_OKAY;
10218}
10219
10220/** changes exact upper bound of original variable in original problem */
10222 SCIP_VAR* var, /**< problem variable to change */
10223 SCIP_SET* set, /**< global SCIP settings */
10224 SCIP_RATIONAL* newbound /**< new bound for variable */
10225 )
10226{
10227 SCIP_RATIONAL* tmpval;
10228 int i;
10229
10230 assert(var != NULL);
10233 assert(set != NULL);
10234 assert(var->scip == set->scip);
10235 assert(set->stage == SCIP_STAGE_PROBLEM);
10236
10237 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmpval) );
10238
10239 /* check that the bound is feasible */
10241
10242 /* adjust bound to integral value if variable is of integral type */
10244
10245 /* original domains are only stored for ORIGINAL variables, not for NEGATED */
10247 {
10248 SCIPrationalDebugMessage("changing original upper bound of <%s> from %q to %q\n",
10249 var->name, var->exactdata->origdom.ub, newbound);
10250
10251 if( SCIPrationalIsEQ(var->exactdata->origdom.ub, newbound) )
10252 {
10253 SCIPrationalFreeBuffer(set->buffer, &tmpval);
10254 return SCIP_OKAY;
10255 }
10256
10257 /* change the bound */
10258 SCIPrationalSetRational(var->exactdata->origdom.ub, newbound);
10259 var->data.original.origdom.ub = SCIPrationalRoundReal(newbound, SCIP_R_ROUND_UPWARDS);
10260 }
10262 {
10263 assert( var->negatedvar != NULL );
10264
10265 SCIPrationalSetReal(tmpval, var->data.negate.constant);
10266 SCIPrationalDiff(tmpval, tmpval, newbound);
10267
10268 SCIP_CALL( SCIPvarChgLbOriginalExact(var->negatedvar, set, tmpval) );
10269 }
10270
10271 /* process parent variables */
10272 for( i = 0; i < var->nparentvars; ++i )
10273 {
10274 SCIP_VAR* parentvar;
10275
10276 parentvar = var->parentvars[i];
10277 assert(parentvar != NULL);
10279 assert(parentvar->negatedvar == var);
10280 assert(var->negatedvar == parentvar);
10281
10282 SCIPrationalSetReal(tmpval, parentvar->data.negate.constant);
10283 SCIPrationalDiff(tmpval, tmpval, newbound);
10284
10285 SCIP_CALL( SCIPvarChgLbOriginalExact(parentvar, set, tmpval) );
10286 }
10287
10288 SCIPrationalFreeBuffer(set->buffer, &tmpval);
10289
10290 return SCIP_OKAY;
10291}
10292
10293/** appends GLBCHANGED event to the event queue */
10294static
10296 SCIP_VAR* var, /**< problem variable to change */
10297 BMS_BLKMEM* blkmem, /**< block memory */
10298 SCIP_SET* set, /**< global SCIP settings */
10299 SCIP_LP* lp, /**< current LP data */
10300 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10301 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10302 SCIP_Real oldbound, /**< old lower bound for variable */
10303 SCIP_Real newbound /**< new lower bound for variable */
10304 )
10305{
10306 assert(var != NULL);
10307 assert(var->eventfilter != NULL);
10309 assert(!SCIPsetIsEQ(set, oldbound, newbound) || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
10310 assert(set != NULL);
10311 assert(var->scip == set->scip);
10312
10313 /* check, if the variable is being tracked for bound changes
10314 * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
10315 */
10316 if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GLBCHANGED) != 0)
10319 {
10320 SCIP_EVENT* event;
10321
10322 SCIPsetDebugMsg(set, "issue GLBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
10323
10324 SCIP_CALL( SCIPeventCreateGlbChanged(&event, blkmem, var, oldbound, newbound) );
10325 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
10326 }
10327
10328 return SCIP_OKAY;
10329}
10330
10331/** appends GLBCHANGED event to the event queue */
10332static
10334 SCIP_VAR* var, /**< problem variable to change */
10335 BMS_BLKMEM* blkmem, /**< block memory */
10336 SCIP_SET* set, /**< global SCIP settings */
10337 SCIP_LP* lp, /**< current LP data */
10338 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10339 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10340 SCIP_RATIONAL* oldbound, /**< old lower bound for variable */
10341 SCIP_RATIONAL* newbound /**< new lower bound for variable */
10342 )
10343{
10344 assert(var != NULL);
10345 assert(var->eventfilter != NULL);
10347 assert(!SCIPrationalIsEQ(oldbound, newbound));
10348 assert(set != NULL);
10349 assert(var->scip == set->scip);
10350
10351 /* check, if the variable is being tracked for bound changes
10352 * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
10353 */
10354 if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GLBCHANGED) != 0)
10357 {
10358 SCIP_EVENT* event;
10359
10360 SCIPrationalDebugMessage("issue exact GLBCHANGED event for variable <%s>: %q -> %q\n", var->name, oldbound, newbound);
10361
10363 SCIP_CALL( SCIPeventAddExactBdChg(event, blkmem, oldbound, newbound) );
10364 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
10365 }
10366
10367 return SCIP_OKAY;
10368}
10369
10370/** appends GUBCHANGED event to the event queue */
10371static
10373 SCIP_VAR* var, /**< problem variable to change */
10374 BMS_BLKMEM* blkmem, /**< block memory */
10375 SCIP_SET* set, /**< global SCIP settings */
10376 SCIP_LP* lp, /**< current LP data */
10377 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10378 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10379 SCIP_Real oldbound, /**< old lower bound for variable */
10380 SCIP_Real newbound /**< new lower bound for variable */
10381 )
10382{
10383 assert(var != NULL);
10384 assert(var->eventfilter != NULL);
10386 assert(!SCIPsetIsEQ(set, oldbound, newbound) || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
10387 assert(set != NULL);
10388 assert(var->scip == set->scip);
10389
10390 /* check, if the variable is being tracked for bound changes
10391 * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
10392 */
10393 if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GUBCHANGED) != 0)
10396 {
10397 SCIP_EVENT* event;
10398
10399 SCIPsetDebugMsg(set, "issue GUBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
10400
10401 SCIP_CALL( SCIPeventCreateGubChanged(&event, blkmem, var, oldbound, newbound) );
10402 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
10403 }
10404
10405 return SCIP_OKAY;
10406}
10407
10408/** appends exact GUBCHANGED event to the event queue */
10409static
10411 SCIP_VAR* var, /**< problem variable to change */
10412 BMS_BLKMEM* blkmem, /**< block memory */
10413 SCIP_SET* set, /**< global SCIP settings */
10414 SCIP_LP* lp, /**< current LP data */
10415 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10416 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10417 SCIP_RATIONAL* oldbound, /**< old lower bound for variable */
10418 SCIP_RATIONAL* newbound /**< new lower bound for variable */
10419 )
10420{
10421 assert(var != NULL);
10422 assert(var->eventfilter != NULL);
10424 assert(!SCIPrationalIsEQ(oldbound, newbound));
10425 assert(set != NULL);
10426 assert(var->scip == set->scip);
10427
10428 /* check, if the variable is being tracked for bound changes
10429 * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
10430 */
10431 if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GUBCHANGED) != 0)
10434 {
10435 SCIP_EVENT* event;
10436
10437 SCIPsetDebugMsg(set, "issue GUBCHANGED event for variable <%s>: %g -> %g\n", var->name, SCIPrationalGetReal(oldbound), SCIPrationalGetReal(newbound));
10438
10440 SCIP_CALL( SCIPeventAddExactBdChg(event, blkmem, oldbound, newbound) );
10441 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
10442 }
10443
10444 return SCIP_OKAY;
10445}
10446
10447/** appends GHOLEADDED event to the event queue */
10448static
10450 SCIP_VAR* var, /**< problem variable to change */
10451 BMS_BLKMEM* blkmem, /**< block memory */
10452 SCIP_SET* set, /**< global SCIP settings */
10453 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10454 SCIP_Real left, /**< left bound of open interval in new hole */
10455 SCIP_Real right /**< right bound of open interval in new hole */
10456 )
10457{
10458 assert(var != NULL);
10459 assert(var->eventfilter != NULL);
10461 assert(set != NULL);
10462 assert(var->scip == set->scip);
10463 assert(SCIPsetIsLT(set, left, right));
10464
10465 /* check, if the variable is being tracked for bound changes */
10466 if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GHOLEADDED) != 0) )
10467 {
10468 SCIP_EVENT* event;
10469
10470 SCIPsetDebugMsg(set, "issue GHOLEADDED event for variable <%s>: (%.15g,%.15g)\n", var->name, left, right);
10471
10472 SCIP_CALL( SCIPeventCreateGholeAdded(&event, blkmem, var, left, right) );
10473 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
10474 }
10475
10476 return SCIP_OKAY;
10477}
10478
10479/** increases root bound change statistics after a global bound change */
10480static
10482 SCIP_VAR* var, /**< problem variable to change */
10483 SCIP_SET* set, /**< global SCIP settings */
10484 SCIP_STAT* stat /**< problem statistics */
10485 )
10486{
10487 assert(var != NULL);
10488 assert(set != NULL);
10489 assert(var->scip == set->scip);
10490 assert(stat != NULL);
10491
10493 {
10494 stat->nrootboundchgs++;
10495 stat->nrootboundchgsrun++;
10497 {
10498 stat->nrootintfixings++;
10499 stat->nrootintfixingsrun++;
10500 }
10501 }
10502}
10503
10504/* forward declaration, because both methods call each other recursively */
10505
10506/* performs the current change in upper bound, changes all parents accordingly */
10507static
10509 SCIP_VAR* var, /**< problem variable to change */
10510 BMS_BLKMEM* blkmem, /**< block memory */
10511 SCIP_SET* set, /**< global SCIP settings */
10512 SCIP_STAT* stat, /**< problem statistics */
10513 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
10514 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
10515 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
10516 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10517 SCIP_Real newbound /**< new bound for variable */
10518 );
10519
10520/** performs the current change in lower bound, changes all parents accordingly */
10521static
10523 SCIP_VAR* var, /**< problem variable to change */
10524 BMS_BLKMEM* blkmem, /**< block memory */
10525 SCIP_SET* set, /**< global SCIP settings */
10526 SCIP_STAT* stat, /**< problem statistics */
10527 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
10528 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
10529 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
10530 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10531 SCIP_Real newbound /**< new bound for variable */
10532 )
10533{
10534 SCIP_VAR* parentvar;
10535 SCIP_Real oldbound;
10536 int i;
10537
10538 assert(var != NULL);
10539 /* local domains can violate global bounds but not more than feasibility epsilon */
10540 assert(SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb));
10541 assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
10542 assert(blkmem != NULL);
10543 assert(set != NULL);
10544 assert(var->scip == set->scip);
10545 assert(stat != NULL);
10546
10547 /* adjust bound to integral value if variable is of integral type */
10548 newbound = adjustedLb(set, SCIPvarIsIntegral(var), newbound);
10549
10550 /* check that the bound is feasible */
10551 if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound > var->glbdom.ub )
10552 {
10553 /* due to numerics we only want to be feasible in feasibility tolerance */
10554 assert(SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
10555 newbound = var->glbdom.ub;
10556 }
10558
10559 assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
10560
10561 SCIPsetDebugMsg(set, "process changing global lower bound of <%s> from %f to %f\n", var->name, var->glbdom.lb, newbound);
10562
10563 if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) && !(newbound != var->glbdom.lb && newbound * var->glbdom.lb <= 0.0) ) /*lint !e777*/
10564 return SCIP_OKAY;
10565
10566 /* check bound on debugging solution */
10567 SCIP_CALL( SCIPdebugCheckLbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
10568
10569 /* change the bound */
10570 oldbound = var->glbdom.lb;
10571 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
10572 var->glbdom.lb = newbound;
10573 if( set->exact_enable && SCIPrationalIsLTReal(SCIPvarGetLbGlobalExact(var), newbound) )
10574 SCIPrationalSetReal(var->exactdata->glbdom.lb, newbound);
10575 assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
10576 assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
10577
10579 {
10580 /* merges overlapping holes into single holes, moves bounds respectively */
10581 domMerge(&var->glbdom, blkmem, set, &newbound, NULL);
10582 }
10583
10584 /* update the root bound changes counters */
10585 varIncRootboundchgs(var, set, stat);
10586
10587 /* update the lbchginfos array by replacing worse local bounds with the new global bound and changing the
10588 * redundant bound changes to be branching decisions
10589 */
10590 for( i = 0; i < var->nlbchginfos; ++i )
10591 {
10592 assert(var->lbchginfos[i].var == var);
10593
10594 if( var->lbchginfos[i].oldbound < var->glbdom.lb )
10595 {
10596 SCIPsetDebugMsg(set, " -> adjust lower bound change <%s>: %g -> %g due to new global lower bound %g\n",
10597 SCIPvarGetName(var), var->lbchginfos[i].oldbound, var->lbchginfos[i].newbound, var->glbdom.lb);
10598 var->lbchginfos[i].oldbound = var->glbdom.lb;
10599 if( SCIPsetIsLE(set, var->lbchginfos[i].newbound, var->glbdom.lb) )
10600 {
10601 /* this bound change is redundant due to the new global bound */
10602 var->lbchginfos[i].newbound = var->glbdom.lb;
10603 var->lbchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
10604 var->lbchginfos[i].redundant = TRUE;
10605 }
10606 else
10607 break; /* from now on, the remaining local bound changes are not redundant */
10608 }
10609 else
10610 break; /* from now on, the remaining local bound changes are not redundant */
10611 }
10612
10613 /* remove redundant implications and variable bounds */
10615 && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
10616 {
10617 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
10618 }
10619
10620 /* issue bound change event */
10621 assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
10622 if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && var->eventfilter != NULL )
10623 {
10624 SCIP_CALL( varEventGlbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
10625 }
10626
10627 /* process parent variables */
10628 for( i = 0; i < var->nparentvars; ++i )
10629 {
10630 parentvar = var->parentvars[i];
10631 assert(parentvar != NULL);
10632
10633 switch( SCIPvarGetStatus(parentvar) )
10634 {
10636 SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
10637 break;
10638
10643 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
10644 return SCIP_INVALIDDATA;
10645
10646 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
10647 /* this change does not affect the behavior in floating-point SCIP although it looks like it at first glance */
10648 {
10649 SCIP_Real parentnewbound;
10650 assert(parentvar->data.aggregate.var == var);
10651
10652 if( parentvar->data.aggregate.scalar > 0 )
10653 {
10654 /* a > 0 -> change lower bound of y */
10655 assert(SCIPsetIsInfinity(set, -parentvar->glbdom.lb) || SCIPsetIsInfinity(set, -oldbound)
10656 || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
10657 || (SCIPsetIsZero(set, parentvar->glbdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
10658
10659 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
10660 parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
10661 else
10662 parentnewbound = newbound;
10663 SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
10664 }
10665 else
10666 {
10667 /* a < 0 -> change upper bound of y */
10669 assert(SCIPsetIsInfinity(set, parentvar->glbdom.ub) || SCIPsetIsInfinity(set, -oldbound)
10670 || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
10671 || (SCIPsetIsZero(set, parentvar->glbdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
10672
10673 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
10674 parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
10675 else
10676 parentnewbound = -newbound;
10677 SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
10678 }
10679 break;
10680 }
10681
10682 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
10683 assert(parentvar->negatedvar != NULL);
10685 assert(parentvar->negatedvar->negatedvar == parentvar);
10686 SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
10687 parentvar->data.negate.constant - newbound) );
10688 break;
10689
10690 default:
10691 SCIPerrorMessage("unknown variable status\n");
10692 return SCIP_INVALIDDATA;
10693 }
10694 }
10695
10696 return SCIP_OKAY;
10697}
10698
10699/** performs the current change in upper bound, changes all parents accordingly */
10700static
10702 SCIP_VAR* var, /**< problem variable to change */
10703 BMS_BLKMEM* blkmem, /**< block memory */
10704 SCIP_SET* set, /**< global SCIP settings */
10705 SCIP_STAT* stat, /**< problem statistics */
10706 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
10707 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
10708 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
10709 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10710 SCIP_Real newbound /**< new bound for variable */
10711 )
10712{
10713 SCIP_VAR* parentvar;
10714 SCIP_Real oldbound;
10715 int i;
10716
10717 assert(var != NULL);
10718 /* local domains can violate global bounds but not more than feasibility epsilon */
10719 assert(SCIPsetIsFeasLE(set, var->glbdom.lb , var->locdom.lb));
10720 assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
10721 assert(blkmem != NULL);
10722 assert(set != NULL);
10723 assert(var->scip == set->scip);
10724 assert(stat != NULL);
10725
10726 /* adjust bound to integral value if variable is of integral type */
10727 newbound = adjustedUb(set, SCIPvarIsIntegral(var), newbound);
10728
10729 /* check that the bound is feasible */
10730 if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound < var->glbdom.lb )
10731 {
10732 /* due to numerics we only want to be feasible in feasibility tolerance */
10733 assert(SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
10734 newbound = var->glbdom.lb;
10735 }
10737
10738 assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
10739
10740 SCIPsetDebugMsg(set, "process changing global upper bound of <%s> from %f to %f\n", var->name, var->glbdom.ub, newbound);
10741
10742 if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) && !(newbound != var->glbdom.ub && newbound * var->glbdom.ub <= 0.0) ) /*lint !e777*/
10743 return SCIP_OKAY;
10744
10745 /* check bound on debugging solution */
10746 SCIP_CALL( SCIPdebugCheckUbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
10747
10748 /* change the bound */
10749 oldbound = var->glbdom.ub;
10750 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
10751 var->glbdom.ub = newbound;
10752 if( set->exact_enable && SCIPrationalIsGTReal(SCIPvarGetUbGlobalExact(var), newbound) )
10753 SCIPrationalSetReal(var->exactdata->glbdom.ub, newbound);
10754
10755 assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
10756 assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
10757
10759 {
10760 /* merges overlapping holes into single holes, moves bounds respectively */
10761 domMerge(&var->glbdom, blkmem, set, NULL, &newbound);
10762 }
10763
10764 /* update the root bound changes counters */
10765 varIncRootboundchgs(var, set, stat);
10766
10767 /* update the ubchginfos array by replacing worse local bounds with the new global bound and changing the
10768 * redundant bound changes to be branching decisions
10769 */
10770 for( i = 0; i < var->nubchginfos; ++i )
10771 {
10772 assert(var->ubchginfos[i].var == var);
10773 if( var->ubchginfos[i].oldbound > var->glbdom.ub )
10774 {
10775 SCIPsetDebugMsg(set, " -> adjust upper bound change <%s>: %g -> %g due to new global upper bound %g\n",
10776 SCIPvarGetName(var), var->ubchginfos[i].oldbound, var->ubchginfos[i].newbound, var->glbdom.ub);
10777 var->ubchginfos[i].oldbound = var->glbdom.ub;
10778 if( SCIPsetIsGE(set, var->ubchginfos[i].newbound, var->glbdom.ub) )
10779 {
10780 /* this bound change is redundant due to the new global bound */
10781 var->ubchginfos[i].newbound = var->glbdom.ub;
10782 var->ubchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
10783 var->ubchginfos[i].redundant = TRUE;
10784 }
10785 else
10786 break; /* from now on, the remaining local bound changes are not redundant */
10787 }
10788 else
10789 break; /* from now on, the remaining local bound changes are not redundant */
10790 }
10791
10792 /* remove redundant implications and variable bounds */
10794 && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
10795 {
10796 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
10797 }
10798
10799 /* issue bound change event */
10800 assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
10801 if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && var->eventfilter != NULL )
10802 {
10803 SCIP_CALL( varEventGubChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
10804 }
10805
10806 /* process parent variables */
10807 for( i = 0; i < var->nparentvars; ++i )
10808 {
10809 parentvar = var->parentvars[i];
10810 assert(parentvar != NULL);
10811
10812 switch( SCIPvarGetStatus(parentvar) )
10813 {
10815 SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
10816 break;
10817
10822 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
10823 return SCIP_INVALIDDATA;
10824
10825 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
10826 /* this change does not affect the behavior in floating-point SCIP although it looks like it at first glance */
10827 {
10828 SCIP_Real parentnewbound;
10829 assert(parentvar->data.aggregate.var == var);
10830
10831 if( parentvar->data.aggregate.scalar > 0 )
10832 {
10833 /* a > 0 -> change upper bound of y */
10834 assert(SCIPsetIsInfinity(set, parentvar->glbdom.ub) || SCIPsetIsInfinity(set, oldbound)
10835 || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub,
10836 oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
10837 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
10838 parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
10839 else
10840 parentnewbound = newbound;
10841 SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
10842 }
10843 else
10844 {
10845 /* a < 0 -> change lower bound of y */
10847 assert(SCIPsetIsInfinity(set, -parentvar->glbdom.lb) || SCIPsetIsInfinity(set, oldbound)
10848 || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb,
10849 oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
10850 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
10851 parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
10852 else
10853 parentnewbound = -newbound;
10854 SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
10855 }
10856 break;
10857 }
10858
10859 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
10860 assert(parentvar->negatedvar != NULL);
10862 assert(parentvar->negatedvar->negatedvar == parentvar);
10863 SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
10864 parentvar->data.negate.constant - newbound) );
10865 break;
10866
10867 default:
10868 SCIPerrorMessage("unknown variable status\n");
10869 return SCIP_INVALIDDATA;
10870 }
10871 }
10872
10873 return SCIP_OKAY;
10874}
10875
10876/* forward declaration, because both methods call each other recursively */
10877
10878/* performs the current change in upper bound, changes all parents accordingly */
10879static
10881 SCIP_VAR* var, /**< problem variable to change */
10882 BMS_BLKMEM* blkmem, /**< block memory */
10883 SCIP_SET* set, /**< global SCIP settings */
10884 SCIP_STAT* stat, /**< problem statistics */
10885 SCIP_LPEXACT* lpexact, /**< current LP data, may be NULL for original variables */
10886 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
10887 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
10888 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10889 SCIP_RATIONAL* newbound /**< new bound for variable */
10890 );
10891
10892/** performs the current change in lower bound, changes all parents accordingly */
10893static
10895 SCIP_VAR* var, /**< problem variable to change */
10896 BMS_BLKMEM* blkmem, /**< block memory */
10897 SCIP_SET* set, /**< global SCIP settings */
10898 SCIP_STAT* stat, /**< problem statistics */
10899 SCIP_LPEXACT* lpexact, /**< current LP data, may be NULL for original variables */
10900 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
10901 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
10902 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10903 SCIP_RATIONAL* newbound /**< new bound for variable */
10904 )
10905{
10906 SCIP_VAR* parentvar;
10907 SCIP_RATIONAL* oldbound;
10908 SCIP_RATIONAL* parentnewbound;
10909 int i;
10910
10911 assert(var != NULL);
10912 assert(SCIPrationalIsLE(var->exactdata->glbdom.lb, var->exactdata->locdom.lb));
10913 assert(SCIPrationalIsLE(var->exactdata->locdom.ub, var->exactdata->glbdom.ub));
10914 assert(blkmem != NULL);
10915 assert(set != NULL);
10916 assert(var->scip == set->scip);
10917 assert(stat != NULL);
10918
10919 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &oldbound) );
10920
10921 /* adjust bound to integral value if variable is of integral type */
10923
10924 /* check that the bound is feasible */
10925 if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && SCIPrationalIsGT(newbound, var->exactdata->glbdom.ub) )
10926 {
10927 /* due to numerics we only want to be feasible in feasibility tolerance */
10928 assert(SCIPrationalIsLE(newbound, var->exactdata->glbdom.ub));
10929 SCIPrationalSetRational(newbound, var->exactdata->glbdom.ub);
10930 }
10932
10933 assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPrationalIsEQReal(newbound, 0.0) || SCIPrationalIsEQReal(newbound, 1.0)); /*lint !e641*/
10934
10935 SCIPrationalDebugMessage("process changing exact global lower bound of <%s> from %q to %q\n", var->name, var->exactdata->glbdom.lb, newbound);
10936
10937 if( SCIPrationalIsEQ(newbound, var->exactdata->glbdom.lb) )
10938 {
10939 SCIPrationalFreeBuffer(set->buffer, &oldbound);
10940 return SCIP_OKAY;
10941 }
10942
10943 /* change the bound */
10944 SCIPrationalSetRational(oldbound, var->exactdata->glbdom.lb);
10945 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPrationalIsLE(newbound, var->exactdata->glbdom.ub));
10946 SCIPrationalSetRational(var->exactdata->glbdom.lb, newbound);
10947 var->glbdom.lb = SCIPrationalRoundReal(newbound, SCIP_R_ROUND_DOWNWARDS);
10948 assert( SCIPrationalIsLE(var->exactdata->glbdom.lb, var->exactdata->locdom.lb) );
10949 assert( SCIPrationalIsLE(var->exactdata->locdom.ub, var->exactdata->glbdom.ub) );
10950
10951 /* update the root bound changes counters */
10952 varIncRootboundchgs(var, set, stat);
10953
10954 /* issue bound change event */
10955 assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
10956 if( var->eventfilter != NULL )
10957 {
10958 SCIP_CALL( varEventGlbChangedExact(var, blkmem, set, lpexact->fplp, branchcand, eventqueue, oldbound, newbound) );
10959 }
10960
10961 /* process parent variables */
10962 for( i = 0; i < var->nparentvars; ++i )
10963 {
10964 parentvar = var->parentvars[i];
10965 assert(parentvar != NULL);
10966
10967 switch( SCIPvarGetStatus(parentvar) )
10968 {
10970 SCIP_CALL( varProcessChgLbGlobalExact(parentvar, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable, newbound) );
10971 break;
10972
10977 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
10978 return SCIP_INVALIDDATA;
10979
10980 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
10981 assert(parentvar->data.aggregate.var == var);
10983 {
10984 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &parentnewbound) );
10985 /* a > 0 -> change lower bound of y */
10986 if( !SCIPrationalIsAbsInfinity(newbound) )
10987 {
10988 SCIPrationalMult(parentnewbound, parentvar->exactdata->aggregate.scalar, newbound);
10989 SCIPrationalAdd(parentnewbound, parentnewbound, parentvar->exactdata->aggregate.constant);
10990 }
10991 else
10992 SCIPrationalSetRational(parentnewbound, newbound);
10993 SCIP_CALL( varProcessChgLbGlobalExact(parentvar, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable, parentnewbound) );
10994 SCIPrationalFreeBuffer(set->buffer, &parentnewbound);
10995 }
10996 else
10997 {
10998 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &parentnewbound) );
10999 /* a < 0 -> change upper bound of y */
11000 if( !SCIPrationalIsAbsInfinity(newbound) )
11001 {
11002 SCIPrationalMult(parentnewbound, parentvar->exactdata->aggregate.scalar, newbound);
11003 SCIPrationalAdd(parentnewbound, parentnewbound, parentvar->exactdata->aggregate.constant);
11004 }
11005 else
11006 SCIPrationalNegate(parentnewbound, newbound);
11007 SCIP_CALL( varProcessChgUbGlobalExact(parentvar, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable, parentnewbound) );
11008 SCIPrationalFreeBuffer(set->buffer, &parentnewbound);
11009 }
11010 break;
11011
11012 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
11013 assert(parentvar->negatedvar != NULL);
11015 assert(parentvar->negatedvar->negatedvar == parentvar);
11016 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &parentnewbound) );
11017 SCIPrationalDiffReal(parentnewbound, newbound, parentvar->data.negate.constant);
11018 SCIPrationalNegate(parentnewbound, parentnewbound);
11019 SCIP_CALL( varProcessChgUbGlobalExact(parentvar, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable,
11020 parentnewbound) );
11021 SCIPrationalFreeBuffer(set->buffer, &parentnewbound);
11022 break;
11023
11024 default:
11025 SCIPerrorMessage("unknown variable status\n");
11026 return SCIP_INVALIDDATA;
11027 }
11028 }
11029 SCIPrationalFreeBuffer(set->buffer, &oldbound);
11030
11031 return SCIP_OKAY;
11032}
11033
11034/** performs the current change in exact upper bound, changes all parents accordingly */
11035static
11037 SCIP_VAR* var, /**< problem variable to change */
11038 BMS_BLKMEM* blkmem, /**< block memory */
11039 SCIP_SET* set, /**< global SCIP settings */
11040 SCIP_STAT* stat, /**< problem statistics */
11041 SCIP_LPEXACT* lpexact, /**< current exact LP data, may be NULL for original variables */
11042 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
11043 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
11044 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11045 SCIP_RATIONAL* newbound /**< new bound for variable */
11046 )
11047{
11048 SCIP_VAR* parentvar;
11049 SCIP_RATIONAL* oldbound;
11050 SCIP_RATIONAL* parentnewbound;
11051 int i;
11052
11053 assert(var != NULL);
11054 assert(SCIPrationalIsLE(var->exactdata->glbdom.lb, var->exactdata->locdom.lb));
11055 assert(SCIPrationalIsLE(var->exactdata->locdom.ub, var->exactdata->glbdom.ub));
11056 assert(blkmem != NULL);
11057 assert(set != NULL);
11058 assert(var->scip == set->scip);
11059 assert(stat != NULL);
11060
11061 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &oldbound) );
11062
11063 /* adjust bound to integral value if variable is of integral type */
11065
11066 /* check that the bound is feasible */
11067 if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && SCIPrationalIsLT(newbound, var->exactdata->glbdom.lb) )
11068 {
11069 /* due to numerics we only want to be feasible in feasibility tolerance */
11070 assert(SCIPrationalIsGE(newbound, var->exactdata->glbdom.lb));
11071 SCIPrationalSetRational(newbound, var->exactdata->glbdom.ub);
11072 }
11074
11075 assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPrationalIsEQReal(newbound, 0.0) || SCIPrationalIsEQReal(newbound, 1.0)); /*lint !e641*/
11076
11077 SCIPrationalDebugMessage("process changing exact global upper bound of <%s> from %q to %q\n", var->name, var->exactdata->glbdom.lb, newbound);
11078
11079 if( SCIPrationalIsEQ(newbound, var->exactdata->glbdom.ub) )
11080 {
11081 SCIPrationalFreeBuffer(set->buffer, &oldbound);
11082 return SCIP_OKAY;
11083 }
11084
11085 /* change the bound */
11086 SCIPrationalSetRational(oldbound, var->exactdata->glbdom.ub);
11087 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPrationalIsGE(newbound, var->exactdata->glbdom.lb));
11088 SCIPrationalSetRational(var->exactdata->glbdom.ub, newbound);
11089 var->glbdom.ub = SCIPrationalRoundReal(newbound, SCIP_R_ROUND_UPWARDS);
11090 assert( SCIPrationalIsLE(var->exactdata->glbdom.lb, var->exactdata->locdom.lb) );
11091 assert( SCIPrationalIsLE(var->exactdata->locdom.ub, var->exactdata->glbdom.ub) );
11092
11093 /* update the root bound changes counters */
11094 varIncRootboundchgs(var, set, stat);
11095
11096 /* issue bound change event */
11097 assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
11098 if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && var->eventfilter != NULL )
11099 {
11100 SCIP_CALL( varEventGubChangedExact(var, blkmem, set, lpexact->fplp, branchcand, eventqueue, oldbound, newbound) );
11101 }
11102
11103 /* process parent variables */
11104 for( i = 0; i < var->nparentvars; ++i )
11105 {
11106 parentvar = var->parentvars[i];
11107 assert(parentvar != NULL);
11108
11109 switch( SCIPvarGetStatus(parentvar) )
11110 {
11112 SCIP_CALL( varProcessChgUbGlobalExact(parentvar, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable, newbound) );
11113 break;
11114
11119 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11120 return SCIP_INVALIDDATA;
11121
11122 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
11123 assert(parentvar->data.aggregate.var == var);
11125 {
11126 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &parentnewbound) );
11127 /* a > 0 -> change lower bound of y */
11128 if( !SCIPrationalIsAbsInfinity(newbound) )
11129 {
11130 SCIPrationalMult(parentnewbound, parentvar->exactdata->aggregate.scalar, newbound);
11131 SCIPrationalAdd(parentnewbound, parentnewbound, parentvar->exactdata->aggregate.constant);
11132 }
11133 else
11134 SCIPrationalSetRational(parentnewbound, newbound);
11135 SCIP_CALL( varProcessChgUbGlobalExact(parentvar, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable, parentnewbound) );
11136 SCIPrationalFreeBuffer(set->buffer, &parentnewbound);
11137 }
11138 else
11139 {
11140 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &parentnewbound) );
11141 /* a < 0 -> change upper bound of y */
11142 if( !SCIPrationalIsAbsInfinity(newbound) )
11143 {
11144 SCIPrationalMult(parentnewbound, parentvar->exactdata->aggregate.scalar, newbound);
11145 SCIPrationalAdd(parentnewbound, parentnewbound, parentvar->exactdata->aggregate.constant);
11146 }
11147 else
11148 SCIPrationalNegate(parentnewbound, newbound);
11149 SCIP_CALL( varProcessChgLbGlobalExact(parentvar, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable, parentnewbound) );
11150 SCIPrationalFreeBuffer(set->buffer, &parentnewbound);
11151 }
11152 break;
11153
11154 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
11155 assert(parentvar->negatedvar != NULL);
11157 assert(parentvar->negatedvar->negatedvar == parentvar);
11158 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &parentnewbound) );
11159 SCIPrationalDiffReal(parentnewbound, newbound, parentvar->data.negate.constant);
11160 SCIPrationalNegate(parentnewbound, parentnewbound);
11161 SCIP_CALL( varProcessChgLbGlobalExact(parentvar, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable,
11162 parentnewbound) );
11163 SCIPrationalFreeBuffer(set->buffer, &parentnewbound);
11164 break;
11165
11166 default:
11167 SCIPerrorMessage("unknown variable status\n");
11168 return SCIP_INVALIDDATA;
11169 }
11170 }
11171 SCIPrationalFreeBuffer(set->buffer, &oldbound);
11172
11173 return SCIP_OKAY;
11174}
11175
11176/** changes global lower bound of variable; if possible, adjusts bound to integral value;
11177 * updates local lower bound if the global bound is tighter
11178 */
11180 SCIP_VAR* var, /**< problem variable to change */
11181 BMS_BLKMEM* blkmem, /**< block memory */
11182 SCIP_SET* set, /**< global SCIP settings */
11183 SCIP_STAT* stat, /**< problem statistics */
11184 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
11185 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
11186 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
11187 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11188 SCIP_Real newbound /**< new bound for variable */
11189 )
11190{
11191 assert(var != NULL);
11192 assert(blkmem != NULL);
11193 assert(set != NULL);
11194 assert(var->scip == set->scip);
11195
11196 /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
11197 * of the domain within feastol
11198 */
11199 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
11200
11201 /* adjust bound to integral value if variable is of integral type */
11202 newbound = adjustedLb(set, SCIPvarIsIntegral(var), newbound);
11203
11204 /* check that the adjusted bound is feasible
11205 * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
11206 * here because we reset bounds to their original value!
11207 */
11208 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
11209
11211 {
11212 /* we do not want to exceed the upperbound, which could have happened due to numerics */
11213 newbound = MIN(newbound, var->glbdom.ub);
11214 }
11216
11217 /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
11218 * SCIPvarFix() allows fixings that are outside of the domain within feastol
11219 */
11220 assert(lp == NULL || SCIPsetIsFeasLE(set, var->glbdom.lb, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
11221
11222 SCIPsetDebugMsg(set, "changing global lower bound of <%s> from %g to %g\n", var->name, var->glbdom.lb, newbound);
11223
11224 if( SCIPsetIsEQ(set, var->glbdom.lb, newbound) && !(newbound != var->glbdom.lb && newbound * var->glbdom.lb <= 0.0) ) /*lint !e777*/
11225 return SCIP_OKAY;
11226
11227 /* change bounds of attached variables */
11228 switch( SCIPvarGetStatus(var) )
11229 {
11231 if( var->data.original.transvar != NULL )
11232 {
11233 SCIP_CALL( SCIPvarChgLbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
11234 cliquetable, newbound) );
11235 }
11236 else
11237 {
11238 assert(set->stage == SCIP_STAGE_PROBLEM);
11239 if( newbound > SCIPvarGetLbLocal(var) )
11240 {
11241 SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
11242 }
11243 SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
11244 }
11245 break;
11246
11249 if( newbound > SCIPvarGetLbLocal(var) )
11250 {
11251 /* ensure that the local bound change is not blocked */
11252 if( newbound > SCIPvarGetUbLocal(var) )
11253 {
11254 SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
11255 }
11256 SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
11257 }
11258 SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
11259 break;
11260
11262 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
11263 return SCIP_INVALIDDATA;
11264
11265 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
11266 {
11267 SCIP_Real childnewbound;
11268 assert(var->data.aggregate.var != NULL);
11269
11270 if( var->data.aggregate.scalar > 0 )
11271 {
11272 /* a > 0 -> change lower bound of y */
11273 assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, -var->data.aggregate.var->glbdom.lb))
11274 || SCIPsetIsFeasEQ(set, var->glbdom.lb,
11275 var->data.aggregate.var->glbdom.lb * var->data.aggregate.scalar + var->data.aggregate.constant));
11276 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
11277 childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
11278 else
11279 childnewbound = newbound;
11280 SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
11281 childnewbound) );
11282 }
11283 else
11284 {
11285 /* a < 0 -> change upper bound of y */
11286 assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
11287 || SCIPsetIsFeasEQ(set, var->glbdom.lb,
11288 var->data.aggregate.var->glbdom.ub * var->data.aggregate.scalar + var->data.aggregate.constant));
11289 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
11290 childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
11291 else
11292 childnewbound = -newbound;
11293 SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
11294 childnewbound) );
11295 }
11296 break;
11297 }
11298
11300 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
11301 return SCIP_INVALIDDATA;
11302
11303 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
11304 assert(var->negatedvar != NULL);
11306 assert(var->negatedvar->negatedvar == var);
11307 SCIP_CALL( SCIPvarChgUbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
11308 var->data.negate.constant - newbound) );
11309 break;
11310
11311 default:
11312 SCIPerrorMessage("unknown variable status\n");
11313 return SCIP_INVALIDDATA;
11314 }
11315
11316 return SCIP_OKAY;
11317}
11318
11319/** changes global lower bound of variable; if possible, adjusts bound to integral value;
11320 * updates local lower bound if the global bound is tighter
11321 */
11323 SCIP_VAR* var, /**< problem variable to change */
11324 BMS_BLKMEM* blkmem, /**< block memory */
11325 SCIP_SET* set, /**< global SCIP settings */
11326 SCIP_STAT* stat, /**< problem statistics */
11327 SCIP_LPEXACT* lpexact, /**< current exact LP data, may be NULL for original variables */
11328 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
11329 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
11330 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11331 SCIP_RATIONAL* newbound /**< new bound for variable */
11332 )
11333{
11334 SCIP_RATIONAL* childnewbound;
11335
11336 assert(var != NULL);
11337 assert(blkmem != NULL);
11338 assert(set != NULL);
11339 assert(var->scip == set->scip);
11340
11341 /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
11342 * of the domain within feastol
11343 */
11344 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPrationalIsGT(newbound, var->exactdata->glbdom.ub));
11345
11346 /* adjust bound to integral value if variable is of integral type */
11348
11349 /* check that the adjusted bound is feasible
11350 * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
11351 * here because we reset bounds to their original value!
11352 */
11353 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPrationalIsGT(newbound, var->exactdata->glbdom.ub));
11354
11356 {
11357 /* we do not want to undercut the lowerbound, which could have happened due to numerics */
11358 SCIPrationalMin(newbound, newbound, var->exactdata->glbdom.ub);
11359 }
11361
11362 /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
11363 * SCIPvarFix() allows fixings that are outside of the domain within feastol
11364 */
11365 assert(lpexact == NULL || SCIPrationalIsLE(var->exactdata->glbdom.lb, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
11366
11367 SCIPrationalDebugMessage("changing global lower bound of <%s> from %q to %q\n", var->name, var->exactdata->glbdom.lb, newbound);
11368
11369 /* change bounds of attached variables */
11370 switch( SCIPvarGetStatus(var) )
11371 {
11373 if( var->data.original.transvar != NULL )
11374 {
11375 SCIP_CALL( SCIPvarChgLbGlobalExact(var->data.original.transvar, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable,
11376 newbound) );
11377 }
11378 else
11379 {
11380 assert(set->stage == SCIP_STAGE_PROBLEM);
11382 {
11383 SCIP_CALL( SCIPvarChgLbLocalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, newbound) );
11384 }
11385 SCIP_CALL( varProcessChgLbGlobalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable, newbound) );
11386 }
11387 break;
11388
11392 {
11394 SCIP_CALL( SCIPvarChgLbLocalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, newbound) );
11395 }
11396 SCIP_CALL( varProcessChgLbGlobalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable, newbound) );
11397 break;
11398
11400 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
11401 return SCIP_INVALIDDATA;
11402
11403 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
11404 assert(var->data.aggregate.var != NULL);
11405 if( SCIPrationalIsPositive(var->exactdata->aggregate.scalar) )
11406 {
11407 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &childnewbound) );
11408
11409 /* a > 0 -> change lower bound of y */
11410 if( !SCIPrationalIsAbsInfinity(newbound) )
11411 {
11412 SCIPrationalDiff(childnewbound, newbound, var->exactdata->aggregate.constant);
11413 SCIPrationalDiv(childnewbound, childnewbound, var->exactdata->aggregate.scalar);
11414 }
11415 else
11416 SCIPrationalSetRational(childnewbound, newbound);
11417
11418 SCIP_CALL( SCIPvarChgLbGlobalExact(var->data.aggregate.var, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable,
11419 childnewbound) );
11420
11421 SCIPrationalFreeBuffer(set->buffer, &childnewbound);
11422 }
11423 else if( SCIPrationalIsNegative(var->exactdata->aggregate.scalar) )
11424 {
11425 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &childnewbound) );
11426
11427 /* a < 0 -> change upper bound of y */
11428 if( !SCIPrationalIsAbsInfinity(newbound) )
11429 {
11430 SCIPrationalDiff(childnewbound, newbound, var->exactdata->aggregate.constant);
11431 SCIPrationalDiv(childnewbound, childnewbound, var->exactdata->aggregate.scalar);
11432 }
11433 else
11434 SCIPrationalSetRational(childnewbound, newbound);
11435
11436 SCIP_CALL( SCIPvarChgUbGlobalExact(var->data.aggregate.var, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable,
11437 childnewbound) );
11438
11439 SCIPrationalFreeBuffer(set->buffer, &childnewbound);
11440 }
11441 else
11442 {
11443 SCIPerrorMessage("scalar is zero in aggregation\n");
11444 return SCIP_INVALIDDATA;
11445 }
11446 break;
11447
11449 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
11450 return SCIP_INVALIDDATA;
11451
11452 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
11453 assert(var->negatedvar != NULL);
11455 assert(var->negatedvar->negatedvar == var);
11456
11457 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &childnewbound) );
11458 SCIPrationalDiffReal(childnewbound, newbound, var->data.negate.constant);
11459 SCIPrationalNegate(childnewbound, childnewbound);
11460 SCIP_CALL( SCIPvarChgUbGlobalExact(var->negatedvar, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable,
11461 childnewbound) );
11462 SCIPrationalFreeBuffer(set->buffer, &childnewbound);
11463 break;
11464
11465 default:
11466 SCIPerrorMessage("unknown variable status\n");
11467 return SCIP_INVALIDDATA;
11468 }
11469
11470 return SCIP_OKAY;
11471}
11472
11473/** changes global upper bound of variable; if possible, adjusts bound to integral value;
11474 * updates local upper bound if the global bound is tighter
11475 */
11477 SCIP_VAR* var, /**< problem variable to change */
11478 BMS_BLKMEM* blkmem, /**< block memory */
11479 SCIP_SET* set, /**< global SCIP settings */
11480 SCIP_STAT* stat, /**< problem statistics */
11481 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
11482 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
11483 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
11484 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11485 SCIP_Real newbound /**< new bound for variable */
11486 )
11487{
11488 assert(var != NULL);
11489 assert(blkmem != NULL);
11490 assert(set != NULL);
11491 assert(var->scip == set->scip);
11492
11493 /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
11494 * of the domain within feastol
11495 */
11496 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
11497
11498 /* adjust bound to integral value if variable is of integral type */
11499 newbound = adjustedUb(set, SCIPvarIsIntegral(var), newbound);
11500
11501 /* check that the adjusted bound is feasible
11502 * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
11503 * here because we reset bounds to their original value!
11504 */
11505 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
11506
11508 {
11509 /* we do not want to undercut the lowerbound, which could have happened due to numerics */
11510 newbound = MAX(newbound, var->glbdom.lb);
11511 }
11513
11514 /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
11515 * SCIPvarFix() allows fixings that are outside of the domain within feastol
11516 */
11517 assert(lp == NULL || SCIPsetIsFeasGE(set, var->glbdom.ub, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
11518
11519 SCIPsetDebugMsg(set, "changing global upper bound of <%s> from %g to %g\n", var->name, var->glbdom.ub, newbound);
11520
11521 if( SCIPsetIsEQ(set, var->glbdom.ub, newbound) && !(newbound != var->glbdom.ub && newbound * var->glbdom.ub <= 0.0) ) /*lint !e777*/
11522 return SCIP_OKAY;
11523
11524 /* change bounds of attached variables */
11525 switch( SCIPvarGetStatus(var) )
11526 {
11528 if( var->data.original.transvar != NULL )
11529 {
11530 SCIP_CALL( SCIPvarChgUbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
11531 newbound) );
11532 }
11533 else
11534 {
11535 assert(set->stage == SCIP_STAGE_PROBLEM);
11536 if( newbound < SCIPvarGetUbLocal(var) )
11537 {
11538 SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
11539 }
11540 SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
11541 }
11542 break;
11543
11546 if( newbound < SCIPvarGetUbLocal(var) )
11547 {
11548 /* ensure that the local bound change is not blocked */
11549 if( newbound < SCIPvarGetLbLocal(var) )
11550 {
11551 SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
11552 }
11553 SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
11554 }
11555 SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
11556 break;
11557
11559 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
11560 return SCIP_INVALIDDATA;
11561
11562 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
11563 {
11564 SCIP_Real childnewbound;
11565 assert(var->data.aggregate.var != NULL);
11566
11567 if( var->data.aggregate.scalar > 0 )
11568 {
11569 /* a > 0 -> change lower bound of y */
11570 assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
11571 || SCIPsetIsFeasEQ(set, var->glbdom.ub,
11572 var->data.aggregate.var->glbdom.ub * var->data.aggregate.scalar + var->data.aggregate.constant));
11573 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
11574 childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
11575 else
11576 childnewbound = newbound;
11577 SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
11578 childnewbound) );
11579 }
11580 else
11581 {
11582 /* a < 0 -> change upper bound of y */
11583 assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, -var->data.aggregate.var->glbdom.lb))
11584 || SCIPsetIsFeasEQ(set, var->glbdom.ub,
11585 var->data.aggregate.var->glbdom.lb * var->data.aggregate.scalar + var->data.aggregate.constant));
11586 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
11587 childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
11588 else
11589 childnewbound = -newbound;
11590 SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
11591 childnewbound) );
11592 }
11593 break;
11594 }
11595
11597 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
11598 return SCIP_INVALIDDATA;
11599
11600 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
11601 assert(var->negatedvar != NULL);
11603 assert(var->negatedvar->negatedvar == var);
11604 SCIP_CALL( SCIPvarChgLbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
11605 var->data.negate.constant - newbound) );
11606 break;
11607
11608 default:
11609 SCIPerrorMessage("unknown variable status\n");
11610 return SCIP_INVALIDDATA;
11611 }
11612
11613 return SCIP_OKAY;
11614}
11615
11616/** changes global upper bound of variable; if possible, adjusts bound to integral value;
11617 * updates local upper bound if the global bound is tighter
11618 */
11620 SCIP_VAR* var, /**< problem variable to change */
11621 BMS_BLKMEM* blkmem, /**< block memory */
11622 SCIP_SET* set, /**< global SCIP settings */
11623 SCIP_STAT* stat, /**< problem statistics */
11624 SCIP_LPEXACT* lpexact, /**< current exact LP data, may be NULL for original variables */
11625 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
11626 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
11627 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11628 SCIP_RATIONAL* newbound /**< new bound for variable */
11629 )
11630{
11631 SCIP_RATIONAL* childnewbound;
11632
11633 assert(var != NULL);
11634 assert(blkmem != NULL);
11635 assert(set != NULL);
11636 assert(var->scip == set->scip);
11637
11638 /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
11639 * of the domain within feastol
11640 */
11641 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPrationalIsLT(newbound, var->exactdata->glbdom.lb));
11642
11643 /* adjust bound to integral value if variable is of integral type */
11645
11646 /* check that the adjusted bound is feasible
11647 * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
11648 * here because we reset bounds to their original value!
11649 */
11650 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPrationalIsLT(newbound, var->exactdata->glbdom.lb));
11651
11653 {
11654 /* we do not want to undercut the lowerbound, which could have happened due to numerics */
11655 SCIPrationalMax(newbound, newbound, var->exactdata->glbdom.lb);
11656 }
11658
11659 /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
11660 * SCIPvarFix() allows fixings that are outside of the domain within feastol
11661 */
11662 assert(lpexact == NULL || SCIPrationalIsGE(var->exactdata->glbdom.ub, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
11663
11664 SCIPrationalDebugMessage("changing global upper bound of <%s> from %q to %q\n", var->name, var->exactdata->glbdom.ub, newbound);
11665
11666 /* change bounds of attached variables */
11667 switch( SCIPvarGetStatus(var) )
11668 {
11670 if( var->data.original.transvar != NULL )
11671 {
11672 SCIP_CALL( SCIPvarChgUbGlobalExact(var->data.original.transvar, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable,
11673 newbound) );
11674 }
11675 else
11676 {
11677 assert(set->stage == SCIP_STAGE_PROBLEM);
11679 {
11680 SCIP_CALL( SCIPvarChgUbLocalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, newbound) );
11681 }
11682
11683 SCIP_CALL( varProcessChgUbGlobalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable, newbound) );
11684 }
11685 break;
11686
11690 {
11692 SCIP_CALL( SCIPvarChgUbLocalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, newbound) );
11693 }
11694 SCIP_CALL( varProcessChgUbGlobalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable, newbound) );
11695 break;
11696
11698 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
11699 return SCIP_INVALIDDATA;
11700
11701 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
11702 assert(var->data.aggregate.var != NULL);
11703 if( SCIPrationalIsPositive(var->exactdata->aggregate.scalar) )
11704 {
11705 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &childnewbound) );
11706
11707 /* a > 0 -> change lower bound of y */
11708 if( !SCIPrationalIsAbsInfinity(newbound) )
11709 {
11710 SCIPrationalDiff(childnewbound, newbound, var->exactdata->aggregate.constant);
11711 SCIPrationalDiv(childnewbound, childnewbound, var->exactdata->aggregate.scalar);
11712 }
11713 else
11714 SCIPrationalSetRational(childnewbound, newbound);
11715
11716 SCIP_CALL( SCIPvarChgUbGlobalExact(var->data.aggregate.var, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable,
11717 childnewbound) );
11718
11719 SCIPrationalFreeBuffer(set->buffer, &childnewbound);
11720 }
11721 else if( SCIPrationalIsNegative(var->exactdata->aggregate.scalar) )
11722 {
11723 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &childnewbound) );
11724
11725 /* a < 0 -> change upper bound of y */
11726 if( !SCIPrationalIsAbsInfinity(newbound) )
11727 {
11728 SCIPrationalDiff(childnewbound, newbound, var->exactdata->aggregate.constant);
11729 SCIPrationalDiv(childnewbound, childnewbound, var->exactdata->aggregate.scalar);
11730 }
11731 else
11732 SCIPrationalSetRational(childnewbound, newbound);
11733
11734 SCIP_CALL( SCIPvarChgLbGlobalExact(var->data.aggregate.var, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable,
11735 childnewbound) );
11736
11737 SCIPrationalFreeBuffer(set->buffer, &childnewbound);
11738 }
11739 else
11740 {
11741 SCIPerrorMessage("scalar is zero in aggregation\n");
11742 return SCIP_INVALIDDATA;
11743 }
11744 break;
11745
11747 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
11748 return SCIP_INVALIDDATA;
11749
11750 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
11751 assert(var->negatedvar != NULL);
11753 assert(var->negatedvar->negatedvar == var);
11754
11755 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &childnewbound) );
11756 SCIPrationalDiffReal(childnewbound, newbound, var->data.negate.constant);
11757 SCIPrationalNegate(childnewbound, childnewbound);
11758 SCIP_CALL( SCIPvarChgLbGlobalExact(var->negatedvar, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable,
11759 childnewbound) );
11760 SCIPrationalFreeBuffer(set->buffer, &childnewbound);
11761 break;
11762
11763 default:
11764 SCIPerrorMessage("unknown variable status\n");
11765 return SCIP_INVALIDDATA;
11766 }
11767
11768 return SCIP_OKAY;
11769}
11770
11771/** changes lazy lower bound of the variable, this is only possible if the variable is not in the LP yet */
11773 SCIP_VAR* var, /**< problem variable */
11774 SCIP_SET* set, /**< global SCIP settings */
11775 SCIP_Real lazylb /**< the lazy lower bound to be set */
11776 )
11777{
11778 assert(var != NULL);
11779 assert(var->probindex != -1);
11780 assert(SCIPsetIsFeasGE(set, var->glbdom.ub, lazylb));
11781 assert(SCIPsetIsFeasGE(set, var->lazyub, lazylb));
11782 assert(set != NULL);
11783 assert(var->scip == set->scip);
11784
11785 /* variable should not be in the LP */
11787 return SCIP_INVALIDCALL;
11788
11789 var->lazylb = lazylb;
11790
11791 return SCIP_OKAY;
11792}
11793
11794/** changes lazy upper bound of the variable, this is only possible if the variable is not in the LP yet */
11796 SCIP_VAR* var, /**< problem variable */
11797 SCIP_SET* set, /**< global SCIP settings */
11798 SCIP_Real lazyub /**< the lazy upper bound to be set */
11799 )
11800{
11801 assert(var != NULL);
11802 assert(var->probindex != -1);
11803 assert(SCIPsetIsFeasGE(set, lazyub, var->glbdom.lb));
11804 assert(SCIPsetIsFeasGE(set, lazyub, var->lazylb));
11805 assert(set != NULL);
11806 assert(var->scip == set->scip);
11807
11808 /* variable should not be in the LP */
11810 return SCIP_INVALIDCALL;
11811
11812 var->lazyub = lazyub;
11813
11814 return SCIP_OKAY;
11815}
11816
11817/** changes global bound of variable; if possible, adjusts bound to integral value;
11818 * updates local bound if the global bound is tighter
11819 */
11821 SCIP_VAR* var, /**< problem variable to change */
11822 BMS_BLKMEM* blkmem, /**< block memory */
11823 SCIP_SET* set, /**< global SCIP settings */
11824 SCIP_STAT* stat, /**< problem statistics */
11825 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
11826 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
11827 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
11828 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11829 SCIP_Real newbound, /**< new bound for variable */
11830 SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
11831 )
11832{
11833 /* apply bound change to the LP data */
11834 switch( boundtype )
11835 {
11837 return SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
11839 return SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
11840 default:
11841 SCIPerrorMessage("unknown bound type\n");
11842 return SCIP_INVALIDDATA;
11843 }
11844}
11845
11846/** changes exact global bound of variable; if possible, adjusts bound to integral value;
11847 * updates local bound if the global bound is tighter
11848 */
11850 SCIP_VAR* var, /**< problem variable to change */
11851 BMS_BLKMEM* blkmem, /**< block memory */
11852 SCIP_SET* set, /**< global SCIP settings */
11853 SCIP_STAT* stat, /**< problem statistics */
11854 SCIP_LPEXACT* lpexact, /**< current LP data, may be NULL for original variables */
11855 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
11856 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
11857 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11858 SCIP_RATIONAL* newbound, /**< new bound for variable */
11859 SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
11860 )
11861{
11862 /* apply bound change to the LP data */
11863 switch( boundtype )
11864 {
11866 return SCIPvarChgLbGlobalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable, newbound);
11868 return SCIPvarChgUbGlobalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable, newbound);
11869 default:
11870 SCIPerrorMessage("unknown bound type\n");
11871 return SCIP_INVALIDDATA;
11872 }
11873}
11874
11875/** appends LBTIGHTENED or LBRELAXED event to the event queue */
11876static
11878 SCIP_VAR* var, /**< problem variable to change */
11879 BMS_BLKMEM* blkmem, /**< block memory */
11880 SCIP_SET* set, /**< global SCIP settings */
11881 SCIP_LP* lp, /**< current LP data */
11882 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
11883 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
11884 SCIP_Real oldbound, /**< old lower bound for variable */
11885 SCIP_Real newbound /**< new lower bound for variable */
11886 )
11887{
11888 assert(var != NULL);
11889 assert(var->eventfilter != NULL);
11891 assert(!SCIPsetIsEQ(set, oldbound, newbound) || newbound == var->glbdom.lb || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
11892 assert(set != NULL);
11893 assert(var->scip == set->scip);
11894
11895 /* check, if the variable is being tracked for bound changes
11896 * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
11897 */
11898 if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_LBCHANGED) != 0)
11901 {
11902 SCIP_EVENT* event;
11903
11904 SCIPsetDebugMsg(set, "issue LBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
11905
11906 SCIP_CALL( SCIPeventCreateLbChanged(&event, blkmem, var, oldbound, newbound) );
11907 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
11908 }
11909
11910 return SCIP_OKAY;
11911}
11912
11913/** appends LBTIGHTENED or LBRELAXED event to the event queue */
11914static
11916 SCIP_VAR* var, /**< problem variable to change */
11917 BMS_BLKMEM* blkmem, /**< block memory */
11918 SCIP_SET* set, /**< global SCIP settings */
11919 SCIP_LPEXACT* lp, /**< current LP data */
11920 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
11921 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
11922 SCIP_RATIONAL* oldbound, /**< old lower bound for variable */
11923 SCIP_RATIONAL* newbound /**< new lower bound for variable */
11924 )
11925{
11926 assert(var != NULL);
11927 assert(var->eventfilter != NULL);
11929 assert(set != NULL);
11930 assert(var->scip == set->scip);
11931
11932 /* check, if the variable is being tracked for bound changes
11933 * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
11934 */
11935 if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_LBCHANGED) != 0)
11938 {
11939 SCIP_EVENT* event;
11940
11941 SCIPrationalDebugMessage("issue exact LBCHANGED event for variable <%s>: %q -> %q\n", var->name, oldbound, newbound);
11942
11944 SCIP_CALL( SCIPeventAddExactBdChg(event, blkmem, oldbound, newbound) );
11945 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp->fplp, branchcand, NULL, &event) );
11946 }
11947
11948 return SCIP_OKAY;
11949}
11950
11951/** appends UBTIGHTENED or UBRELAXED event to the event queue */
11952static
11954 SCIP_VAR* var, /**< problem variable to change */
11955 BMS_BLKMEM* blkmem, /**< block memory */
11956 SCIP_SET* set, /**< global SCIP settings */
11957 SCIP_LP* lp, /**< current LP data */
11958 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
11959 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
11960 SCIP_Real oldbound, /**< old upper bound for variable */
11961 SCIP_Real newbound /**< new upper bound for variable */
11962 )
11963{
11964 assert(var != NULL);
11965 assert(var->eventfilter != NULL);
11967 assert(!SCIPsetIsEQ(set, oldbound, newbound) || newbound == var->glbdom.ub || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
11968 assert(set != NULL);
11969 assert(var->scip == set->scip);
11970
11971 /* check, if the variable is being tracked for bound changes
11972 * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
11973 */
11974 if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_UBCHANGED) != 0)
11977 {
11978 SCIP_EVENT* event;
11979
11980 SCIPsetDebugMsg(set, "issue UBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
11981
11982 SCIP_CALL( SCIPeventCreateUbChanged(&event, blkmem, var, oldbound, newbound) );
11983 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
11984 }
11985
11986 return SCIP_OKAY;
11987}
11988
11989/** appends exact UBTIGHTENED or UBRELAXED event to the event queue */
11990static
11992 SCIP_VAR* var, /**< problem variable to change */
11993 BMS_BLKMEM* blkmem, /**< block memory */
11994 SCIP_SET* set, /**< global SCIP settings */
11995 SCIP_LPEXACT* lp, /**< current LP data */
11996 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
11997 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
11998 SCIP_RATIONAL* oldbound, /**< old upper bound for variable */
11999 SCIP_RATIONAL* newbound /**< new upper bound for variable */
12000 )
12001{
12002 assert(var != NULL);
12003 assert(var->eventfilter != NULL);
12005 assert(set != NULL);
12006 assert(var->scip == set->scip);
12007
12008 /* check, if the variable is being tracked for bound changes
12009 * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
12010 */
12011 if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_UBCHANGED) != 0)
12014 {
12015 SCIP_EVENT* event;
12016
12017 SCIPsetDebugMsg(set, "issue UBCHANGED event for variable <%s>: %g -> %g\n", var->name, SCIPrationalGetReal(oldbound), SCIPrationalGetReal(newbound));
12018
12020 SCIP_CALL( SCIPeventAddExactBdChg(event, blkmem, oldbound, newbound) );
12021 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp->fplp, branchcand, NULL, &event) );
12022 }
12023
12024 return SCIP_OKAY;
12025}
12026
12027/* forward declaration, because both methods call each other recursively */
12028
12029/* performs the current change in upper bound, changes all parents accordingly */
12030static
12032 SCIP_VAR* var, /**< problem variable to change */
12033 BMS_BLKMEM* blkmem, /**< block memory */
12034 SCIP_SET* set, /**< global SCIP settings */
12035 SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
12036 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
12037 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
12038 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
12039 SCIP_Real newbound /**< new bound for variable */
12040 );
12041
12042/** performs the current change in lower bound, changes all parents accordingly */
12043static
12045 SCIP_VAR* var, /**< problem variable to change */
12046 BMS_BLKMEM* blkmem, /**< block memory */
12047 SCIP_SET* set, /**< global SCIP settings */
12048 SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
12049 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
12050 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
12051 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
12052 SCIP_Real newbound /**< new bound for variable */
12053 )
12054{
12055 SCIP_VAR* parentvar;
12056 SCIP_Real oldbound;
12057 int i;
12058
12059 assert(var != NULL);
12060 assert(set != NULL);
12061 assert(var->scip == set->scip);
12062 assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)
12063 || SCIPsetIsEQ(set, newbound, var->locdom.ub)))
12064 || (SCIPvarIsIntegral(var) && (SCIPsetIsIntegral(set, newbound)
12065 || SCIPsetIsEQ(set, newbound, var->locdom.ub)))
12066 || !SCIPvarIsIntegral(var));
12067
12068 /* check that the bound is feasible */
12069 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsLE(set, newbound, var->glbdom.ub));
12070 /* adjust bound to integral value if variable is of integral type */
12071 newbound = adjustedLb(set, SCIPvarIsIntegral(var), newbound);
12072
12074 {
12075 /* we do not want to exceed the upper bound, which could have happened due to numerics */
12076 newbound = MIN(newbound, var->locdom.ub);
12077
12078 /* we do not want to undercut the global lower bound, which could have happened due to numerics */
12079 newbound = MAX(newbound, var->glbdom.lb);
12080 }
12082
12083 SCIPsetDebugMsg(set, "process changing lower bound of <%s> from %g to %g\n", var->name, var->locdom.lb, newbound);
12084
12085 if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) && var->glbdom.lb != var->locdom.lb ) /*lint !e777*/
12086 newbound = var->glbdom.lb;
12087 else if( SCIPsetIsEQ(set, newbound, var->locdom.lb) && !(newbound != var->locdom.lb && newbound * var->locdom.lb <= 0.0) ) /*lint !e777*/
12088 return SCIP_OKAY;
12089
12090 /* change the bound */
12091 oldbound = var->locdom.lb;
12092 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->locdom.ub));
12093 var->locdom.lb = newbound;
12094 /* adjust the exact bound as well */
12095 if( set->exact_enable )
12096 {
12097 SCIPrationalSetReal(var->exactdata->locdom.lb, var->locdom.lb);
12098 SCIPrationalMax(var->exactdata->locdom.lb, var->exactdata->locdom.lb, var->exactdata->glbdom.lb);
12099 }
12100
12101 /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
12102 * once update the statistic
12103 */
12104 if( stat != NULL )
12105 SCIPstatIncrement(stat, set, domchgcount);
12106
12108 {
12109 /* merges overlapping holes into single holes, moves bounds respectively */
12110 domMerge(&var->locdom, blkmem, set, &newbound, NULL);
12111 }
12112
12115
12116 /* issue bound change event */
12117 assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
12118 if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && var->eventfilter != NULL )
12119 {
12120 SCIP_CALL( varEventLbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
12121 }
12122
12123 /* process parent variables */
12124 for( i = 0; i < var->nparentvars; ++i )
12125 {
12126 parentvar = var->parentvars[i];
12127 assert(parentvar != NULL);
12128
12129 switch( SCIPvarGetStatus(parentvar) )
12130 {
12132 SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
12133 break;
12134
12139 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
12140 return SCIP_INVALIDDATA;
12141
12142 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12143 /* this change does not affect the behavior in floating-point SCIP although it looks like it at first glance */
12144 {
12145 SCIP_Real parentnewbound;
12146 assert(parentvar->data.aggregate.var == var);
12147
12148 if (!set->exact_enable)
12149 {
12150 parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
12151 }
12152 else
12153 {
12154 SCIP_INTERVAL parentboundinterval;
12155 SCIPintervalSet(&parentboundinterval, newbound);
12156 SCIPintervalMulScalar(SCIP_INTERVAL_INFINITY, &parentboundinterval, parentboundinterval, parentvar->data.aggregate.scalar);
12157 SCIPintervalAddScalar(SCIP_INTERVAL_INFINITY, &parentboundinterval, parentboundinterval, parentvar->data.aggregate.constant);
12158 parentnewbound = parentvar->data.aggregate.scalar > 0 ? parentboundinterval.inf : parentboundinterval.sup;
12159 }
12160
12161 if( parentvar->data.aggregate.scalar > 0 )
12162 {
12163 /* a > 0 -> change lower bound of y */
12164 assert(SCIPsetIsInfinity(set, -parentvar->locdom.lb) || SCIPsetIsInfinity(set, -oldbound)
12165 || SCIPsetIsFeasEQ(set, parentvar->locdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
12166 || (SCIPsetIsZero(set, parentvar->locdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
12167
12168 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
12169 {
12170 /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
12171 * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
12172 * as a result, the parent's lower bound is set to it's upper bound, and not above
12173 */
12174 if( parentnewbound > parentvar->glbdom.ub )
12175 {
12176 /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
12177 assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
12178 parentnewbound = parentvar->glbdom.ub;
12179 }
12180 }
12181 else
12182 parentnewbound = newbound;
12183 SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
12184 }
12185 else
12186 {
12187 /* a < 0 -> change upper bound of y */
12189 assert(SCIPsetIsInfinity(set, parentvar->locdom.ub) || SCIPsetIsInfinity(set, -oldbound)
12190 || SCIPsetIsFeasEQ(set, parentvar->locdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
12191 || (SCIPsetIsZero(set, parentvar->locdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
12192
12193 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
12194 {
12195 /* 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
12196 * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
12197 * as a result, the parent's upper bound is set to it's lower bound, and not below
12198 */
12199 if( parentnewbound < parentvar->glbdom.lb )
12200 {
12201 /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
12202 assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
12203 parentnewbound = parentvar->glbdom.lb;
12204 }
12205 }
12206 else
12207 parentnewbound = -newbound;
12208 SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
12209 }
12210 break;
12211 }
12212 case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
12213 assert(parentvar->negatedvar != NULL);
12215 assert(parentvar->negatedvar->negatedvar == parentvar);
12216 SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
12217 parentvar->data.negate.constant - newbound) );
12218 break;
12219
12220 default:
12221 SCIPerrorMessage("unknown variable status\n");
12222 return SCIP_INVALIDDATA;
12223 }
12224 }
12225
12226 return SCIP_OKAY;
12227}
12228
12229/** performs the current change in upper bound, changes all parents accordingly */
12230static
12232 SCIP_VAR* var, /**< problem variable to change */
12233 BMS_BLKMEM* blkmem, /**< block memory */
12234 SCIP_SET* set, /**< global SCIP settings */
12235 SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
12236 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
12237 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
12238 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
12239 SCIP_Real newbound /**< new bound for variable */
12240 )
12241{
12242 SCIP_VAR* parentvar;
12243 SCIP_Real oldbound;
12244 int i;
12245
12246 assert(var != NULL);
12247 assert(set != NULL);
12248 assert(var->scip == set->scip);
12249 assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)
12250 || SCIPsetIsEQ(set, newbound, var->locdom.lb)))
12251 || (SCIPvarIsIntegral(var) && (SCIPsetIsIntegral(set, newbound)
12252 || SCIPsetIsEQ(set, newbound, var->locdom.lb)))
12253 || !SCIPvarIsIntegral(var));
12254
12255 /* check that the bound is feasible */
12256 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsGE(set, newbound, var->glbdom.lb));
12257 /* adjust bound to integral value if variable is of integral type */
12258 newbound = adjustedUb(set, SCIPvarIsIntegral(var), newbound);
12259
12261 {
12262 /* we do not want to undercut the lower bound, which could have happened due to numerics */
12263 newbound = MAX(newbound, var->locdom.lb);
12264
12265 /* we do not want to exceed the global upper bound, which could have happened due to numerics */
12266 newbound = MIN(newbound, var->glbdom.ub);
12267 }
12269
12270 SCIPsetDebugMsg(set, "process changing upper bound of <%s> from %g to %g\n", var->name, var->locdom.ub, newbound);
12271
12272 if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) && var->glbdom.ub != var->locdom.ub ) /*lint !e777*/
12273 newbound = var->glbdom.ub;
12274 else if( SCIPsetIsEQ(set, newbound, var->locdom.ub) && !(newbound != var->locdom.ub && newbound * var->locdom.ub <= 0.0) ) /*lint !e777*/
12275 return SCIP_OKAY;
12276
12277 /* change the bound */
12278 oldbound = var->locdom.ub;
12279 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->locdom.lb));
12280 var->locdom.ub = newbound;
12281 /* adjust the exact bound as well */
12282 if( set->exact_enable )
12283 {
12284 SCIPrationalSetReal(var->exactdata->locdom.ub, var->locdom.ub);
12285 SCIPrationalMin(var->exactdata->locdom.ub, var->exactdata->locdom.ub, var->exactdata->glbdom.ub);
12286 }
12287
12288 /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
12289 * once update the statistic
12290 */
12291 if( stat != NULL )
12292 SCIPstatIncrement(stat, set, domchgcount);
12293
12295 {
12296 /* merges overlapping holes into single holes, moves bounds respectively */
12297 domMerge(&var->locdom, blkmem, set, NULL, &newbound);
12298 }
12299
12302
12303 /* issue bound change event */
12304 assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
12305 if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && var->eventfilter != NULL )
12306 {
12307 SCIP_CALL( varEventUbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
12308 }
12309
12310 /* process parent variables */
12311 for( i = 0; i < var->nparentvars; ++i )
12312 {
12313 parentvar = var->parentvars[i];
12314 assert(parentvar != NULL);
12315
12316 switch( SCIPvarGetStatus(parentvar) )
12317 {
12319 SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
12320 break;
12321
12326 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
12327 return SCIP_INVALIDDATA;
12328
12329 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12330 /* this change does not affect the behavior in floating-point SCIP although it looks like it at first glance */
12331 {
12332 SCIP_Real parentnewbound;
12333 assert(parentvar->data.aggregate.var == var);
12334
12335 if( !set->exact_enable )
12336 {
12337 parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
12338 }
12339 else
12340 {
12341 SCIP_INTERVAL parentboundinterval;
12342 SCIPintervalSet(&parentboundinterval, newbound);
12343 SCIPintervalMulScalar(SCIP_INTERVAL_INFINITY, &parentboundinterval, parentboundinterval, parentvar->data.aggregate.scalar);
12344 SCIPintervalAddScalar(SCIP_INTERVAL_INFINITY, &parentboundinterval, parentboundinterval, parentvar->data.aggregate.constant);
12345 parentnewbound = parentvar->data.aggregate.scalar > 0 ? parentboundinterval.sup : parentboundinterval.inf;
12346 }
12347 if( parentvar->data.aggregate.scalar > 0 )
12348 {
12349 /* a > 0 -> change upper bound of x */
12350 assert(SCIPsetIsInfinity(set, parentvar->locdom.ub) || SCIPsetIsInfinity(set, oldbound)
12351 || SCIPsetIsFeasEQ(set, parentvar->locdom.ub,
12352 oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
12353 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
12354 {
12355 /* 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
12356 * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
12357 * as a result, the parent's upper bound is set to it's lower bound, and not below
12358 */
12359 if( parentnewbound < parentvar->glbdom.lb )
12360 {
12361 /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
12362 assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
12363 parentnewbound = parentvar->glbdom.lb;
12364 }
12365 }
12366 else
12367 parentnewbound = newbound;
12368 SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
12369 }
12370 else
12371 {
12372 /* a < 0 -> change lower bound of x */
12374 assert(SCIPsetIsInfinity(set, -parentvar->locdom.lb) || SCIPsetIsInfinity(set, oldbound)
12375 || SCIPsetIsFeasEQ(set, parentvar->locdom.lb,
12376 oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
12377 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
12378 {
12379 /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
12380 * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
12381 * as a result, the parent's lower bound is set to it's upper bound, and not above
12382 */
12383 if( parentnewbound > parentvar->glbdom.ub )
12384 {
12385 /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
12386 assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
12387 parentnewbound = parentvar->glbdom.ub;
12388 }
12389 }
12390 else
12391 parentnewbound = -newbound;
12392 SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
12393 }
12394 break;
12395 }
12396
12397 case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
12398 assert(parentvar->negatedvar != NULL);
12400 assert(parentvar->negatedvar->negatedvar == parentvar);
12401 SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
12402 parentvar->data.negate.constant - newbound) );
12403 break;
12404
12405 default:
12406 SCIPerrorMessage("unknown variable status\n");
12407 return SCIP_INVALIDDATA;
12408 }
12409 }
12410
12411 return SCIP_OKAY;
12412}
12413
12414/* forward declaration, because both methods call each other recursively */
12415
12416/* performs the current change in upper bound, changes all parents accordingly */
12417static
12419 SCIP_VAR* var, /**< problem variable to change */
12420 BMS_BLKMEM* blkmem, /**< block memory */
12421 SCIP_SET* set, /**< global SCIP settings */
12422 SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
12423 SCIP_LPEXACT* lpexact, /**< current exact LP data, may be NULL for original variables */
12424 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
12425 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
12426 SCIP_RATIONAL* newbound /**< new bound for variable */
12427 );
12428
12429/** performs the current change in lower bound, changes all parents accordingly */
12430static
12432 SCIP_VAR* var, /**< problem variable to change */
12433 BMS_BLKMEM* blkmem, /**< block memory */
12434 SCIP_SET* set, /**< global SCIP settings */
12435 SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
12436 SCIP_LPEXACT* lpexact, /**< current exact LP data, may be NULL for original variables */
12437 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
12438 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
12439 SCIP_RATIONAL* newbound /**< new bound for variable */
12440 )
12441{
12442 SCIP_VAR* parentvar;
12443 SCIP_RATIONAL* oldbound;
12444 SCIP_RATIONAL* parentnewbound;
12445 int i;
12446
12447 assert(var != NULL);
12448 assert(set != NULL);
12449 assert(var->scip == set->scip);
12451 || SCIPrationalIsEQ(newbound, var->exactdata->locdom.ub)))
12453 || SCIPrationalIsEQ(newbound, var->exactdata->locdom.ub)))
12454 || !SCIPvarIsIntegral(var));
12455
12456 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &oldbound) );
12457
12458 /* check that the bound is feasible */
12459 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPrationalIsLE(newbound, var->exactdata->glbdom.ub));
12460 /* adjust bound to integral value if variable is of integral type */
12462
12464 {
12465 /* we do not want to exceed the upper bound, which could have happened due to numerics */
12466 SCIPrationalMin(newbound, newbound, var->exactdata->locdom.ub);
12467
12468 /* we do not want to undercut the global lower bound, which could have happened due to numerics */
12469 SCIPrationalMax(newbound, newbound, var->exactdata->glbdom.lb);
12470 }
12472
12473 SCIPrationalDebugMessage("process changing lower bound of <%s> from %q to %q\n", var->name, var->exactdata->locdom.lb, newbound);
12474
12475 if( SCIPrationalIsEQ(newbound, var->exactdata->glbdom.lb) && !SCIPrationalIsEQ(var->exactdata->glbdom.lb, var->exactdata->locdom.lb) ) /*lint !e777*/
12476 SCIPrationalSetRational(newbound, var->exactdata->glbdom.lb);
12477
12478 /* change the bound */
12479 SCIPrationalSetRational(oldbound, var->exactdata->locdom.lb);
12480 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPrationalIsLE(newbound, var->exactdata->locdom.ub));
12481 SCIPrationalSetRational(var->exactdata->locdom.lb, newbound);
12482 var->locdom.lb = SCIPrationalRoundReal(newbound, SCIP_R_ROUND_DOWNWARDS);
12483
12484 /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
12485 * once update the statistic
12486 */
12487 if( stat != NULL )
12488 SCIPstatIncrement(stat, set, domchgcount);
12489
12490 /* issue bound change event */
12491 assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
12492 if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && var->eventfilter != NULL )
12493 {
12494 SCIP_CALL( varEventLbChangedExact(var, blkmem, set, lpexact, branchcand, eventqueue, oldbound, newbound) );
12495 }
12496
12497 /* process parent variables */
12498 for( i = 0; i < var->nparentvars; ++i )
12499 {
12500 parentvar = var->parentvars[i];
12501 assert(parentvar != NULL);
12502
12503 switch( SCIPvarGetStatus(parentvar) )
12504 {
12506 SCIP_CALL( varProcessChgLbLocalExact(parentvar, blkmem, set, NULL, lpexact, branchcand, eventqueue, newbound) );
12507 break;
12508
12513 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
12514 return SCIP_INVALIDDATA;
12515
12516 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12517 assert(parentvar->data.aggregate.var == var);
12518 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &parentnewbound) );
12520 {
12521 /* a > 0 -> change lower bound of y */
12522 if( !SCIPrationalIsAbsInfinity(newbound) )
12523 {
12524 SCIPrationalMult(parentnewbound, parentvar->exactdata->aggregate.scalar, newbound);
12525 SCIPrationalAdd(parentnewbound, parentnewbound, parentvar->exactdata->aggregate.constant);
12526 }
12527 else
12528 SCIPrationalSetRational(parentnewbound, newbound);
12529
12530 SCIP_CALL( varProcessChgLbLocalExact(parentvar, blkmem, set, NULL, lpexact, branchcand, eventqueue, parentnewbound) );
12531 }
12532 else
12533 {
12534 /* a < 0 -> change upper bound of y */
12535 if( !SCIPrationalIsAbsInfinity(newbound) )
12536 {
12537 SCIPrationalMult(parentnewbound, parentvar->exactdata->aggregate.scalar, newbound);
12538 SCIPrationalAdd(parentnewbound, parentnewbound, parentvar->exactdata->aggregate.constant);
12539 }
12540 else
12541 SCIPrationalNegate(parentnewbound, newbound);
12542
12543 SCIP_CALL( varProcessChgUbLocalExact(parentvar, blkmem, set, NULL, lpexact, branchcand, eventqueue, parentnewbound) );
12544 }
12545 SCIPrationalFreeBuffer(set->buffer, &parentnewbound);
12546 break;
12547
12548 case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
12549 assert(parentvar->negatedvar != NULL);
12551 assert(parentvar->negatedvar->negatedvar == parentvar);
12552 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &parentnewbound) );
12553 SCIPrationalDiffReal(parentnewbound, newbound, parentvar->data.negate.constant);
12554 SCIPrationalNegate(parentnewbound, parentnewbound);
12555 SCIP_CALL( varProcessChgUbLocalExact(parentvar, blkmem, set, NULL, lpexact, branchcand, eventqueue,
12556 parentnewbound) );
12557 SCIPrationalFreeBuffer(set->buffer, &parentnewbound);
12558 break;
12559
12560 default:
12561 SCIPerrorMessage("unknown variable status\n");
12562 return SCIP_INVALIDDATA;
12563 }
12564 }
12565
12566 SCIPrationalFreeBuffer(set->buffer, &oldbound);
12567
12568 return SCIP_OKAY;
12569}
12570
12571/** performs the current change in upper bound, changes all parents accordingly */
12572static
12574 SCIP_VAR* var, /**< problem variable to change */
12575 BMS_BLKMEM* blkmem, /**< block memory */
12576 SCIP_SET* set, /**< global SCIP settings */
12577 SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
12578 SCIP_LPEXACT* lpexact, /**< current exact LP data, may be NULL for original variables */
12579 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
12580 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
12581 SCIP_RATIONAL* newbound /**< new bound for variable */
12582 )
12583{
12584 SCIP_VAR* parentvar;
12585 SCIP_RATIONAL* oldbound;
12586 SCIP_RATIONAL* parentnewbound;
12587 int i;
12588
12589 assert(var != NULL);
12590 assert(set != NULL);
12591 assert(var->scip == set->scip);
12593 || SCIPrationalIsEQ(newbound, var->exactdata->locdom.ub)))
12595 || SCIPrationalIsEQ(newbound, var->exactdata->locdom.ub)))
12596 || !SCIPvarIsIntegral(var));
12597
12598 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &oldbound) );
12599
12600 /* check that the bound is feasible */
12601 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPrationalIsGE(newbound, var->exactdata->glbdom.lb));
12602 /* adjust bound to integral value if variable is of integral type */
12604
12606 {
12607 /* we do not want to exceed the upper bound, which could have happened due to numerics */
12608 SCIPrationalMax(newbound, newbound, var->exactdata->locdom.lb);
12609
12610 /* we do not want to undercut the global lower bound, which could have happened due to numerics */
12611 SCIPrationalMin(newbound, newbound, var->exactdata->glbdom.ub);
12612 }
12614
12615 SCIPrationalDebugMessage("process changing exact upper bound of <%s> from %q to %q\n", var->name, var->exactdata->locdom.ub, newbound);
12616
12617 if( SCIPrationalIsEQ(newbound, var->exactdata->glbdom.ub) && !SCIPrationalIsEQ(var->exactdata->glbdom.ub, var->exactdata->locdom.ub) ) /*lint !e777*/
12618 SCIPrationalSetRational(newbound, var->exactdata->glbdom.ub);
12619
12620 /* change the bound */
12621 SCIPrationalSetRational(oldbound, var->exactdata->locdom.ub);
12622 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPrationalIsGE(newbound, var->exactdata->locdom.lb));
12623 SCIPrationalSetRational(var->exactdata->locdom.ub, newbound);
12624 var->locdom.ub = SCIPrationalRoundReal(newbound, SCIP_R_ROUND_UPWARDS);
12625
12626 /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
12627 * once update the statistic
12628 */
12629 if( stat != NULL )
12630 SCIPstatIncrement(stat, set, domchgcount);
12631
12632 /* issue bound change event */
12633 assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
12634 if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && var->eventfilter != NULL )
12635 {
12636 SCIP_CALL( varEventUbChangedExact(var, blkmem, set, lpexact, branchcand, eventqueue, oldbound, newbound) );
12637 }
12638
12639 /* process parent variables */
12640 for( i = 0; i < var->nparentvars; ++i )
12641 {
12642 parentvar = var->parentvars[i];
12643 assert(parentvar != NULL);
12644
12645 switch( SCIPvarGetStatus(parentvar) )
12646 {
12648 SCIP_CALL( varProcessChgUbLocalExact(parentvar, blkmem, set, NULL, lpexact, branchcand, eventqueue, newbound) );
12649 break;
12650
12655 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
12656 return SCIP_INVALIDDATA;
12657
12658 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12659 assert(parentvar->data.aggregate.var == var);
12660 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &parentnewbound) );
12662 {
12663 /* a > 0 -> change upper bound of y */
12664 if( !SCIPrationalIsAbsInfinity(newbound) )
12665 {
12666 SCIPrationalMult(parentnewbound, parentvar->exactdata->aggregate.scalar, newbound);
12667 SCIPrationalAdd(parentnewbound, parentnewbound, parentvar->exactdata->aggregate.constant);
12668 }
12669 else
12670 SCIPrationalSetRational(parentnewbound, newbound);
12671
12672 SCIP_CALL( varProcessChgUbLocalExact(parentvar, blkmem, set, NULL, lpexact, branchcand, eventqueue, parentnewbound) );
12673 }
12674 else
12675 {
12676 /* a < 0 -> change lower bound of y */
12677 if( !SCIPrationalIsAbsInfinity(newbound) )
12678 {
12679 SCIPrationalMult(parentnewbound, parentvar->exactdata->aggregate.scalar, newbound);
12680 SCIPrationalAdd(parentnewbound, parentnewbound, parentvar->exactdata->aggregate.constant);
12681 }
12682 else
12683 SCIPrationalNegate(parentnewbound, newbound);
12684
12685 SCIP_CALL( varProcessChgLbLocalExact(parentvar, blkmem, set, NULL, lpexact, branchcand, eventqueue, parentnewbound) );
12686 }
12687 SCIPrationalFreeBuffer(set->buffer, &parentnewbound);
12688 break;
12689
12690 case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
12691 assert(parentvar->negatedvar != NULL);
12693 assert(parentvar->negatedvar->negatedvar == parentvar);
12694 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &parentnewbound) );
12695 SCIPrationalDiffReal(parentnewbound, newbound, parentvar->data.negate.constant);
12696 SCIPrationalNegate(parentnewbound, parentnewbound);
12697 SCIP_CALL( varProcessChgLbLocalExact(parentvar, blkmem, set, NULL, lpexact, branchcand, eventqueue,
12698 parentnewbound) );
12699 SCIPrationalFreeBuffer(set->buffer, &parentnewbound);
12700 break;
12701
12702 default:
12703 SCIPerrorMessage("unknown variable status\n");
12704 return SCIP_INVALIDDATA;
12705 }
12706 }
12707
12708 SCIPrationalFreeBuffer(set->buffer, &oldbound);
12709
12710 return SCIP_OKAY;
12711}
12712
12713/** changes current local lower bound of variable; if possible, adjusts bound to integral value; stores inference
12714 * information in variable
12715 */
12717 SCIP_VAR* var, /**< problem variable to change */
12718 BMS_BLKMEM* blkmem, /**< block memory */
12719 SCIP_SET* set, /**< global SCIP settings */
12720 SCIP_STAT* stat, /**< problem statistics */
12721 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
12722 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
12723 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
12724 SCIP_Real newbound /**< new bound for variable */
12725 )
12726{
12727 assert(var != NULL);
12728 assert(blkmem != NULL);
12729 assert(set != NULL);
12730 assert(var->scip == set->scip);
12731
12732 /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
12733 * of the domain within feastol
12734 */
12735 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
12736
12737 /* adjust bound to integral value if variable is of integral type */
12738 newbound = adjustedLb(set, SCIPvarIsIntegral(var), newbound);
12739
12740 /* check that the adjusted bound is feasible */
12741 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
12742
12744 {
12745 /* we do not want to exceed the upperbound, which could have happened due to numerics */
12746 newbound = MIN(newbound, var->locdom.ub);
12747 }
12749
12750 SCIPsetDebugMsg(set, "changing lower bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
12751
12752 if( SCIPsetIsEQ(set, var->locdom.lb, newbound) && (!SCIPsetIsEQ(set, var->glbdom.lb, newbound) || var->locdom.lb == newbound) /*lint !e777*/
12753 && !(newbound != var->locdom.lb && newbound * var->locdom.lb <= 0.0) ) /*lint !e777*/
12754 return SCIP_OKAY;
12755
12758
12759 /* change bounds of attached variables */
12760 switch( SCIPvarGetStatus(var) )
12761 {
12763 if( var->data.original.transvar != NULL )
12764 {
12765 SCIP_CALL( SCIPvarChgLbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
12766 newbound) );
12767 }
12768 else
12769 {
12770 assert(set->stage == SCIP_STAGE_PROBLEM);
12771 SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
12772 }
12773 break;
12774
12777 SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
12778 break;
12779
12781 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
12782 return SCIP_INVALIDDATA;
12783
12784 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12785 {
12786 SCIP_Real childnewbound;
12787 assert(var->data.aggregate.var != NULL);
12788
12789 if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
12790 {
12791 /* a > 0 -> change lower bound of y */
12792 assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, -var->data.aggregate.var->locdom.lb))
12793 || SCIPsetIsFeasEQ(set, var->locdom.lb,
12794 var->data.aggregate.var->locdom.lb * var->data.aggregate.scalar + var->data.aggregate.constant));
12795 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
12796 childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
12797 else
12798 childnewbound = newbound;
12799 SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
12800 childnewbound) );
12801 }
12802 else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
12803 {
12804 /* a < 0 -> change upper bound of y */
12805 assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->locdom.ub))
12806 || SCIPsetIsFeasEQ(set, var->locdom.lb,
12807 var->data.aggregate.var->locdom.ub * var->data.aggregate.scalar + var->data.aggregate.constant));
12808 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
12809 childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
12810 else
12811 childnewbound = -newbound;
12812 SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
12813 childnewbound) );
12814 }
12815 else
12816 {
12817 SCIPerrorMessage("scalar is zero in aggregation\n");
12818 return SCIP_INVALIDDATA;
12819 }
12820 break;
12821 }
12822
12824 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
12825 return SCIP_INVALIDDATA;
12826
12827 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12828 assert(var->negatedvar != NULL);
12830 assert(var->negatedvar->negatedvar == var);
12831 SCIP_CALL( SCIPvarChgUbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
12832 var->data.negate.constant - newbound) );
12833 break;
12834
12835 default:
12836 SCIPerrorMessage("unknown variable status\n");
12837 return SCIP_INVALIDDATA;
12838 }
12839
12840 return SCIP_OKAY;
12841}
12842
12843/** changes current local lower bound of variable; if possible, adjusts bound to integral value; stores inference
12844 * information in variable
12845 */
12847 SCIP_VAR* var, /**< problem variable to change */
12848 BMS_BLKMEM* blkmem, /**< block memory */
12849 SCIP_SET* set, /**< global SCIP settings */
12850 SCIP_STAT* stat, /**< problem statistics */
12851 SCIP_LPEXACT* lpexact, /**< current exact LP data, may be NULL for original variables */
12852 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
12853 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
12854 SCIP_RATIONAL* newbound /**< new bound for variable */
12855 )
12856{
12857 assert(var != NULL);
12858 assert(blkmem != NULL);
12859 assert(set != NULL);
12860 assert(var->scip == set->scip);
12861
12862 /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
12863 * of the domain within feastol
12864 */
12865 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPrationalIsGT(newbound, var->exactdata->locdom.ub));
12866
12867 /* adjust bound to integral value if variable is of integral type */
12869
12870 /* check that the adjusted bound is feasible */
12871 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPrationalIsGT(newbound, var->exactdata->locdom.ub));
12872
12874 {
12875 /* we do not want to exceed the upperbound, which could have happened due to numerics */
12876 SCIPrationalMin(newbound, newbound, var->exactdata->locdom.ub);
12877 }
12879
12880 SCIPrationalDebugMessage("changing lower bound of <%s>[%q,%q] to %q\n", var->name, var->exactdata->locdom.lb, var->exactdata->locdom.ub, newbound);
12881
12884
12885 /* change bounds of attached variables */
12886 switch( SCIPvarGetStatusExact(var) )
12887 {
12889 if( var->data.original.transvar != NULL )
12890 {
12891 SCIP_CALL( SCIPvarChgLbLocalExact(var->data.original.transvar, blkmem, set, stat, lpexact, branchcand, eventqueue,
12892 newbound) );
12893 }
12894 else
12895 {
12896 assert(set->stage == SCIP_STAGE_PROBLEM);
12897 SCIP_CALL( varProcessChgLbLocalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, newbound) );
12898 }
12899 break;
12900
12903 SCIP_CALL( varProcessChgLbLocalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, newbound) );
12904 break;
12905
12907 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
12908 return SCIP_INVALIDDATA;
12909
12910 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12911 assert(var->data.aggregate.var != NULL);
12912 if( SCIPrationalIsPositive(var->exactdata->aggregate.scalar) )
12913 {
12914 SCIP_RATIONAL* childnewbound;
12915
12916 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &childnewbound) );
12917
12918 /* a > 0 -> change lower bound of y */
12919 if( !SCIPrationalIsNegInfinity(newbound) && !SCIPrationalIsInfinity(newbound) )
12920 {
12921 SCIPrationalDiff(childnewbound, newbound, var->exactdata->aggregate.constant);
12922 SCIPrationalDiv(childnewbound, childnewbound, var->exactdata->aggregate.scalar);
12923 }
12924 else
12925 SCIPrationalSetRational(childnewbound, newbound);
12926
12927 SCIP_CALL( SCIPvarChgLbLocalExact(var->data.aggregate.var, blkmem, set, stat, lpexact, branchcand, eventqueue,
12928 childnewbound) );
12929
12930 SCIPrationalFreeBuffer(set->buffer, &childnewbound);
12931 }
12932 else if( SCIPrationalIsNegative(var->exactdata->aggregate.scalar) )
12933 {
12934 SCIP_RATIONAL* childnewbound;
12935
12936 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &childnewbound) );
12937
12938 /* a < 0 -> change upper bound of y */
12939 if( !SCIPrationalIsNegInfinity(newbound) && !SCIPrationalIsInfinity(newbound) )
12940 {
12941 SCIPrationalDiff(childnewbound, newbound, var->exactdata->aggregate.constant);
12942 SCIPrationalDiv(childnewbound, childnewbound, var->exactdata->aggregate.scalar);
12943 }
12944 else
12945 SCIPrationalNegate(childnewbound, newbound);
12946
12947 SCIP_CALL( SCIPvarChgUbLocalExact(var->data.aggregate.var, blkmem, set, stat, lpexact, branchcand, eventqueue,
12948 childnewbound) );
12949
12950 SCIPrationalFreeBuffer(set->buffer, &childnewbound);
12951 }
12952 else
12953 {
12954 SCIPerrorMessage("scalar is zero in aggregation\n");
12955 return SCIP_INVALIDDATA;
12956 }
12957 break;
12958
12960 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
12961 return SCIP_INVALIDDATA;
12962
12963 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12964 assert(var->negatedvar != NULL);
12966 assert(var->negatedvar->negatedvar == var);
12967 SCIPrationalDiffReal(newbound, newbound, var->data.negate.constant);
12968 SCIPrationalNegate(newbound, newbound);
12969 SCIP_CALL( SCIPvarChgUbLocalExact(var->negatedvar, blkmem, set, stat, lpexact, branchcand, eventqueue,
12970 newbound) );
12971 break;
12972
12973 default:
12974 SCIPerrorMessage("unknown variable status\n");
12975 return SCIP_INVALIDDATA;
12976 }
12977
12978 return SCIP_OKAY;
12979}
12980
12981/** changes current local upper bound of variable; if possible, adjusts bound to integral value; stores inference
12982 * information in variable
12983 */
12985 SCIP_VAR* var, /**< problem variable to change */
12986 BMS_BLKMEM* blkmem, /**< block memory */
12987 SCIP_SET* set, /**< global SCIP settings */
12988 SCIP_STAT* stat, /**< problem statistics */
12989 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
12990 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
12991 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
12992 SCIP_Real newbound /**< new bound for variable */
12993 )
12994{
12995 assert(var != NULL);
12996 assert(blkmem != NULL);
12997 assert(set != NULL);
12998 assert(var->scip == set->scip);
12999
13000 /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
13001 * of the domain within feastol
13002 */
13003 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
13004
13005 /* adjust bound to integral value if variable is of integral type */
13006 newbound = adjustedUb(set, SCIPvarIsIntegral(var), newbound);
13007
13008 /* check that the adjusted bound is feasible */
13009 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
13010
13012 {
13013 /* we do not want to undercut the lowerbound, which could have happened due to numerics */
13014 newbound = MAX(newbound, var->locdom.lb);
13015 }
13017
13018 SCIPsetDebugMsg(set, "changing upper bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
13019
13020 if( SCIPsetIsEQ(set, var->locdom.ub, newbound) && (!SCIPsetIsEQ(set, var->glbdom.ub, newbound) || var->locdom.ub == newbound) /*lint !e777*/
13021 && !(newbound != var->locdom.ub && newbound * var->locdom.ub <= 0.0) ) /*lint !e777*/
13022 return SCIP_OKAY;
13023
13026
13027 /* change bounds of attached variables */
13028 switch( SCIPvarGetStatus(var) )
13029 {
13031 if( var->data.original.transvar != NULL )
13032 {
13033 SCIP_CALL( SCIPvarChgUbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
13034 }
13035 else
13036 {
13037 assert(set->stage == SCIP_STAGE_PROBLEM);
13038 SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
13039 }
13040 break;
13041
13044 SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
13045 break;
13046
13048 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
13049 return SCIP_INVALIDDATA;
13050
13051 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
13052 {
13053 SCIP_Real childnewbound;
13054 assert(var->data.aggregate.var != NULL);
13055
13056 if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
13057 {
13058 /* a > 0 -> change upper bound of y */
13059 assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, var->data.aggregate.var->locdom.ub))
13060 || SCIPsetIsFeasEQ(set, var->locdom.ub,
13061 var->data.aggregate.var->locdom.ub * var->data.aggregate.scalar + var->data.aggregate.constant));
13062 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
13063 childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
13064 else
13065 childnewbound = newbound;
13066 SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
13067 childnewbound) );
13068 }
13069 else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
13070 {
13071 /* a < 0 -> change lower bound of y */
13072 assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, -var->data.aggregate.var->locdom.lb))
13073 || SCIPsetIsFeasEQ(set, var->locdom.ub,
13074 var->data.aggregate.var->locdom.lb * var->data.aggregate.scalar + var->data.aggregate.constant));
13075 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
13076 childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
13077 else
13078 childnewbound = -newbound;
13079 SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
13080 childnewbound) );
13081 }
13082 else
13083 {
13084 SCIPerrorMessage("scalar is zero in aggregation\n");
13085 return SCIP_INVALIDDATA;
13086 }
13087 break;
13088 }
13089
13091 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
13092 return SCIP_INVALIDDATA;
13093
13094 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13095 assert(var->negatedvar != NULL);
13097 assert(var->negatedvar->negatedvar == var);
13098 SCIP_CALL( SCIPvarChgLbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
13099 var->data.negate.constant - newbound) );
13100 break;
13101
13102 default:
13103 SCIPerrorMessage("unknown variable status\n");
13104 return SCIP_INVALIDDATA;
13105 }
13106
13107 return SCIP_OKAY;
13108}
13109
13110/** changes current exact local upper bound of variable; if possible, adjusts bound to integral value; stores inference
13111 * information in variable
13112 */
13114 SCIP_VAR* var, /**< problem variable to change */
13115 BMS_BLKMEM* blkmem, /**< block memory */
13116 SCIP_SET* set, /**< global SCIP settings */
13117 SCIP_STAT* stat, /**< problem statistics */
13118 SCIP_LPEXACT* lpexact, /**< current exact LP data, may be NULL for original variables */
13119 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
13120 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
13121 SCIP_RATIONAL* newbound /**< new bound for variable */
13122 )
13123{
13124 assert(var != NULL);
13125 assert(blkmem != NULL);
13126 assert(set != NULL);
13127 assert(var->scip == set->scip);
13128
13129 /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
13130 * of the domain within feastol
13131 */
13132 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPrationalIsLT(newbound, var->exactdata->locdom.lb));
13133
13134 /* adjust bound to integral value if variable is of integral type */
13136
13137 /* check that the adjusted bound is feasible */
13138 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPrationalIsLT(newbound, var->exactdata->locdom.lb));
13139
13141 {
13142 /* we do not want to undercut the lowerbound, which could have happened due to numerics */
13143 SCIPrationalMax(newbound, newbound, var->exactdata->locdom.lb);
13144 }
13146
13147 SCIPrationalDebugMessage("changing upper bound of <%s>[%q,%q] to %q\n", var->name, var->exactdata->locdom.lb, var->exactdata->locdom.ub, newbound);
13148
13151
13152 /* change bounds of attached variables */
13153 switch( SCIPvarGetStatusExact(var) )
13154 {
13156 if( var->data.original.transvar != NULL )
13157 {
13158 SCIP_CALL( SCIPvarChgUbLocalExact(var->data.original.transvar, blkmem, set, stat, lpexact, branchcand, eventqueue,
13159 newbound) );
13160 }
13161 else
13162 {
13163 assert(set->stage == SCIP_STAGE_PROBLEM);
13164 SCIP_CALL( varProcessChgUbLocalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, newbound) );
13165 }
13166 break;
13167
13170 SCIP_CALL( varProcessChgUbLocalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, newbound) );
13171 break;
13172
13174 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
13175 return SCIP_INVALIDDATA;
13176
13177 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
13178 assert(var->data.aggregate.var != NULL);
13179 if( SCIPrationalIsPositive(var->exactdata->aggregate.scalar) )
13180 {
13181 SCIP_RATIONAL* childnewbound;
13182
13183 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &childnewbound) );
13184
13185 /* a > 0 -> change upper bound of y */
13186 if( !SCIPrationalIsNegInfinity(newbound) && !SCIPrationalIsInfinity(newbound) )
13187 {
13188 SCIPrationalDiff(childnewbound, newbound, var->exactdata->aggregate.constant);
13189 SCIPrationalDiv(childnewbound, childnewbound, var->exactdata->aggregate.scalar);
13190 }
13191 else
13192 SCIPrationalSetRational(childnewbound, newbound);
13193 SCIP_CALL( SCIPvarChgUbLocalExact(var->data.aggregate.var, blkmem, set, stat, lpexact, branchcand, eventqueue,
13194 childnewbound) );
13195
13196 SCIPrationalFreeBuffer(set->buffer, &childnewbound);
13197 }
13198 else if( SCIPrationalIsNegative(var->exactdata->aggregate.scalar) )
13199 {
13200 SCIP_RATIONAL* childnewbound;
13201
13202 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &childnewbound) );
13203
13204 /* a < 0 -> change lower bound of y */
13205 if( !SCIPrationalIsNegInfinity(newbound) && !SCIPrationalIsInfinity(newbound) )
13206 {
13207 SCIPrationalDiff(childnewbound, newbound, var->exactdata->aggregate.constant);
13208 SCIPrationalDiv(childnewbound, childnewbound, var->exactdata->aggregate.scalar);
13209 }
13210 else
13211 SCIPrationalNegate(childnewbound, newbound);
13212
13213 SCIP_CALL( SCIPvarChgLbLocalExact(var->data.aggregate.var, blkmem, set, stat, lpexact, branchcand, eventqueue,
13214 childnewbound) );
13215
13216 SCIPrationalFreeBuffer(set->buffer, &childnewbound);
13217 }
13218 else
13219 {
13220 SCIPerrorMessage("scalar is zero in aggregation\n");
13221 return SCIP_INVALIDDATA;
13222 }
13223 break;
13224
13226 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
13227 return SCIP_INVALIDDATA;
13228
13229 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13230 assert(var->negatedvar != NULL);
13232 assert(var->negatedvar->negatedvar == var);
13233 SCIPrationalDiffReal(newbound, newbound, var->data.negate.constant);
13234 SCIPrationalNegate(newbound, newbound);
13235 SCIP_CALL( SCIPvarChgLbLocalExact(var->negatedvar, blkmem, set, stat, lpexact, branchcand, eventqueue,
13236 newbound) );
13237 break;
13238
13239 default:
13240 SCIPerrorMessage("unknown variable status\n");
13241 return SCIP_INVALIDDATA;
13242 }
13243
13244 return SCIP_OKAY;
13245}
13246
13247/** changes current local bound of variable; if possible, adjusts bound to integral value; stores inference
13248 * information in variable
13249 */
13251 SCIP_VAR* var, /**< problem variable to change */
13252 BMS_BLKMEM* blkmem, /**< block memory */
13253 SCIP_SET* set, /**< global SCIP settings */
13254 SCIP_STAT* stat, /**< problem statistics */
13255 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
13256 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
13257 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
13258 SCIP_Real newbound, /**< new bound for variable */
13259 SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
13260 )
13261{
13262 /* apply bound change to the LP data */
13263 switch( boundtype )
13264 {
13266 return SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
13268 return SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
13269 default:
13270 SCIPerrorMessage("unknown bound type\n");
13271 return SCIP_INVALIDDATA;
13272 }
13273}
13274
13275/** changes lower bound of variable in current dive; if possible, adjusts bound to integral value */
13277 SCIP_VAR* var, /**< problem variable to change */
13278 SCIP_SET* set, /**< global SCIP settings */
13279 SCIP_LP* lp, /**< current LP data */
13280 SCIP_Real newbound /**< new bound for variable */
13281 )
13282{
13283 assert(var != NULL);
13284 assert(set != NULL);
13285 assert(var->scip == set->scip);
13286 assert(lp != NULL);
13287 assert(SCIPlpDiving(lp));
13288
13289 /* adjust bound for integral variables */
13290 SCIPvarAdjustLb(var, set, &newbound);
13291
13292 SCIPsetDebugMsg(set, "changing lower bound of <%s> to %g in current dive\n", var->name, newbound);
13293
13294 /* change bounds of attached variables */
13295 switch( SCIPvarGetStatus(var) )
13296 {
13298 assert(var->data.original.transvar != NULL);
13299 SCIP_CALL( SCIPvarChgLbDive(var->data.original.transvar, set, lp, newbound) );
13300 break;
13301
13303 assert(var->data.col != NULL);
13304 SCIP_CALL( SCIPcolChgLb(var->data.col, set, lp, newbound) );
13305 break;
13306
13308 SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
13309 return SCIP_INVALIDDATA;
13310
13312 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
13313 return SCIP_INVALIDDATA;
13314
13315 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
13316 assert(var->data.aggregate.var != NULL);
13317 if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
13318 {
13319 SCIP_Real childnewbound;
13320
13321 /* a > 0 -> change lower bound of y */
13322 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
13323 childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
13324 else
13325 childnewbound = newbound;
13326 SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
13327 }
13328 else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
13329 {
13330 SCIP_Real childnewbound;
13331
13332 /* a < 0 -> change upper bound of y */
13333 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
13334 childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
13335 else
13336 childnewbound = -newbound;
13337 SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
13338 }
13339 else
13340 {
13341 SCIPerrorMessage("scalar is zero in aggregation\n");
13342 return SCIP_INVALIDDATA;
13343 }
13344 break;
13345
13347 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
13348 return SCIP_INVALIDDATA;
13349
13350 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13351 assert(var->negatedvar != NULL);
13353 assert(var->negatedvar->negatedvar == var);
13354 SCIP_CALL( SCIPvarChgUbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
13355 break;
13356
13357 default:
13358 SCIPerrorMessage("unknown variable status\n");
13359 return SCIP_INVALIDDATA;
13360 }
13361
13362 return SCIP_OKAY;
13363}
13364
13365/** changes lower bound of variable in current exact dive */
13367 SCIP_VAR* var, /**< problem variable to change */
13368 SCIP_SET* set, /**< global SCIP settings */
13369 SCIP_LPEXACT* lpexact, /**< current exact LP data */
13370 SCIP_RATIONAL* newbound /**< new bound for variable */
13371 )
13372{
13373 assert(var != NULL);
13374 assert(set != NULL);
13375 assert(var->scip == set->scip);
13376 assert(lpexact != NULL);
13377 assert(SCIPlpExactDiving(lpexact));
13378
13379 SCIPrationalDebugMessage("changing lower bound of <%s> to %q in current exact dive\n", var->name, newbound);
13380
13381 /* change bounds of attached variables */
13382 switch( SCIPvarGetStatusExact(var) )
13383 {
13385 assert(var->data.original.transvar != NULL);
13386 SCIP_CALL( SCIPvarChgLbExactDive(var->data.original.transvar, set, lpexact, newbound) );
13387 break;
13388
13390 assert(var->data.col != NULL);
13391 SCIP_CALL( SCIPcolExactChgLb(var->exactdata->colexact, set, lpexact, newbound) );
13392 break;
13393
13395 SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
13396 return SCIP_INVALIDDATA;
13397
13399 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
13400 return SCIP_INVALIDDATA;
13401
13402 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
13403 SCIPerrorMessage("cannot change the bounds of an aggregated variable\n");
13404 return SCIP_INVALIDDATA;
13405
13407 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable\n");
13408 return SCIP_INVALIDDATA;
13409
13410 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13411 SCIPerrorMessage("cannot change the bounds of a negated variable\n");
13412 return SCIP_INVALIDDATA;
13413
13414 default:
13415 SCIPerrorMessage("unknown variable status\n");
13416 return SCIP_INVALIDDATA;
13417 }
13418
13419 return SCIP_OKAY;
13420}
13421
13422/** changes upper bound of variable in current dive; if possible, adjusts bound to integral value */
13424 SCIP_VAR* var, /**< problem variable to change */
13425 SCIP_SET* set, /**< global SCIP settings */
13426 SCIP_LP* lp, /**< current LP data */
13427 SCIP_Real newbound /**< new bound for variable */
13428 )
13429{
13430 assert(var != NULL);
13431 assert(set != NULL);
13432 assert(var->scip == set->scip);
13433 assert(lp != NULL);
13434 assert(SCIPlpDiving(lp));
13435
13436 /* adjust bound for integral variables */
13437 SCIPvarAdjustUb(var, set, &newbound);
13438
13439 SCIPsetDebugMsg(set, "changing upper bound of <%s> to %g in current dive\n", var->name, newbound);
13440
13441 /* change bounds of attached variables */
13442 switch( SCIPvarGetStatus(var) )
13443 {
13445 assert(var->data.original.transvar != NULL);
13446 SCIP_CALL( SCIPvarChgUbDive(var->data.original.transvar, set, lp, newbound) );
13447 break;
13448
13450 assert(var->data.col != NULL);
13451 SCIP_CALL( SCIPcolChgUb(var->data.col, set, lp, newbound) );
13452 break;
13453
13455 SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
13456 return SCIP_INVALIDDATA;
13457
13459 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
13460 return SCIP_INVALIDDATA;
13461
13462 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
13463 assert(var->data.aggregate.var != NULL);
13464 if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
13465 {
13466 SCIP_Real childnewbound;
13467
13468 /* a > 0 -> change upper bound of y */
13469 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
13470 childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
13471 else
13472 childnewbound = newbound;
13473 SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
13474 }
13475 else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
13476 {
13477 SCIP_Real childnewbound;
13478
13479 /* a < 0 -> change lower bound of y */
13480 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
13481 childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
13482 else
13483 childnewbound = -newbound;
13484 SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
13485 }
13486 else
13487 {
13488 SCIPerrorMessage("scalar is zero in aggregation\n");
13489 return SCIP_INVALIDDATA;
13490 }
13491 break;
13492
13494 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
13495 return SCIP_INVALIDDATA;
13496
13497 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13498 assert(var->negatedvar != NULL);
13500 assert(var->negatedvar->negatedvar == var);
13501 SCIP_CALL( SCIPvarChgLbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
13502 break;
13503
13504 default:
13505 SCIPerrorMessage("unknown variable status\n");
13506 return SCIP_INVALIDDATA;
13507 }
13508
13509 return SCIP_OKAY;
13510}
13511
13512/** changes upper bound of variable in current exact dive */
13514 SCIP_VAR* var, /**< problem variable to change */
13515 SCIP_SET* set, /**< global SCIP settings */
13516 SCIP_LPEXACT* lpexact, /**< current exact LP data */
13517 SCIP_RATIONAL* newbound /**< new bound for variable */
13518 )
13519{
13520 assert(var != NULL);
13521 assert(set != NULL);
13522 assert(var->scip == set->scip);
13523 assert(lpexact != NULL);
13524 assert(SCIPlpExactDiving(lpexact));
13525
13526 SCIPrationalDebugMessage("changing upper bound of <%s> to %d in current dive\n", var->name, newbound);
13527
13528 /* change bounds of attached variables */
13529 switch( SCIPvarGetStatusExact(var) )
13530 {
13532 assert(var->data.original.transvar != NULL);
13533 SCIP_CALL( SCIPvarChgUbExactDive(var->data.original.transvar, set, lpexact, newbound) );
13534 break;
13535
13537 assert(var->data.col != NULL);
13538 SCIP_CALL( SCIPcolExactChgUb(var->exactdata->colexact, set, lpexact, newbound) );
13539 break;
13540
13542 SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
13543 return SCIP_INVALIDDATA;
13544
13546 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
13547 return SCIP_INVALIDDATA;
13548
13549 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
13550 SCIPerrorMessage("cannot change the bounds of an aggregated variable\n");
13551 return SCIP_INVALIDDATA;
13552
13554 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
13555 return SCIP_INVALIDDATA;
13556
13557 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13558 SCIPerrorMessage("cannot change the bounds of a negated variable\n");
13559 return SCIP_INVALIDDATA;
13560
13561 default:
13562 SCIPerrorMessage("unknown variable status\n");
13563 return SCIP_INVALIDDATA;
13564 }
13565
13566 return SCIP_OKAY;
13567}
13568
13569/** for a multi-aggregated variable, gives the local lower bound computed by adding the local bounds from all
13570 * aggregation variables, this lower bound may be tighter than the one given by SCIPvarGetLbLocal, since the latter is
13571 * not updated if bounds of aggregation variables are changing
13572 *
13573 * calling this function for a non-multi-aggregated variable is not allowed
13574 */
13576 SCIP_VAR* var, /**< problem variable */
13577 SCIP_SET* set /**< global SCIP settings */
13578 )
13579{
13580 int i;
13581 SCIP_Real lb;
13582 SCIP_Real bnd;
13583 SCIP_VAR* aggrvar;
13584 SCIP_Bool posinf;
13585 SCIP_Bool neginf;
13586
13587 assert(var != NULL);
13588 assert(set != NULL);
13589 assert(var->scip == set->scip);
13591
13592 posinf = FALSE;
13593 neginf = FALSE;
13594 lb = var->data.multaggr.constant;
13595 for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
13596 {
13597 aggrvar = var->data.multaggr.vars[i];
13598 if( var->data.multaggr.scalars[i] > 0.0 )
13599 {
13601
13602 if( SCIPsetIsInfinity(set, bnd) )
13603 posinf = TRUE;
13604 else if( SCIPsetIsInfinity(set, -bnd) )
13605 neginf = TRUE;
13606 else
13607 lb += var->data.multaggr.scalars[i] * bnd;
13608 }
13609 else
13610 {
13612
13613 if( SCIPsetIsInfinity(set, -bnd) )
13614 posinf = TRUE;
13615 else if( SCIPsetIsInfinity(set, bnd) )
13616 neginf = TRUE;
13617 else
13618 lb += var->data.multaggr.scalars[i] * bnd;
13619 }
13620
13621 /* stop if two diffrent infinities (or a -infinity) were found and return local lower bound of multi aggregated
13622 * variable
13623 */
13624 if( neginf )
13625 return SCIPvarGetLbLocal(var);
13626 }
13627
13628 /* if positive infinity flag was set to true return infinity */
13629 if( posinf )
13630 return SCIPsetInfinity(set);
13631
13632 return (MAX(lb, SCIPvarGetLbLocal(var))); /*lint !e666*/
13633}
13634
13635/** for a multi-aggregated variable, gives the exact local lower bound computed by adding the local bounds from all aggregation variables
13636 * this lower bound may be tighter than the one given by SCIPvarGetLbLocal, since the latter is not updated if bounds of aggregation variables are changing
13637 * calling this function for a non-multi-aggregated variable is not allowed
13638 */
13640 SCIP_VAR* var, /**< problem variable */
13641 SCIP_SET* set, /**< global SCIP settings */
13642 SCIP_RATIONAL* result /**< the resulting bound */
13643 )
13644{
13645 int i;
13646 SCIP_RATIONAL* lb;
13647 SCIP_RATIONAL* bnd;
13648 SCIP_VAR* aggrvar;
13649 SCIP_Bool posinf;
13650 SCIP_Bool neginf;
13651
13652 assert(var != NULL);
13653 assert(set != NULL);
13654 assert(var->scip == set->scip);
13656
13657 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &lb) );
13658 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &bnd) );
13659
13660 posinf = FALSE;
13661 neginf = FALSE;
13662 SCIPrationalSetRational(lb, var->exactdata->multaggr.constant);
13663 for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
13664 {
13665 aggrvar = var->data.multaggr.vars[i];
13666 if( SCIPrationalIsPositive(var->exactdata->multaggr.scalars[i]) )
13667 {
13670 else
13672
13673 if( SCIPrationalIsInfinity(bnd) )
13674 posinf = TRUE;
13675 else if( SCIPrationalIsNegInfinity(bnd) )
13676 neginf = TRUE;
13677 else
13678 SCIPrationalAddProd(lb, var->exactdata->multaggr.scalars[i], bnd);
13679 }
13680 else
13681 {
13684 else
13686
13687 if( SCIPrationalIsNegInfinity(bnd) )
13688 posinf = TRUE;
13689 else if( SCIPrationalIsInfinity(bnd) )
13690 neginf = TRUE;
13691 else
13692 SCIPrationalAddProd(lb, var->exactdata->multaggr.scalars[i], bnd);
13693 }
13694
13695 /* stop if two diffrent infinities (or a -infinity) were found and return local lower bound of multi aggregated
13696 * variable
13697 */
13698 if( neginf )
13699 {
13701 break;
13702 }
13703 }
13704
13705 /* if positive infinity flag was set to true return infinity */
13706 if( posinf && !neginf )
13708 else
13710
13711 SCIPrationalFreeBuffer(set->buffer, &bnd);
13712 SCIPrationalFreeBuffer(set->buffer, &lb);
13713
13714 return SCIP_OKAY;
13715}
13716
13717/** for a multi-aggregated variable, gives the local upper bound computed by adding the local bounds from all
13718 * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbLocal, since the latter is
13719 * not updated if bounds of aggregation variables are changing
13720 *
13721 * calling this function for a non-multi-aggregated variable is not allowed
13722 */
13724 SCIP_VAR* var, /**< problem variable */
13725 SCIP_SET* set /**< global SCIP settings */
13726 )
13727{
13728 int i;
13729 SCIP_Real ub;
13730 SCIP_Real bnd;
13731 SCIP_VAR* aggrvar;
13732 SCIP_Bool posinf;
13733 SCIP_Bool neginf;
13734
13735 assert(var != NULL);
13736 assert(set != NULL);
13737 assert(var->scip == set->scip);
13739
13740 posinf = FALSE;
13741 neginf = FALSE;
13742 ub = var->data.multaggr.constant;
13743 for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
13744 {
13745 aggrvar = var->data.multaggr.vars[i];
13746 if( var->data.multaggr.scalars[i] > 0.0 )
13747 {
13749
13750 if( SCIPsetIsInfinity(set, bnd) )
13751 posinf = TRUE;
13752 else if( SCIPsetIsInfinity(set, -bnd) )
13753 neginf = TRUE;
13754 else
13755 ub += var->data.multaggr.scalars[i] * bnd;
13756 }
13757 else
13758 {
13760
13761 if( SCIPsetIsInfinity(set, -bnd) )
13762 posinf = TRUE;
13763 else if( SCIPsetIsInfinity(set, bnd) )
13764 neginf = TRUE;
13765 else
13766 ub += var->data.multaggr.scalars[i] * bnd;
13767 }
13768
13769 /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
13770 * variable
13771 */
13772 if( posinf )
13773 return SCIPvarGetUbLocal(var);
13774 }
13775
13776 /* if negative infinity flag was set to true return -infinity */
13777 if( neginf )
13778 return -SCIPsetInfinity(set);
13779
13780 return (MIN(ub, SCIPvarGetUbLocal(var))); /*lint !e666*/
13781}
13782
13783/** for a multi-aggregated variable, gives the exact local upper bound computed by adding the local bounds from all aggregation variables
13784 * this upper bound may be tighter than the one given by SCIPvarGetLbLocal, since the latter is not updated if bounds of aggregation variables are changing
13785 * calling this function for a non-multi-aggregated variable is not allowed
13786 */
13788 SCIP_VAR* var, /**< problem variable */
13789 SCIP_SET* set, /**< global SCIP settings */
13790 SCIP_RATIONAL* result /**< the resulting bound */
13791 )
13792{
13793 int i;
13794 SCIP_RATIONAL* ub;
13795 SCIP_RATIONAL* bnd;
13796 SCIP_VAR* aggrvar;
13797 SCIP_Bool posinf;
13798 SCIP_Bool neginf;
13799
13800 assert(var != NULL);
13801 assert(set != NULL);
13802 assert(var->scip == set->scip);
13804
13805 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &ub) );
13806 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &bnd) );
13807
13808 posinf = FALSE;
13809 neginf = FALSE;
13810 SCIPrationalSetRational(ub, var->exactdata->multaggr.constant);
13811 for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
13812 {
13813 aggrvar = var->data.multaggr.vars[i];
13814 if( SCIPrationalIsPositive(var->exactdata->multaggr.scalars[i]) )
13815 {
13818 else
13820
13821 if( SCIPrationalIsInfinity(bnd) )
13822 posinf = TRUE;
13823 else if( SCIPrationalIsNegInfinity(bnd) )
13824 neginf = TRUE;
13825 else
13826 SCIPrationalAddProd(ub, var->exactdata->multaggr.scalars[i], bnd);
13827 }
13828 else
13829 {
13832 else
13834
13835 if( SCIPrationalIsNegInfinity(bnd) )
13836 posinf = TRUE;
13837 else if( SCIPrationalIsInfinity(bnd) )
13838 neginf = TRUE;
13839 else
13840 SCIPrationalAddProd(ub, var->exactdata->multaggr.scalars[i], bnd);
13841 }
13842
13843 /* stop if two diffrent infinities (or a -infinity) were found and return local lower bound of multi aggregated
13844 * variable
13845 */
13846 if( posinf )
13847 {
13849 break;
13850 }
13851 }
13852
13853 /* if positive infinity flag was set to true return infinity */
13854 if( !posinf && neginf )
13856 else
13858
13859 SCIPrationalFreeBuffer(set->buffer, &bnd);
13860 SCIPrationalFreeBuffer(set->buffer, &ub);
13861
13862 return SCIP_OKAY;
13863}
13864
13865/** for a multi-aggregated variable, gives the global lower bound computed by adding the global bounds from all
13866 * aggregation variables, this global bound may be tighter than the one given by SCIPvarGetLbGlobal, since the latter is
13867 * not updated if bounds of aggregation variables are changing
13868 *
13869 * calling this function for a non-multi-aggregated variable is not allowed
13870 */
13872 SCIP_VAR* var, /**< problem variable */
13873 SCIP_SET* set /**< global SCIP settings */
13874 )
13875{
13876 int i;
13877 SCIP_Real lb;
13878 SCIP_Real bnd;
13879 SCIP_VAR* aggrvar;
13880 SCIP_Bool posinf;
13881 SCIP_Bool neginf;
13882
13883 assert(var != NULL);
13884 assert(set != NULL);
13885 assert(var->scip == set->scip);
13887
13888 posinf = FALSE;
13889 neginf = FALSE;
13890 lb = var->data.multaggr.constant;
13891 for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
13892 {
13893 aggrvar = var->data.multaggr.vars[i];
13894 if( var->data.multaggr.scalars[i] > 0.0 )
13895 {
13897
13898 if( SCIPsetIsInfinity(set, bnd) )
13899 posinf = TRUE;
13900 else if( SCIPsetIsInfinity(set, -bnd) )
13901 neginf = TRUE;
13902 else
13903 lb += var->data.multaggr.scalars[i] * bnd;
13904 }
13905 else
13906 {
13908
13909 if( SCIPsetIsInfinity(set, -bnd) )
13910 posinf = TRUE;
13911 else if( SCIPsetIsInfinity(set, bnd) )
13912 neginf = TRUE;
13913 else
13914 lb += var->data.multaggr.scalars[i] * bnd;
13915 }
13916
13917 /* stop if two diffrent infinities (or a -infinity) were found and return global lower bound of multi aggregated
13918 * variable
13919 */
13920 if( neginf )
13921 return SCIPvarGetLbGlobal(var);
13922 }
13923
13924 /* if positive infinity flag was set to true return infinity */
13925 if( posinf )
13926 return SCIPsetInfinity(set);
13927
13928 return (MAX(lb, SCIPvarGetLbGlobal(var))); /*lint !e666*/
13929}
13930
13931/** for a multi-aggregated variable, gives the global upper bound computed by adding the global bounds from all
13932 * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbGlobal, since the latter is
13933 * not updated if bounds of aggregation variables are changing
13934 *
13935 * calling this function for a non-multi-aggregated variable is not allowed
13936 */
13938 SCIP_VAR* var, /**< problem variable */
13939 SCIP_SET* set /**< global SCIP settings */
13940 )
13941{
13942 int i;
13943 SCIP_Real ub;
13944 SCIP_Real bnd;
13945 SCIP_VAR* aggrvar;
13946 SCIP_Bool posinf;
13947 SCIP_Bool neginf;
13948
13949 assert(var != NULL);
13950 assert(set != NULL);
13951 assert(var->scip == set->scip);
13953
13954 posinf = FALSE;
13955 neginf = FALSE;
13956 ub = var->data.multaggr.constant;
13957 for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
13958 {
13959 aggrvar = var->data.multaggr.vars[i];
13960 if( var->data.multaggr.scalars[i] > 0.0 )
13961 {
13963
13964 if( SCIPsetIsInfinity(set, bnd) )
13965 posinf = TRUE;
13966 else if( SCIPsetIsInfinity(set, -bnd) )
13967 neginf = TRUE;
13968 else
13969 ub += var->data.multaggr.scalars[i] * bnd;
13970 }
13971 else
13972 {
13974
13975 if( SCIPsetIsInfinity(set, -bnd) )
13976 posinf = TRUE;
13977 else if( SCIPsetIsInfinity(set, bnd) )
13978 neginf = TRUE;
13979 else
13980 ub += var->data.multaggr.scalars[i] * bnd;
13981 }
13982
13983 /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
13984 * variable
13985 */
13986 if( posinf )
13987 return SCIPvarGetUbGlobal(var);
13988 }
13989
13990 /* if negative infinity flag was set to true return -infinity */
13991 if( neginf )
13992 return -SCIPsetInfinity(set);
13993
13994 return (MIN(ub, SCIPvarGetUbGlobal(var))); /*lint !e666*/
13995}
13996
13997/** adds a hole to the original domain of the variable */
13999 SCIP_VAR* var, /**< problem variable */
14000 BMS_BLKMEM* blkmem, /**< block memory */
14001 SCIP_SET* set, /**< global SCIP settings */
14002 SCIP_Real left, /**< left bound of open interval in new hole */
14003 SCIP_Real right /**< right bound of open interval in new hole */
14004 )
14005{
14006 SCIP_Bool added;
14007
14008 assert(var != NULL);
14012 assert(set != NULL);
14013 assert(var->scip == set->scip);
14014 assert(set->stage == SCIP_STAGE_PROBLEM);
14015
14016 SCIPsetDebugMsg(set, "adding original hole (%g,%g) to <%s>\n", left, right, var->name);
14017
14018 if( SCIPsetIsEQ(set, left, right) )
14019 return SCIP_OKAY;
14020
14021 /* the interval should not be empty */
14022 assert(SCIPsetIsLT(set, left, right));
14023
14024 /* the the interval bound should already be adjusted */
14027
14028 /* the the interval should lay between the lower and upper bound */
14031
14032 /* add domain hole */
14033 SCIP_CALL( domAddHole(&var->data.original.origdom, blkmem, set, left, right, &added) );
14034
14035 /* merges overlapping holes into single holes, moves bounds respectively if hole was added */
14036 if( added )
14037 {
14038 domMerge(&var->data.original.origdom, blkmem, set, NULL, NULL);
14039 }
14040
14041 /**@todo add hole in parent and child variables (just like with bound changes);
14042 * warning! original vars' holes are in original blkmem, transformed vars' holes in transformed blkmem
14043 */
14044
14045 return SCIP_OKAY;
14046}
14047
14048/** performs the current add of domain, changes all parents accordingly */
14049static
14051 SCIP_VAR* var, /**< problem variable */
14052 BMS_BLKMEM* blkmem, /**< block memory */
14053 SCIP_SET* set, /**< global SCIP settings */
14054 SCIP_STAT* stat, /**< problem statistics */
14055 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
14056 SCIP_Real left, /**< left bound of open interval in new hole */
14057 SCIP_Real right, /**< right bound of open interval in new hole */
14058 SCIP_Bool* added /**< pointer to store whether the hole was added */
14059 )
14060{
14061 SCIP_VAR* parentvar;
14062 SCIP_Real newlb;
14063 SCIP_Real newub;
14064 int i;
14065
14066 assert(var != NULL);
14067 assert(added != NULL);
14068 assert(blkmem != NULL);
14069
14070 /* the interval should not be empty */
14071 assert(SCIPsetIsLT(set, left, right));
14072
14073 /* the interval bound should already be adjusted */
14076
14077 /* the interval should lay between the lower and upper bound */
14080
14081 /* @todo add debugging mechanism for holes when using a debugging solution */
14082
14083 /* add hole to hole list */
14084 SCIP_CALL( domAddHole(&var->glbdom, blkmem, set, left, right, added) );
14085
14086 /* check if the hole is redundant */
14087 if( !(*added) )
14088 return SCIP_OKAY;
14089
14090 /* current bounds */
14091 newlb = var->glbdom.lb;
14092 newub = var->glbdom.ub;
14093
14094 /* merge domain holes */
14095 domMerge(&var->glbdom, blkmem, set, &newlb, &newub);
14096
14097 /* the bound should not be changed */
14098 assert(SCIPsetIsEQ(set, newlb, var->glbdom.lb));
14099 assert(SCIPsetIsEQ(set, newub, var->glbdom.ub));
14100
14101 /* issue bound change event */
14102 assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
14103 if( var->eventfilter != NULL )
14104 {
14105 SCIP_CALL( varEventGholeAdded(var, blkmem, set, eventqueue, left, right) );
14106 }
14107
14108 /* process parent variables */
14109 for( i = 0; i < var->nparentvars; ++i )
14110 {
14111 SCIP_Real parentnewleft;
14112 SCIP_Real parentnewright;
14113 SCIP_Bool localadded;
14114
14115 parentvar = var->parentvars[i];
14116 assert(parentvar != NULL);
14117
14118 switch( SCIPvarGetStatus(parentvar) )
14119 {
14121 parentnewleft = left;
14122 parentnewright = right;
14123 break;
14124
14129 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
14130 return SCIP_INVALIDDATA;
14131
14132 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
14133 assert(parentvar->data.aggregate.var == var);
14134
14135 if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
14136 {
14137 /* a > 0 -> change upper bound of x */
14138 parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
14139 parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
14140 }
14141 else
14142 {
14143 /* a < 0 -> change lower bound of x */
14145
14146 parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
14147 parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
14148 }
14149 break;
14150
14151 case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
14152 assert(parentvar->negatedvar != NULL);
14154 assert(parentvar->negatedvar->negatedvar == parentvar);
14155
14156 parentnewright = -left + parentvar->data.negate.constant;
14157 parentnewleft = -right + parentvar->data.negate.constant;
14158 break;
14159
14160 default:
14161 SCIPerrorMessage("unknown variable status\n");
14162 return SCIP_INVALIDDATA;
14163 }
14164
14165 SCIPsetDebugMsg(set, "add global hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
14166
14167 /* perform hole added for parent variable */
14168 assert(blkmem != NULL);
14169 assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
14170 SCIP_CALL( varProcessAddHoleGlobal(parentvar, blkmem, set, stat, eventqueue,
14171 parentnewleft, parentnewright, &localadded) );
14172 assert(localadded);
14173 }
14174
14175 return SCIP_OKAY;
14176}
14177
14178/** adds a hole to the variable's global and local domain */
14180 SCIP_VAR* var, /**< problem variable */
14181 BMS_BLKMEM* blkmem, /**< block memory */
14182 SCIP_SET* set, /**< global SCIP settings */
14183 SCIP_STAT* stat, /**< problem statistics */
14184 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
14185 SCIP_Real left, /**< left bound of open interval in new hole */
14186 SCIP_Real right, /**< right bound of open interval in new hole */
14187 SCIP_Bool* added /**< pointer to store whether the hole was added */
14188 )
14189{
14190 SCIP_Real childnewleft;
14191 SCIP_Real childnewright;
14192
14193 assert(var != NULL);
14195 assert(blkmem != NULL);
14196 assert(added != NULL);
14197
14198 SCIPsetDebugMsg(set, "adding global hole (%g,%g) to <%s>\n", left, right, var->name);
14199
14200 /* the interval should not be empty */
14201 assert(SCIPsetIsLT(set, left, right));
14202
14203 /* the the interval bound should already be adjusted */
14206
14207 /* the the interval should lay between the lower and upper bound */
14210
14211 /* change bounds of attached variables */
14212 switch( SCIPvarGetStatus(var) )
14213 {
14215 if( var->data.original.transvar != NULL )
14216 {
14217 SCIP_CALL( SCIPvarAddHoleGlobal(var->data.original.transvar, blkmem, set, stat, eventqueue,
14218 left, right, added) );
14219 }
14220 else
14221 {
14222 assert(set->stage == SCIP_STAGE_PROBLEM);
14223
14224 SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
14225 if( *added )
14226 {
14227 SCIP_Bool localadded;
14228
14229 SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
14230 }
14231 }
14232 break;
14233
14236 SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
14237 if( *added )
14238 {
14239 SCIP_Bool localadded;
14240
14241 SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
14242 }
14243 break;
14244
14246 SCIPerrorMessage("cannot add hole of a fixed variable\n");
14247 return SCIP_INVALIDDATA;
14248
14249 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
14250 assert(var->data.aggregate.var != NULL);
14251
14252 if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
14253 {
14254 /* a > 0 -> change lower bound of y */
14255 childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
14256 childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
14257 }
14258 else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
14259 {
14260 childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
14261 childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
14262 }
14263 else
14264 {
14265 SCIPerrorMessage("scalar is zero in aggregation\n");
14266 return SCIP_INVALIDDATA;
14267 }
14268 SCIP_CALL( SCIPvarAddHoleGlobal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
14269 childnewleft, childnewright, added) );
14270 break;
14271
14273 SCIPerrorMessage("cannot add a hole of a multi-aggregated variable.\n");
14274 return SCIP_INVALIDDATA;
14275
14276 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
14277 assert(var->negatedvar != NULL);
14279 assert(var->negatedvar->negatedvar == var);
14280
14281 childnewright = -left + var->data.negate.constant;
14282 childnewleft = -right + var->data.negate.constant;
14283
14284 SCIP_CALL( SCIPvarAddHoleGlobal(var->negatedvar, blkmem, set, stat, eventqueue,
14285 childnewleft, childnewright, added) );
14286 break;
14287
14288 default:
14289 SCIPerrorMessage("unknown variable status\n");
14290 return SCIP_INVALIDDATA;
14291 }
14292
14293 return SCIP_OKAY;
14294}
14295
14296/** performs the current add of domain, changes all parents accordingly */
14297static
14299 SCIP_VAR* var, /**< problem variable */
14300 BMS_BLKMEM* blkmem, /**< block memory */
14301 SCIP_SET* set, /**< global SCIP settings */
14302 SCIP_STAT* stat, /**< problem statistics */
14303 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
14304 SCIP_Real left, /**< left bound of open interval in new hole */
14305 SCIP_Real right, /**< right bound of open interval in new hole */
14306 SCIP_Bool* added /**< pointer to store whether the hole was added, or NULL */
14307 )
14308{
14309 SCIP_VAR* parentvar;
14310 SCIP_Real newlb;
14311 SCIP_Real newub;
14312 int i;
14313
14314 assert(var != NULL);
14315 assert(added != NULL);
14316 assert(blkmem != NULL);
14317
14318 /* the interval should not be empty */
14319 assert(SCIPsetIsLT(set, left, right));
14320
14321 /* the the interval bound should already be adjusted */
14324
14325 /* the the interval should lay between the lower and upper bound */
14328
14329 /* add hole to hole list */
14330 SCIP_CALL( domAddHole(&var->locdom, blkmem, set, left, right, added) );
14331
14332 /* check if the hole is redundant */
14333 if( !(*added) )
14334 return SCIP_OKAY;
14335
14336 /* current bounds */
14337 newlb = var->locdom.lb;
14338 newub = var->locdom.ub;
14339
14340 /* merge domain holes */
14341 domMerge(&var->locdom, blkmem, set, &newlb, &newub);
14342
14343 /* the bound should not be changed */
14344 assert(SCIPsetIsEQ(set, newlb, var->locdom.lb));
14345 assert(SCIPsetIsEQ(set, newub, var->locdom.ub));
14346
14347#ifdef SCIP_DISABLED_CODE
14348 /* issue LHOLEADDED event */
14349 SCIP_EVENT event;
14350 assert(var->eventfilter != NULL);
14352 SCIP_CALL( SCIPeventProcess(&event, set, NULL, NULL, NULL, var->eventfilter) );
14353#endif
14354
14355 /* process parent variables */
14356 for( i = 0; i < var->nparentvars; ++i )
14357 {
14358 SCIP_Real parentnewleft;
14359 SCIP_Real parentnewright;
14360 SCIP_Bool localadded;
14361
14362 parentvar = var->parentvars[i];
14363 assert(parentvar != NULL);
14364
14365 switch( SCIPvarGetStatus(parentvar) )
14366 {
14368 parentnewleft = left;
14369 parentnewright = right;
14370 break;
14371
14376 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
14377 return SCIP_INVALIDDATA;
14378
14379 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
14380 assert(parentvar->data.aggregate.var == var);
14381
14382 if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
14383 {
14384 /* a > 0 -> change upper bound of x */
14385 parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
14386 parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
14387 }
14388 else
14389 {
14390 /* a < 0 -> change lower bound of x */
14392
14393 parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
14394 parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
14395 }
14396 break;
14397
14398 case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
14399 assert(parentvar->negatedvar != NULL);
14401 assert(parentvar->negatedvar->negatedvar == parentvar);
14402
14403 parentnewright = -left + parentvar->data.negate.constant;
14404 parentnewleft = -right + parentvar->data.negate.constant;
14405 break;
14406
14407 default:
14408 SCIPerrorMessage("unknown variable status\n");
14409 return SCIP_INVALIDDATA;
14410 }
14411
14412 SCIPsetDebugMsg(set, "add local hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
14413
14414 /* perform hole added for parent variable */
14415 assert(blkmem != NULL);
14416 assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
14417 SCIP_CALL( varProcessAddHoleLocal(parentvar, blkmem, set, stat, eventqueue,
14418 parentnewleft, parentnewright, &localadded) );
14419 assert(localadded);
14420 }
14421
14422 return SCIP_OKAY;
14423}
14424
14425/** adds a hole to the variable's current local domain */
14427 SCIP_VAR* var, /**< problem variable */
14428 BMS_BLKMEM* blkmem, /**< block memory */
14429 SCIP_SET* set, /**< global SCIP settings */
14430 SCIP_STAT* stat, /**< problem statistics */
14431 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
14432 SCIP_Real left, /**< left bound of open interval in new hole */
14433 SCIP_Real right, /**< right bound of open interval in new hole */
14434 SCIP_Bool* added /**< pointer to store whether the hole was added */
14435 )
14436{
14437 SCIP_Real childnewleft;
14438 SCIP_Real childnewright;
14439
14440 assert(var != NULL);
14441
14442 SCIPsetDebugMsg(set, "adding local hole (%g,%g) to <%s>\n", left, right, var->name);
14443
14444 assert(set != NULL);
14445 assert(var->scip == set->scip);
14447 assert(blkmem != NULL);
14448 assert(added != NULL);
14449
14450 /* the interval should not be empty */
14451 assert(SCIPsetIsLT(set, left, right));
14452
14453 /* the the interval bound should already be adjusted */
14456
14457 /* the the interval should lay between the lower and upper bound */
14460
14461 /* change bounds of attached variables */
14462 switch( SCIPvarGetStatus(var) )
14463 {
14465 if( var->data.original.transvar != NULL )
14466 {
14467 SCIP_CALL( SCIPvarAddHoleLocal(var->data.original.transvar, blkmem, set, stat, eventqueue,
14468 left, right, added) );
14469 }
14470 else
14471 {
14472 assert(set->stage == SCIP_STAGE_PROBLEM);
14473 SCIPstatIncrement(stat, set, domchgcount);
14474 SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
14475 }
14476 break;
14477
14480 SCIPstatIncrement(stat, set, domchgcount);
14481 SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
14482 break;
14483
14485 SCIPerrorMessage("cannot add domain hole to a fixed variable\n");
14486 return SCIP_INVALIDDATA;
14487
14488 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
14489 assert(var->data.aggregate.var != NULL);
14490
14491 if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
14492 {
14493 /* a > 0 -> change lower bound of y */
14494 childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
14495 childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
14496 }
14497 else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
14498 {
14499 childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
14500 childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
14501 }
14502 else
14503 {
14504 SCIPerrorMessage("scalar is zero in aggregation\n");
14505 return SCIP_INVALIDDATA;
14506 }
14507 SCIP_CALL( SCIPvarAddHoleLocal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
14508 childnewleft, childnewright, added) );
14509 break;
14510
14512 SCIPerrorMessage("cannot add domain hole to a multi-aggregated variable.\n");
14513 return SCIP_INVALIDDATA;
14514
14515 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
14516 assert(var->negatedvar != NULL);
14518 assert(var->negatedvar->negatedvar == var);
14519
14520 childnewright = -left + var->data.negate.constant;
14521 childnewleft = -right + var->data.negate.constant;
14522
14523 SCIP_CALL( SCIPvarAddHoleLocal(var->negatedvar, blkmem, set, stat, eventqueue, childnewleft, childnewright, added) );
14524 break;
14525
14526 default:
14527 SCIPerrorMessage("unknown variable status\n");
14528 return SCIP_INVALIDDATA;
14529 }
14530
14531 return SCIP_OKAY;
14532}
14533
14534/** resets the global and local bounds of original variable to their original values */
14536 SCIP_VAR* var, /**< problem variable */
14537 BMS_BLKMEM* blkmem, /**< block memory */
14538 SCIP_SET* set, /**< global SCIP settings */
14539 SCIP_STAT* stat /**< problem statistics */
14540 )
14541{
14542 assert(var != NULL);
14543 assert(set != NULL);
14544 assert(var->scip == set->scip);
14546 /* resetting of bounds on original variables which have a transformed counterpart easily fails if, e.g.,
14547 * the transformed variable has been fixed */
14549
14550 /* copy the original bounds back to the global and local bounds */
14551 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.lb) );
14552 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.ub) );
14553 SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.lb) );
14554 SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.ub) );
14555
14556 if( var->exactdata != NULL )
14557 {
14558 SCIP_CALL( SCIPvarChgLbGlobalExact(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->exactdata->origdom.lb) );
14559 SCIP_CALL( SCIPvarChgUbGlobalExact(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->exactdata->origdom.ub) );
14560 SCIP_CALL( SCIPvarChgLbLocalExact(var, blkmem, set, stat, NULL, NULL, NULL, var->exactdata->origdom.lb) );
14561 SCIP_CALL( SCIPvarChgUbLocalExact(var, blkmem, set, stat, NULL, NULL, NULL, var->exactdata->origdom.ub) );
14562 }
14563
14564 /* free the global and local holelists and duplicate the original ones */
14565 /**@todo this has also to be called recursively with methods similar to SCIPvarChgLbGlobal() */
14566 holelistFree(&var->glbdom.holelist, blkmem);
14567 holelistFree(&var->locdom.holelist, blkmem);
14568 SCIP_CALL( holelistDuplicate(&var->glbdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
14569 SCIP_CALL( holelistDuplicate(&var->locdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
14570
14571 return SCIP_OKAY;
14572}
14573
14574/** issues a IMPLADDED event on the given variable */
14575static
14577 SCIP_VAR* var, /**< problem variable to change */
14578 BMS_BLKMEM* blkmem, /**< block memory */
14579 SCIP_SET* set, /**< global SCIP settings */
14580 SCIP_EVENTQUEUE* eventqueue /**< event queue */
14581 )
14582{
14583 SCIP_EVENT* event;
14584
14585 assert(var != NULL);
14586
14587 /* issue IMPLADDED event on variable */
14588 SCIP_CALL( SCIPeventCreateImplAdded(&event, blkmem, var) );
14589 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
14590
14591 return SCIP_OKAY;
14592}
14593
14594/** actually performs the addition of a variable bound to the variable's vbound arrays */
14595static
14597 SCIP_VAR* var, /**< problem variable x in x <= b*z + d or x >= b*z + d */
14598 BMS_BLKMEM* blkmem, /**< block memory */
14599 SCIP_SET* set, /**< global SCIP settings */
14600 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
14601 SCIP_BOUNDTYPE vbtype, /**< type of variable bound (LOWER or UPPER) */
14602 SCIP_VAR* vbvar, /**< variable z in x <= b*z + d or x >= b*z + d */
14603 SCIP_Real vbcoef, /**< coefficient b in x <= b*z + d or x >= b*z + d */
14604 SCIP_Real vbconstant /**< constant d in x <= b*z + d or x >= b*z + d */
14605 )
14606{
14607 SCIP_Bool added;
14608
14609 /* It can happen that the variable "var" and the variable "vbvar" are the same variable. For example if a variable
14610 * gets aggregated, the variable bounds (vbound) of that variable are copied to the other variable. A variable bound
14611 * variable of the aggregated variable might be the same as the one its gets aggregated too.
14612 *
14613 * If the variable "var" and the variable "vbvar" are the same, the variable bound which should be added here has to
14614 * be redundant. This is the case since an infeasibility should have be detected in the previous methods. As well as
14615 * the bounds of the variable which should be also already be tightened in the previous methods. Therefore, the
14616 * variable bound can be ignored.
14617 *
14618 * From the way the the variable bound system is implemented (detecting infeasibility, tighten bounds), the
14619 * equivalence of the variables should be checked here.
14620 */
14621 if( var == vbvar )
14622 {
14623 /* in this case the variable bound has to be redundant, this means for possible assignments to this variable; this
14624 * can be checked via the global bounds of the variable */
14625#ifndef NDEBUG
14626 SCIP_Real lb;
14627 SCIP_Real ub;
14628
14629 lb = SCIPvarGetLbGlobal(var);
14630 ub = SCIPvarGetUbGlobal(var);
14631
14632 if(vbtype == SCIP_BOUNDTYPE_LOWER)
14633 {
14634 if( vbcoef > 0.0 )
14635 {
14636 assert(SCIPsetIsGE(set, lb, lb * vbcoef + vbconstant) );
14637 assert(SCIPsetIsGE(set, ub, ub * vbcoef + vbconstant) );
14638 }
14639 else
14640 {
14641 assert(SCIPsetIsGE(set, lb, ub * vbcoef + vbconstant) );
14642 assert(SCIPsetIsGE(set, ub, lb * vbcoef + vbconstant) );
14643 }
14644 }
14645 else
14646 {
14647 assert(vbtype == SCIP_BOUNDTYPE_UPPER);
14648 if( vbcoef > 0.0 )
14649 {
14650 assert(SCIPsetIsLE(set, lb, lb * vbcoef + vbconstant) );
14651 assert(SCIPsetIsLE(set, ub, ub * vbcoef + vbconstant) );
14652 }
14653 else
14654 {
14655 assert(SCIPsetIsLE(set, lb, ub * vbcoef + vbconstant) );
14656 assert(SCIPsetIsLE(set, ub, lb * vbcoef + vbconstant) );
14657 }
14658 }
14659#endif
14660 SCIPsetDebugMsg(set, "redundant variable bound: <%s> %s %g<%s> %+g\n",
14661 SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
14662
14663 return SCIP_OKAY;
14664 }
14665
14666 SCIPsetDebugMsg(set, "adding variable bound: <%s> %s %g<%s> %+g\n",
14667 SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
14668
14669 /* check variable bound on debugging solution */
14670 SCIP_CALL( SCIPdebugCheckVbound(set, var, vbtype, vbvar, vbcoef, vbconstant) ); /*lint !e506 !e774*/
14671
14672 /* perform the addition */
14673 if( vbtype == SCIP_BOUNDTYPE_LOWER )
14674 {
14675 SCIP_CALL( SCIPvboundsAdd(&var->vlbs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
14676 }
14677 else
14678 {
14679 SCIP_CALL( SCIPvboundsAdd(&var->vubs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
14680 }
14681 var->closestvblpcount = -1;
14682
14683 if( added )
14684 {
14685 /* issue IMPLADDED event */
14686 SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
14687 }
14688
14689 return SCIP_OKAY;
14690}
14691
14692/** checks whether the given implication is redundant or infeasible w.r.t. the implied variables global bounds */
14693static
14695 SCIP_SET* set, /**< global SCIP settings */
14696 SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
14697 SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
14698 SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
14699 SCIP_Bool* redundant, /**< pointer to store whether the implication is redundant */
14700 SCIP_Bool* infeasible /**< pointer to store whether the implication is infeasible */
14701 )
14702{
14703 SCIP_Real impllb;
14704 SCIP_Real implub;
14705
14706 assert(redundant != NULL);
14707 assert(infeasible != NULL);
14708
14709 impllb = SCIPvarGetLbGlobal(implvar);
14710 implub = SCIPvarGetUbGlobal(implvar);
14711 if( impltype == SCIP_BOUNDTYPE_LOWER )
14712 {
14713 *infeasible = SCIPsetIsFeasGT(set, implbound, implub);
14714 *redundant = SCIPsetIsFeasLE(set, implbound, impllb);
14715 }
14716 else
14717 {
14718 *infeasible = SCIPsetIsFeasLT(set, implbound, impllb);
14719 *redundant = SCIPsetIsFeasGE(set, implbound, implub);
14720 }
14721}
14722
14723/** applies the given implication, if it is not redundant */
14724static
14726 BMS_BLKMEM* blkmem, /**< block memory */
14727 SCIP_SET* set, /**< global SCIP settings */
14728 SCIP_STAT* stat, /**< problem statistics */
14729 SCIP_PROB* transprob, /**< transformed problem */
14730 SCIP_PROB* origprob, /**< original problem */
14731 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
14732 SCIP_REOPT* reopt, /**< reoptimization data structure */
14733 SCIP_LP* lp, /**< current LP data */
14734 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
14735 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
14736 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
14737 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
14738 SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
14739 SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
14740 SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
14741 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
14742 int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
14743 )
14744{
14745 SCIP_Real implub;
14746 SCIP_Real impllb;
14747
14748 assert(infeasible != NULL);
14749
14750 *infeasible = FALSE;
14751
14752 implub = SCIPvarGetUbGlobal(implvar);
14753 impllb = SCIPvarGetLbGlobal(implvar);
14754 if( impltype == SCIP_BOUNDTYPE_LOWER )
14755 {
14756 if( SCIPsetIsFeasGT(set, implbound, implub) )
14757 {
14758 /* the implication produces a conflict: the problem is infeasible */
14759 *infeasible = TRUE;
14760 }
14761 else if( SCIPsetIsFeasGT(set, implbound, impllb) )
14762 {
14763 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
14764 * with the local bound, in this case we need to store the bound change as pending bound change
14765 */
14767 {
14768 assert(tree != NULL);
14769 assert(transprob != NULL);
14770 assert(SCIPprobIsTransformed(transprob));
14771
14772 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
14773 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
14774 }
14775 else
14776 {
14777 SCIP_CALL( SCIPvarChgLbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
14778 }
14779
14780 if( nbdchgs != NULL )
14781 (*nbdchgs)++;
14782 }
14783 }
14784 else
14785 {
14786 if( SCIPsetIsFeasLT(set, implbound, impllb) )
14787 {
14788 /* the implication produces a conflict: the problem is infeasible */
14789 *infeasible = TRUE;
14790 }
14791 else if( SCIPsetIsFeasLT(set, implbound, implub) )
14792 {
14793 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
14794 * with the local bound, in this case we need to store the bound change as pending bound change
14795 */
14797 {
14798 assert(tree != NULL);
14799 assert(transprob != NULL);
14800 assert(SCIPprobIsTransformed(transprob));
14801
14802 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
14803 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
14804 }
14805 else
14806 {
14807 SCIP_CALL( SCIPvarChgUbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
14808 }
14809
14810 if( nbdchgs != NULL )
14811 (*nbdchgs)++;
14812 }
14813 }
14814
14815 return SCIP_OKAY;
14816}
14817
14818/** actually performs the addition of an implication to the variable's implication arrays,
14819 * and adds the corresponding implication or variable bound to the implied variable;
14820 * if the implication is conflicting, the variable is fixed to the opposite value;
14821 * if the variable is already fixed to the given value, the implication is performed immediately;
14822 * if the implication is redundant with respect to the variables' global bounds, it is ignored
14823 */
14824static
14826 SCIP_VAR* var, /**< problem variable */
14827 BMS_BLKMEM* blkmem, /**< block memory */
14828 SCIP_SET* set, /**< global SCIP settings */
14829 SCIP_STAT* stat, /**< problem statistics */
14830 SCIP_PROB* transprob, /**< transformed problem */
14831 SCIP_PROB* origprob, /**< original problem */
14832 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
14833 SCIP_REOPT* reopt, /**< reoptimization data structure */
14834 SCIP_LP* lp, /**< current LP data */
14835 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
14836 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
14837 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
14838 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
14839 SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
14840 SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
14841 SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
14842 SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
14843 SCIP_Bool isshortcut, /**< is the implication a shortcut, i.e., added as part of the transitive closure of another implication? */
14844 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
14845 int* nbdchgs, /**< pointer to count the number of performed bound changes, or NULL */
14846 SCIP_Bool* added /**< pointer to store whether an implication was added */
14847 )
14848{
14849 SCIP_Bool redundant;
14850 SCIP_Bool conflict;
14851
14852 assert(var != NULL);
14857 assert(infeasible != NULL);
14858 assert(added != NULL);
14859
14860 /* check implication on debugging solution */
14861 SCIP_CALL( SCIPdebugCheckImplic(set, var, varfixing, implvar, impltype, implbound) ); /*lint !e506 !e774*/
14862
14863 *infeasible = FALSE;
14864 *added = FALSE;
14865
14866 /* check, if the implication is redundant or infeasible */
14867 checkImplic(set, implvar, impltype, implbound, &redundant, &conflict);
14868 assert(!redundant || !conflict);
14869 if( redundant )
14870 return SCIP_OKAY;
14871
14872 if( var == implvar )
14873 {
14874 /* special cases appear were a bound to a variable implies itself to be outside the bounds:
14875 * x == varfixing => x < 0 or x > 1
14876 */
14877 if( SCIPsetIsLT(set, implbound, 0.0) || SCIPsetIsGT(set, implbound, 1.0) )
14878 conflict = TRUE;
14879 else
14880 {
14881 /* variable implies itself: x == varfixing => x == (impltype == SCIP_BOUNDTYPE_LOWER) */
14882 assert(SCIPsetIsZero(set, implbound) || SCIPsetIsEQ(set, implbound, 1.0));
14883 assert(SCIPsetIsZero(set, implbound) == (impltype == SCIP_BOUNDTYPE_UPPER));
14884 assert(SCIPsetIsEQ(set, implbound, 1.0) == (impltype == SCIP_BOUNDTYPE_LOWER));
14885 conflict = conflict || ((varfixing == TRUE) == (impltype == SCIP_BOUNDTYPE_UPPER));
14886 if( !conflict )
14887 return SCIP_OKAY;
14888 }
14889 }
14890
14891 /* check, if the variable is already fixed */
14892 if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
14893 {
14894 /* if the variable is fixed to the given value, perform the implication; otherwise, ignore the implication */
14895 if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
14896 {
14897 SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
14898 eventfilter, cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
14899 }
14900 return SCIP_OKAY;
14901 }
14902
14903 assert((impltype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, implbound, SCIPvarGetLbGlobal(implvar)))
14904 || (impltype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, implbound, SCIPvarGetUbGlobal(implvar))));
14905
14906 if( !conflict )
14907 {
14908 assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
14909
14910 if( SCIPvarIsBinary(implvar) )
14911 {
14912 SCIP_VAR* vars[2];
14913 SCIP_Bool vals[2];
14914
14915 assert(SCIPsetIsFeasEQ(set, implbound, 1.0) || SCIPsetIsFeasZero(set, implbound));
14916 assert((impltype == SCIP_BOUNDTYPE_UPPER) == SCIPsetIsFeasZero(set, implbound));
14917
14918 vars[0] = var;
14919 vars[1] = implvar;
14920 vals[0] = varfixing;
14921 vals[1] = (impltype == SCIP_BOUNDTYPE_UPPER);
14922
14923 /* add the clique to the clique table */
14924 SCIP_CALL( SCIPcliquetableAdd(cliquetable, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
14925 eventqueue, eventfilter, vars, vals, 2, FALSE, &conflict, nbdchgs) );
14926
14927 if( !conflict )
14928 return SCIP_OKAY;
14929 }
14930 else
14931 {
14932 /* add implication x == 0/1 -> y <= b / y >= b to the implications list of x */
14933 SCIPsetDebugMsg(set, "adding implication: <%s> == %u ==> <%s> %s %g\n",
14934 SCIPvarGetName(var), varfixing,
14935 SCIPvarGetName(implvar), impltype == SCIP_BOUNDTYPE_UPPER ? "<=" : ">=", implbound);
14936 SCIP_CALL( SCIPimplicsAdd(&var->implics, blkmem, set, stat, varfixing, implvar, impltype, implbound,
14937 isshortcut, &conflict, added) );
14938 }
14939 }
14940 assert(!conflict || !(*added));
14941
14942 /* on conflict, fix the variable to the opposite value */
14943 if( conflict )
14944 {
14945 SCIPsetDebugMsg(set, " -> implication yields a conflict: fix <%s> == %d\n", SCIPvarGetName(var), !varfixing);
14946
14947 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
14948 * with the local bound, in this case we need to store the bound change as pending bound change
14949 */
14951 {
14952 assert(tree != NULL);
14953 assert(transprob != NULL);
14954 assert(SCIPprobIsTransformed(transprob));
14955
14956 if( varfixing )
14957 {
14958 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
14959 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
14960 }
14961 else
14962 {
14963 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
14964 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
14965 }
14966 }
14967 else
14968 {
14969 if( varfixing )
14970 {
14971 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
14972 }
14973 else
14974 {
14975 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
14976 }
14977 }
14978 if( nbdchgs != NULL )
14979 (*nbdchgs)++;
14980
14981 return SCIP_OKAY;
14982 }
14983 else if( *added )
14984 {
14985 /* issue IMPLADDED event */
14986 SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
14987 }
14988 else
14989 {
14990 /* the implication was redundant: the inverse is also redundant */
14991 return SCIP_OKAY;
14992 }
14993
14994 assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
14995
14996 /* check, whether implied variable is binary */
14997 if( !SCIPvarIsBinary(implvar) )
14998 {
14999 SCIP_Real lb;
15000 SCIP_Real ub;
15001
15002 /* add inverse variable bound to the variable bounds of y with global bounds y \in [lb,ub]:
15003 * x == 0 -> y <= b <-> y <= (ub - b)*x + b
15004 * x == 1 -> y <= b <-> y <= (b - ub)*x + ub
15005 * x == 0 -> y >= b <-> y >= (lb - b)*x + b
15006 * x == 1 -> y >= b <-> y >= (b - lb)*x + lb
15007 * for numerical reasons, ignore variable bounds with large absolute coefficient
15008 */
15009 lb = SCIPvarGetLbGlobal(implvar);
15010 ub = SCIPvarGetUbGlobal(implvar);
15011 if( impltype == SCIP_BOUNDTYPE_UPPER )
15012 {
15013 if( REALABS(implbound - ub) <= MAXABSVBCOEF )
15014 {
15015 SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, var,
15016 varfixing ? implbound - ub : ub - implbound, varfixing ? ub : implbound) );
15017 }
15018 }
15019 else
15020 {
15021 if( REALABS(implbound - lb) <= MAXABSVBCOEF )
15022 {
15023 SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, var,
15024 varfixing ? implbound - lb : lb - implbound, varfixing ? lb : implbound) );
15025 }
15026 }
15027 }
15028
15029 return SCIP_OKAY;
15030}
15031
15032/** adds transitive closure for binary implication x = a -> y = b */
15033static
15035 SCIP_VAR* var, /**< problem variable */
15036 BMS_BLKMEM* blkmem, /**< block memory */
15037 SCIP_SET* set, /**< global SCIP settings */
15038 SCIP_STAT* stat, /**< problem statistics */
15039 SCIP_PROB* transprob, /**< transformed problem */
15040 SCIP_PROB* origprob, /**< original problem */
15041 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
15042 SCIP_REOPT* reopt, /**< reoptimization data structure */
15043 SCIP_LP* lp, /**< current LP data */
15044 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
15045 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
15046 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15047 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
15048 SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
15049 SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
15050 SCIP_Bool implvarfixing, /**< fixing b in implication */
15051 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
15052 int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
15053 )
15054{
15055 SCIP_VAR** implvars;
15056 SCIP_BOUNDTYPE* impltypes;
15057 SCIP_Real* implbounds;
15058 int nimpls;
15059 int i;
15060
15061 *infeasible = FALSE;
15062
15063 /* binary variable: implications of implvar */
15064 nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
15065 implvars = SCIPimplicsGetVars(implvar->implics, implvarfixing);
15066 impltypes = SCIPimplicsGetTypes(implvar->implics, implvarfixing);
15067 implbounds = SCIPimplicsGetBounds(implvar->implics, implvarfixing);
15068
15069 /* if variable has too many implications, the implication graph may become too dense */
15070 i = MIN(nimpls, MAXIMPLSCLOSURE) - 1;
15071
15072 /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
15073 * implvars[i] is fixed, s.t. the implication y == varfixing -> z <= b / z >= b is deleted; this affects the
15074 * array over which we currently iterate; the only thing that can happen, is that elements of the array are
15075 * deleted; in this case, the subsequent elements are moved to the front; if we iterate from back to front, the
15076 * only thing that can happen is that we add the same implication twice - this does no harm
15077 */
15078 while ( i >= 0 && !(*infeasible) )
15079 {
15080 SCIP_Bool added;
15081
15082 assert(implvars[i] != implvar);
15083
15084 /* we have x == varfixing -> y == implvarfixing -> z <= b / z >= b:
15085 * add implication x == varfixing -> z <= b / z >= b to the implications list of x
15086 */
15087 if( SCIPvarIsActive(implvars[i]) )
15088 {
15089 SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
15090 eventqueue, eventfilter, varfixing, implvars[i], impltypes[i], implbounds[i], TRUE, infeasible, nbdchgs, &added) );
15091 assert(SCIPimplicsGetNImpls(implvar->implics, implvarfixing) <= nimpls);
15092 nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
15093 i = MIN(i, nimpls); /* some elements from the array could have been removed */
15094 }
15095 --i;
15096 }
15097
15098 return SCIP_OKAY;
15099}
15100
15101/** adds given implication to the variable's implication list, and adds all implications directly implied by this
15102 * implication to the variable's implication list;
15103 * if the implication is conflicting, the variable is fixed to the opposite value;
15104 * if the variable is already fixed to the given value, the implication is performed immediately;
15105 * if the implication is redundant with respect to the variables' global bounds, it is ignored
15106 */
15107static
15109 SCIP_VAR* var, /**< problem variable */
15110 BMS_BLKMEM* blkmem, /**< block memory */
15111 SCIP_SET* set, /**< global SCIP settings */
15112 SCIP_STAT* stat, /**< problem statistics */
15113 SCIP_PROB* transprob, /**< transformed problem */
15114 SCIP_PROB* origprob, /**< original problem */
15115 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
15116 SCIP_REOPT* reopt, /**< reoptimization data structure */
15117 SCIP_LP* lp, /**< current LP data */
15118 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
15119 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
15120 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15121 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
15122 SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
15123 SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
15124 SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
15125 SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
15126 SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
15127 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
15128 int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
15129 )
15130{
15131 SCIP_Bool added;
15132
15133 assert(var != NULL);
15136 assert(implvar != NULL);
15138 assert(infeasible != NULL);
15139
15140 /* add implication x == varfixing -> y <= b / y >= b to the implications list of x */
15141 SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
15142 eventqueue, eventfilter, varfixing, implvar, impltype, implbound, FALSE, infeasible, nbdchgs, &added) );
15143
15144 if( *infeasible || var == implvar || !transitive || !added )
15145 return SCIP_OKAY;
15146
15147 assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
15148
15149 /* add transitive closure */
15150 if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY && !SCIPvarIsImpliedIntegral(implvar) )
15151 {
15152 SCIP_Bool implvarfixing;
15153
15154 implvarfixing = (impltype == SCIP_BOUNDTYPE_LOWER);
15155
15156 /* binary variable: implications of implvar */
15157 SCIP_CALL( varAddTransitiveBinaryClosureImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
15158 cliquetable, branchcand, eventqueue, eventfilter, varfixing, implvar, implvarfixing, infeasible, nbdchgs) );
15159
15160 /* inverse implication */
15161 if( !(*infeasible) )
15162 {
15163 SCIP_CALL( varAddTransitiveBinaryClosureImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
15164 cliquetable, branchcand, eventqueue, eventfilter, !implvarfixing, var, !varfixing, infeasible, nbdchgs) );
15165 }
15166 }
15167 else
15168 {
15169 /* non-binary variable: variable lower bounds of implvar */
15170 if( impltype == SCIP_BOUNDTYPE_UPPER && implvar->vlbs != NULL )
15171 {
15172 SCIP_VAR** vlbvars;
15173 SCIP_Real* vlbcoefs;
15174 SCIP_Real* vlbconstants;
15175 int nvlbvars;
15176 int i;
15177
15178 nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
15179 vlbvars = SCIPvboundsGetVars(implvar->vlbs);
15180 vlbcoefs = SCIPvboundsGetCoefs(implvar->vlbs);
15181 vlbconstants = SCIPvboundsGetConstants(implvar->vlbs);
15182
15183 /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
15184 * vlbvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
15185 * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
15186 * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
15187 * is that we add the same implication twice - this does no harm
15188 */
15189 i = nvlbvars-1;
15190 while ( i >= 0 && !(*infeasible) )
15191 {
15192 assert(vlbvars[i] != implvar);
15193 assert(!SCIPsetIsZero(set, vlbcoefs[i]));
15194
15195 /* we have x == varfixing -> y <= b and y >= c*z + d:
15196 * c > 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
15197 * c < 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
15198 *
15199 * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
15200 * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
15201 * aggregation variable (the one which will stay active);
15202 *
15203 * W.l.o.g. we consider the variable upper bounds for now. Let "vubvar" be a variable upper bound of
15204 * the aggregated variable "aggvar"; During that copying of that variable upper bound variable
15205 * "vubvar" the variable lower and upper bounds of this variable "vubvar" are also considered; note
15206 * that the "aggvar" can be a variable lower bound variable of the variable "vubvar"; Due to that
15207 * situation it can happen that we reach that code place where "vlbvars[i] == aggvar". In particular
15208 * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
15209 * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
15210 * have to explicitly check that the active variable has not a variable status
15211 * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
15212 */
15214 {
15215 SCIP_Real vbimplbound;
15216
15217 vbimplbound = (implbound - vlbconstants[i])/vlbcoefs[i];
15218 if( vlbcoefs[i] >= 0.0 )
15219 {
15220 vbimplbound = adjustedUb(set, SCIPvarIsIntegral(vlbvars[i]), vbimplbound);
15221 SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
15222 branchcand, eventqueue, eventfilter, varfixing, vlbvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
15223 infeasible, nbdchgs, &added) );
15224 }
15225 else
15226 {
15227 vbimplbound = adjustedLb(set, SCIPvarIsIntegral(vlbvars[i]), vbimplbound);
15228 SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
15229 branchcand, eventqueue, eventfilter, varfixing, vlbvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
15230 infeasible, nbdchgs, &added) );
15231 }
15232 nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
15233 i = MIN(i, nvlbvars); /* some elements from the array could have been removed */
15234 }
15235 --i;
15236 }
15237 }
15238
15239 /* non-binary variable: variable upper bounds of implvar */
15240 if( impltype == SCIP_BOUNDTYPE_LOWER && implvar->vubs != NULL )
15241 {
15242 SCIP_VAR** vubvars;
15243 SCIP_Real* vubcoefs;
15244 SCIP_Real* vubconstants;
15245 int nvubvars;
15246 int i;
15247
15248 nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
15249 vubvars = SCIPvboundsGetVars(implvar->vubs);
15250 vubcoefs = SCIPvboundsGetCoefs(implvar->vubs);
15251 vubconstants = SCIPvboundsGetConstants(implvar->vubs);
15252
15253 /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
15254 * vubvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
15255 * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
15256 * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
15257 * is that we add the same implication twice - this does no harm
15258 */
15259 i = nvubvars-1;
15260 while ( i >= 0 && !(*infeasible) )
15261 {
15262 assert(vubvars[i] != implvar);
15263 assert(!SCIPsetIsZero(set, vubcoefs[i]));
15264
15265 /* we have x == varfixing -> y >= b and y <= c*z + d:
15266 * c > 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
15267 * c < 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
15268 *
15269 * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
15270 * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
15271 * aggregation variable (the one which will stay active);
15272 *
15273 * W.l.o.g. we consider the variable lower bounds for now. Let "vlbvar" be a variable lower bound of
15274 * the aggregated variable "aggvar"; During that copying of that variable lower bound variable
15275 * "vlbvar" the variable lower and upper bounds of this variable "vlbvar" are also considered; note
15276 * that the "aggvar" can be a variable upper bound variable of the variable "vlbvar"; Due to that
15277 * situation it can happen that we reach that code place where "vubvars[i] == aggvar". In particular
15278 * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
15279 * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
15280 * have to explicitly check that the active variable has not a variable status
15281 * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
15282 */
15284 {
15285 SCIP_Real vbimplbound;
15286
15287 vbimplbound = (implbound - vubconstants[i])/vubcoefs[i];
15288 if( vubcoefs[i] >= 0.0 )
15289 {
15290 vbimplbound = adjustedLb(set, SCIPvarIsIntegral(vubvars[i]), vbimplbound);
15291 SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
15292 branchcand, eventqueue, eventfilter, varfixing, vubvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
15293 infeasible, nbdchgs, &added) );
15294 }
15295 else
15296 {
15297 vbimplbound = adjustedUb(set, SCIPvarIsIntegral(vubvars[i]), vbimplbound);
15298 SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
15299 branchcand, eventqueue, eventfilter, varfixing, vubvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
15300 infeasible, nbdchgs, &added) );
15301 }
15302 nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
15303 i = MIN(i, nvubvars); /* some elements from the array could have been removed */
15304 }
15305 --i;
15306 }
15307 }
15308 }
15309
15310 return SCIP_OKAY;
15311}
15312
15313/** informs variable x about a globally valid variable lower bound x >= b*z + d with integer variable z;
15314 * if z is binary, the corresponding valid implication for z is also added;
15315 * improves the global bounds of the variable and the vlb variable if possible
15316 */
15318 SCIP_VAR* var, /**< problem variable */
15319 BMS_BLKMEM* blkmem, /**< block memory */
15320 SCIP_SET* set, /**< global SCIP settings */
15321 SCIP_STAT* stat, /**< problem statistics */
15322 SCIP_PROB* transprob, /**< transformed problem */
15323 SCIP_PROB* origprob, /**< original problem */
15324 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
15325 SCIP_REOPT* reopt, /**< reoptimization data structure */
15326 SCIP_LP* lp, /**< current LP data */
15327 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
15328 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
15329 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15330 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
15331 SCIP_VAR* vlbvar, /**< variable z in x >= b*z + d */
15332 SCIP_Real vlbcoef, /**< coefficient b in x >= b*z + d */
15333 SCIP_Real vlbconstant, /**< constant d in x >= b*z + d */
15334 SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
15335 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
15336 int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
15337 )
15338{
15339 assert(var != NULL);
15340 assert(set != NULL);
15341 assert(var->scip == set->scip);
15342 assert(SCIPvarIsIntegral(vlbvar));
15343 assert(infeasible != NULL);
15344
15345 SCIPsetDebugMsg(set, "adding variable lower bound <%s> >= %g<%s> + %g\n", SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
15346
15347 *infeasible = FALSE;
15348 if( nbdchgs != NULL )
15349 *nbdchgs = 0;
15350
15351 switch( SCIPvarGetStatus(var) )
15352 {
15354 assert(var->data.original.transvar != NULL);
15355 SCIP_CALL( SCIPvarAddVlb(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
15356 cliquetable, branchcand, eventqueue, eventfilter, vlbvar, vlbcoef, vlbconstant, transitive, infeasible, nbdchgs) );
15357 break;
15358
15362 /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
15363 SCIP_CALL( SCIPvarGetProbvarSum(&vlbvar, set, &vlbcoef, &vlbconstant) );
15364 SCIPsetDebugMsg(set, " -> transformed to variable lower bound <%s> >= %g<%s> + %g\n",
15365 SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
15366
15367 /* if the variables are the same, just update the corresponding bound */
15368 if( var == vlbvar )
15369 {
15370 /* if the variables cancel out, the variable bound constraint is redundant or proves global infeasibility */
15371 if( SCIPsetIsEQ(set, vlbcoef, 1.0) )
15372 {
15373 if( SCIPsetIsFeasPositive(set, vlbconstant) )
15374 *infeasible = TRUE;
15375 }
15376 else
15377 {
15380
15381 /* the variable bound constraint defines a new upper bound */
15382 if( SCIPsetIsGT(set, vlbcoef, 1.0) )
15383 {
15384 /* bound might be adjusted due to integrality condition */
15385 SCIP_Real newub = adjustedUb(set, SCIPvarIsIntegral(var), vlbconstant / (1.0 - vlbcoef));
15386
15387 /* check bounds for feasibility */
15388 if( SCIPsetIsFeasLT(set, newub, lb) )
15389 {
15390 *infeasible = TRUE;
15391 return SCIP_OKAY;
15392 }
15393
15394 /* improve global upper bound of variable */
15395 if( SCIPsetIsFeasLT(set, newub, ub) )
15396 {
15397 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
15398 * with the local bound, in this case we need to store the bound change as pending bound change
15399 */
15401 {
15402 assert(tree != NULL);
15403 assert(transprob != NULL);
15404 assert(SCIPprobIsTransformed(transprob));
15405
15406 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
15407 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, newub, SCIP_BOUNDTYPE_UPPER, FALSE) );
15408 }
15409 else
15410 {
15411 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newub) );
15412 }
15413
15414 if( nbdchgs != NULL )
15415 (*nbdchgs)++;
15416 }
15417 }
15418 /* the variable bound constraint defines a new lower bound */
15419 else
15420 {
15421 assert(SCIPsetIsLT(set, vlbcoef, 1.0));
15422
15423 /* bound might be adjusted due to integrality condition */
15424 SCIP_Real newlb = adjustedLb(set, SCIPvarIsIntegral(var), vlbconstant / (1.0 - vlbcoef));
15425
15426 /* check bounds for feasibility */
15427 if( SCIPsetIsFeasGT(set, newlb, ub) )
15428 {
15429 *infeasible = TRUE;
15430 return SCIP_OKAY;
15431 }
15432
15433 /* improve global lower bound of variable */
15434 if( SCIPsetIsFeasGT(set, newlb, lb) )
15435 {
15436 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
15437 * with the local bound, in this case we need to store the bound change as pending bound change
15438 */
15440 {
15441 assert(tree != NULL);
15442 assert(transprob != NULL);
15443 assert(SCIPprobIsTransformed(transprob));
15444
15445 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
15446 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, newlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
15447 }
15448 else
15449 {
15450 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newlb) );
15451 }
15452
15453 if( nbdchgs != NULL )
15454 (*nbdchgs)++;
15455 }
15456 }
15457 }
15458 }
15459 /* if the vlb coefficient is zero, just update the lower bound of the variable */
15460 else if( SCIPsetIsZero(set, vlbcoef) )
15461 {
15462 /* bound might be adjusted due to integrality condition */
15463 vlbconstant = adjustedLb(set, SCIPvarIsIntegral(var), vlbconstant);
15464
15465 /* check bounds for feasibility */
15466 if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetUbGlobal(var)) )
15467 *infeasible = TRUE;
15468 /* improve global lower bound of variable */
15469 else if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetLbGlobal(var)) )
15470 {
15471 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
15472 * with the local bound, in this case we need to store the bound change as pending bound change
15473 */
15475 {
15476 assert(tree != NULL);
15477 assert(transprob != NULL);
15478 assert(SCIPprobIsTransformed(transprob));
15479
15480 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
15481 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, vlbconstant, SCIP_BOUNDTYPE_LOWER, FALSE) );
15482 }
15483 else
15484 {
15485 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vlbconstant) );
15486 }
15487
15488 if( nbdchgs != NULL )
15489 (*nbdchgs)++;
15490 }
15491 }
15492 else if( SCIPvarIsActive(vlbvar) )
15493 {
15494 SCIP_Real xlb;
15495 SCIP_Real xub;
15496 SCIP_Real zlb;
15497 SCIP_Real zub;
15498 SCIP_Real minvlb;
15499 SCIP_Real maxvlb;
15500
15502 assert(vlbcoef != 0.0);
15503
15504 minvlb = -SCIPsetInfinity(set);
15505 maxvlb = SCIPsetInfinity(set);
15506
15507 xlb = SCIPvarGetLbGlobal(var);
15508 xub = SCIPvarGetUbGlobal(var);
15509 zlb = SCIPvarGetLbGlobal(vlbvar);
15510 zub = SCIPvarGetUbGlobal(vlbvar);
15511
15512 /* improve global bounds of vlb variable, and calculate minimal and maximal value of variable bound */
15513 if( vlbcoef >= 0.0 )
15514 {
15515 if( !SCIPsetIsInfinity(set, xub) )
15516 {
15517 /* x >= b*z + d -> z <= (x-d)/b */
15518 SCIP_Real newzub = adjustedUb(set, SCIPvarIsIntegral(vlbvar), (xub - vlbconstant) / vlbcoef);
15519
15520 /* check bounds for feasibility */
15521 if( SCIPsetIsFeasLT(set, newzub, zlb) )
15522 {
15523 *infeasible = TRUE;
15524 return SCIP_OKAY;
15525 }
15526
15527 /* improve global upper bound of variable */
15528 if( SCIPsetIsFeasLT(set, newzub, zub) )
15529 {
15530 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
15531 * with the local bound, in this case we need to store the bound change as pending bound change
15532 */
15534 {
15535 assert(tree != NULL);
15536 assert(transprob != NULL);
15537 assert(SCIPprobIsTransformed(transprob));
15538
15539 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
15540 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, vlbvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
15541 }
15542 else
15543 {
15544 SCIP_CALL( SCIPvarChgUbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
15545 }
15546 zub = newzub;
15547
15548 if( nbdchgs != NULL )
15549 (*nbdchgs)++;
15550 }
15551 maxvlb = vlbcoef * zub + vlbconstant;
15552 if( !SCIPsetIsInfinity(set, -zlb) )
15553 minvlb = vlbcoef * zlb + vlbconstant;
15554 }
15555 else
15556 {
15557 if( !SCIPsetIsInfinity(set, zub) )
15558 maxvlb = vlbcoef * zub + vlbconstant;
15559 if( !SCIPsetIsInfinity(set, -zlb) )
15560 minvlb = vlbcoef * zlb + vlbconstant;
15561 }
15562 }
15563 else
15564 {
15565 if( !SCIPsetIsInfinity(set, xub) )
15566 {
15567 /* x >= b*z + d -> z >= (x-d)/b */
15568 SCIP_Real newzlb = adjustedLb(set, SCIPvarIsIntegral(vlbvar), (xub - vlbconstant) / vlbcoef);
15569
15570 /* check bounds for feasibility */
15571 if( SCIPsetIsFeasGT(set, newzlb, zub) )
15572 {
15573 *infeasible = TRUE;
15574 return SCIP_OKAY;
15575 }
15576
15577 /* improve global lower bound of variable */
15578 if( SCIPsetIsFeasGT(set, newzlb, zlb) )
15579 {
15580 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
15581 * with the local bound, in this case we need to store the bound change as pending bound change
15582 */
15584 {
15585 assert(tree != NULL);
15586 assert(transprob != NULL);
15587 assert(SCIPprobIsTransformed(transprob));
15588
15589 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
15590 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, vlbvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
15591 }
15592 else
15593 {
15594 SCIP_CALL( SCIPvarChgLbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
15595 }
15596 zlb = newzlb;
15597
15598 if( nbdchgs != NULL )
15599 (*nbdchgs)++;
15600 }
15601 maxvlb = vlbcoef * zlb + vlbconstant;
15602 if( !SCIPsetIsInfinity(set, zub) )
15603 minvlb = vlbcoef * zub + vlbconstant;
15604 }
15605 else
15606 {
15607 if( !SCIPsetIsInfinity(set, -zlb) )
15608 maxvlb = vlbcoef * zlb + vlbconstant;
15609 if( !SCIPsetIsInfinity(set, zub) )
15610 minvlb = vlbcoef * zub + vlbconstant;
15611 }
15612 }
15613 if( maxvlb < minvlb )
15614 maxvlb = minvlb;
15615
15616 /* adjust bounds due to integrality of variable */
15617 minvlb = adjustedLb(set, SCIPvarIsIntegral(var), minvlb);
15618 maxvlb = adjustedLb(set, SCIPvarIsIntegral(var), maxvlb);
15619
15620 /* check bounds for feasibility */
15621 if( SCIPsetIsFeasGT(set, minvlb, xub) )
15622 {
15623 *infeasible = TRUE;
15624 return SCIP_OKAY;
15625 }
15626
15627 /* improve global lower bound of variable */
15628 if( SCIPsetIsFeasGT(set, minvlb, xlb) )
15629 {
15630 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
15631 * with the local bound, in this case we need to store the bound change as pending bound change
15632 */
15634 {
15635 assert(tree != NULL);
15636 assert(transprob != NULL);
15637 assert(SCIPprobIsTransformed(transprob));
15638
15639 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
15640 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, minvlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
15641 }
15642 else
15643 {
15644 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, minvlb) );
15645 }
15646 xlb = minvlb;
15647
15648 if( nbdchgs != NULL )
15649 (*nbdchgs)++;
15650 }
15651 minvlb = xlb;
15652
15653 /* improve variable bound for binary z by moving the variable's global bound to the vlb constant */
15655 {
15656 /* b > 0: x >= (maxvlb - minvlb) * z + minvlb
15657 * b < 0: x >= (minvlb - maxvlb) * z + maxvlb
15658 */
15659
15660 assert(!SCIPsetIsInfinity(set, maxvlb) && !SCIPsetIsInfinity(set, -minvlb));
15661
15662 if( vlbcoef >= 0.0 )
15663 {
15664 vlbcoef = maxvlb - minvlb;
15665 vlbconstant = minvlb;
15666 }
15667 else
15668 {
15669 vlbcoef = minvlb - maxvlb;
15670 vlbconstant = maxvlb;
15671 }
15672 }
15673
15674 /* add variable bound to the variable bounds list */
15675 if( SCIPsetIsFeasGT(set, maxvlb, xlb) )
15676 {
15678 assert(!SCIPsetIsZero(set, vlbcoef));
15679
15680 /* if one of the variables is binary, add the corresponding implication to the variable's implication
15681 * list, thereby also adding the variable bound (or implication) to the other variable
15682 */
15684 {
15685 /* add corresponding implication:
15686 * b > 0, x >= b*z + d <-> z == 1 -> x >= b+d
15687 * b < 0, x >= b*z + d <-> z == 0 -> x >= d
15688 */
15689 SCIP_CALL( varAddTransitiveImplic(vlbvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
15690 cliquetable, branchcand, eventqueue, eventfilter, (vlbcoef >= 0.0), var, SCIP_BOUNDTYPE_LOWER, maxvlb, transitive,
15691 infeasible, nbdchgs) );
15692 }
15694 {
15695 /* add corresponding implication:
15696 * b > 0, x >= b*z + d <-> x == 0 -> z <= -d/b
15697 * b < 0, x >= b*z + d <-> x == 0 -> z >= -d/b
15698 */
15699 SCIP_Real implbound;
15700 implbound = -vlbconstant/vlbcoef;
15701
15702 /* tighten the implication bound if the variable is integer */
15703 if( SCIPvarIsIntegral(vlbvar) )
15704 {
15705 if( vlbcoef >= 0 )
15706 implbound = SCIPsetFloor(set, implbound);
15707 else
15708 implbound = SCIPsetCeil(set, implbound);
15709 }
15710 SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
15711 cliquetable, branchcand, eventqueue, eventfilter, FALSE, vlbvar, (vlbcoef >= 0.0 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER),
15712 implbound, transitive, infeasible, nbdchgs) );
15713 }
15714 else
15715 {
15716 SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, vlbvar, vlbcoef, vlbconstant) );
15717 }
15718 }
15719 }
15720 break;
15721
15723 /* x = a*y + c: x >= b*z + d <=> a*y + c >= b*z + d <=> y >= b/a * z + (d-c)/a, if a > 0
15724 * y <= b/a * z + (d-c)/a, if a < 0
15725 */
15726
15727 /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
15728 SCIP_CALL( SCIPvarGetProbvarSum(&vlbvar, set, &vlbcoef, &vlbconstant) );
15729
15730 /* if the variables cancel out, the variable bound constraint is redundant or proves global infeasibility */
15731 assert(var->data.aggregate.var != NULL);
15732 if( var->data.aggregate.var == vlbvar && SCIPsetIsEQ(set, var->data.aggregate.scalar, vlbcoef) )
15733 {
15734 if( SCIPsetIsFeasLT(set, var->data.aggregate.constant, vlbconstant) )
15735 *infeasible = TRUE;
15736 }
15737 else if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
15738 {
15739 /* a > 0 -> add variable lower bound */
15740 SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
15741 cliquetable, branchcand, eventqueue, eventfilter, vlbvar, vlbcoef/var->data.aggregate.scalar,
15742 (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
15743 }
15744 else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
15745 {
15746 /* a < 0 -> add variable upper bound */
15747 SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
15748 cliquetable, branchcand, eventqueue, eventfilter, vlbvar, vlbcoef/var->data.aggregate.scalar,
15749 (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
15750 }
15751 else
15752 {
15753 SCIPerrorMessage("scalar is zero in aggregation\n");
15754 return SCIP_INVALIDDATA;
15755 }
15756 break;
15757
15759 /* nothing to do here */
15760 break;
15761
15763 /* x = offset - x': x >= b*z + d <=> offset - x' >= b*z + d <=> x' <= -b*z + (offset-d) */
15764 assert(var->negatedvar != NULL);
15766 assert(var->negatedvar->negatedvar == var);
15767 SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
15768 branchcand, eventqueue, eventfilter, vlbvar, -vlbcoef, var->data.negate.constant - vlbconstant, transitive, infeasible,
15769 nbdchgs) );
15770 break;
15771
15772 default:
15773 SCIPerrorMessage("unknown variable status\n");
15774 return SCIP_INVALIDDATA;
15775 }
15776
15777 return SCIP_OKAY;
15778}
15779
15780/** informs variable x about a globally valid variable upper bound x <= b*z + d with integer variable z;
15781 * if z is binary, the corresponding valid implication for z is also added;
15782 * updates the global bounds of the variable and the vub variable correspondingly
15783 */
15785 SCIP_VAR* var, /**< problem variable */
15786 BMS_BLKMEM* blkmem, /**< block memory */
15787 SCIP_SET* set, /**< global SCIP settings */
15788 SCIP_STAT* stat, /**< problem statistics */
15789 SCIP_PROB* transprob, /**< transformed problem */
15790 SCIP_PROB* origprob, /**< original problem */
15791 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
15792 SCIP_REOPT* reopt, /**< reoptimization data structure */
15793 SCIP_LP* lp, /**< current LP data */
15794 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
15795 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
15796 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15797 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
15798 SCIP_VAR* vubvar, /**< variable z in x <= b*z + d */
15799 SCIP_Real vubcoef, /**< coefficient b in x <= b*z + d */
15800 SCIP_Real vubconstant, /**< constant d in x <= b*z + d */
15801 SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
15802 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
15803 int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
15804 )
15805{
15806 assert(var != NULL);
15807 assert(set != NULL);
15808 assert(var->scip == set->scip);
15809 assert(SCIPvarIsIntegral(vubvar));
15810 assert(infeasible != NULL);
15811
15812 SCIPsetDebugMsg(set, "adding variable upper bound <%s> <= %g<%s> + %g\n", SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
15813
15814 *infeasible = FALSE;
15815 if( nbdchgs != NULL )
15816 *nbdchgs = 0;
15817
15818 switch( SCIPvarGetStatus(var) )
15819 {
15821 assert(var->data.original.transvar != NULL);
15822 SCIP_CALL( SCIPvarAddVub(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
15823 cliquetable, branchcand, eventqueue, eventfilter, vubvar, vubcoef, vubconstant, transitive, infeasible, nbdchgs) );
15824 break;
15825
15829 /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
15830 SCIP_CALL( SCIPvarGetProbvarSum(&vubvar, set, &vubcoef, &vubconstant) );
15831 SCIPsetDebugMsg(set, " -> transformed to variable upper bound <%s> <= %g<%s> + %g\n",
15832 SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
15833
15834 /* if the variables are the same, just update the corresponding bound */
15835 if( var == vubvar )
15836 {
15837 /* if the variables cancel out, the variable bound constraint is redundant or proves global infeasibility */
15838 if( SCIPsetIsEQ(set, vubcoef, 1.0) )
15839 {
15840 if( SCIPsetIsFeasNegative(set, vubconstant) )
15841 *infeasible = TRUE;
15842 }
15843 else
15844 {
15847
15848 /* the variable bound constraint defines a new lower bound */
15849 if( SCIPsetIsGT(set, vubcoef, 1.0) )
15850 {
15851 /* bound might be adjusted due to integrality condition */
15852 SCIP_Real newlb = adjustedLb(set, SCIPvarIsIntegral(var), vubconstant / (1.0 - vubcoef));
15853
15854 /* check bounds for feasibility */
15855 if( SCIPsetIsFeasGT(set, newlb, ub) )
15856 {
15857 *infeasible = TRUE;
15858 return SCIP_OKAY;
15859 }
15860
15861 /* improve global lower bound of variable */
15862 if( SCIPsetIsFeasGT(set, newlb, lb) )
15863 {
15864 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
15865 * with the local bound, in this case we need to store the bound change as pending bound change
15866 */
15868 {
15869 assert(tree != NULL);
15870 assert(transprob != NULL);
15871 assert(SCIPprobIsTransformed(transprob));
15872
15873 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
15874 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, newlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
15875 }
15876 else
15877 {
15878 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newlb) );
15879 }
15880
15881 if( nbdchgs != NULL )
15882 (*nbdchgs)++;
15883 }
15884 }
15885 /* the variable bound constraint defines a new upper bound */
15886 else
15887 {
15888 assert(SCIPsetIsLT(set, vubcoef, 1.0));
15889
15890 /* bound might be adjusted due to integrality condition */
15891 SCIP_Real newub = adjustedUb(set, SCIPvarIsIntegral(var), vubconstant / (1.0 - vubcoef));
15892
15893 /* check bounds for feasibility */
15894 if( SCIPsetIsFeasLT(set, newub, lb) )
15895 {
15896 *infeasible = TRUE;
15897 return SCIP_OKAY;
15898 }
15899
15900 /* improve global upper bound of variable */
15901 if( SCIPsetIsFeasLT(set, newub, ub) )
15902 {
15903 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
15904 * with the local bound, in this case we need to store the bound change as pending bound change
15905 */
15907 {
15908 assert(tree != NULL);
15909 assert(transprob != NULL);
15910 assert(SCIPprobIsTransformed(transprob));
15911
15912 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
15913 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, newub, SCIP_BOUNDTYPE_UPPER, FALSE) );
15914 }
15915 else
15916 {
15917 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newub) );
15918 }
15919
15920 if( nbdchgs != NULL )
15921 (*nbdchgs)++;
15922 }
15923 }
15924 }
15925 }
15926 /* if the vub coefficient is zero, just update the upper bound of the variable */
15927 else if( SCIPsetIsZero(set, vubcoef) )
15928 {
15929 /* bound might be adjusted due to integrality condition */
15930 vubconstant = adjustedUb(set, SCIPvarIsIntegral(var), vubconstant);
15931
15932 /* check bounds for feasibility */
15933 if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetLbGlobal(var)) )
15934 *infeasible = TRUE;
15935 /* improve global upper bound of variable */
15936 else if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetUbGlobal(var)) )
15937 {
15938 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
15939 * with the local bound, in this case we need to store the bound change as pending bound change
15940 */
15942 {
15943 assert(tree != NULL);
15944 assert(transprob != NULL);
15945 assert(SCIPprobIsTransformed(transprob));
15946
15947 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
15948 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, vubconstant, SCIP_BOUNDTYPE_UPPER, FALSE) );
15949 }
15950 else
15951 {
15952 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vubconstant) );
15953 }
15954
15955 if( nbdchgs != NULL )
15956 (*nbdchgs)++;
15957 }
15958 }
15959 else if( SCIPvarIsActive(vubvar) )
15960 {
15961 SCIP_Real xlb;
15962 SCIP_Real xub;
15963 SCIP_Real zlb;
15964 SCIP_Real zub;
15965 SCIP_Real minvub;
15966 SCIP_Real maxvub;
15967
15969 assert(vubcoef != 0.0);
15970
15971 minvub = -SCIPsetInfinity(set);
15972 maxvub = SCIPsetInfinity(set);
15973
15974 xlb = SCIPvarGetLbGlobal(var);
15975 xub = SCIPvarGetUbGlobal(var);
15976 zlb = SCIPvarGetLbGlobal(vubvar);
15977 zub = SCIPvarGetUbGlobal(vubvar);
15978
15979 /* improve global bounds of vub variable, and calculate minimal and maximal value of variable bound */
15980 if( vubcoef >= 0.0 )
15981 {
15982 if( !SCIPsetIsInfinity(set, -xlb) )
15983 {
15984 /* x <= b*z + d -> z >= (x-d)/b */
15985 SCIP_Real newzlb = adjustedLb(set, SCIPvarIsIntegral(vubvar), (xlb - vubconstant) / vubcoef);
15986
15987 /* check bounds for feasibility */
15988 if( SCIPsetIsFeasGT(set, newzlb, zub) )
15989 {
15990 *infeasible = TRUE;
15991 return SCIP_OKAY;
15992 }
15993
15994 /* improve global lower bound of variable */
15995 if( SCIPsetIsFeasGT(set, newzlb, zlb) )
15996 {
15997 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
15998 * with the local bound, in this case we need to store the bound change as pending bound change
15999 */
16001 {
16002 assert(tree != NULL);
16003 assert(transprob != NULL);
16004 assert(SCIPprobIsTransformed(transprob));
16005
16006 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
16007 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, vubvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
16008 }
16009 else
16010 {
16011 SCIP_CALL( SCIPvarChgLbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
16012 }
16013 zlb = newzlb;
16014
16015 if( nbdchgs != NULL )
16016 (*nbdchgs)++;
16017 }
16018 minvub = vubcoef * zlb + vubconstant;
16019 if( !SCIPsetIsInfinity(set, zub) )
16020 maxvub = vubcoef * zub + vubconstant;
16021 }
16022 else
16023 {
16024 if( !SCIPsetIsInfinity(set, zub) )
16025 maxvub = vubcoef * zub + vubconstant;
16026 if( !SCIPsetIsInfinity(set, -zlb) )
16027 minvub = vubcoef * zlb + vubconstant;
16028 }
16029 }
16030 else
16031 {
16032 if( !SCIPsetIsInfinity(set, -xlb) )
16033 {
16034 /* x <= b*z + d -> z <= (x-d)/b */
16035 SCIP_Real newzub = adjustedUb(set, SCIPvarIsIntegral(vubvar), (xlb - vubconstant) / vubcoef);
16036
16037 /* check bounds for feasibility */
16038 if( SCIPsetIsFeasLT(set, newzub, zlb) )
16039 {
16040 *infeasible = TRUE;
16041 return SCIP_OKAY;
16042 }
16043
16044 /* improve global upper bound of variable */
16045 if( SCIPsetIsFeasLT(set, newzub, zub) )
16046 {
16047 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
16048 * with the local bound, in this case we need to store the bound change as pending bound change
16049 */
16051 {
16052 assert(tree != NULL);
16053 assert(transprob != NULL);
16054 assert(SCIPprobIsTransformed(transprob));
16055
16056 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
16057 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, vubvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
16058 }
16059 else
16060 {
16061 SCIP_CALL( SCIPvarChgUbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
16062 }
16063 zub = newzub;
16064
16065 if( nbdchgs != NULL )
16066 (*nbdchgs)++;
16067 }
16068 minvub = vubcoef * zub + vubconstant;
16069 if( !SCIPsetIsInfinity(set, -zlb) )
16070 maxvub = vubcoef * zlb + vubconstant;
16071 }
16072 else
16073 {
16074 if( !SCIPsetIsInfinity(set, zub) )
16075 minvub = vubcoef * zub + vubconstant;
16076 if( !SCIPsetIsInfinity(set, -zlb) )
16077 maxvub = vubcoef * zlb + vubconstant;
16078 }
16079 }
16080 if( minvub > maxvub )
16081 minvub = maxvub;
16082
16083 /* adjust bounds due to integrality of vub variable */
16084 minvub = adjustedUb(set, SCIPvarIsIntegral(var), minvub);
16085 maxvub = adjustedUb(set, SCIPvarIsIntegral(var), maxvub);
16086
16087 /* check bounds for feasibility */
16088 if( SCIPsetIsFeasLT(set, maxvub, xlb) )
16089 {
16090 *infeasible = TRUE;
16091 return SCIP_OKAY;
16092 }
16093
16094 /* improve global upper bound of variable */
16095 if( SCIPsetIsFeasLT(set, maxvub, xub) )
16096 {
16097 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
16098 * with the local bound, in this case we need to store the bound change as pending bound change
16099 */
16101 {
16102 assert(tree != NULL);
16103 assert(transprob != NULL);
16104 assert(SCIPprobIsTransformed(transprob));
16105
16106 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
16107 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, maxvub, SCIP_BOUNDTYPE_UPPER, FALSE) );
16108 }
16109 else
16110 {
16111 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, maxvub) );
16112 }
16113 xub = maxvub;
16114
16115 if( nbdchgs != NULL )
16116 (*nbdchgs)++;
16117 }
16118 maxvub = xub;
16119
16120 /* improve variable bound for binary z by moving the variable's global bound to the vub constant */
16121 if( SCIPvarIsBinary(vubvar) )
16122 {
16123 /* b > 0: x <= (maxvub - minvub) * z + minvub
16124 * b < 0: x <= (minvub - maxvub) * z + maxvub
16125 */
16126
16127 assert(!SCIPsetIsInfinity(set, maxvub) && !SCIPsetIsInfinity(set, -minvub));
16128
16129 if( vubcoef >= 0.0 )
16130 {
16131 vubcoef = maxvub - minvub;
16132 vubconstant = minvub;
16133 }
16134 else
16135 {
16136 vubcoef = minvub - maxvub;
16137 vubconstant = maxvub;
16138 }
16139 }
16140
16141 /* add variable bound to the variable bounds list */
16142 if( SCIPsetIsFeasLT(set, minvub, xub) )
16143 {
16145 assert(!SCIPsetIsZero(set, vubcoef));
16146
16147 /* if one of the variables is binary, add the corresponding implication to the variable's implication
16148 * list, thereby also adding the variable bound (or implication) to the other variable
16149 */
16151 {
16152 /* add corresponding implication:
16153 * b > 0, x <= b*z + d <-> z == 0 -> x <= d
16154 * b < 0, x <= b*z + d <-> z == 1 -> x <= b+d
16155 */
16156 SCIP_CALL( varAddTransitiveImplic(vubvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
16157 cliquetable, branchcand, eventqueue, eventfilter, (vubcoef < 0.0), var, SCIP_BOUNDTYPE_UPPER, minvub, transitive,
16158 infeasible, nbdchgs) );
16159 }
16161 {
16162 /* add corresponding implication:
16163 * b > 0, x <= b*z + d <-> x == 1 -> z >= (1-d)/b
16164 * b < 0, x <= b*z + d <-> x == 1 -> z <= (1-d)/b
16165 */
16166 SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
16167 cliquetable, branchcand, eventqueue, eventfilter, TRUE, vubvar, (vubcoef >= 0.0 ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER),
16168 (1.0-vubconstant)/vubcoef, transitive, infeasible, nbdchgs) );
16169 }
16170 else
16171 {
16172 SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, vubvar, vubcoef, vubconstant) );
16173 }
16174 }
16175 }
16176 break;
16177
16179 /* x = a*y + c: x <= b*z + d <=> a*y + c <= b*z + d <=> y <= b/a * z + (d-c)/a, if a > 0
16180 * y >= b/a * z + (d-c)/a, if a < 0
16181 */
16182
16183 /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
16184 SCIP_CALL( SCIPvarGetProbvarSum(&vubvar, set, &vubcoef, &vubconstant) );
16185
16186 /* if the variables cancel out, the variable bound constraint is redundant or proves global infeasibility */
16187 assert(var->data.aggregate.var != NULL);
16188 if( var->data.aggregate.var == vubvar && SCIPsetIsEQ(set, var->data.aggregate.scalar, vubcoef) )
16189 {
16190 if( SCIPsetIsFeasGT(set, var->data.aggregate.constant, vubconstant) )
16191 *infeasible = TRUE;
16192 }
16193 else if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
16194 {
16195 /* a > 0 -> add variable upper bound */
16196 SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
16197 cliquetable, branchcand, eventqueue, eventfilter, vubvar, vubcoef/var->data.aggregate.scalar,
16198 (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
16199 }
16200 else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
16201 {
16202 /* a < 0 -> add variable lower bound */
16203 SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
16204 cliquetable, branchcand, eventqueue, eventfilter, vubvar, vubcoef/var->data.aggregate.scalar,
16205 (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
16206 }
16207 else
16208 {
16209 SCIPerrorMessage("scalar is zero in aggregation\n");
16210 return SCIP_INVALIDDATA;
16211 }
16212 break;
16213
16215 /* nothing to do here */
16216 break;
16217
16219 /* x = offset - x': x <= b*z + d <=> offset - x' <= b*z + d <=> x' >= -b*z + (offset-d) */
16220 assert(var->negatedvar != NULL);
16222 assert(var->negatedvar->negatedvar == var);
16223 SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
16224 branchcand, eventqueue, eventfilter, vubvar, -vubcoef, var->data.negate.constant - vubconstant, transitive, infeasible,
16225 nbdchgs) );
16226 break;
16227
16228 default:
16229 SCIPerrorMessage("unknown variable status\n");
16230 return SCIP_INVALIDDATA;
16231 }
16232
16233 return SCIP_OKAY;
16234}
16235
16236/** informs binary variable x about a globally valid implication: x == 0 or x == 1 ==> y <= b or y >= b;
16237 * also adds the corresponding implication or variable bound to the implied variable;
16238 * if the implication is conflicting, the variable is fixed to the opposite value;
16239 * if the variable is already fixed to the given value, the implication is performed immediately;
16240 * if the implication is redundant with respect to the variables' global bounds, it is ignored
16241 */
16243 SCIP_VAR* var, /**< problem variable */
16244 BMS_BLKMEM* blkmem, /**< block memory */
16245 SCIP_SET* set, /**< global SCIP settings */
16246 SCIP_STAT* stat, /**< problem statistics */
16247 SCIP_PROB* transprob, /**< transformed problem */
16248 SCIP_PROB* origprob, /**< original problem */
16249 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
16250 SCIP_REOPT* reopt, /**< reoptimization data structure */
16251 SCIP_LP* lp, /**< current LP data */
16252 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
16253 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
16254 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
16255 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
16256 SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
16257 SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
16258 SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
16259 SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
16260 SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
16261 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
16262 int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
16263 )
16264{
16265 assert(var != NULL);
16266 assert(set != NULL);
16267 assert(var->scip == set->scip);
16269 assert(infeasible != NULL);
16270
16271 *infeasible = FALSE;
16272 if( nbdchgs != NULL )
16273 *nbdchgs = 0;
16274
16275 switch( SCIPvarGetStatus(var) )
16276 {
16278 assert(var->data.original.transvar != NULL);
16279 SCIP_CALL( SCIPvarAddImplic(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
16280 cliquetable, branchcand, eventqueue, eventfilter, varfixing, implvar, impltype, implbound, transitive, infeasible,
16281 nbdchgs) );
16282 break;
16283
16286 /* if the variable is fixed (although it has no FIXED status), and varfixing corresponds to the fixed value of
16287 * the variable, the implication can be applied directly;
16288 * otherwise, add implication to the implications list (and add inverse of implication to the implied variable)
16289 */
16290 if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
16291 {
16292 if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
16293 {
16294 SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
16295 eventfilter, cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
16296 }
16297 }
16298 else
16299 {
16300 SCIP_CALL( SCIPvarGetProbvarBound(&implvar, &implbound, &impltype) );
16301 SCIPvarAdjustBd(implvar, set, impltype, &implbound);
16302 if( SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED )
16303 {
16304 SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
16305 branchcand, eventqueue, eventfilter, varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
16306 }
16307 }
16308 break;
16309
16311 /* if varfixing corresponds to the fixed value of the variable, the implication can be applied directly */
16312 if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
16313 {
16314 SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
16315 eventfilter, cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
16316 }
16317 break;
16318
16320 /* implication added for x == 1:
16321 * x == 1 && x = 1*z + 0 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
16322 * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
16323 * implication added for x == 0:
16324 * x == 0 && x = 1*z + 0 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
16325 * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
16326 *
16327 * use only binary variables z
16328 */
16329 assert(var->data.aggregate.var != NULL);
16330 if( SCIPvarIsBinary(var->data.aggregate.var) )
16331 {
16332 assert( (SCIPsetIsEQ(set, var->data.aggregate.scalar, 1.0) && SCIPsetIsZero(set, var->data.aggregate.constant))
16333 || (SCIPsetIsEQ(set, var->data.aggregate.scalar, -1.0) && SCIPsetIsEQ(set, var->data.aggregate.constant, 1.0)) );
16334
16335 if( var->data.aggregate.scalar > 0 )
16336 {
16337 SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
16338 cliquetable, branchcand, eventqueue, eventfilter, varfixing, implvar, impltype, implbound, transitive, infeasible,
16339 nbdchgs) );
16340 }
16341 else
16342 {
16343 SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
16344 cliquetable, branchcand, eventqueue, eventfilter, !varfixing, implvar, impltype, implbound, transitive, infeasible,
16345 nbdchgs) );
16346 }
16347 }
16348 break;
16349
16351 /* nothing to do here */
16352 break;
16353
16355 /* implication added for x == 1:
16356 * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
16357 * implication added for x == 0:
16358 * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
16359 */
16360 assert(var->negatedvar != NULL);
16362 assert(var->negatedvar->negatedvar == var);
16363 assert(SCIPvarIsBinary(var->negatedvar));
16364
16365 if( SCIPvarGetType(var->negatedvar) == SCIP_VARTYPE_BINARY && !SCIPvarIsImpliedIntegral(var->negatedvar) )
16366 {
16367 SCIP_CALL( SCIPvarAddImplic(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
16368 cliquetable, branchcand, eventqueue, eventfilter, !varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
16369 }
16370 /* in case one both variables are not of binary type we have to add the implication as variable bounds */
16371 else
16372 {
16373 /* if the implied variable is of binary type exchange the variables */
16374 if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
16375 {
16376 SCIP_CALL( SCIPvarAddImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
16377 branchcand, eventqueue, eventfilter, (impltype == SCIP_BOUNDTYPE_UPPER) ? TRUE : FALSE, var->negatedvar,
16378 varfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER, varfixing ? 1.0 : 0.0, transitive,
16379 infeasible, nbdchgs) );
16380 }
16381 else
16382 {
16383 /* both variables are not of binary type but are implicit binary; in that case we can only add this
16384 * implication as variable bounds
16385 */
16386
16387 /* add variable lower bound on the negation of var */
16388 if( varfixing )
16389 {
16390 /* (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
16391 * as variable lower bound
16392 */
16393 SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
16394 cliquetable, branchcand, eventqueue, eventfilter, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : -1.0,
16395 (impltype == SCIP_BOUNDTYPE_UPPER) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
16396 }
16397 else
16398 {
16399 /* (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
16400 * as variable upper bound
16401 */
16402 SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
16403 cliquetable, branchcand, eventqueue, eventfilter, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? -1.0 : 1.0,
16404 (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : 0.0, transitive, infeasible, nbdchgs) );
16405 }
16406
16407 /* add variable bound on implvar */
16408 if( impltype == SCIP_BOUNDTYPE_UPPER )
16409 {
16410 /* (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
16411 * as variable upper bound
16412 */
16413 SCIP_CALL( SCIPvarAddVub(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
16414 branchcand, eventqueue, eventfilter, var->negatedvar, (varfixing) ? 1.0 : -1.0,
16415 (varfixing) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
16416 }
16417 else
16418 {
16419 /* (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
16420 * as variable upper bound
16421 */
16422 SCIP_CALL( SCIPvarAddVlb(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
16423 branchcand, eventqueue, eventfilter, var->negatedvar, (varfixing) ? -1.0 : 1.0, (varfixing) ? 1.0 : 0.0,
16424 transitive, infeasible, nbdchgs) );
16425 }
16426 }
16427 }
16428 break;
16429
16430 default:
16431 SCIPerrorMessage("unknown variable status\n");
16432 return SCIP_INVALIDDATA;
16433 }
16434
16435 return SCIP_OKAY;
16436}
16437
16438/** returns whether there is an implication x == varfixing -> y <= b or y >= b in the implication graph;
16439 * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
16440 * both variables must be active, variable x must be binary
16441 */
16443 SCIP_VAR* var, /**< problem variable x */
16444 SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
16445 SCIP_VAR* implvar, /**< variable y to search for */
16446 SCIP_BOUNDTYPE impltype /**< type of implication y <=/>= b to search for */
16447 )
16448{
16449 assert(var != NULL);
16450 assert(implvar != NULL);
16452 assert(SCIPvarIsActive(implvar));
16454
16455 return var->implics != NULL && SCIPimplicsContainsImpl(var->implics, varfixing, implvar, impltype);
16456}
16457
16458/** returns whether there is an implication x == varfixing -> y == implvarfixing in the implication graph;
16459 * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
16460 * both variables must be active binary variables
16461 */
16463 SCIP_VAR* var, /**< problem variable x */
16464 SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
16465 SCIP_VAR* implvar, /**< variable y to search for */
16466 SCIP_Bool implvarfixing /**< value of the implied variable to search for */
16467 )
16468{
16469 assert(SCIPvarIsBinary(implvar));
16470
16471 return SCIPvarHasImplic(var, varfixing, implvar, implvarfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER);
16472}
16473
16474/** gets the values of b in implications x == varfixing -> y <= b or y >= b in the implication graph;
16475 * the values are set to SCIP_INVALID if there is no implied bound
16476 */
16478 SCIP_VAR* var, /**< problem variable x */
16479 SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
16480 SCIP_VAR* implvar, /**< variable y to search for */
16481 SCIP_Real* lb, /**< buffer to store the value of the implied lower bound */
16482 SCIP_Real* ub /**< buffer to store the value of the implied upper bound */
16483 )
16484{
16485 int lowerpos;
16486 int upperpos;
16487 SCIP_Real* bounds;
16488
16489 assert(lb != NULL);
16490 assert(ub != NULL);
16491
16492 *lb = SCIP_INVALID;
16493 *ub = SCIP_INVALID;
16494
16495 if( var->implics == NULL )
16496 return;
16497
16498 SCIPimplicsGetVarImplicPoss(var->implics, varfixing, implvar, &lowerpos, &upperpos);
16499 bounds = SCIPvarGetImplBounds(var, varfixing);
16500
16501 if( bounds == NULL )
16502 return;
16503
16504 if( lowerpos >= 0 )
16505 *lb = bounds[lowerpos];
16506
16507 if( upperpos >= 0 )
16508 *ub = bounds[upperpos];
16509}
16510
16511
16512/** fixes the bounds of a binary variable to the given value, counting bound changes and detecting infeasibility */
16514 SCIP_VAR* var, /**< problem variable */
16515 BMS_BLKMEM* blkmem, /**< block memory */
16516 SCIP_SET* set, /**< global SCIP settings */
16517 SCIP_STAT* stat, /**< problem statistics */
16518 SCIP_PROB* transprob, /**< transformed problem */
16519 SCIP_PROB* origprob, /**< original problem */
16520 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
16521 SCIP_REOPT* reopt, /**< reoptimization data structure */
16522 SCIP_LP* lp, /**< current LP data */
16523 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
16524 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
16525 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
16526 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
16527 SCIP_Bool value, /**< value to fix variable to */
16528 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
16529 int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
16530 )
16531{
16532 assert(var != NULL);
16533 assert(set != NULL);
16534 assert(var->scip == set->scip);
16535 assert(infeasible != NULL);
16536
16537 *infeasible = FALSE;
16538
16539 if( value == FALSE )
16540 {
16541 if( var->glbdom.lb > 0.5 )
16542 *infeasible = TRUE;
16543 else if( var->glbdom.ub > 0.5 )
16544 {
16545 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
16546 * with the local bound, in this case we need to store the bound change as pending bound change
16547 */
16549 {
16550 assert(tree != NULL);
16551 assert(transprob != NULL);
16552 assert(SCIPprobIsTransformed(transprob));
16553
16554 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
16555 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
16556 }
16557 else
16558 {
16559 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
16560 }
16561
16562 if( nbdchgs != NULL )
16563 (*nbdchgs)++;
16564 }
16565 }
16566 else
16567 {
16568 if( var->glbdom.ub < 0.5 )
16569 *infeasible = TRUE;
16570 else if( var->glbdom.lb < 0.5 )
16571 {
16572 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
16573 * with the local bound, in this case we need to store the bound change as pending bound change
16574 */
16576 {
16577 assert(tree != NULL);
16578 assert(transprob != NULL);
16579 assert(SCIPprobIsTransformed(transprob));
16580
16581 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
16582 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
16583 }
16584 else
16585 {
16586 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
16587 }
16588
16589 if( nbdchgs != NULL )
16590 (*nbdchgs)++;
16591 }
16592 }
16593
16594 return SCIP_OKAY;
16595}
16596
16597/** adds the variable to the given clique and updates the list of cliques the binary variable is member of;
16598 * if the variable now appears twice in the clique with the same value, it is fixed to the opposite value;
16599 * if the variable now appears twice in the clique with opposite values, all other variables are fixed to
16600 * the opposite of the value they take in the clique
16601 */
16603 SCIP_VAR* var, /**< problem variable */
16604 BMS_BLKMEM* blkmem, /**< block memory */
16605 SCIP_SET* set, /**< global SCIP settings */
16606 SCIP_STAT* stat, /**< problem statistics */
16607 SCIP_PROB* transprob, /**< transformed problem */
16608 SCIP_PROB* origprob, /**< original problem */
16609 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
16610 SCIP_REOPT* reopt, /**< reoptimization data structure */
16611 SCIP_LP* lp, /**< current LP data */
16612 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
16613 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
16614 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
16615 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
16616 SCIP_Bool value, /**< value of the variable in the clique */
16617 SCIP_CLIQUE* clique, /**< clique the variable should be added to */
16618 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
16619 int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
16620 )
16621{
16622 assert(var != NULL);
16623 assert(set != NULL);
16624 assert(var->scip == set->scip);
16626 assert(infeasible != NULL);
16627
16628 *infeasible = FALSE;
16629
16630 /* get corresponding active problem variable */
16637
16638 /* only column and loose variables may be member of a clique */
16640 {
16641 SCIP_Bool doubleentry;
16642 SCIP_Bool oppositeentry;
16643
16644 /* add variable to clique */
16645 SCIP_CALL( SCIPcliqueAddVar(clique, blkmem, set, var, value, &doubleentry, &oppositeentry) );
16646
16647 /* add clique to variable's clique list */
16648 SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
16649
16650 /* check consistency of cliquelist */
16651 SCIPcliquelistCheck(var->cliquelist, var);
16652
16653 /* if the variable now appears twice with the same value in the clique, it can be fixed to the opposite value */
16654 if( doubleentry )
16655 {
16656 SCIP_CALL( SCIPvarFixBinary(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
16657 eventqueue, eventfilter, cliquetable, !value, infeasible, nbdchgs) );
16658 }
16659
16660 /* if the variable appears with both values in the clique, all other variables of the clique can be fixed
16661 * to the opposite of the value they take in the clique
16662 */
16663 if( oppositeentry )
16664 {
16665 SCIP_VAR** vars;
16666 SCIP_Bool* values;
16667 int nvars;
16668 int i;
16669
16670 nvars = SCIPcliqueGetNVars(clique);
16671 vars = SCIPcliqueGetVars(clique);
16672 values = SCIPcliqueGetValues(clique);
16673 for( i = 0; i < nvars && !(*infeasible); ++i )
16674 {
16675 if( vars[i] == var )
16676 continue;
16677
16678 SCIP_CALL( SCIPvarFixBinary(vars[i], blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
16679 eventqueue, eventfilter, cliquetable, !values[i], infeasible, nbdchgs) );
16680 }
16681 }
16682 }
16683
16684 return SCIP_OKAY;
16685}
16686
16687/** adds a filled clique to the cliquelists of all corresponding variables */
16689 SCIP_VAR** vars, /**< problem variables */
16690 SCIP_Bool* values, /**< values of the variables in the clique */
16691 int nvars, /**< number of problem variables */
16692 BMS_BLKMEM* blkmem, /**< block memory */
16693 SCIP_SET* set, /**< global SCIP settings */
16694 SCIP_CLIQUE* clique /**< clique that contains all given variables and values */
16695 )
16696{
16697 SCIP_VAR* var;
16698 int v;
16699
16700 assert(vars != NULL);
16701 assert(values != NULL);
16702 assert(nvars > 0);
16703 assert(set != NULL);
16704 assert(blkmem != NULL);
16705 assert(clique != NULL);
16706
16707 for( v = nvars - 1; v >= 0; --v )
16708 {
16709 var = vars[v];
16712
16713 /* add clique to variable's clique list */
16714 SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, values[v], clique) );
16715
16716 /* check consistency of cliquelist */
16717 SCIPcliquelistCheck(var->cliquelist, var);
16718 }
16719
16720 return SCIP_OKAY;
16721}
16722
16723/** adds a clique to the list of cliques of the given binary variable, but does not change the clique
16724 * itself
16725 */
16727 SCIP_VAR* var, /**< problem variable */
16728 BMS_BLKMEM* blkmem, /**< block memory */
16729 SCIP_SET* set, /**< global SCIP settings */
16730 SCIP_Bool value, /**< value of the variable in the clique */
16731 SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
16732 )
16733{
16734 assert(var != NULL);
16737
16738 /* add clique to variable's clique list */
16739 SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
16740
16741 return SCIP_OKAY;
16742}
16743
16744
16745/** deletes a clique from the list of cliques the binary variable is member of, but does not change the clique
16746 * itself
16747 */
16749 SCIP_VAR* var, /**< problem variable */
16750 BMS_BLKMEM* blkmem, /**< block memory */
16751 SCIP_Bool value, /**< value of the variable in the clique */
16752 SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
16753 )
16754{
16755 assert(var != NULL);
16757
16758 /* delete clique from variable's clique list */
16759 SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
16760
16761 return SCIP_OKAY;
16762}
16763
16764/** deletes the variable from the given clique and updates the list of cliques the binary variable is member of */
16766 SCIP_VAR* var, /**< problem variable */
16767 BMS_BLKMEM* blkmem, /**< block memory */
16768 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
16769 SCIP_Bool value, /**< value of the variable in the clique */
16770 SCIP_CLIQUE* clique /**< clique the variable should be removed from */
16771 )
16772{
16773 assert(var != NULL);
16775
16776 /* get corresponding active problem variable */
16783
16784 /* only column and loose variables may be member of a clique */
16786 {
16787 /* delete clique from variable's clique list */
16788 SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
16789
16790 /* delete variable from clique */
16791 SCIPcliqueDelVar(clique, cliquetable, var, value);
16792
16793 /* check consistency of cliquelist */
16794 SCIPcliquelistCheck(var->cliquelist, var);
16795 }
16796
16797 return SCIP_OKAY;
16798}
16799
16800/** returns whether there is a clique that contains both given variable/value pairs;
16801 * the variables must be active binary variables;
16802 * if regardimplics is FALSE, only the cliques in the clique table are looked at;
16803 * if regardimplics is TRUE, both the cliques and the implications of the implication graph are regarded
16804 *
16805 * @note a variable with it's negated variable are NOT! in a clique
16806 * @note a variable with itself are in a clique
16807 */
16809 SCIP_VAR* var1, /**< first variable */
16810 SCIP_Bool value1, /**< value of first variable */
16811 SCIP_VAR* var2, /**< second variable */
16812 SCIP_Bool value2, /**< value of second variable */
16813 SCIP_Bool regardimplics /**< should the implication graph also be searched for a clique? */
16814 )
16815{
16816 assert(var1 != NULL);
16817 assert(var2 != NULL);
16818 assert(SCIPvarIsActive(var1));
16819 assert(SCIPvarIsActive(var2));
16820 assert(SCIPvarIsBinary(var1));
16821 assert(SCIPvarIsBinary(var2));
16822
16823 return (SCIPcliquelistsHaveCommonClique(var1->cliquelist, value1, var2->cliquelist, value2)
16824 || (regardimplics && SCIPvarHasImplic(var1, value1, var2, value2 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER)));
16825}
16826
16827/** actually changes the branch factor of the variable and of all parent variables */
16828static
16830 SCIP_VAR* var, /**< problem variable */
16831 SCIP_SET* set, /**< global SCIP settings */
16832 SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
16833 )
16834{
16835 SCIP_VAR* parentvar;
16836 SCIP_Real eps;
16837 int i;
16838
16839 assert(var != NULL);
16840 assert(set != NULL);
16841 assert(var->scip == set->scip);
16842
16843 /* only use positive values */
16845 branchfactor = MAX(branchfactor, eps);
16846
16847 SCIPsetDebugMsg(set, "process changing branch factor of <%s> from %f to %f\n", var->name, var->branchfactor, branchfactor);
16848
16849 if( SCIPsetIsEQ(set, branchfactor, var->branchfactor) )
16850 return SCIP_OKAY;
16851
16852 /* change the branch factor */
16853 var->branchfactor = branchfactor;
16854
16855 /* process parent variables */
16856 for( i = 0; i < var->nparentvars; ++i )
16857 {
16858 parentvar = var->parentvars[i];
16859 assert(parentvar != NULL);
16860
16861 switch( SCIPvarGetStatus(parentvar) )
16862 {
16864 /* do not change priorities across the border between transformed and original problem */
16865 break;
16866
16871 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
16872 SCIPABORT();
16873 return SCIP_INVALIDDATA; /*lint !e527*/
16874
16877 SCIP_CALL( varProcessChgBranchFactor(parentvar, set, branchfactor) );
16878 break;
16879
16880 default:
16881 SCIPerrorMessage("unknown variable status\n");
16882 SCIPABORT();
16883 return SCIP_ERROR; /*lint !e527*/
16884 }
16885 }
16886
16887 return SCIP_OKAY;
16888}
16889
16890/** sets the branch factor of the variable; this value can be used in the branching methods to scale the score
16891 * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
16892 */
16894 SCIP_VAR* var, /**< problem variable */
16895 SCIP_SET* set, /**< global SCIP settings */
16896 SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
16897 )
16898{
16899 int v;
16900
16901 assert(var != NULL);
16902 assert(set != NULL);
16903 assert(var->scip == set->scip);
16904 assert(branchfactor >= 0.0);
16905
16906 SCIPdebugMessage("changing branch factor of <%s> from %g to %g\n", var->name, var->branchfactor, branchfactor);
16907
16908 if( SCIPsetIsEQ(set, var->branchfactor, branchfactor) )
16909 return SCIP_OKAY;
16910
16911 /* change priorities of attached variables */
16912 switch( SCIPvarGetStatus(var) )
16913 {
16915 if( var->data.original.transvar != NULL )
16916 {
16917 SCIP_CALL( SCIPvarChgBranchFactor(var->data.original.transvar, set, branchfactor) );
16918 }
16919 else
16920 {
16921 assert(set->stage == SCIP_STAGE_PROBLEM);
16922 var->branchfactor = branchfactor;
16923 }
16924 break;
16925
16929 SCIP_CALL( varProcessChgBranchFactor(var, set, branchfactor) );
16930 break;
16931
16933 assert(!var->donotaggr);
16934 assert(var->data.aggregate.var != NULL);
16935 SCIP_CALL( SCIPvarChgBranchFactor(var->data.aggregate.var, set, branchfactor) );
16936 break;
16937
16939 assert(!var->donotmultaggr);
16940 for( v = 0; v < var->data.multaggr.nvars; ++v )
16941 {
16942 SCIP_CALL( SCIPvarChgBranchFactor(var->data.multaggr.vars[v], set, branchfactor) );
16943 }
16944 break;
16945
16947 assert(var->negatedvar != NULL);
16949 assert(var->negatedvar->negatedvar == var);
16950 SCIP_CALL( SCIPvarChgBranchFactor(var->negatedvar, set, branchfactor) );
16951 break;
16952
16953 default:
16954 SCIPerrorMessage("unknown variable status\n");
16955 SCIPABORT();
16956 return SCIP_ERROR; /*lint !e527*/
16957 }
16958
16959 return SCIP_OKAY;
16960}
16961
16962/** actually changes the branch priority of the variable and of all parent variables */
16963static
16965 SCIP_VAR* var, /**< problem variable */
16966 int branchpriority /**< branching priority of the variable */
16967 )
16968{
16969 SCIP_VAR* parentvar;
16970 int i;
16971
16972 assert(var != NULL);
16973
16974 SCIPdebugMessage("process changing branch priority of <%s> from %d to %d\n",
16975 var->name, var->branchpriority, branchpriority);
16976
16977 if( branchpriority == var->branchpriority )
16978 return SCIP_OKAY;
16979
16980 /* change the branch priority */
16981 var->branchpriority = branchpriority;
16982
16983 /* process parent variables */
16984 for( i = 0; i < var->nparentvars; ++i )
16985 {
16986 parentvar = var->parentvars[i];
16987 assert(parentvar != NULL);
16988
16989 switch( SCIPvarGetStatus(parentvar) )
16990 {
16992 /* do not change priorities across the border between transformed and original problem */
16993 break;
16994
16999 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
17000 SCIPABORT();
17001 return SCIP_INVALIDDATA; /*lint !e527*/
17002
17005 SCIP_CALL( varProcessChgBranchPriority(parentvar, branchpriority) );
17006 break;
17007
17008 default:
17009 SCIPerrorMessage("unknown variable status\n");
17010 return SCIP_ERROR;
17011 }
17012 }
17013
17014 return SCIP_OKAY;
17015}
17016
17017/** sets the branch priority of the variable; variables with higher branch priority are always preferred to variables
17018 * with lower priority in selection of branching variable
17019 */
17021 SCIP_VAR* var, /**< problem variable */
17022 int branchpriority /**< branching priority of the variable */
17023 )
17024{
17025 int v;
17026
17027 assert(var != NULL);
17028
17029 SCIPdebugMessage("changing branch priority of <%s> from %d to %d\n", var->name, var->branchpriority, branchpriority);
17030
17031 if( var->branchpriority == branchpriority )
17032 return SCIP_OKAY;
17033
17034 /* change priorities of attached variables */
17035 switch( SCIPvarGetStatus(var) )
17036 {
17038 if( var->data.original.transvar != NULL )
17039 {
17040 SCIP_CALL( SCIPvarChgBranchPriority(var->data.original.transvar, branchpriority) );
17041 }
17042 else
17043 var->branchpriority = branchpriority;
17044 break;
17045
17049 SCIP_CALL( varProcessChgBranchPriority(var, branchpriority) );
17050 break;
17051
17053 assert(!var->donotaggr);
17054 assert(var->data.aggregate.var != NULL);
17055 SCIP_CALL( SCIPvarChgBranchPriority(var->data.aggregate.var, branchpriority) );
17056 break;
17057
17059 assert(!var->donotmultaggr);
17060 for( v = 0; v < var->data.multaggr.nvars; ++v )
17061 {
17062 SCIP_CALL( SCIPvarChgBranchPriority(var->data.multaggr.vars[v], branchpriority) );
17063 }
17064 break;
17065
17067 assert(var->negatedvar != NULL);
17069 assert(var->negatedvar->negatedvar == var);
17070 SCIP_CALL( SCIPvarChgBranchPriority(var->negatedvar, branchpriority) );
17071 break;
17072
17073 default:
17074 SCIPerrorMessage("unknown variable status\n");
17075 SCIPABORT();
17076 return SCIP_ERROR; /*lint !e527*/
17077 }
17078
17079 return SCIP_OKAY;
17080}
17081
17082/** actually changes the branch direction of the variable and of all parent variables */
17083static
17085 SCIP_VAR* var, /**< problem variable */
17086 SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
17087 )
17088{
17089 SCIP_VAR* parentvar;
17090 int i;
17091
17092 assert(var != NULL);
17093
17094 SCIPdebugMessage("process changing branch direction of <%s> from %u to %d\n",
17095 var->name, var->branchdirection, branchdirection);
17096
17097 if( branchdirection == (SCIP_BRANCHDIR)var->branchdirection )
17098 return SCIP_OKAY;
17099
17100 /* change the branch direction */
17101 var->branchdirection = branchdirection; /*lint !e641*/
17102
17103 /* process parent variables */
17104 for( i = 0; i < var->nparentvars; ++i )
17105 {
17106 parentvar = var->parentvars[i];
17107 assert(parentvar != NULL);
17108
17109 switch( SCIPvarGetStatus(parentvar) )
17110 {
17112 /* do not change directions across the border between transformed and original problem */
17113 break;
17114
17119 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
17120 SCIPABORT();
17121 return SCIP_INVALIDDATA; /*lint !e527*/
17122
17124 if( parentvar->data.aggregate.scalar > 0.0 )
17125 {
17126 SCIP_CALL( varProcessChgBranchDirection(parentvar, branchdirection) );
17127 }
17128 else
17129 {
17130 SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
17131 }
17132 break;
17133
17135 SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
17136 break;
17137
17138 default:
17139 SCIPerrorMessage("unknown variable status\n");
17140 SCIPABORT();
17141 return SCIP_ERROR; /*lint !e527*/
17142 }
17143 }
17144
17145 return SCIP_OKAY;
17146}
17147
17148/** sets the branch direction of the variable; variables with higher branch direction are always preferred to variables
17149 * with lower direction in selection of branching variable
17150 */
17152 SCIP_VAR* var, /**< problem variable */
17153 SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
17154 )
17155{
17156 int v;
17157
17158 assert(var != NULL);
17159
17160 SCIPdebugMessage("changing branch direction of <%s> from %u to %d\n", var->name, var->branchdirection, branchdirection);
17161
17162 if( (SCIP_BRANCHDIR)var->branchdirection == branchdirection )
17163 return SCIP_OKAY;
17164
17165 /* change directions of attached variables */
17166 switch( SCIPvarGetStatus(var) )
17167 {
17169 if( var->data.original.transvar != NULL )
17170 {
17171 SCIP_CALL( SCIPvarChgBranchDirection(var->data.original.transvar, branchdirection) );
17172 }
17173 else
17174 var->branchdirection = branchdirection; /*lint !e641*/
17175 break;
17176
17180 SCIP_CALL( varProcessChgBranchDirection(var, branchdirection) );
17181 break;
17182
17184 assert(!var->donotaggr);
17185 assert(var->data.aggregate.var != NULL);
17186 if( var->data.aggregate.scalar > 0.0 )
17187 {
17188 SCIP_CALL( SCIPvarChgBranchDirection(var->data.aggregate.var, branchdirection) );
17189 }
17190 else
17191 {
17192 SCIP_CALL( SCIPvarChgBranchDirection(var->data.aggregate.var, SCIPbranchdirOpposite(branchdirection)) );
17193 }
17194 break;
17195
17197 assert(!var->donotmultaggr);
17198 for( v = 0; v < var->data.multaggr.nvars; ++v )
17199 {
17200 /* only update branching direction of aggregation variables, if they don't have a preferred direction yet */
17201 assert(var->data.multaggr.vars[v] != NULL);
17202 if( (SCIP_BRANCHDIR)var->data.multaggr.vars[v]->branchdirection == SCIP_BRANCHDIR_AUTO )
17203 {
17204 if( var->data.multaggr.scalars[v] > 0.0 )
17205 {
17206 SCIP_CALL( SCIPvarChgBranchDirection(var->data.multaggr.vars[v], branchdirection) );
17207 }
17208 else
17209 {
17210 SCIP_CALL( SCIPvarChgBranchDirection(var->data.multaggr.vars[v], SCIPbranchdirOpposite(branchdirection)) );
17211 }
17212 }
17213 }
17214 break;
17215
17217 assert(var->negatedvar != NULL);
17219 assert(var->negatedvar->negatedvar == var);
17220 SCIP_CALL( SCIPvarChgBranchDirection(var->negatedvar, SCIPbranchdirOpposite(branchdirection)) );
17221 break;
17222
17223 default:
17224 SCIPerrorMessage("unknown variable status\n");
17225 SCIPABORT();
17226 return SCIP_ERROR; /*lint !e527*/
17227 }
17228
17229 return SCIP_OKAY;
17230}
17231
17232/** compares the index of two variables, only active, fixed or negated variables are allowed, if a variable
17233 * is negated then the index of the corresponding active variable is taken, returns -1 if first is
17234 * smaller than, and +1 if first is greater than second variable index; returns 0 if both indices
17235 * are equal, which means both variables are equal
17236 */
17238 SCIP_VAR* var1, /**< first problem variable */
17239 SCIP_VAR* var2 /**< second problem variable */
17240 )
17241{
17242 assert(var1 != NULL);
17243 assert(var2 != NULL);
17246
17248 var1 = SCIPvarGetNegatedVar(var1);
17250 var2 = SCIPvarGetNegatedVar(var2);
17251
17252 assert(var1 != NULL);
17253 assert(var2 != NULL);
17254
17255 if( SCIPvarGetIndex(var1) < SCIPvarGetIndex(var2) )
17256 return -1;
17257 else if( SCIPvarGetIndex(var1) > SCIPvarGetIndex(var2) )
17258 return +1;
17259
17260 assert(var1 == var2);
17261 return 0;
17262}
17263
17264/** comparison method for sorting active and negated variables by non-decreasing index, active and negated
17265 * variables are handled as the same variables
17266 */
17267SCIP_DECL_SORTPTRCOMP(SCIPvarCompActiveAndNegated)
17268{
17269 return SCIPvarCompareActiveAndNegated((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
17270}
17271
17272/** compares the index of two variables, returns -1 if first is smaller than, and +1 if first is greater than second
17273 * variable index; returns 0 if both indices are equal, which means both variables are equal
17274 */
17276 SCIP_VAR* var1, /**< first problem variable */
17277 SCIP_VAR* var2 /**< second problem variable */
17278 )
17279{
17280 assert(var1 != NULL);
17281 assert(var2 != NULL);
17282
17283 if( var1->index < var2->index )
17284 return -1;
17285 else if( var1->index > var2->index )
17286 return +1;
17287 else
17288 {
17289 assert(var1 == var2);
17290 return 0;
17291 }
17292}
17293
17294/** comparison method for sorting variables by non-decreasing index */
17296{
17297 return SCIPvarCompare((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
17298}
17299
17300/** comparison method for sorting variables by non-decreasing objective coefficient */
17302{
17303 SCIP_Real obj1;
17304 SCIP_Real obj2;
17305
17306 obj1 = SCIPvarGetObj((SCIP_VAR*)elem1);
17307 obj2 = SCIPvarGetObj((SCIP_VAR*)elem2);
17308
17309 if( obj1 < obj2 )
17310 return -1;
17311 else if( obj1 > obj2 )
17312 return +1;
17313 else
17314 return 0;
17315}
17316
17317/** hash key retrieval function for variables */
17318SCIP_DECL_HASHGETKEY(SCIPvarGetHashkey)
17319{ /*lint --e{715}*/
17320 return elem;
17321}
17322
17323/** returns TRUE iff the indices of both variables are equal */
17324SCIP_DECL_HASHKEYEQ(SCIPvarIsHashkeyEq)
17325{ /*lint --e{715}*/
17326 if( key1 == key2 )
17327 return TRUE;
17328 return FALSE;
17329}
17330
17331/** returns the hash value of the key */
17332SCIP_DECL_HASHKEYVAL(SCIPvarGetHashkeyVal)
17333{ /*lint --e{715}*/
17334 assert( SCIPvarGetIndex((SCIP_VAR*) key) >= 0 );
17335 return (unsigned int) SCIPvarGetIndex((SCIP_VAR*) key);
17336}
17337
17338/** return for given variables all their active counterparts; all active variables will be pairwise different */
17340 SCIP_SET* set, /**< global SCIP settings */
17341 SCIP_VAR** vars, /**< variable array with given variables and as output all active
17342 * variables, if enough slots exist
17343 */
17344 int* nvars, /**< number of given variables, and as output number of active variables,
17345 * if enough slots exist
17346 */
17347 int varssize, /**< available slots in vars array */
17348 int* requiredsize /**< pointer to store the required array size for the active variables */
17349 )
17350{
17351 SCIP_VAR** activevars;
17352 int nactivevars;
17353 int activevarssize;
17354
17355 SCIP_VAR* var;
17356 int v;
17357
17358 SCIP_VAR** tmpvars;
17359 SCIP_VAR** multvars;
17360 int tmpvarssize;
17361 int ntmpvars;
17362 int noldtmpvars;
17363 int nmultvars;
17364
17365 assert(set != NULL);
17366 assert(nvars != NULL);
17367 assert(vars != NULL || *nvars == 0);
17368 assert(varssize >= *nvars);
17369 assert(requiredsize != NULL);
17370
17371 *requiredsize = 0;
17372
17373 if( *nvars == 0 )
17374 return SCIP_OKAY;
17375
17376 nactivevars = 0;
17377 activevarssize = *nvars;
17378 ntmpvars = *nvars;
17379 tmpvarssize = *nvars;
17380
17381 /* temporary memory */
17382 SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
17383 /* coverity[copy_paste_error] */
17384 SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
17385
17386 noldtmpvars = ntmpvars;
17387
17388 /* sort all variables to combine equal variables easily */
17389 SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
17390 for( v = ntmpvars - 1; v > 0; --v )
17391 {
17392 /* combine same variables */
17393 if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
17394 {
17395 --ntmpvars;
17396 tmpvars[v] = tmpvars[ntmpvars];
17397 }
17398 }
17399 /* sort all variables again to combine equal variables later on */
17400 if( noldtmpvars > ntmpvars )
17401 SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
17402
17403 /* collect for each variable the representation in active variables */
17404 while( ntmpvars >= 1 )
17405 {
17406 --ntmpvars;
17407 var = tmpvars[ntmpvars];
17408 assert( var != NULL );
17409
17410 switch( SCIPvarGetStatus(var) )
17411 {
17413 if( var->data.original.transvar == NULL )
17414 {
17415 SCIPerrorMessage("original variable has no transformed variable attached\n");
17416 SCIPABORT();
17417 return SCIP_INVALIDDATA; /*lint !e527*/
17418 }
17419 tmpvars[ntmpvars] = var->data.original.transvar;
17420 ++ntmpvars;
17421 break;
17422
17424 tmpvars[ntmpvars] = var->data.aggregate.var;
17425 ++ntmpvars;
17426 break;
17427
17429 tmpvars[ntmpvars] = var->negatedvar;
17430 ++ntmpvars;
17431 break;
17432
17435 /* check for space in temporary memory */
17436 if( nactivevars >= activevarssize )
17437 {
17438 activevarssize *= 2;
17439 SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
17440 assert(nactivevars < activevarssize);
17441 }
17442 activevars[nactivevars] = var;
17443 nactivevars++;
17444 break;
17445
17447 /* x = a_1*y_1 + ... + a_n*y_n + c */
17448 nmultvars = var->data.multaggr.nvars;
17449 multvars = var->data.multaggr.vars;
17450
17451 /* check for space in temporary memory */
17452 if( nmultvars + ntmpvars > tmpvarssize )
17453 {
17454 while( nmultvars + ntmpvars > tmpvarssize )
17455 tmpvarssize *= 2;
17456 SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
17457 assert(nmultvars + ntmpvars <= tmpvarssize);
17458 }
17459
17460 /* copy all multi-aggregation variables into our working array */
17461 BMScopyMemoryArray(&tmpvars[ntmpvars], multvars, nmultvars); /*lint !e866*/
17462
17463 /* get active, fixed or multi-aggregated corresponding variables for all new ones */
17464 SCIPvarsGetProbvar(&tmpvars[ntmpvars], nmultvars);
17465
17466 ntmpvars += nmultvars;
17467 noldtmpvars = ntmpvars;
17468
17469 /* sort all variables to combine equal variables easily */
17470 SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
17471 for( v = ntmpvars - 1; v > 0; --v )
17472 {
17473 /* combine same variables */
17474 if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
17475 {
17476 --ntmpvars;
17477 tmpvars[v] = tmpvars[ntmpvars];
17478 }
17479 }
17480 /* sort all variables again to combine equal variables later on */
17481 if( noldtmpvars > ntmpvars )
17482 SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
17483
17484 break;
17485
17487 /* no need for memorizing fixed variables */
17488 break;
17489
17490 default:
17491 SCIPerrorMessage("unknown variable status\n");
17492 SCIPABORT();
17493 return SCIP_INVALIDDATA; /*lint !e527*/
17494 }
17495 }
17496
17497 /* sort variable array by variable index */
17498 SCIPsortPtr((void**)activevars, SCIPvarComp, nactivevars);
17499
17500 /* eliminate duplicates and count required size */
17501 v = nactivevars - 1;
17502 while( v > 0 )
17503 {
17504 /* combine both variable since they are the same */
17505 if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
17506 {
17507 --nactivevars;
17508 activevars[v] = activevars[nactivevars];
17509 }
17510 --v;
17511 }
17512 *requiredsize = nactivevars;
17513
17514 if( varssize >= *requiredsize )
17515 {
17516 assert(vars != NULL);
17517
17518 *nvars = *requiredsize;
17519 BMScopyMemoryArray(vars, activevars, nactivevars);
17520 }
17521
17522 SCIPsetFreeBufferArray(set, &tmpvars);
17523 SCIPsetFreeBufferArray(set, &activevars);
17524
17525 return SCIP_OKAY;
17526}
17527
17528/** gets corresponding active, fixed, or multi-aggregated problem variables of given variables,
17529 * @note the content of the given array will/might change
17530 */
17532 SCIP_VAR** vars, /**< array of problem variables */
17533 int nvars /**< number of variables */
17534 )
17535{
17536 int v;
17537
17538 assert(vars != NULL || nvars == 0);
17539
17540 for( v = nvars - 1; v >= 0; --v )
17541 {
17542 assert(vars != NULL);
17543 assert(vars[v] != NULL);
17544
17545 vars[v] = SCIPvarGetProbvar(vars[v]);
17546 assert(vars[v] != NULL);
17547 }
17548}
17549
17550/** gets corresponding active, fixed, or multi-aggregated problem variable of a variable */
17552 SCIP_VAR* var /**< problem variable */
17553 )
17554{
17555 SCIP_VAR* retvar;
17556
17557 assert(var != NULL);
17558
17559 retvar = var;
17560
17561 SCIPdebugMessage("get problem variable of <%s>\n", var->name);
17562
17563 while( TRUE ) /*lint !e716 */
17564 {
17565 assert(retvar != NULL);
17566
17567 switch( SCIPvarGetStatus(retvar) )
17568 {
17570 if( retvar->data.original.transvar == NULL )
17571 {
17572 SCIPerrorMessage("original variable has no transformed variable attached\n");
17573 SCIPABORT();
17574 return NULL; /*lint !e527 */
17575 }
17576 retvar = retvar->data.original.transvar;
17577 break;
17578
17582 return retvar;
17583
17585 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
17586 if ( retvar->data.multaggr.nvars == 1 )
17587 retvar = retvar->data.multaggr.vars[0];
17588 else
17589 return retvar;
17590 break;
17591
17593 retvar = retvar->data.aggregate.var;
17594 break;
17595
17597 retvar = retvar->negatedvar;
17598 break;
17599
17600 default:
17601 SCIPerrorMessage("unknown variable status\n");
17602 SCIPABORT();
17603 return NULL; /*lint !e527*/
17604 }
17605 }
17606}
17607
17608/** gets corresponding active, fixed, or multi-aggregated problem variables of binary variables and updates the given
17609 * negation status of each variable
17610 */
17612 SCIP_VAR*** vars, /**< pointer to binary problem variables */
17613 SCIP_Bool** negatedarr, /**< pointer to corresponding array to update the negation status */
17614 int nvars /**< number of variables and values in vars and negated array */
17615 )
17616{
17617 SCIP_VAR** var;
17618 SCIP_Bool* negated;
17619 int v;
17620
17621 assert(vars != NULL);
17622 assert(*vars != NULL || nvars == 0);
17623 assert(negatedarr != NULL);
17624 assert(*negatedarr != NULL || nvars == 0);
17625
17626 for( v = nvars - 1; v >= 0; --v )
17627 {
17628 var = &((*vars)[v]);
17629 negated = &((*negatedarr)[v]);
17630
17631 /* get problem variable */
17633 }
17634
17635 return SCIP_OKAY;
17636}
17637
17638
17639/** gets corresponding active, fixed, or multi-aggregated problem variable of a binary variable and updates the given
17640 * negation status (this means you have to assign a value to SCIP_Bool negated before calling this method, usually
17641 * FALSE is used)
17642 */
17644 SCIP_VAR** var, /**< pointer to binary problem variable */
17645 SCIP_Bool* negated /**< pointer to update the negation status */
17646 )
17647{
17649#ifndef NDEBUG
17650 SCIP_Real constant = 0.0;
17651 SCIP_Bool orignegated;
17652#endif
17653
17654 assert(var != NULL);
17655 assert(*var != NULL);
17656 assert(negated != NULL);
17658
17659#ifndef NDEBUG
17660 orignegated = *negated;
17661#endif
17662
17663 while( !active && *var != NULL )
17664 {
17665 switch( SCIPvarGetStatus(*var) )
17666 {
17668 if( (*var)->data.original.transvar == NULL )
17669 return SCIP_OKAY;
17670 *var = (*var)->data.original.transvar;
17671 break;
17672
17676 active = TRUE;
17677 break;
17678
17680 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
17681 if ( (*var)->data.multaggr.nvars == 1 )
17682 {
17683 assert( (*var)->data.multaggr.vars != NULL );
17684 assert( (*var)->data.multaggr.scalars != NULL );
17685 assert( SCIPvarIsBinary((*var)->data.multaggr.vars[0]) );
17686 assert(!EPSZ((*var)->data.multaggr.scalars[0], 1e-06));
17687
17688 /* if not all variables were fully propagated, it might happen that a variable is multi-aggregated to
17689 * another variable which needs to be fixed
17690 *
17691 * e.g. x = y - 1 => (x = 0 && y = 1)
17692 * e.g. x = y + 1 => (x = 1 && y = 0)
17693 *
17694 * is this special case we need to return the muti-aggregation
17695 */
17696 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)) )
17697 {
17698 assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06));
17699 }
17700 else
17701 {
17702 /* @note due to fixations, a multi-aggregation can have a constant of zero and a negative scalar or even
17703 * a scalar in absolute value unequal to one, in this case this aggregation variable needs to be
17704 * fixed to zero, but this should be done by another enforcement; so not depending on the scalar,
17705 * we will return the aggregated variable;
17706 */
17707 if( !EPSEQ(REALABS((*var)->data.multaggr.scalars[0]), 1.0, 1e-06) )
17708 {
17709 active = TRUE;
17710 break;
17711 }
17712
17713 /* @note it may also happen that the constant is larger than 1 or smaller than 0, in that case the
17714 * aggregation variable needs to be fixed to one, but this should be done by another enforcement;
17715 * so if this is the case, we will return the aggregated variable
17716 */
17717 assert(EPSZ((*var)->data.multaggr.constant, 1e-06) || EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06)
17718 || EPSZ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1e-06)
17719 || EPSEQ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1.0, 1e-06));
17720
17721 if( !EPSZ((*var)->data.multaggr.constant, 1e-06) && !EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06) )
17722 {
17723 active = TRUE;
17724 break;
17725 }
17726
17727 assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06) || EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
17728
17729 if( EPSZ((*var)->data.multaggr.constant, 1e-06) )
17730 {
17731 /* if the scalar is negative, either the aggregation variable is already fixed to zero or has at
17732 * least one uplock (that hopefully will enforce this fixation to zero); can it happen that this
17733 * variable itself is multi-aggregated again?
17734 */
17735 assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06) ?
17736 ((SCIPvarGetUbGlobal((*var)->data.multaggr.vars[0]) < 0.5) ||
17737 SCIPvarGetNLocksUpType((*var)->data.multaggr.vars[0], SCIP_LOCKTYPE_MODEL) > 0) : TRUE);
17738 }
17739 else
17740 {
17741 assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
17742#ifndef NDEBUG
17743 constant += (*negated) != orignegated ? -1.0 : 1.0;
17744#endif
17745
17746 *negated = !(*negated);
17747 }
17748 *var = (*var)->data.multaggr.vars[0];
17749 break;
17750 }
17751 }
17752 active = TRUE; /*lint !e838*/
17753 break;
17754
17755 case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
17756 assert((*var)->data.aggregate.var != NULL);
17757 assert(EPSEQ((*var)->data.aggregate.scalar, 1.0, 1e-06) || EPSEQ((*var)->data.aggregate.scalar, -1.0, 1e-06));
17758 assert(EPSLE((*var)->data.aggregate.var->glbdom.ub - (*var)->data.aggregate.var->glbdom.lb, 1.0, 1e-06));
17759#ifndef NDEBUG
17760 constant += (*negated) != orignegated ? -(*var)->data.aggregate.constant : (*var)->data.aggregate.constant;
17761#endif
17762
17763 *negated = ((*var)->data.aggregate.scalar > 0.0) ? *negated : !(*negated);
17764 *var = (*var)->data.aggregate.var;
17765 break;
17766
17767 case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
17768 assert((*var)->negatedvar != NULL);
17769#ifndef NDEBUG
17770 constant += (*negated) != orignegated ? -1.0 : 1.0;
17771#endif
17772
17773 *negated = !(*negated);
17774 *var = (*var)->negatedvar;
17775 break;
17776
17777 default:
17778 SCIPerrorMessage("unknown variable status\n");
17779 return SCIP_INVALIDDATA;
17780 }
17781 }
17782 assert(active == (*var != NULL));
17783
17784 if( active )
17785 {
17787 assert(EPSZ(constant, 1e-06) || EPSEQ(constant, 1.0, 1e-06));
17788 assert(EPSZ(constant, 1e-06) == ((*negated) == orignegated));
17789
17790 return SCIP_OKAY;
17791 }
17792 else
17793 {
17794 SCIPerrorMessage("active variable path leads to NULL pointer\n");
17795 return SCIP_INVALIDDATA;
17796 }
17797}
17798
17799/** transforms given variable, boundtype and bound to the corresponding active, fixed, or multi-aggregated variable
17800 * values
17801 */
17803 SCIP_VAR** var, /**< pointer to problem variable */
17804 SCIP_Real* bound, /**< pointer to bound value to transform */
17805 SCIP_BOUNDTYPE* boundtype /**< pointer to type of bound: lower or upper bound */
17806 )
17807{
17808 assert(var != NULL);
17809 assert(*var != NULL);
17810 assert(bound != NULL);
17811 assert(boundtype != NULL);
17812
17813 SCIPdebugMessage("get probvar bound %g of type %d of variable <%s>\n", *bound, *boundtype, (*var)->name);
17814
17815 switch( SCIPvarGetStatus(*var) )
17816 {
17818 if( (*var)->data.original.transvar == NULL )
17819 {
17820 SCIPerrorMessage("original variable has no transformed variable attached\n");
17821 return SCIP_INVALIDDATA;
17822 }
17823 *var = (*var)->data.original.transvar;
17824 SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
17825 break;
17826
17830 break;
17831
17833 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
17834 if ( (*var)->data.multaggr.nvars == 1 )
17835 {
17836 assert( (*var)->data.multaggr.vars != NULL );
17837 assert( (*var)->data.multaggr.scalars != NULL );
17838 assert( (*var)->data.multaggr.scalars[0] != 0.0 );
17839
17840 (*bound) /= (*var)->data.multaggr.scalars[0];
17841 (*bound) -= (*var)->data.multaggr.constant/(*var)->data.multaggr.scalars[0];
17842 if ( (*var)->data.multaggr.scalars[0] < 0.0 )
17843 {
17844 if ( *boundtype == SCIP_BOUNDTYPE_LOWER )
17845 *boundtype = SCIP_BOUNDTYPE_UPPER;
17846 else
17847 *boundtype = SCIP_BOUNDTYPE_LOWER;
17848 }
17849 *var = (*var)->data.multaggr.vars[0];
17850 SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
17851 }
17852 break;
17853
17854 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
17855 assert((*var)->data.aggregate.var != NULL);
17856 assert((*var)->data.aggregate.scalar != 0.0);
17857
17858 (*bound) /= (*var)->data.aggregate.scalar;
17859 (*bound) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
17860 if( (*var)->data.aggregate.scalar < 0.0 )
17861 {
17862 if( *boundtype == SCIP_BOUNDTYPE_LOWER )
17863 *boundtype = SCIP_BOUNDTYPE_UPPER;
17864 else
17865 *boundtype = SCIP_BOUNDTYPE_LOWER;
17866 }
17867 *var = (*var)->data.aggregate.var;
17868 SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
17869 break;
17870
17871 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
17872 assert((*var)->negatedvar != NULL);
17873 assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
17874 assert((*var)->negatedvar->negatedvar == *var);
17875 (*bound) = (*var)->data.negate.constant - *bound;
17876 if( *boundtype == SCIP_BOUNDTYPE_LOWER )
17877 *boundtype = SCIP_BOUNDTYPE_UPPER;
17878 else
17879 *boundtype = SCIP_BOUNDTYPE_LOWER;
17880 *var = (*var)->negatedvar;
17881 SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
17882 break;
17883
17884 default:
17885 SCIPerrorMessage("unknown variable status\n");
17886 return SCIP_INVALIDDATA;
17887 }
17888
17889 return SCIP_OKAY;
17890}
17891
17892/** transforms given variable, boundtype and exact bound to the corresponding active, fixed, or multi-aggregated variable
17893 * values
17894 */
17896 SCIP_VAR** var, /**< pointer to problem variable */
17897 SCIP_RATIONAL* bound, /**< pointer to bound value to transform */
17898 SCIP_BOUNDTYPE* boundtype /**< pointer to type of bound: lower or upper bound */
17899 )
17900{
17901 assert(var != NULL);
17902 assert(*var != NULL);
17903 assert(bound != NULL);
17904 assert(boundtype != NULL);
17905
17906 SCIPrationalDebugMessage("get probvar bound %q of type %d of variable <%s>\n", bound, *boundtype, (*var)->name);
17907
17908 switch( SCIPvarGetStatusExact(*var) )
17909 {
17911 if( (*var)->data.original.transvar == NULL )
17912 {
17913 SCIPerrorMessage("original variable has no transformed variable attached\n");
17914 return SCIP_INVALIDDATA;
17915 }
17916 *var = (*var)->data.original.transvar;
17918 break;
17919
17923 break;
17924
17926 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
17927 if( (*var)->data.multaggr.nvars == 1 )
17928 {
17929 assert( (*var)->data.multaggr.vars != NULL );
17930 assert( (*var)->data.multaggr.scalars != NULL );
17931 assert( (*var)->data.multaggr.scalars[0] != 0.0 );
17932
17933 SCIPrationalDiff(bound, bound, (*var)->exactdata->multaggr.constant);
17934 SCIPrationalDiv(bound, bound, (*var)->exactdata->multaggr.scalars[0]);
17935
17936 if( SCIPrationalIsNegative((*var)->exactdata->multaggr.scalars[0]) )
17937 {
17938 if ( *boundtype == SCIP_BOUNDTYPE_LOWER )
17939 *boundtype = SCIP_BOUNDTYPE_UPPER;
17940 else
17941 *boundtype = SCIP_BOUNDTYPE_LOWER;
17942 }
17943 *var = (*var)->data.multaggr.vars[0];
17945 }
17946 break;
17947
17948 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
17949 assert((*var)->data.aggregate.var != NULL);
17950 assert((*var)->data.aggregate.scalar != 0.0);
17951
17952 SCIPrationalDiff(bound, bound, (*var)->exactdata->aggregate.constant);
17953 SCIPrationalDiv(bound, bound, (*var)->exactdata->aggregate.scalar);
17954
17955 if( SCIPrationalIsNegative((*var)->exactdata->aggregate.scalar) )
17956 {
17957 if( *boundtype == SCIP_BOUNDTYPE_LOWER )
17958 *boundtype = SCIP_BOUNDTYPE_UPPER;
17959 else
17960 *boundtype = SCIP_BOUNDTYPE_LOWER;
17961 }
17962 *var = (*var)->data.aggregate.var;
17964 break;
17965
17966 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
17967 assert((*var)->negatedvar != NULL);
17968 assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
17969 assert((*var)->negatedvar->negatedvar == *var);
17970 SCIPrationalDiffReal(bound, bound, (*var)->data.negate.constant);
17972 if( *boundtype == SCIP_BOUNDTYPE_LOWER )
17973 *boundtype = SCIP_BOUNDTYPE_UPPER;
17974 else
17975 *boundtype = SCIP_BOUNDTYPE_LOWER;
17976 *var = (*var)->negatedvar;
17978 break;
17979
17980 default:
17981 SCIPerrorMessage("unknown variable status\n");
17982 return SCIP_INVALIDDATA;
17983 }
17984
17985 return SCIP_OKAY;
17986}
17987
17988/** transforms given variable and domain hole to the corresponding active, fixed, or multi-aggregated variable
17989 * values
17990 */
17992 SCIP_VAR** var, /**< pointer to problem variable */
17993 SCIP_Real* left, /**< pointer to left bound of open interval in hole to transform */
17994 SCIP_Real* right /**< pointer to right bound of open interval in hole to transform */
17995 )
17996{
17997 assert(var != NULL);
17998 assert(*var != NULL);
17999 assert(left != NULL);
18000 assert(right != NULL);
18001
18002 SCIPdebugMessage("get probvar hole (%g,%g) of variable <%s>\n", *left, *right, (*var)->name);
18003
18004 switch( SCIPvarGetStatus(*var) )
18005 {
18007 if( (*var)->data.original.transvar == NULL )
18008 {
18009 SCIPerrorMessage("original variable has no transformed variable attached\n");
18010 return SCIP_INVALIDDATA;
18011 }
18012 *var = (*var)->data.original.transvar;
18013 SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
18014 break;
18015
18020 break;
18021
18022 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
18023 assert((*var)->data.aggregate.var != NULL);
18024 assert((*var)->data.aggregate.scalar != 0.0);
18025
18026 /* scale back */
18027 (*left) /= (*var)->data.aggregate.scalar;
18028 (*right) /= (*var)->data.aggregate.scalar;
18029
18030 /* shift back */
18031 (*left) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
18032 (*right) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
18033
18034 *var = (*var)->data.aggregate.var;
18035
18036 /* check if the interval bounds have to swapped */
18037 if( (*var)->data.aggregate.scalar < 0.0 )
18038 {
18039 SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
18040 }
18041 else
18042 {
18043 SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
18044 }
18045 break;
18046
18047 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
18048 assert((*var)->negatedvar != NULL);
18049 assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
18050 assert((*var)->negatedvar->negatedvar == *var);
18051
18052 /* shift and scale back */
18053 (*left) = (*var)->data.negate.constant - (*left);
18054 (*right) = (*var)->data.negate.constant - (*right);
18055
18056 *var = (*var)->negatedvar;
18057
18058 /* through the negated variable the left and right interval bound have to swapped */
18059 SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
18060 break;
18061
18062 default:
18063 SCIPerrorMessage("unknown variable status\n");
18064 return SCIP_INVALIDDATA;
18065 }
18066
18067 return SCIP_OKAY;
18068}
18069
18070/** transforms given variable, scalar and constant to the corresponding active, fixed, or
18071 * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed variable,
18072 * "scalar" will be 0.0 and the value of the sum will be stored in "constant"; a multi-aggregation
18073 * with only one active variable (this can happen due to fixings after the multi-aggregation),
18074 * is treated like an aggregation; if the multi-aggregation constant is infinite, "scalar" will be 0.0
18075 */
18077 SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
18078 SCIP_SET* set, /**< global SCIP settings */
18079 SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
18080 SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
18081 )
18082{
18083 assert(var != NULL);
18084 assert(scalar != NULL);
18085 assert(constant != NULL);
18086
18087 while( *var != NULL )
18088 {
18089 switch( SCIPvarGetStatus(*var) )
18090 {
18092 if( (*var)->data.original.transvar == NULL )
18093 {
18094 SCIPerrorMessage("original variable has no transformed variable attached\n");
18095 return SCIP_INVALIDDATA;
18096 }
18097 *var = (*var)->data.original.transvar;
18098 break;
18099
18102 return SCIP_OKAY;
18103
18104 case SCIP_VARSTATUS_FIXED: /* x = c' => a*x + c == (a*c' + c) */
18105 if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
18106 {
18107 if( SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)) )
18108 {
18109 assert(*scalar != 0.0);
18110 if( (*scalar) * (*var)->glbdom.lb > 0.0 )
18111 (*constant) = SCIPsetInfinity(set);
18112 else
18113 (*constant) = -SCIPsetInfinity(set);
18114 }
18115 else
18116 (*constant) += *scalar * (*var)->glbdom.lb;
18117 }
18118#ifndef NDEBUG
18119 else
18120 {
18121 assert(!SCIPsetIsInfinity(set, (*constant)) || !((*scalar) * (*var)->glbdom.lb < 0.0 &&
18122 (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
18123 assert(!SCIPsetIsInfinity(set, -(*constant)) || !((*scalar) * (*var)->glbdom.lb > 0.0 &&
18124 (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
18125 }
18126#endif
18127 *scalar = 0.0;
18128 return SCIP_OKAY;
18129
18131 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
18132 if ( (*var)->data.multaggr.nvars == 1 )
18133 {
18134 assert((*var)->data.multaggr.vars != NULL);
18135 assert((*var)->data.multaggr.scalars != NULL);
18136 assert((*var)->data.multaggr.vars[0] != NULL);
18137 if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
18138 {
18139 /* the multi-aggregation constant can be infinite, if one of the multi-aggregation variables
18140 * was fixed to +/-infinity; ensure that the constant is set to +/-infinity, too, and the scalar
18141 * is set to 0.0, because the multi-aggregated variable can be seen as fixed, too
18142 */
18143 if( SCIPsetIsInfinity(set, (*var)->data.multaggr.constant)
18144 || SCIPsetIsInfinity(set, -((*var)->data.multaggr.constant)) )
18145 {
18146 if( (*scalar) * (*var)->data.multaggr.constant > 0 )
18147 {
18148 assert(!SCIPsetIsInfinity(set, -(*constant)));
18149 (*constant) = SCIPsetInfinity(set);
18150 }
18151 else
18152 {
18153 assert(!SCIPsetIsInfinity(set, *constant));
18154 (*constant) = -SCIPsetInfinity(set);
18155 }
18156 (*scalar) = 0.0;
18157 }
18158 else
18159 (*constant) += *scalar * (*var)->data.multaggr.constant;
18160 }
18161 (*scalar) *= (*var)->data.multaggr.scalars[0];
18162 *var = (*var)->data.multaggr.vars[0];
18163 break;
18164 }
18165 return SCIP_OKAY;
18166
18167 case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
18168 assert((*var)->data.aggregate.var != NULL);
18169 assert(!SCIPsetIsInfinity(set, (*var)->data.aggregate.constant)
18170 && !SCIPsetIsInfinity(set, (*var)->data.aggregate.constant));
18171 if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
18172 (*constant) += *scalar * (*var)->data.aggregate.constant;
18173 (*scalar) *= (*var)->data.aggregate.scalar;
18174 *var = (*var)->data.aggregate.var;
18175 break;
18176
18177 case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
18178 assert((*var)->negatedvar != NULL);
18179 assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
18180 assert((*var)->negatedvar->negatedvar == *var);
18181 assert(!SCIPsetIsInfinity(set, (*var)->data.negate.constant)
18182 && !SCIPsetIsInfinity(set, (*var)->data.negate.constant));
18183 if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
18184 (*constant) += *scalar * (*var)->data.negate.constant;
18185 (*scalar) *= -1.0;
18186 *var = (*var)->negatedvar;
18187 break;
18188
18189 default:
18190 SCIPerrorMessage("unknown variable status\n");
18191 SCIPABORT();
18192 return SCIP_INVALIDDATA; /*lint !e527*/
18193 }
18194 }
18195 *scalar = 0.0;
18196
18197 return SCIP_OKAY;
18198}
18199
18200/** transforms given variable, scalar and constant to the corresponding active, fixed, or
18201 * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed variable,
18202 * "scalar" will be 0.0 and the value of the sum will be stored in "constant"; a multi-aggregation
18203 * with only one active variable (this can happen due to fixings after the multi-aggregation),
18204 * is treated like an aggregation; if the multi-aggregation constant is infinite, "scalar" will be 0.0
18205 */
18207 SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
18208 SCIP_RATIONAL* scalar, /**< pointer to scalar a in sum a*x + c */
18209 SCIP_RATIONAL* constant /**< pointer to constant c in sum a*x + c */
18210 )
18211{
18212 assert(var != NULL);
18213 assert(scalar != NULL);
18214 assert(constant != NULL);
18216
18217 while( *var != NULL )
18218 {
18219 switch( SCIPvarGetStatusExact(*var) )
18220 {
18222 if( (*var)->data.original.transvar == NULL )
18223 {
18224 SCIPerrorMessage("original variable has no transformed variable attached\n");
18225 return SCIP_INVALIDDATA;
18226 }
18227 *var = (*var)->data.original.transvar;
18228 break;
18229
18232 return SCIP_OKAY;
18233
18234 case SCIP_VARSTATUS_FIXED: /* x = c' => a*x + c == (a*c' + c) */
18235 if( !SCIPrationalIsInfinity(constant) && !SCIPrationalIsNegInfinity(constant) )
18236 {
18237 if( SCIPrationalIsInfinity((*var)->exactdata->glbdom.lb) || SCIPrationalIsNegInfinity(((*var)->exactdata->glbdom.lb)) )
18238 {
18239 assert(!SCIPrationalIsZero(scalar));
18240 if( SCIPrationalIsPositive(scalar) == SCIPrationalIsPositive((*var)->exactdata->glbdom.lb) )
18241 SCIPrationalSetInfinity(constant);
18242 else
18244 }
18245 else
18246 SCIPrationalAddProd(constant, scalar, (*var)->exactdata->glbdom.lb);
18247 }
18248 SCIPrationalSetReal(scalar, 0.0);
18249 return SCIP_OKAY;
18250
18252 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
18253 if ( (*var)->data.multaggr.nvars == 1 )
18254 {
18255 assert((*var)->data.multaggr.vars != NULL);
18256 assert((*var)->data.multaggr.scalars != NULL);
18257 assert((*var)->data.multaggr.vars[0] != NULL);
18258 if( !SCIPrationalIsAbsInfinity(constant) )
18259 {
18260 /* the multi-aggregation constant can be infinite, if one of the multi-aggregation variables
18261 * was fixed to +/-infinity; ensure that the constant is set to +/-infinity, too, and the scalar
18262 * is set to 0.0, because the multi-aggregated variable can be seen as fixed, too
18263 */
18264 if( SCIPrationalIsAbsInfinity((*var)->exactdata->multaggr.constant) )
18265 {
18266 if( SCIPrationalGetSign(scalar) == SCIPrationalGetSign((*var)->exactdata->multaggr.constant) && !SCIPrationalIsZero(scalar) )
18267 {
18269 SCIPrationalSetInfinity(constant);
18270 }
18271 else
18272 {
18273 assert(!SCIPrationalIsInfinity(constant));
18275 }
18276 SCIPrationalSetReal(scalar, 0.0);
18277 }
18278 else
18279 SCIPrationalAddProd(constant, scalar, (*var)->exactdata->multaggr.constant);
18280 }
18281 SCIPrationalMult(scalar, scalar, (*var)->exactdata->multaggr.scalars[0]);
18282 *var = (*var)->data.multaggr.vars[0];
18283 break;
18284 }
18285 return SCIP_OKAY;
18286
18287 case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
18288 assert((*var)->data.aggregate.var != NULL);
18289 assert(!SCIPrationalIsAbsInfinity((*var)->exactdata->aggregate.constant));
18290 if( !SCIPrationalIsAbsInfinity(constant) )
18291 SCIPrationalAddProd(constant, scalar, (*var)->exactdata->aggregate.constant);
18292 SCIPrationalMult(scalar, scalar, (*var)->exactdata->aggregate.scalar);
18293 *var = (*var)->data.aggregate.var;
18294 break;
18295 case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
18296 assert((*var)->negatedvar != NULL);
18297 assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
18298 assert((*var)->negatedvar->negatedvar == *var);
18299 if( !SCIPrationalIsInfinity(constant) && !SCIPrationalIsNegInfinity(constant) )
18300 SCIPrationalAddProdReal(constant, scalar, (*var)->data.negate.constant);
18301
18302 SCIPrationalNegate(scalar, scalar);
18303 *var = (*var)->negatedvar;
18304 break;
18305
18306 default:
18307 SCIPerrorMessage("unknown variable status\n");
18308 SCIPABORT();
18309 return SCIP_INVALIDDATA; /*lint !e527*/
18310 }
18311 }
18312 SCIPrationalSetReal(scalar, 0.0);
18313
18314 return SCIP_OKAY;
18315}
18316
18317
18318/** retransforms given variable, scalar and constant to the corresponding original variable, scalar
18319 * and constant, if possible; if the retransformation is impossible, NULL is returned as variable
18320 */
18322 SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
18323 SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
18324 SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
18325 )
18326{
18327 SCIP_VAR* parentvar;
18328
18329 assert(var != NULL);
18330 assert(*var != NULL);
18331 assert(scalar != NULL);
18332 assert(constant != NULL);
18333
18334 while( !SCIPvarIsOriginal(*var) )
18335 {
18336 /* if the variable has no parent variables, it was generated during solving and has no corresponding original
18337 * var
18338 */
18339 if( (*var)->nparentvars == 0 )
18340 {
18341 /* negated variables do not need to have a parent variables, and negated variables can exist in original
18342 * space
18343 */
18345 ((*var)->negatedvar->nparentvars == 0 || (*var)->negatedvar->parentvars[0] != *var) )
18346 {
18347 *scalar *= -1.0;
18348 *constant -= (*var)->data.negate.constant * (*scalar);
18349 *var = (*var)->negatedvar;
18350
18351 continue;
18352 }
18353 /* if the variables does not have any parent the variables was created during solving and has no original
18354 * counterpart
18355 */
18356 else
18357 {
18358 *var = NULL;
18359
18360 return SCIP_OKAY;
18361 }
18362 }
18363
18364 /* follow the link to the first parent variable */
18365 parentvar = (*var)->parentvars[0];
18366 assert(parentvar != NULL);
18367
18368 switch( SCIPvarGetStatus(parentvar) )
18369 {
18371 break;
18372
18377 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
18378 return SCIP_INVALIDDATA;
18379
18380 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + b -> y = (x-b)/a, s*y + c = (s/a)*x + c-b*s/a */
18381 assert(parentvar->data.aggregate.var == *var);
18382 assert(parentvar->data.aggregate.scalar != 0.0);
18383 *scalar /= parentvar->data.aggregate.scalar;
18384 *constant -= parentvar->data.aggregate.constant * (*scalar);
18385 break;
18386
18387 case SCIP_VARSTATUS_NEGATED: /* x = b - y -> y = b - x, s*y + c = -s*x + c+b*s */
18388 assert(parentvar->negatedvar != NULL);
18390 assert(parentvar->negatedvar->negatedvar == parentvar);
18391 *scalar *= -1.0;
18392 *constant -= parentvar->data.negate.constant * (*scalar);
18393 break;
18394
18395 default:
18396 SCIPerrorMessage("unknown variable status\n");
18397 return SCIP_INVALIDDATA;
18398 }
18399
18400 assert( parentvar != NULL );
18401 *var = parentvar;
18402 }
18403
18404 return SCIP_OKAY;
18405}
18406
18407/** retransforms given variable, scalar anqd constant to the corresponding original variable, scalar
18408 * and constant, if possible; if the retransformation is impossible, NULL is returned as variable
18409 */
18411 SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
18412 SCIP_RATIONAL* scalar, /**< pointer to scalar a in sum a*x + c */
18413 SCIP_RATIONAL* constant /**< pointer to constant c in sum a*x + c */
18414 )
18415{
18416 SCIP_VAR* parentvar;
18417
18418 assert(var != NULL);
18419 assert(*var != NULL);
18420 assert(scalar != NULL);
18421 assert(constant != NULL);
18422
18423 while( !SCIPvarIsOriginal(*var) )
18424 {
18425 /* if the variable has no parent variables, it was generated during solving and has no corresponding original
18426 * var
18427 */
18428 if( (*var)->nparentvars == 0 )
18429 {
18430 /* negated variables do not need to have a parent variables, and negated variables can exist in original
18431 * space
18432 */
18434 ((*var)->negatedvar->nparentvars == 0 || (*var)->negatedvar->parentvars[0] != *var) )
18435 {
18436 SCIPrationalNegate(scalar, scalar);
18437 SCIPrationalDiffProdReal(constant, scalar, (*var)->data.negate.constant);
18438 *var = (*var)->negatedvar;
18439
18440 continue;
18441 }
18442 /* if the variables does not have any parent the variables was created during solving and has no original
18443 * counterpart
18444 */
18445 else
18446 {
18447 *var = NULL;
18448
18449 return SCIP_OKAY;
18450 }
18451 }
18452
18453 /* follow the link to the first parent variable */
18454 parentvar = (*var)->parentvars[0];
18455 assert(parentvar != NULL);
18456
18457 switch( SCIPvarGetStatusExact(parentvar) )
18458 {
18460 break;
18461
18466 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
18467 return SCIP_INVALIDDATA;
18468
18469 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + b -> y = (x-b)/a, s*y + c = (s/a)*x + c-b*s/a */
18470 assert(parentvar->data.aggregate.var == *var);
18471 assert(parentvar->data.aggregate.scalar != 0.0);
18472 SCIPrationalDiv(scalar, scalar, parentvar->exactdata->aggregate.scalar);
18473 SCIPrationalDiffProd(constant, scalar, parentvar->exactdata->aggregate.constant);
18474 break;
18475
18476 case SCIP_VARSTATUS_NEGATED: /* x = b - y -> y = b - x, s*y + c = -s*x + c+b*s */
18477 assert(parentvar->negatedvar != NULL);
18479 assert(parentvar->negatedvar->negatedvar == parentvar);
18480 SCIPrationalNegate(scalar, scalar);
18481 SCIPrationalDiffProdReal(constant, scalar, parentvar->data.negate.constant);
18482 break;
18483
18484 default:
18485 SCIPerrorMessage("unknown variable status\n");
18486 return SCIP_INVALIDDATA;
18487 }
18488
18489 assert( parentvar != NULL );
18490 *var = parentvar;
18491 }
18492
18493 return SCIP_OKAY;
18494}
18495
18496
18497/** returns whether the given variable is the direct counterpart of an original problem variable */
18499 SCIP_VAR* var /**< problem variable */
18500 )
18501{
18502 SCIP_VAR* parentvar;
18503 assert(var != NULL);
18504
18505 if( !SCIPvarIsTransformed(var) || var->nparentvars < 1 )
18506 return FALSE;
18507
18508 assert(var->parentvars != NULL);
18509 parentvar = var->parentvars[0];
18510 assert(parentvar != NULL);
18511
18512 /* we follow the aggregation tree to the root unless an original variable has been found - the first entries in the parentlist are candidates */
18513 while( parentvar->nparentvars >= 1 && SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL )
18514 parentvar = parentvar->parentvars[0];
18515 assert( parentvar != NULL );
18516
18517 return ( SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_ORIGINAL );
18518}
18519
18520/** gets objective value of variable in current SCIP_LP; the value can be different from the objective value stored in
18521 * the variable's own data due to diving, that operate only on the LP without updating the variables
18522 */
18524 SCIP_VAR* var /**< problem variable */
18525 )
18526{
18527 assert(var != NULL);
18528
18529 /* get bounds of attached variables */
18530 switch( SCIPvarGetStatus(var) )
18531 {
18533 assert(var->data.original.transvar != NULL);
18534 return SCIPvarGetObjLP(var->data.original.transvar);
18535
18537 assert(var->data.col != NULL);
18538 return SCIPcolGetObj(var->data.col);
18539
18542 return var->obj;
18543
18544 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
18545 assert(var->data.aggregate.var != NULL);
18546 return var->data.aggregate.scalar * SCIPvarGetObjLP(var->data.aggregate.var);
18547
18549 SCIPerrorMessage("cannot get the objective value of a multiple aggregated variable\n");
18550 SCIPABORT();
18551 return 0.0; /*lint !e527*/
18552
18553 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
18554 assert(var->negatedvar != NULL);
18556 assert(var->negatedvar->negatedvar == var);
18557 return -SCIPvarGetObjLP(var->negatedvar);
18558
18559 default:
18560 SCIPerrorMessage("unknown variable status\n");
18561 SCIPABORT();
18562 return 0.0; /*lint !e527*/
18563 }
18564}
18565
18566/** gets lower bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
18567 * data due to diving or conflict analysis, that operate only on the LP without updating the variables
18568 */
18570 SCIP_VAR* var, /**< problem variable */
18571 SCIP_SET* set /**< global SCIP settings */
18572 )
18573{
18574 assert(var != NULL);
18575 assert(set != NULL);
18576 assert(var->scip == set->scip);
18577
18578 /* get bounds of attached variables */
18579 switch( SCIPvarGetStatus(var) )
18580 {
18582 assert(var->data.original.transvar != NULL);
18583 return SCIPvarGetLbLP(var->data.original.transvar, set);
18584
18586 assert(var->data.col != NULL);
18587 return SCIPcolGetLb(var->data.col);
18588
18591 return var->locdom.lb;
18592
18593 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
18594 assert(var->data.aggregate.var != NULL);
18595 if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set)))
18596 || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set))) )
18597 {
18598 return -SCIPsetInfinity(set);
18599 }
18600 else if( var->data.aggregate.scalar > 0.0 )
18601 {
18602 /* a > 0 -> get lower bound of y */
18603 return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
18604 }
18605 else if( var->data.aggregate.scalar < 0.0 )
18606 {
18607 /* a < 0 -> get upper bound of y */
18608 return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
18609 }
18610 else
18611 {
18612 SCIPerrorMessage("scalar is zero in aggregation\n");
18613 SCIPABORT();
18614 return SCIP_INVALID; /*lint !e527*/
18615 }
18616
18618 /**@todo get the sides of the corresponding linear constraint */
18619 SCIPerrorMessage("getting the bounds of a multiple aggregated variable is not implemented yet\n");
18620 SCIPABORT();
18621 return SCIP_INVALID; /*lint !e527*/
18622
18623 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
18624 assert(var->negatedvar != NULL);
18626 assert(var->negatedvar->negatedvar == var);
18627 return var->data.negate.constant - SCIPvarGetUbLP(var->negatedvar, set);
18628
18629 default:
18630 SCIPerrorMessage("unknown variable status\n");
18631 SCIPABORT();
18632 return SCIP_INVALID; /*lint !e527*/
18633 }
18634}
18635
18636/** gets upper bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
18637 * data due to diving or conflict analysis, that operate only on the LP without updating the variables
18638 */
18640 SCIP_VAR* var, /**< problem variable */
18641 SCIP_SET* set /**< global SCIP settings */
18642 )
18643{
18644 assert(var != NULL);
18645 assert(set != NULL);
18646 assert(var->scip == set->scip);
18647
18648 /* get bounds of attached variables */
18649 switch( SCIPvarGetStatus(var) )
18650 {
18652 assert(var->data.original.transvar != NULL);
18653 return SCIPvarGetUbLP(var->data.original.transvar, set);
18654
18656 assert(var->data.col != NULL);
18657 return SCIPcolGetUb(var->data.col);
18658
18661 return var->locdom.ub;
18662
18663 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
18664 assert(var->data.aggregate.var != NULL);
18665 if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set)))
18666 || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set))) )
18667 {
18668 return SCIPsetInfinity(set);
18669 }
18670 if( var->data.aggregate.scalar > 0.0 )
18671 {
18672 /* a > 0 -> get upper bound of y */
18673 return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
18674 }
18675 else if( var->data.aggregate.scalar < 0.0 )
18676 {
18677 /* a < 0 -> get lower bound of y */
18678 return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
18679 }
18680 else
18681 {
18682 SCIPerrorMessage("scalar is zero in aggregation\n");
18683 SCIPABORT();
18684 return SCIP_INVALID; /*lint !e527*/
18685 }
18686
18688 SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
18689 SCIPABORT();
18690 return SCIP_INVALID; /*lint !e527*/
18691
18692 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
18693 assert(var->negatedvar != NULL);
18695 assert(var->negatedvar->negatedvar == var);
18696 return var->data.negate.constant - SCIPvarGetLbLP(var->negatedvar, set);
18697
18698 default:
18699 SCIPerrorMessage("unknown variable status\n");
18700 SCIPABORT();
18701 return SCIP_INVALID; /*lint !e527*/
18702 }
18703}
18704
18705/** gets primal LP solution value of variable */
18707 SCIP_VAR* var /**< problem variable */
18708 )
18709{
18710 assert(var != NULL);
18711
18712 switch( SCIPvarGetStatus(var) )
18713 {
18715 if( var->data.original.transvar == NULL )
18716 return SCIP_INVALID;
18717 return SCIPvarGetLPSol(var->data.original.transvar);
18718
18721
18723 assert(var->data.col != NULL);
18724 return SCIPcolGetPrimsol(var->data.col);
18725
18727 assert(var->locdom.lb == var->locdom.ub || (var->exactdata != NULL && SCIPrationalIsEQ(var->exactdata->locdom.lb, var->exactdata->locdom.ub))); /*lint !e777*/
18728 return var->locdom.lb;
18729
18731 {
18732 SCIP_Real lpsolval;
18733
18734 assert(!var->donotaggr);
18735 assert(var->data.aggregate.var != NULL);
18736 lpsolval = SCIPvarGetLPSol(var->data.aggregate.var);
18737
18738 /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
18739 * corresponding infinity value instead of performing an arithmetical transformation (compare method
18740 * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
18741 * (or is called by) a public interface method; instead, we only assert that values are finite
18742 * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
18743 * positives and negatives if the parameter <numerics/infinity> is modified by the user
18744 */
18745// assert(lpsolval > -SCIP_DEFAULT_INFINITY);
18746// assert(lpsolval < +SCIP_DEFAULT_INFINITY);
18747
18748 if( lpsolval >= SCIP_DEFAULT_INFINITY )
18749 return (var->data.aggregate.scalar > 0) ? SCIP_DEFAULT_INFINITY : -SCIP_DEFAULT_INFINITY;
18750 else if( lpsolval <= -SCIP_DEFAULT_INFINITY )
18751 return (var->data.aggregate.scalar > 0) ? -SCIP_DEFAULT_INFINITY : SCIP_DEFAULT_INFINITY;
18752
18753 return var->data.aggregate.scalar * lpsolval + var->data.aggregate.constant;
18754 }
18756 {
18758 int i;
18759
18760 assert(!var->donotmultaggr);
18761 assert(var->data.multaggr.vars != NULL);
18762 assert(var->data.multaggr.scalars != NULL);
18763 /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
18764 * assert(var->data.multaggr.nvars >= 2);
18765 */
18766 primsol = var->data.multaggr.constant;
18767 for( i = 0; i < var->data.multaggr.nvars; ++i )
18768 primsol += var->data.multaggr.scalars[i] * SCIPvarGetLPSol(var->data.multaggr.vars[i]);
18769 return primsol;
18770 }
18771 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
18772 assert(var->negatedvar != NULL);
18774 assert(var->negatedvar->negatedvar == var);
18775 return var->data.negate.constant - SCIPvarGetLPSol(var->negatedvar);
18776
18777 default:
18778 SCIPerrorMessage("unknown variable status\n");
18779 SCIPABORT();
18780 return SCIP_INVALID; /*lint !e527*/
18781 }
18782}
18783
18784/** gets exact primal LP solution value of variable or value of safe dual solution */
18786 SCIP_VAR* var, /**< problem variable */
18787 SCIP_RATIONAL* res /**< store the resulting value */
18788 )
18789{
18790 assert(var != NULL);
18791
18792 switch( SCIPvarGetStatusExact(var) )
18793 {
18795 if( var->data.original.transvar == NULL )
18797 SCIPvarGetLPSolExact(var->data.original.transvar, res);
18798 break;
18799
18802 break;
18803
18805 assert(var->data.col != NULL);
18806 SCIPrationalSetRational(res, SCIPcolExactGetPrimsol(var->exactdata->colexact));
18807 break;
18808
18810 assert(SCIPrationalIsEQ(var->exactdata->locdom.lb, var->exactdata->locdom.ub)); /*lint !e777*/
18811 SCIPrationalSetRational(res, var->exactdata->locdom.lb);
18812 break;
18813
18815 assert(var->data.aggregate.var != NULL);
18816 SCIPvarGetLPSolExact(var->data.aggregate.var, res);
18817 SCIPrationalMult(res, res, var->exactdata->aggregate.scalar);
18818 SCIPrationalAdd(res, res, var->exactdata->aggregate.constant);
18819 break;
18820
18822 {
18823 SCIP_RATIONAL* tmp;
18824 int i;
18825
18826 assert(!var->donotmultaggr);
18827 assert(var->data.multaggr.vars != NULL);
18828 assert(var->data.multaggr.scalars != NULL);
18829
18830 (void) SCIPrationalCreate(&tmp);
18831 /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
18832 * assert(var->data.multaggr.nvars >= 2);
18833 */
18834 SCIPrationalSetRational(res, var->exactdata->multaggr.constant);
18835 for( i = 0; i < var->data.multaggr.nvars; ++i )
18836 {
18837 SCIPvarGetLPSolExact(var->data.multaggr.vars[i], tmp);
18838 SCIPrationalAddProd(res, var->exactdata->multaggr.scalars[i], tmp);
18839 }
18840 SCIPrationalFree(&tmp);
18841 break;
18842 }
18843
18844 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
18845 assert(var->negatedvar != NULL);
18847 assert(var->negatedvar->negatedvar == var);
18848 SCIPvarGetLPSolExact(var->negatedvar, res);
18849 SCIPrationalDiffReal(res, res, var->data.negate.constant);
18850 SCIPrationalNegate(res, res);
18851 break;
18852
18853 default:
18854 SCIPerrorMessage("unknown variable status\n");
18855 SCIPABORT();
18856 }
18857}
18858
18859/** gets primal NLP solution value of variable */
18861 SCIP_VAR* var /**< problem variable */
18862 )
18863{
18864 SCIP_Real solval;
18865 int i;
18866
18867 assert(var != NULL);
18868
18869 /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
18870 switch( SCIPvarGetStatus(var) )
18871 {
18873 return SCIPvarGetNLPSol(var->data.original.transvar);
18874
18877 return var->nlpsol;
18878
18880 assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
18881 assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
18882 assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
18883 return SCIPvarGetLbGlobal(var);
18884
18885 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
18886 solval = SCIPvarGetNLPSol(var->data.aggregate.var);
18887 return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
18888
18890 solval = var->data.multaggr.constant;
18891 for( i = 0; i < var->data.multaggr.nvars; ++i )
18892 solval += var->data.multaggr.scalars[i] * SCIPvarGetNLPSol(var->data.multaggr.vars[i]);
18893 return solval;
18894
18896 solval = SCIPvarGetNLPSol(var->negatedvar);
18897 return var->data.negate.constant - solval;
18898
18899 default:
18900 SCIPerrorMessage("unknown variable status\n");
18901 SCIPABORT();
18902 return SCIP_INVALID; /*lint !e527*/
18903 }
18904}
18905
18906/** gets pseudo solution value of variable at current node */
18907static
18909 SCIP_VAR* var /**< problem variable */
18910 )
18911{
18912 SCIP_Real pseudosol;
18913 int i;
18914
18915 assert(var != NULL);
18916
18917 switch( SCIPvarGetStatus(var) )
18918 {
18920 if( var->data.original.transvar == NULL )
18921 return SCIP_INVALID;
18922 return SCIPvarGetPseudoSol(var->data.original.transvar);
18923
18927
18929 assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
18930 return var->locdom.lb;
18931
18933 {
18934 SCIP_Real pseudosolval;
18935 assert(!var->donotaggr);
18936 assert(var->data.aggregate.var != NULL);
18937 /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
18938 * corresponding infinity value instead of performing an arithmetical transformation (compare method
18939 * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
18940 * (or is called by) a public interface method; instead, we only assert that values are finite
18941 * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
18942 * positives and negatives if the parameter <numerics/infinity> is modified by the user
18943 */
18944 pseudosolval = SCIPvarGetPseudoSol(var->data.aggregate.var);
18945 assert(pseudosolval > -SCIP_DEFAULT_INFINITY);
18946 assert(pseudosolval < +SCIP_DEFAULT_INFINITY);
18947 return var->data.aggregate.scalar * pseudosolval + var->data.aggregate.constant;
18948 }
18950 assert(!var->donotmultaggr);
18951 assert(var->data.multaggr.vars != NULL);
18952 assert(var->data.multaggr.scalars != NULL);
18953 /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
18954 * assert(var->data.multaggr.nvars >= 2);
18955 */
18956 pseudosol = var->data.multaggr.constant;
18957 for( i = 0; i < var->data.multaggr.nvars; ++i )
18958 pseudosol += var->data.multaggr.scalars[i] * SCIPvarGetPseudoSol(var->data.multaggr.vars[i]);
18959 return pseudosol;
18960
18961 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
18962 assert(var->negatedvar != NULL);
18964 assert(var->negatedvar->negatedvar == var);
18965 return var->data.negate.constant - SCIPvarGetPseudoSol(var->negatedvar);
18966
18967 default:
18968 SCIPerrorMessage("unknown variable status\n");
18969 SCIPABORT();
18970 return SCIP_INVALID; /*lint !e527*/
18971 }
18972}
18973
18974/** gets exact pseudo solution value of variable at current node */
18975static
18977 SCIP_VAR* var /**< problem variable */
18978 )
18979{
18980 assert(var != NULL);
18981
18982 switch( SCIPvarGetStatusExact(var) )
18983 {
18985 if( var->data.original.transvar == NULL )
18986 return NULL;
18987 return SCIPvarGetPseudoSolExact(var->data.original.transvar);
18988
18992
18994 assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
18995 return var->exactdata->locdom.lb;
18996
19000 default:
19001 SCIPerrorMessage("unknown variable status\n");
19002 SCIPABORT();
19003 return NULL; /*lint !e527*/
19004 }
19005}
19006
19007/** gets current LP or pseudo solution value of variable */
19009 SCIP_VAR* var, /**< problem variable */
19010 SCIP_Bool getlpval /**< should the LP solution value be returned? */
19011 )
19012{
19013 if( getlpval )
19014 return SCIPvarGetLPSol(var);
19015 else
19016 return SCIPvarGetPseudoSol(var);
19017}
19018
19019/** gets current exact LP or pseudo solution value of variable */
19021 SCIP_VAR* var, /**< problem variable */
19022 SCIP_RATIONAL* res, /**< the resulting value */
19023 SCIP_Bool getlpval /**< should the LP solution value be returned? */
19024 )
19025{
19026 assert(var != NULL);
19027
19028 if( getlpval )
19030 else
19032}
19033
19034/** remembers the current solution as root solution in the problem variables */
19036 SCIP_VAR* var, /**< problem variable */
19037 SCIP_Bool roothaslp /**< is the root solution from LP? */
19038 )
19039{
19040 assert(var != NULL);
19041
19042 var->rootsol = SCIPvarGetSol(var, roothaslp);
19043}
19044
19045/** updates the current solution as best root solution of the given variable if it is better */
19047 SCIP_VAR* var, /**< problem variable */
19048 SCIP_SET* set, /**< global SCIP settings */
19049 SCIP_Real rootsol, /**< root solution value */
19050 SCIP_Real rootredcost, /**< root reduced cost */
19051 SCIP_Real rootlpobjval /**< objective value of the root LP */
19052 )
19053{
19054 assert(var != NULL);
19055 assert(set != NULL);
19056 assert(var->scip == set->scip);
19057
19058 /* if reduced cost are zero nothing to update */
19059 if( SCIPsetIsDualfeasZero(set, rootredcost) )
19060 return;
19061
19062 /* check if we have already a best combination stored */
19063 if( !SCIPsetIsDualfeasZero(set, var->bestrootredcost) )
19064 {
19065 SCIP_Real currcutoffbound;
19066 SCIP_Real cutoffbound;
19068
19069 /* compute the cutoff bound which would improve the corresponding bound with the current stored root solution,
19070 * root reduced cost, and root LP objective value combination
19071 */
19072 if( var->bestrootredcost > 0.0 )
19074 else
19076
19077 currcutoffbound = (bound - var->bestrootsol) * var->bestrootredcost + var->bestrootlpobjval;
19078
19079 /* compute the cutoff bound which would improve the corresponding bound with new root solution, root reduced
19080 * cost, and root LP objective value combination
19081 */
19082 if( rootredcost > 0.0 )
19084 else
19086
19087 cutoffbound = (bound - rootsol) * rootredcost + rootlpobjval;
19088
19089 /* check if an improving root solution, root reduced cost, and root LP objective value is at hand */
19090 if( cutoffbound > currcutoffbound )
19091 {
19092 SCIPsetDebugMsg(set, "-> <%s> update potential cutoff bound <%g> -> <%g>\n",
19093 SCIPvarGetName(var), currcutoffbound, cutoffbound);
19094
19095 var->bestrootsol = rootsol;
19096 var->bestrootredcost = rootredcost;
19097 var->bestrootlpobjval = rootlpobjval;
19098 }
19099 }
19100 else
19101 {
19102 SCIPsetDebugMsg(set, "-> <%s> initialize best root reduced cost information\n", SCIPvarGetName(var));
19103 SCIPsetDebugMsg(set, " -> rootsol <%g>\n", rootsol);
19104 SCIPsetDebugMsg(set, " -> rootredcost <%g>\n", rootredcost);
19105 SCIPsetDebugMsg(set, " -> rootlpobjval <%g>\n", rootlpobjval);
19106
19107 var->bestrootsol = rootsol;
19108 var->bestrootredcost = rootredcost;
19109 var->bestrootlpobjval = rootlpobjval;
19110 }
19111}
19112
19113/** returns the solution of the variable in the last root node's relaxation, if the root relaxation is not yet
19114 * completely solved, zero is returned
19115 */
19117 SCIP_VAR* var /**< problem variable */
19118 )
19119{
19121 int i;
19122
19123 assert(var != NULL);
19124
19125 switch( SCIPvarGetStatus(var) )
19126 {
19128 if( var->data.original.transvar == NULL )
19129 return 0.0;
19130 return SCIPvarGetRootSol(var->data.original.transvar);
19131
19134 return var->rootsol;
19135
19137 assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
19138 return var->locdom.lb;
19139
19141 assert(!var->donotaggr);
19142 assert(var->data.aggregate.var != NULL);
19143 /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
19144 * corresponding infinity value instead of performing an arithmetical transformation (compare method
19145 * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
19146 * (or is called by) a public interface method; instead, we only assert that values are finite
19147 * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
19148 * positives and negatives if the parameter <numerics/infinity> is modified by the user
19149 */
19150 assert(SCIPvarGetRootSol(var->data.aggregate.var) > -SCIP_DEFAULT_INFINITY);
19151 assert(SCIPvarGetRootSol(var->data.aggregate.var) < +SCIP_DEFAULT_INFINITY);
19152 return var->data.aggregate.scalar * SCIPvarGetRootSol(var->data.aggregate.var) + var->data.aggregate.constant;
19153
19155 assert(!var->donotmultaggr);
19156 assert(var->data.multaggr.vars != NULL);
19157 assert(var->data.multaggr.scalars != NULL);
19158 /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
19159 * assert(var->data.multaggr.nvars >= 2);
19160 */
19161 rootsol = var->data.multaggr.constant;
19162 for( i = 0; i < var->data.multaggr.nvars; ++i )
19163 rootsol += var->data.multaggr.scalars[i] * SCIPvarGetRootSol(var->data.multaggr.vars[i]);
19164 return rootsol;
19165
19166 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
19167 assert(var->negatedvar != NULL);
19169 assert(var->negatedvar->negatedvar == var);
19170 return var->data.negate.constant - SCIPvarGetRootSol(var->negatedvar);
19171
19172 default:
19173 SCIPerrorMessage("unknown variable status\n");
19174 SCIPABORT();
19175 return SCIP_INVALID; /*lint !e527*/
19176 }
19177}
19178
19179/** returns for given variable the reduced cost */
19180static
19182 SCIP_VAR* var, /**< problem variable */
19183 SCIP_SET* set, /**< global SCIP settings */
19184 SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
19185 SCIP_STAT* stat, /**< problem statistics */
19186 SCIP_LP* lp /**< current LP data */
19187 )
19188{
19190 {
19191 SCIP_COL* col;
19193 SCIP_BASESTAT basestat;
19194 SCIP_Bool lpissolbasic;
19195
19196 col = SCIPvarGetCol(var);
19197 assert(col != NULL);
19198
19199 basestat = SCIPcolGetBasisStatus(col);
19200 lpissolbasic = SCIPlpIsSolBasic(lp);
19202
19203 if( (lpissolbasic && (basestat == SCIP_BASESTAT_LOWER || basestat == SCIP_BASESTAT_UPPER)) ||
19205 {
19206 SCIP_Real redcost = SCIPcolGetRedcost(col, stat, lp);
19207
19208 assert(set->exact_enable || (((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)) ||
19209 (lpissolbasic && basestat == SCIP_BASESTAT_LOWER)) ? (!SCIPsetIsDualfeasNegative(set, redcost) ||
19211 assert(set->exact_enable || (((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)) ||
19212 (lpissolbasic && basestat == SCIP_BASESTAT_UPPER)) ? (!SCIPsetIsDualfeasPositive(set, redcost) ||
19214
19215 if( (varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_LOWER) ||
19216 (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)))) ||
19217 (!varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_UPPER) ||
19218 (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)))) )
19219 return redcost;
19220 else
19221 return 0.0;
19222 }
19223
19224 return 0.0;
19225 }
19226
19227 return 0.0;
19228}
19229
19230#define MAX_CLIQUELENGTH 50
19231/** returns for the given binary variable the reduced cost which are given by the variable itself and its implication if
19232 * the binary variable is fixed to the given value
19233 */
19235 SCIP_VAR* var, /**< problem variable */
19236 SCIP_SET* set, /**< global SCIP settings */
19237 SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
19238 SCIP_STAT* stat, /**< problem statistics */
19239 SCIP_PROB* prob, /**< transformed problem, or NULL */
19240 SCIP_LP* lp /**< current LP data */
19241 )
19242{
19243 SCIP_Real implredcost;
19244 int ncliques;
19245 int nvars;
19246
19249
19250 /* get reduced cost of given variable */
19251 implredcost = getImplVarRedcost(var, set, varfixing, stat, lp);
19252
19253#ifdef SCIP_MORE_DEBUG
19254 SCIPsetDebugMsg(set, "variable <%s> itself has reduced cost of %g\n", SCIPvarGetName(var), implredcost);
19255#endif
19256
19257 /* the following algorithm is expensive */
19258 ncliques = SCIPvarGetNCliques(var, varfixing);
19259
19260 if( ncliques > 0 )
19261 {
19262 SCIP_CLIQUE** cliques;
19263 SCIP_CLIQUE* clique;
19264 SCIP_VAR** clqvars;
19265 SCIP_VAR** probvars;
19266 SCIP_VAR* clqvar;
19267 SCIP_Bool* clqvalues;
19268 int* entries;
19269 int* ids;
19270 SCIP_Real redcost;
19271 SCIP_Bool cleanedup;
19272 int nclqvars;
19273 int nentries;
19274 int nids;
19275 int id;
19276 int c;
19277 int v;
19278
19279 assert(prob != NULL);
19281
19282 nentries = SCIPprobGetNVars(prob) - SCIPprobGetNContVars(prob) + 1;
19283
19284 SCIP_CALL_ABORT( SCIPsetAllocBufferArray(set, &ids, nentries) );
19285 nids = 0;
19286 SCIP_CALL_ABORT( SCIPsetAllocCleanBufferArray(set, &entries, nentries) );
19287
19288 cliques = SCIPvarGetCliques(var, varfixing);
19289 assert(cliques != NULL);
19290
19291 for( c = ncliques - 1; c >= 0; --c )
19292 {
19293 clique = cliques[c];
19294 assert(clique != NULL);
19295 nclqvars = SCIPcliqueGetNVars(clique);
19296 assert(nclqvars > 0);
19297
19298 if( nclqvars > MAX_CLIQUELENGTH )
19299 continue;
19300
19301 clqvars = SCIPcliqueGetVars(clique);
19302 clqvalues = SCIPcliqueGetValues(clique);
19303 assert(clqvars != NULL);
19304 assert(clqvalues != NULL);
19305
19306 cleanedup = SCIPcliqueIsCleanedUp(clique);
19307
19308 for( v = nclqvars - 1; v >= 0; --v )
19309 {
19310 clqvar = clqvars[v];
19311 assert(clqvar != NULL);
19312
19313 /* ignore binary variable which are fixed */
19314 if( clqvar != var && (cleanedup || SCIPvarIsActive(clqvar)) &&
19315 (SCIPvarGetLbLocal(clqvar) < 0.5 && SCIPvarGetUbLocal(clqvar) > 0.5) )
19316 {
19317 int probindex = SCIPvarGetProbindex(clqvar) + 1;
19318 assert(0 < probindex && probindex < nentries);
19319
19320#ifdef SCIP_DISABLED_CODE
19321 /* check that the variable was not yet visited or does not appear with two contradicting implications, ->
19322 * can appear since there is no guarantee that all these infeasible bounds were found
19323 */
19324 assert(!entries[probindex] || entries[probindex] == (clqvalues[v] ? probindex : -probindex));
19325#endif
19326 if( entries[probindex] == 0 )
19327 {
19328 ids[nids] = probindex;
19329 ++nids;
19330
19331 /* mark variable as visited */
19332 entries[probindex] = (clqvalues[v] ? probindex : -probindex);
19333 }
19334 }
19335 }
19336 }
19337
19338 probvars = SCIPprobGetVars(prob);
19339 assert(probvars != NULL);
19340
19341 /* add all implied reduced cost */
19342 for( v = nids - 1; v >= 0; --v )
19343 {
19344 id = ids[v];
19345 assert(0 < id && id < nentries);
19346 assert(entries[id] != 0);
19347 assert(probvars[id - 1] != NULL);
19348 assert(SCIPvarIsActive(probvars[id - 1]));
19349 assert(SCIPvarIsBinary(probvars[id - 1]));
19350 assert(SCIPvarGetLbLocal(probvars[id - 1]) < 0.5 && SCIPvarGetUbLocal(probvars[id - 1]) > 0.5);
19351
19352 if( (entries[id] > 0) != varfixing )
19353 redcost = getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
19354 else
19355 redcost = -getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
19356
19357 if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
19358 implredcost += redcost;
19359
19360 /* reset entries clear buffer array */
19361 entries[id] = 0;
19362 }
19363
19366 }
19367
19368#ifdef SCIP_MORE_DEBUG
19369 SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) has implied reduced cost of %g\n", SCIPvarGetName(var), ncliques,
19370 implredcost);
19371#endif
19372
19373 /* collect non-binary implication information */
19374 nvars = SCIPimplicsGetNImpls(var->implics, varfixing);
19375
19376 if( nvars > 0 )
19377 {
19378 SCIP_VAR** vars;
19379 SCIP_VAR* implvar;
19380 SCIP_COL* col;
19381 SCIP_Real* bounds;
19382 SCIP_BOUNDTYPE* boundtypes;
19383 SCIP_Real redcost;
19384 SCIP_Real lb;
19385 SCIP_Real ub;
19386 SCIP_Bool lpissolbasic;
19387 int v;
19388
19389 vars = SCIPimplicsGetVars(var->implics, varfixing);
19390 boundtypes = SCIPimplicsGetTypes(var->implics, varfixing);
19391 bounds = SCIPimplicsGetBounds(var->implics, varfixing);
19392 lpissolbasic = SCIPlpIsSolBasic(lp);
19393
19394 for( v = nvars - 1; v >= 0; --v )
19395 {
19396 implvar = vars[v];
19397 assert(implvar != NULL);
19398
19399 lb = SCIPvarGetLbLocal(implvar);
19400 ub = SCIPvarGetUbLocal(implvar);
19401
19402 /* ignore binary variable which are fixed or not of column status */
19403 if( SCIPvarGetStatus(implvar) != SCIP_VARSTATUS_COLUMN || SCIPsetIsFeasEQ(set, lb, ub) )
19404 continue;
19405
19406 col = SCIPvarGetCol(implvar);
19407 assert(col != NULL);
19408 redcost = 0.0;
19409
19410 /* solved lp with basis information or not? */
19411 if( lpissolbasic )
19412 {
19413 SCIP_BASESTAT basestat = SCIPcolGetBasisStatus(col);
19414
19415 /* check if the implication is not not yet applied */
19416 if( basestat == SCIP_BASESTAT_LOWER && boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGT(set, bounds[v], lb) )
19417 {
19418 redcost = SCIPcolGetRedcost(col, stat, lp);
19420
19421 if( !varfixing )
19422 redcost *= (lb - bounds[v]);
19423 else
19424 redcost *= (bounds[v] - lb);
19425 }
19426 else if( basestat == SCIP_BASESTAT_UPPER && boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLT(set, bounds[v], ub) )
19427 {
19428 redcost = SCIPcolGetRedcost(col, stat, lp);
19430
19431 if( varfixing )
19432 redcost *= (bounds[v] - ub);
19433 else
19434 redcost *= (ub - bounds[v]);
19435 }
19436 }
19437 else
19438 {
19440
19441 /* check if the implication is not not yet applied */
19442 if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasEQ(set, lb, primsol) && SCIPsetIsFeasGT(set, bounds[v], lb) )
19443 {
19444 redcost = SCIPcolGetRedcost(col, stat, lp);
19446
19447 if( varfixing )
19448 redcost *= (lb - bounds[v]);
19449 else
19450 redcost *= (bounds[v] - lb);
19451 }
19452 else if( boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasEQ(set, ub, primsol) && SCIPsetIsFeasLT(set, bounds[v], ub) )
19453 {
19454 redcost = SCIPcolGetRedcost(col, stat, lp);
19456
19457 if( varfixing )
19458 redcost *= (bounds[v] - ub);
19459 else
19460 redcost *= (ub - bounds[v]);
19461 }
19462 }
19463
19464 /* improve implied reduced cost */
19465 if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
19466 implredcost += redcost;
19467 }
19468 }
19469
19470#ifdef SCIP_MORE_DEBUG
19471 SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) and implications (%d) has implied reduced cost of %g\n",
19472 SCIPvarGetName(var), ncliques, nvars, implredcost);
19473#endif
19474
19475 return implredcost;
19476}
19477
19478/** returns the best solution (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation, if
19479 * the root relaxation is not yet completely solved, zero is returned
19480 */
19482 SCIP_VAR* var /**< problem variable */
19483 )
19484{
19486 int i;
19487
19488 assert(var != NULL);
19489
19490 switch( SCIPvarGetStatus(var) )
19491 {
19493 if( var->data.original.transvar == NULL )
19494 return 0.0;
19495 return SCIPvarGetBestRootSol(var->data.original.transvar);
19496
19499 return var->bestrootsol;
19500
19502 assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
19503 return var->locdom.lb;
19504
19506 assert(!var->donotaggr);
19507 assert(var->data.aggregate.var != NULL);
19508 /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
19509 * corresponding infinity value instead of performing an arithmetical transformation (compare method
19510 * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
19511 * (or is called by) a public interface method; instead, we only assert that values are finite
19512 * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
19513 * positives and negatives if the parameter <numerics/infinity> is modified by the user
19514 */
19515 assert(SCIPvarGetBestRootSol(var->data.aggregate.var) > -SCIP_DEFAULT_INFINITY);
19516 assert(SCIPvarGetBestRootSol(var->data.aggregate.var) < +SCIP_DEFAULT_INFINITY);
19517 return var->data.aggregate.scalar * SCIPvarGetBestRootSol(var->data.aggregate.var) + var->data.aggregate.constant;
19518
19520 assert(!var->donotmultaggr);
19521 assert(var->data.multaggr.vars != NULL);
19522 assert(var->data.multaggr.scalars != NULL);
19523 /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
19524 * assert(var->data.multaggr.nvars >= 2);
19525 */
19526 rootsol = var->data.multaggr.constant;
19527 for( i = 0; i < var->data.multaggr.nvars; ++i )
19528 rootsol += var->data.multaggr.scalars[i] * SCIPvarGetBestRootSol(var->data.multaggr.vars[i]);
19529 return rootsol;
19530
19531 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
19532 assert(var->negatedvar != NULL);
19534 assert(var->negatedvar->negatedvar == var);
19535 return var->data.negate.constant - SCIPvarGetBestRootSol(var->negatedvar);
19536
19537 default:
19538 SCIPerrorMessage("unknown variable status\n");
19539 SCIPABORT();
19540 return 0.0; /*lint !e527*/
19541 }
19542}
19543
19544/** returns the best reduced costs (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation,
19545 * if the root relaxation is not yet completely solved, or the variable was no column of the root LP, SCIP_INVALID is
19546 * returned
19547 */
19549 SCIP_VAR* var /**< problem variable */
19550 )
19551{
19552 assert(var != NULL);
19553
19554 switch( SCIPvarGetStatus(var) )
19555 {
19557 if( var->data.original.transvar == NULL )
19558 return SCIP_INVALID;
19559 return SCIPvarGetBestRootRedcost(var->data.original.transvar);
19560
19563 return var->bestrootredcost;
19564
19569 return 0.0;
19570
19571 default:
19572 SCIPerrorMessage("unknown variable status\n");
19573 SCIPABORT();
19574 return 0.0; /*lint !e527*/
19575 }
19576}
19577
19578/** returns the best objective value (w.r.t. root reduced cost propagation) of the root LP which belongs the root
19579 * reduced cost which is accessible via SCIPvarGetRootRedcost() or the variable was no column of the root LP,
19580 * SCIP_INVALID is returned
19581 */
19583 SCIP_VAR* var /**< problem variable */
19584 )
19585{
19586 assert(var != NULL);
19587
19588 switch( SCIPvarGetStatus(var) )
19589 {
19591 if( var->data.original.transvar == NULL )
19592 return SCIP_INVALID;
19593 return SCIPvarGetBestRootLPObjval(var->data.original.transvar);
19594
19597 return var->bestrootlpobjval;
19598
19603 return SCIP_INVALID;
19604
19605 default:
19606 SCIPerrorMessage("unknown variable status\n");
19607 SCIPABORT();
19608 return SCIP_INVALID; /*lint !e527*/
19609 }
19610}
19611
19612/** set the given solution as the best root solution w.r.t. root reduced cost propagation in the variables */
19614 SCIP_VAR* var, /**< problem variable */
19615 SCIP_Real rootsol, /**< root solution value */
19616 SCIP_Real rootredcost, /**< root reduced cost */
19617 SCIP_Real rootlpobjval /**< objective value of the root LP */
19618 )
19619{
19620 assert(var != NULL);
19621
19622 var->bestrootsol = rootsol;
19623 var->bestrootredcost = rootredcost;
19624 var->bestrootlpobjval = rootlpobjval;
19625}
19626
19627/** stores the solution value as relaxation solution in the problem variable */
19629 SCIP_VAR* var, /**< problem variable */
19630 SCIP_SET* set, /**< global SCIP settings */
19631 SCIP_RELAXATION* relaxation, /**< global relaxation data */
19632 SCIP_Real solval, /**< solution value in the current relaxation solution */
19633 SCIP_Bool updateobj /**< should the objective value be updated? */
19634 )
19635{
19636 assert(var != NULL);
19637 assert(relaxation != NULL);
19638 assert(set != NULL);
19639 assert(var->scip == set->scip);
19640
19641 /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
19642 switch( SCIPvarGetStatus(var) )
19643 {
19645 SCIP_CALL( SCIPvarSetRelaxSol(var->data.original.transvar, set, relaxation, solval, updateobj) );
19646 break;
19647
19650 if( updateobj )
19651 SCIPrelaxationSolObjAdd(relaxation, var->obj * (solval - var->relaxsol));
19652 var->relaxsol = solval;
19653 break;
19654
19656 if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
19657 {
19658 SCIPerrorMessage("cannot set relaxation solution value for variable <%s> fixed to %.15g to different value %.15g\n",
19659 SCIPvarGetName(var), var->glbdom.lb, solval);
19660 return SCIP_INVALIDDATA;
19661 }
19662 break;
19663
19664 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
19665 assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
19666 SCIP_CALL( SCIPvarSetRelaxSol(var->data.aggregate.var, set, relaxation,
19667 (solval - var->data.aggregate.constant)/var->data.aggregate.scalar, updateobj) );
19668 break;
19670 SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
19671 return SCIP_INVALIDDATA;
19672
19674 SCIP_CALL( SCIPvarSetRelaxSol(var->negatedvar, set, relaxation, var->data.negate.constant - solval, updateobj) );
19675 break;
19676
19677 default:
19678 SCIPerrorMessage("unknown variable status\n");
19679 return SCIP_INVALIDDATA;
19680 }
19681
19682 return SCIP_OKAY;
19683}
19684
19685/** returns the solution value of the problem variable in the relaxation solution
19686 *
19687 * @todo Inline this function - similar to SCIPvarGetLPSol_rec.
19688 */
19690 SCIP_VAR* var, /**< problem variable */
19691 SCIP_SET* set /**< global SCIP settings */
19692 )
19693{
19694 SCIP_Real solvalsum;
19695 SCIP_Real solval;
19696 int i;
19697
19698 assert(var != NULL);
19699 assert(set != NULL);
19700 assert(var->scip == set->scip);
19701
19702 /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
19703 switch( SCIPvarGetStatus(var) )
19704 {
19706 return SCIPvarGetRelaxSol(var->data.original.transvar, set);
19707
19710 return var->relaxsol;
19711
19713 assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
19714 assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
19715 assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
19716 return SCIPvarGetLbGlobal(var);
19717
19718 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
19719 solval = SCIPvarGetRelaxSol(var->data.aggregate.var, set);
19720 if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
19721 {
19722 if( var->data.aggregate.scalar * solval > 0.0 )
19723 return SCIPsetInfinity(set);
19724 if( var->data.aggregate.scalar * solval < 0.0 )
19725 return -SCIPsetInfinity(set);
19726 }
19727 return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
19728
19730 solvalsum = var->data.multaggr.constant;
19731 for( i = 0; i < var->data.multaggr.nvars; ++i )
19732 {
19733 solval = SCIPvarGetRelaxSol(var->data.multaggr.vars[i], set);
19734 if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
19735 {
19736 if( var->data.multaggr.scalars[i] * solval > 0.0 )
19737 return SCIPsetInfinity(set);
19738 if( var->data.multaggr.scalars[i] * solval < 0.0 )
19739 return -SCIPsetInfinity(set);
19740 }
19741 solvalsum += var->data.multaggr.scalars[i] * solval;
19742 }
19743 return solvalsum;
19744
19746 solval = SCIPvarGetRelaxSol(var->negatedvar, set);
19747 if( SCIPsetIsInfinity(set, solval) )
19748 return -SCIPsetInfinity(set);
19749 if( SCIPsetIsInfinity(set, -solval) )
19750 return SCIPsetInfinity(set);
19751 return var->data.negate.constant - solval;
19752
19753 default:
19754 SCIPerrorMessage("unknown variable status\n");
19755 SCIPABORT();
19756 return SCIP_INVALID; /*lint !e527*/
19757 }
19758}
19759
19760/** returns the solution value of the transformed problem variable in the relaxation solution */
19762 SCIP_VAR* var /**< problem variable */
19763 )
19764{
19765 assert(var != NULL);
19767
19768 return var->relaxsol;
19769}
19770
19771/** stores the solution value as NLP solution in the problem variable */
19773 SCIP_VAR* var, /**< problem variable */
19774 SCIP_SET* set, /**< global SCIP settings */
19775 SCIP_Real solval /**< solution value in the current NLP solution */
19776 )
19777{
19778 assert(var != NULL);
19779 assert(set != NULL);
19780 assert(var->scip == set->scip);
19781
19782 /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
19783 switch( SCIPvarGetStatus(var) )
19784 {
19786 SCIP_CALL( SCIPvarSetNLPSol(var->data.original.transvar, set, solval) );
19787 break;
19788
19791 var->nlpsol = solval;
19792 break;
19793
19795 if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
19796 {
19797 SCIPerrorMessage("cannot set NLP solution value for variable <%s> fixed to %.15g to different value %.15g\n",
19798 SCIPvarGetName(var), var->glbdom.lb, solval);
19799 SCIPABORT();
19800 return SCIP_INVALIDCALL; /*lint !e527*/
19801 }
19802 break;
19803
19804 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
19805 assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
19806 SCIP_CALL( SCIPvarSetNLPSol(var->data.aggregate.var, set, (solval - var->data.aggregate.constant)/var->data.aggregate.scalar) );
19807 break;
19808
19810 SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
19811 SCIPABORT();
19812 return SCIP_INVALIDCALL; /*lint !e527*/
19813
19815 SCIP_CALL( SCIPvarSetNLPSol(var->negatedvar, set, var->data.negate.constant - solval) );
19816 break;
19817
19818 default:
19819 SCIPerrorMessage("unknown variable status\n");
19820 SCIPABORT();
19821 return SCIP_ERROR; /*lint !e527*/
19822 }
19823
19824 return SCIP_OKAY;
19825}
19826
19827/** returns a weighted average solution value of the variable in all feasible primal solutions found so far */
19829 SCIP_VAR* var /**< problem variable */
19830 )
19831{
19832 SCIP_Real avgsol;
19833 int i;
19834
19835 assert(var != NULL);
19836
19837 switch( SCIPvarGetStatus(var) )
19838 {
19840 if( var->data.original.transvar == NULL )
19841 return 0.0;
19842 return SCIPvarGetAvgSol(var->data.original.transvar);
19843
19846 avgsol = var->primsolavg;
19847 avgsol = MAX(avgsol, var->glbdom.lb);
19848 avgsol = MIN(avgsol, var->glbdom.ub);
19849 return avgsol;
19850
19852 assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
19853 return var->locdom.lb;
19854
19856 assert(!var->donotaggr);
19857 assert(var->data.aggregate.var != NULL);
19858 return var->data.aggregate.scalar * SCIPvarGetAvgSol(var->data.aggregate.var)
19859 + var->data.aggregate.constant;
19860
19862 assert(!var->donotmultaggr);
19863 assert(var->data.multaggr.vars != NULL);
19864 assert(var->data.multaggr.scalars != NULL);
19865 /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
19866 * assert(var->data.multaggr.nvars >= 2);
19867 */
19868 avgsol = var->data.multaggr.constant;
19869 for( i = 0; i < var->data.multaggr.nvars; ++i )
19870 avgsol += var->data.multaggr.scalars[i] * SCIPvarGetAvgSol(var->data.multaggr.vars[i]);
19871 return avgsol;
19872
19873 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
19874 assert(var->negatedvar != NULL);
19876 assert(var->negatedvar->negatedvar == var);
19877 return var->data.negate.constant - SCIPvarGetAvgSol(var->negatedvar);
19878
19879 default:
19880 SCIPerrorMessage("unknown variable status\n");
19881 SCIPABORT();
19882 return 0.0; /*lint !e527*/
19883 }
19884}
19885
19886/** returns solution value and index of variable lower bound that is closest to the variable's value in the given primal solution
19887 * or current LP solution if no primal solution is given; returns an index of -1 if no variable lower bound is available
19888 */
19890 SCIP_VAR* var, /**< active problem variable */
19891 SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
19892 SCIP_SET* set, /**< global SCIP settings */
19893 SCIP_STAT* stat, /**< problem statistics */
19894 SCIP_Real* closestvlb, /**< pointer to store the value of the closest variable lower bound */
19895 int* closestvlbidx /**< pointer to store the index of the closest variable lower bound */
19896 )
19897{
19898 int nvlbs;
19899
19900 assert(var != NULL);
19901 assert(stat != NULL);
19902 assert(set != NULL);
19903 assert(var->scip == set->scip);
19904 assert(closestvlb != NULL);
19905 assert(closestvlbidx != NULL);
19906
19907 *closestvlbidx = -1;
19908 *closestvlb = SCIP_REAL_MIN;
19909
19910 nvlbs = SCIPvarGetNVlbs(var);
19911 if( nvlbs > 0 )
19912 {
19913 SCIP_VAR** vlbvars;
19914 SCIP_Real* vlbcoefs;
19915 SCIP_Real* vlbconsts;
19916 int i;
19917
19918 vlbvars = SCIPvarGetVlbVars(var);
19919 vlbcoefs = SCIPvarGetVlbCoefs(var);
19920 vlbconsts = SCIPvarGetVlbConstants(var);
19921
19922 /* check for cached values */
19923 if( var->closestvblpcount == stat->lpcount && var->closestvlbidx != -1 && sol == NULL)
19924 {
19925 i = var->closestvlbidx;
19926 assert(0 <= i && i < nvlbs);
19927 assert(SCIPvarIsActive(vlbvars[i]));
19928 *closestvlbidx = i;
19929 *closestvlb = vlbcoefs[i] * SCIPvarGetLPSol(vlbvars[i]) + vlbconsts[i];
19930 }
19931 else
19932 {
19933 /* search best VUB */
19934 for( i = 0; i < nvlbs; i++ )
19935 {
19936 if( SCIPvarIsActive(vlbvars[i]) )
19937 {
19938 SCIP_Real vlbsol;
19939
19940 vlbsol = vlbcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vlbvars[i]) : SCIPsolGetVal(sol, set, stat, vlbvars[i])) + vlbconsts[i];
19941 if( vlbsol > *closestvlb )
19942 {
19943 *closestvlb = vlbsol;
19944 *closestvlbidx = i;
19945 }
19946 }
19947 }
19948
19949 if( sol == NULL )
19950 {
19951 /* update cached value */
19952 if( var->closestvblpcount != stat->lpcount )
19953 var->closestvubidx = -1;
19954 var->closestvlbidx = *closestvlbidx;
19955 var->closestvblpcount = stat->lpcount;
19956 }
19957 }
19958 }
19959}
19960
19961/** returns solution value and index of variable upper bound that is closest to the variable's value in the given primal solution;
19962 * or current LP solution if no primal solution is given; returns an index of -1 if no variable upper bound is available
19963 */
19965 SCIP_VAR* var, /**< active problem variable */
19966 SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
19967 SCIP_SET* set, /**< global SCIP settings */
19968 SCIP_STAT* stat, /**< problem statistics */
19969 SCIP_Real* closestvub, /**< pointer to store the value of the closest variable upper bound */
19970 int* closestvubidx /**< pointer to store the index of the closest variable upper bound */
19971 )
19972{
19973 int nvubs;
19974
19975 assert(var != NULL);
19976 assert(set != NULL);
19977 assert(var->scip == set->scip);
19978 assert(closestvub != NULL);
19979 assert(closestvubidx != NULL);
19980
19981 *closestvubidx = -1;
19982 *closestvub = SCIP_REAL_MAX;
19983
19984 nvubs = SCIPvarGetNVubs(var);
19985 if( nvubs > 0 )
19986 {
19987 SCIP_VAR** vubvars;
19988 SCIP_Real* vubcoefs;
19989 SCIP_Real* vubconsts;
19990 int i;
19991
19992 vubvars = SCIPvarGetVubVars(var);
19993 vubcoefs = SCIPvarGetVubCoefs(var);
19994 vubconsts = SCIPvarGetVubConstants(var);
19995
19996 /* check for cached values */
19997 if( var->closestvblpcount == stat->lpcount && var->closestvubidx != -1 && sol == NULL)
19998 {
19999 i = var->closestvubidx;
20000 assert(0 <= i && i < nvubs);
20001 assert(SCIPvarIsActive(vubvars[i]));
20002 *closestvubidx = i;
20003 *closestvub = vubcoefs[i] * SCIPvarGetLPSol(vubvars[i]) + vubconsts[i];
20004 }
20005 else
20006 {
20007 /* search best VUB */
20008 for( i = 0; i < nvubs; i++ )
20009 {
20010 if( SCIPvarIsActive(vubvars[i]) )
20011 {
20012 SCIP_Real vubsol;
20013
20014 vubsol = vubcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vubvars[i]) : SCIPsolGetVal(sol, set, stat, vubvars[i])) + vubconsts[i];
20015 if( vubsol < *closestvub )
20016 {
20017 *closestvub = vubsol;
20018 *closestvubidx = i;
20019 }
20020 }
20021 }
20022
20023 if( sol == NULL )
20024 {
20025 /* update cached value */
20026 if( var->closestvblpcount != stat->lpcount )
20027 var->closestvlbidx = -1;
20028 var->closestvubidx = *closestvubidx;
20029 var->closestvblpcount = stat->lpcount;
20030 }
20031 }
20032 }
20033}
20034
20035/** resolves variable to columns and adds them with the coefficient to the row */
20037 SCIP_VAR* var, /**< problem variable */
20038 BMS_BLKMEM* blkmem, /**< block memory */
20039 SCIP_SET* set, /**< global SCIP settings */
20040 SCIP_STAT* stat, /**< problem statistics */
20041 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
20042 SCIP_PROB* prob, /**< problem data */
20043 SCIP_LP* lp, /**< current LP data */
20044 SCIP_ROW* row, /**< LP row */
20045 SCIP_Real val /**< value of coefficient */
20046 )
20047{
20048 int i;
20049
20050 assert(var != NULL);
20051 assert(set != NULL);
20052 assert(var->scip == set->scip);
20053 assert(row != NULL);
20055
20056 SCIPsetDebugMsg(set, "adding coefficient %g<%s> to row <%s>\n", val, var->name, row->name);
20057
20058 if ( SCIPsetIsZero(set, val) )
20059 return SCIP_OKAY;
20060
20061 switch( SCIPvarGetStatus(var) )
20062 {
20064 if( var->data.original.transvar == NULL )
20065 {
20066 SCIPerrorMessage("cannot add untransformed original variable <%s> to LP row <%s>\n", var->name, row->name);
20067 return SCIP_INVALIDDATA;
20068 }
20069 SCIP_CALL( SCIPvarAddToRow(var->data.original.transvar, blkmem, set, stat, eventqueue, prob, lp, row, val) );
20070 return SCIP_OKAY;
20071
20073 /* add globally fixed variables as constant */
20074 if( SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub) )
20075 {
20076 SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->glbdom.lb) );
20077 return SCIP_OKAY;
20078 }
20079 /* convert loose variable into column */
20080 SCIP_CALL( SCIPvarColumn(var, blkmem, set, stat, prob, lp) );
20082 /*lint -fallthrough*/
20083
20085 assert(var->data.col != NULL);
20086 assert(var->data.col->var == var);
20087 SCIP_CALL( SCIProwIncCoef(row, blkmem, set, eventqueue, lp, var->data.col, val) );
20088 return SCIP_OKAY;
20089
20091 assert(var->glbdom.lb == var->glbdom.ub || (set->exact_enable && SCIPrationalIsEQ(var->exactdata->glbdom.lb, var->exactdata->glbdom.ub))); /*lint !e777*/
20092 assert(var->locdom.lb == var->locdom.ub || (set->exact_enable && SCIPrationalIsEQ(var->exactdata->locdom.lb, var->exactdata->locdom.ub))); /*lint !e777*/
20093 assert(var->locdom.lb == var->glbdom.lb || (set->exact_enable && SCIPrationalIsEQ(var->exactdata->glbdom.lb, var->exactdata->locdom.lb))); /*lint !e777*/
20094 assert(!SCIPsetIsInfinity(set, REALABS(var->locdom.lb)));
20095 SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->locdom.lb) );
20096 return SCIP_OKAY;
20097
20099 assert(!var->donotaggr);
20100 assert(var->data.aggregate.var != NULL);
20101 SCIP_CALL( SCIPvarAddToRow(var->data.aggregate.var, blkmem, set, stat, eventqueue, prob, lp,
20102 row, var->data.aggregate.scalar * val) );
20103 SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.aggregate.constant * val) );
20104 return SCIP_OKAY;
20105
20107 assert(!var->donotmultaggr);
20108 assert(var->data.multaggr.vars != NULL);
20109 assert(var->data.multaggr.scalars != NULL);
20110 /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
20111 * assert(var->data.multaggr.nvars >= 2);
20112 */
20113 for( i = 0; i < var->data.multaggr.nvars; ++i )
20114 {
20115 SCIP_CALL( SCIPvarAddToRow(var->data.multaggr.vars[i], blkmem, set, stat, eventqueue, prob, lp,
20116 row, var->data.multaggr.scalars[i] * val) );
20117 }
20118 SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.multaggr.constant * val) );
20119 return SCIP_OKAY;
20120
20121 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
20122 assert(var->negatedvar != NULL);
20124 assert(var->negatedvar->negatedvar == var);
20125 SCIP_CALL( SCIPvarAddToRow(var->negatedvar, blkmem, set, stat, eventqueue, prob, lp, row, -val) );
20126 SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.negate.constant * val) );
20127 return SCIP_OKAY;
20128
20129 default:
20130 SCIPerrorMessage("unknown variable status\n");
20131 return SCIP_INVALIDDATA;
20132 }
20133}
20134
20135/** resolves variable to exact columns and adds them with the coefficient to the exact Row */
20137 SCIP_VAR* var, /**< problem variable */
20138 BMS_BLKMEM* blkmem, /**< block memory */
20139 SCIP_SET* set, /**< global SCIP settings */
20140 SCIP_STAT* stat, /**< problem statistics */
20141 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
20142 SCIP_PROB* prob, /**< problem data */
20143 SCIP_LPEXACT* lpexact, /**< current LP data */
20144 SCIP_ROWEXACT* rowexact, /**< LP row */
20145 SCIP_RATIONAL* val /**< value of coefficient */
20146 )
20147{
20148 SCIP_RATIONAL* tmp;
20149 int i;
20150
20151 assert(var != NULL);
20152 assert(set != NULL);
20153 assert(var->scip == set->scip);
20154 assert(rowexact != NULL);
20156
20157 SCIPrationalDebugMessage("adding coefficient %q<%s> to exact row <%s>\n", val, var->name, rowexact->fprow->name);
20158
20159 if ( SCIPrationalIsZero(val) )
20160 return SCIP_OKAY;
20161
20162 switch( SCIPvarGetStatusExact(var) )
20163 {
20165 if( var->data.original.transvar == NULL )
20166 {
20167 SCIPerrorMessage("cannot add untransformed original variable <%s> to excact LP row <%s>\n", var->name, rowexact->fprow->name);
20168 return SCIP_INVALIDDATA;
20169 }
20170 SCIP_CALL( SCIPvarAddToRowExact(var->data.original.transvar, blkmem, set, stat, eventqueue, prob, lpexact, rowexact, val) );
20171 break;
20172
20174 /* add globally fixed variables as constant */
20175 if( SCIPrationalIsEQ(var->exactdata->glbdom.lb, var->exactdata->glbdom.ub) )
20176 {
20177 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmp) );
20178 SCIPrationalMult(tmp, val, var->exactdata->glbdom.lb);
20179 SCIP_CALL( SCIProwExactAddConstant(rowexact, set, stat, lpexact, tmp) );
20180 SCIPrationalFreeBuffer(set->buffer, &tmp);
20181 break;
20182 }
20183 /* convert loose variable into column */
20184 SCIP_CALL( SCIPvarColumnExact(var, blkmem, set, stat, lpexact) );
20186 /*lint -fallthrough*/
20187
20189 assert(var->data.col != NULL);
20190 assert(var->data.col->var == var);
20191 SCIP_CALL( SCIProwExactIncCoef(rowexact, blkmem, set, eventqueue, lpexact, var->exactdata->colexact, val) );
20192 break;
20193
20195 assert(SCIPrationalIsEQ(var->exactdata->glbdom.lb, var->exactdata->glbdom.ub)); /*lint !e777*/
20196 assert(SCIPrationalIsEQ(var->exactdata->locdom.lb, var->exactdata->locdom.ub)); /*lint !e777*/
20197 assert(SCIPrationalIsEQ(var->exactdata->locdom.lb, var->exactdata->glbdom.lb)); /*lint !e777*/
20198 assert(!SCIPrationalIsAbsInfinity(var->exactdata->locdom.lb));
20199
20200 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmp) );
20201
20202 SCIPrationalMult(tmp, val, var->exactdata->locdom.lb);
20203 SCIP_CALL( SCIProwExactAddConstant(rowexact, set, stat, lpexact, tmp) );
20204
20205 SCIPrationalFreeBuffer(set->buffer, &tmp);
20206
20207 break;
20208
20210 assert(var->data.aggregate.var != NULL);
20211
20212 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmp) );
20213 SCIPrationalMult(tmp, var->exactdata->aggregate.scalar, val);
20214 SCIP_CALL( SCIPvarAddToRowExact(var->data.aggregate.var, blkmem, set, stat, eventqueue, prob, lpexact,
20215 rowexact, tmp) );
20216 SCIPrationalMult(tmp, var->exactdata->aggregate.constant, val);
20217 SCIP_CALL( SCIProwExactAddConstant(rowexact, set, stat, lpexact, tmp) );
20218 SCIPrationalFreeBuffer(set->buffer, &tmp);
20219 return SCIP_OKAY;
20220
20222 assert(!var->donotmultaggr);
20223 assert(var->data.multaggr.vars != NULL);
20224 assert(var->data.multaggr.scalars != NULL);
20225
20226 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmp) );
20227
20228 for( i = 0; i < var->data.multaggr.nvars; ++i )
20229 {
20230 SCIPrationalMult(tmp, var->exactdata->multaggr.scalars[i], val);
20231 SCIP_CALL( SCIPvarAddToRowExact(var->data.multaggr.vars[i], blkmem, set, stat, eventqueue, prob, lpexact,
20232 rowexact, tmp) );
20233 }
20234 SCIPrationalMult(tmp, var->exactdata->multaggr.constant, val);
20235 SCIP_CALL( SCIProwExactAddConstant(rowexact, set, stat, lpexact, tmp) );
20236
20237 SCIPrationalFreeBuffer(set->buffer, &tmp);
20238 return SCIP_OKAY;
20239
20240 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
20241 assert(var->negatedvar != NULL);
20243 assert(var->negatedvar->negatedvar == var);
20244
20245 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmp) );
20246
20247 SCIPrationalNegate(tmp, val);
20248 SCIP_CALL( SCIPvarAddToRowExact(var->negatedvar, blkmem, set, stat, eventqueue, prob, lpexact, rowexact, tmp) );
20249
20250 SCIPrationalMultReal(tmp, val, var->data.negate.constant);
20251 SCIP_CALL( SCIProwExactAddConstant(rowexact, set, stat, lpexact, tmp) );
20252
20253 SCIPrationalFreeBuffer(set->buffer, &tmp);
20254
20255 break;
20256
20257 default:
20258 SCIPerrorMessage("unknown variable status\n");
20259 return SCIP_INVALIDDATA;
20260 }
20261
20262 return SCIP_OKAY;
20263}
20264
20265/* optionally, define this compiler flag to write complete variable histories to a file */
20266#ifdef SCIP_HISTORYTOFILE
20267SCIP_Longint counter = 0l;
20268const char* historypath="."; /* allows for user-defined path; use '.' for calling directory of SCIP */
20269#include "scip/scip.h"
20270#endif
20271
20272/** updates the pseudo costs of the given variable and the global pseudo costs after a change of
20273 * "solvaldelta" in the variable's solution value and resulting change of "objdelta" in the LP's objective value
20274 */
20276 SCIP_VAR* var, /**< problem variable */
20277 SCIP_SET* set, /**< global SCIP settings */
20278 SCIP_STAT* stat, /**< problem statistics */
20279 SCIP_Real solvaldelta, /**< difference of variable's new LP value - old LP value */
20280 SCIP_Real objdelta, /**< difference of new LP's objective value - old LP's objective value */
20281 SCIP_Real weight /**< weight in (0,1] of this update in pseudo cost sum */
20282 )
20283{
20284 SCIP_Real oldrootpseudocosts;
20285 assert(var != NULL);
20286 assert(set != NULL);
20287 assert(var->scip == set->scip);
20288 assert(stat != NULL);
20289
20290 /* check if history statistics should be collected for a variable */
20291 if( !stat->collectvarhistory )
20292 return SCIP_OKAY;
20293
20294 switch( SCIPvarGetStatus(var) )
20295 {
20297 if( var->data.original.transvar == NULL )
20298 {
20299 SCIPerrorMessage("cannot update pseudo costs of original untransformed variable\n");
20300 return SCIP_INVALIDDATA;
20301 }
20302 SCIP_CALL( SCIPvarUpdatePseudocost(var->data.original.transvar, set, stat, solvaldelta, objdelta, weight) );
20303 return SCIP_OKAY;
20304
20307 /* store old pseudo-costs for root LP best-estimate update */
20308 oldrootpseudocosts = SCIPvarGetMinPseudocostScore(var, stat, set, SCIPvarGetRootSol(var));
20309
20310 /* update history */
20311 SCIPhistoryUpdatePseudocost(var->history, set, solvaldelta, objdelta, weight);
20312 SCIPhistoryUpdatePseudocost(var->historycrun, set, solvaldelta, objdelta, weight);
20313 SCIPhistoryUpdatePseudocost(stat->glbhistory, set, solvaldelta, objdelta, weight);
20314 SCIPhistoryUpdatePseudocost(stat->glbhistorycrun, set, solvaldelta, objdelta, weight);
20315
20316 /* update root LP best-estimate */
20317 SCIP_CALL( SCIPstatUpdateVarRootLPBestEstimate(stat, set, var, oldrootpseudocosts) );
20318
20319 /* append history to file */
20320#ifdef SCIP_HISTORYTOFILE
20321 {
20322 FILE* f;
20323 char filename[256];
20324 SCIP_NODE* currentnode;
20325 SCIP_NODE* parentnode;
20326 currentnode = SCIPgetFocusNode(set->scip);
20327 parentnode = SCIPnodeGetParent(currentnode);
20328
20329 sprintf(filename, "%s/%s.pse", historypath, SCIPgetProbName(set->scip));
20330 f = fopen(filename, "a");
20331 if( NULL != f )
20332 {
20333 fprintf(f, "%lld %s \t %lld \t %lld \t %lld \t %d \t %15.9f \t %.3f\n",
20334 ++counter,
20336 SCIPnodeGetNumber(currentnode),
20337 parentnode != NULL ? SCIPnodeGetNumber(parentnode) : -1,
20339 SCIPgetDepth(set->scip),
20340 objdelta,
20341 solvaldelta);
20342 fclose(f);
20343 }
20344 }
20345#endif
20346 return SCIP_OKAY;
20347
20349 SCIPerrorMessage("cannot update pseudo cost values of a fixed variable\n");
20350 return SCIP_INVALIDDATA;
20351
20353 assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
20354 SCIP_CALL( SCIPvarUpdatePseudocost(var->data.aggregate.var, set, stat,
20355 solvaldelta/var->data.aggregate.scalar, objdelta, weight) );
20356 return SCIP_OKAY;
20357
20359 SCIPerrorMessage("cannot update pseudo cost values of a multi-aggregated variable\n");
20360 return SCIP_INVALIDDATA;
20361
20363 SCIP_CALL( SCIPvarUpdatePseudocost(var->negatedvar, set, stat, -solvaldelta, objdelta, weight) );
20364 return SCIP_OKAY;
20365
20366 default:
20367 SCIPerrorMessage("unknown variable status\n");
20368 return SCIP_INVALIDDATA;
20369 }
20370}
20371
20372/** updates the ancestral pseudo costs of the given variable and the global ancestral pseudo costs after a change of
20373 * "solvaldelta" in the variable's solution value and resulting change of "objdelta" in the LP's objective value
20374 */
20376 SCIP_VAR* var, /**< problem variable */
20377 SCIP_SET* set, /**< global SCIP settings */
20378 SCIP_STAT* stat, /**< problem statistics */
20379 SCIP_Real solvaldelta, /**< difference of variable's new LP value - old LP value */
20380 SCIP_Real objdelta, /**< difference of new LP's objective value - old LP's objective value */
20381 SCIP_Real weight /**< weight in (0,1] of this update in discounted pseudo cost sum */
20382 )
20383{
20384 assert(var != NULL);
20385 assert(set != NULL);
20386 assert(var->scip == set->scip);
20387 assert(stat != NULL);
20388
20389 /* check if history statistics should be collected for a variable */
20390 if( !stat->collectvarhistory )
20391 return SCIP_OKAY;
20392
20393 switch( SCIPvarGetStatus(var) )
20394 {
20396 if( var->data.original.transvar == NULL )
20397 {
20398 SCIPerrorMessage("cannot update ancestral pseudo costs of original untransformed variable\n");
20399 return SCIP_INVALIDDATA;
20400 }
20401 SCIP_CALL( SCIPvarUpdateAncPseudocost(var->data.original.transvar, set, stat, solvaldelta, objdelta, weight) );
20402 return SCIP_OKAY;
20403
20406 /* update history */
20407 SCIPhistoryUpdateAncPseudocost(var->history, set, solvaldelta, objdelta, weight);
20408 SCIPhistoryUpdateAncPseudocost(var->historycrun, set, solvaldelta, objdelta, weight);
20409 SCIPhistoryUpdateAncPseudocost(stat->glbhistory, set, solvaldelta, objdelta, weight);
20410 SCIPhistoryUpdateAncPseudocost(stat->glbhistorycrun, set, solvaldelta, objdelta, weight);
20411 return SCIP_OKAY;
20412
20414 SCIPerrorMessage("cannot update ancestral pseudo cost values of a fixed variable\n");
20415 return SCIP_INVALIDDATA;
20416
20418 assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
20419 SCIP_CALL( SCIPvarUpdateAncPseudocost(var->data.aggregate.var, set, stat,
20420 solvaldelta/var->data.aggregate.scalar, objdelta, weight) );
20421 return SCIP_OKAY;
20422
20424 SCIPerrorMessage("cannot update ancestral pseudo cost values of a multi-aggregated variable\n");
20425 return SCIP_INVALIDDATA;
20426
20428 SCIP_CALL( SCIPvarUpdateAncPseudocost(var->negatedvar, set, stat, -solvaldelta, objdelta, weight) );
20429 return SCIP_OKAY;
20430
20431 default:
20432 SCIPerrorMessage("unknown variable status\n");
20433 return SCIP_INVALIDDATA;
20434 }
20435}
20436
20437/** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value */
20439 SCIP_VAR* var, /**< problem variable */
20440 SCIP_STAT* stat, /**< problem statistics */
20441 SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
20442 )
20443{
20444 SCIP_BRANCHDIR dir;
20445
20446 assert(var != NULL);
20447 assert(stat != NULL);
20448
20449 switch( SCIPvarGetStatus(var) )
20450 {
20452 if( var->data.original.transvar == NULL )
20453 return SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
20454 else
20455 return SCIPvarGetPseudocost(var->data.original.transvar, stat, solvaldelta);
20456
20459 dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
20460
20461 return SCIPhistoryGetPseudocostCount(var->history, dir) > 0.0
20462 ? SCIPhistoryGetPseudocost(var->history, solvaldelta)
20463 : SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
20464
20466 return 0.0;
20467
20469 return SCIPvarGetPseudocost(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
20470
20472 return 0.0;
20473
20475 return SCIPvarGetPseudocost(var->negatedvar, stat, -solvaldelta);
20476
20477 default:
20478 SCIPerrorMessage("unknown variable status\n");
20479 SCIPABORT();
20480 return 0.0; /*lint !e527*/
20481 }
20482}
20483
20484/** gets the variable's ancestral pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value */
20486 SCIP_VAR* var, /**< problem variable */
20487 SCIP_STAT* stat, /**< problem statistics */
20488 SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
20489 )
20490{
20491 SCIP_BRANCHDIR dir;
20492
20493 assert(var != NULL);
20494 assert(stat != NULL);
20495
20496 switch( SCIPvarGetStatus(var) )
20497 {
20499 if( var->data.original.transvar == NULL )
20500 return SCIPhistoryGetAncPseudocost(stat->glbhistory, solvaldelta);
20501 else
20502 return SCIPvarGetAncPseudocost(var->data.original.transvar, stat, solvaldelta);
20503
20506 dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
20507
20508 return SCIPhistoryGetAncPseudocostCount(var->history, dir) > 0.0
20509 ? SCIPhistoryGetAncPseudocost(var->history, solvaldelta)
20510 : SCIPhistoryGetAncPseudocost(stat->glbhistory, solvaldelta);
20511
20513 return 0.0;
20514
20516 return SCIPvarGetAncPseudocost(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
20517
20519 return 0.0;
20520
20522 return SCIPvarGetAncPseudocost(var->negatedvar, stat, -solvaldelta);
20523
20524 default:
20525 SCIPerrorMessage("unknown variable status\n");
20526 SCIPABORT();
20527 return 0.0; /*lint !e527*/
20528 }
20529}
20530
20531/** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value,
20532 * only using the pseudo cost information of the current run
20533 */
20535 SCIP_VAR* var, /**< problem variable */
20536 SCIP_STAT* stat, /**< problem statistics */
20537 SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
20538 )
20539{
20540 SCIP_BRANCHDIR dir;
20541
20542 assert(var != NULL);
20543 assert(stat != NULL);
20544
20545 switch( SCIPvarGetStatus(var) )
20546 {
20548 if( var->data.original.transvar == NULL )
20549 return SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
20550 else
20551 return SCIPvarGetPseudocostCurrentRun(var->data.original.transvar, stat, solvaldelta);
20552
20555 dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
20556
20557 return SCIPhistoryGetPseudocostCount(var->historycrun, dir) > 0.0
20558 ? SCIPhistoryGetPseudocost(var->historycrun, solvaldelta)
20559 : SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
20560
20562 return 0.0;
20563
20565 return SCIPvarGetPseudocostCurrentRun(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
20566
20568 return 0.0;
20569
20571 return SCIPvarGetPseudocostCurrentRun(var->negatedvar, stat, -solvaldelta);
20572
20573 default:
20574 SCIPerrorMessage("unknown variable status\n");
20575 SCIPABORT();
20576 return 0.0; /*lint !e527*/
20577 }
20578}
20579
20580/** gets the variable's (possible fractional) number of pseudo cost updates for the given direction */
20582 SCIP_VAR* var, /**< problem variable */
20583 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
20584 )
20585{
20586 assert(var != NULL);
20588
20589 switch( SCIPvarGetStatus(var) )
20590 {
20592 if( var->data.original.transvar == NULL )
20593 return 0.0;
20594 else
20595 return SCIPvarGetPseudocostCount(var->data.original.transvar, dir);
20596
20599 return SCIPhistoryGetPseudocostCount(var->history, dir);
20600
20602 return 0.0;
20603
20605 if( var->data.aggregate.scalar > 0.0 )
20606 return SCIPvarGetPseudocostCount(var->data.aggregate.var, dir);
20607 else
20608 return SCIPvarGetPseudocostCount(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
20609
20611 return 0.0;
20612
20614 return SCIPvarGetPseudocostCount(var->negatedvar, SCIPbranchdirOpposite(dir));
20615
20616 default:
20617 SCIPerrorMessage("unknown variable status\n");
20618 SCIPABORT();
20619 return 0.0; /*lint !e527*/
20620 }
20621}
20622
20623/** gets the variable's (possible fractional) number of pseudo cost updates for the given direction,
20624 * only using the pseudo cost information of the current run
20625 */
20627 SCIP_VAR* var, /**< problem variable */
20628 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
20629 )
20630{
20631 assert(var != NULL);
20633
20634 switch( SCIPvarGetStatus(var) )
20635 {
20637 if( var->data.original.transvar == NULL )
20638 return 0.0;
20639 else
20640 return SCIPvarGetPseudocostCountCurrentRun(var->data.original.transvar, dir);
20641
20644 return SCIPhistoryGetPseudocostCount(var->historycrun, dir);
20645
20647 return 0.0;
20648
20650 if( var->data.aggregate.scalar > 0.0 )
20651 return SCIPvarGetPseudocostCountCurrentRun(var->data.aggregate.var, dir);
20652 else
20653 return SCIPvarGetPseudocostCountCurrentRun(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
20654
20656 return 0.0;
20657
20660
20661 default:
20662 SCIPerrorMessage("unknown variable status\n");
20663 SCIPABORT();
20664 return 0.0; /*lint !e527*/
20665 }
20666}
20667
20668/** gets the variable's (possible fractional) number of ancestor pseudo cost updates for the given direction,
20669 * only using the pseudo cost information of the current run
20670 */
20672 SCIP_VAR* var, /**< problem variable */
20673 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
20674 )
20675{
20676 assert(var != NULL);
20678
20679 switch( SCIPvarGetStatus(var) )
20680 {
20682 if( var->data.original.transvar == NULL )
20683 return 0.0;
20684 else
20685 return SCIPvarGetAncPseudocostCountCurrentRun(var->data.original.transvar, dir);
20686
20689 return SCIPhistoryGetAncPseudocostCount(var->historycrun, dir);
20690
20692 return 0.0;
20693
20695 if( var->data.aggregate.scalar > 0.0 )
20696 return SCIPvarGetAncPseudocostCountCurrentRun(var->data.aggregate.var, dir);
20697 else
20698 return SCIPvarGetAncPseudocostCountCurrentRun(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
20699
20701 return 0.0;
20702
20705
20706 default:
20707 SCIPerrorMessage("unknown variable status\n");
20708 SCIPABORT();
20709 return 0.0; /*lint !e527*/
20710 }
20711}
20712
20713/** compares both possible directions for rounding the given solution value and returns the minimum pseudo-costs of the variable */
20715 SCIP_VAR* var, /**< problem variable */
20716 SCIP_STAT* stat, /**< problem statistics */
20717 SCIP_SET* set, /**< global SCIP settings */
20718 SCIP_Real solval /**< solution value, e.g., LP solution value */
20719 )
20720{
20721 SCIP_Real upscore;
20722 SCIP_Real downscore;
20723 SCIP_Real solvaldeltaup;
20724 SCIP_Real solvaldeltadown;
20725
20726 /* LP root estimate only works for variables with fractional LP root solution */
20727 if( SCIPsetIsFeasIntegral(set, solval) )
20728 return 0.0;
20729
20730 /* no min pseudo-cost score is calculated as long as the variable was not initialized in a direction */
20732 return 0.0;
20733
20734 /* compute delta's to ceil and floor of root LP solution value */
20735 solvaldeltaup = SCIPsetCeil(set, solval) - solval;
20736 solvaldeltadown = SCIPsetFloor(set, solval) - solval;
20737
20738 upscore = SCIPvarGetPseudocost(var, stat, solvaldeltaup);
20739 downscore = SCIPvarGetPseudocost(var, stat, solvaldeltadown);
20740
20741 return MIN(upscore, downscore);
20742}
20743
20744/** gets the an estimate of the variable's pseudo cost variance in direction \p dir */
20746 SCIP_VAR* var, /**< problem variable */
20747 SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
20748 SCIP_Bool onlycurrentrun /**< return pseudo cost variance only for current branch and bound run */
20749 )
20750{
20751 assert(var != NULL);
20753
20754 switch( SCIPvarGetStatus(var) )
20755 {
20757 if( var->data.original.transvar == NULL )
20758 return 0.0;
20759 else
20760 return SCIPvarGetPseudocostVariance(var->data.original.transvar, dir, onlycurrentrun);
20761
20764 if( onlycurrentrun )
20765 return SCIPhistoryGetPseudocostVariance(var->historycrun, dir);
20766 else
20767 return SCIPhistoryGetPseudocostVariance(var->history, dir);
20768
20770 return 0.0;
20771
20773 if( var->data.aggregate.scalar > 0.0 )
20774 return SCIPvarGetPseudocostVariance(var->data.aggregate.var, dir, onlycurrentrun);
20775 else
20776 return SCIPvarGetPseudocostVariance(var->data.aggregate.var, SCIPbranchdirOpposite(dir), onlycurrentrun);
20777
20779 return 0.0;
20780
20782 return SCIPvarGetPseudocostVariance(var->negatedvar, SCIPbranchdirOpposite(dir), onlycurrentrun);
20783
20784 default:
20785 SCIPerrorMessage("unknown variable status\n");
20786 SCIPABORT();
20787 return 0.0; /*lint !e527*/
20788 }
20789}
20790
20791/** calculates a confidence bound for this variable under the assumption of normally distributed pseudo costs
20792 *
20793 * The confidence bound \f$ \theta \geq 0\f$ denotes the interval borders \f$ [X - \theta, \ X + \theta]\f$, which contains
20794 * the true pseudo costs of the variable, i.e., the expected value of the normal distribution, with a probability
20795 * of 2 * clevel - 1.
20796 *
20797 * @return value of confidence bound for this variable
20798 */
20800 SCIP_VAR* var, /**< variable in question */
20801 SCIP_SET* set, /**< global SCIP settings */
20802 SCIP_BRANCHDIR dir, /**< the branching direction for the confidence bound */
20803 SCIP_Bool onlycurrentrun, /**< should only the current run be taken into account */
20804 SCIP_CONFIDENCELEVEL clevel /**< confidence level for the interval */
20805 )
20806{
20807 SCIP_Real confidencebound;
20808
20809 confidencebound = SCIPvarGetPseudocostVariance(var, dir, onlycurrentrun);
20810 if( SCIPsetIsFeasPositive(set, confidencebound) )
20811 {
20812 SCIP_Real count;
20813
20814 if( onlycurrentrun )
20816 else
20817 count = SCIPvarGetPseudocostCount(var, dir);
20818 /* assertion is valid because variance is positive */
20819 assert(count >= 1.9);
20820
20821 confidencebound /= count; /*lint !e414 division by zero can obviously not occur */
20822 confidencebound = sqrt(confidencebound);
20823
20824 /* the actual, underlying distribution of the mean is a student-t-distribution with degrees of freedom equal to
20825 * the number of pseudo cost evaluations of this variable in the respective direction. */
20826 confidencebound *= SCIPstudentTGetCriticalValue(clevel, (int)SCIPsetFloor(set, count) - 1);
20827 }
20828 else
20829 confidencebound = 0.0;
20830
20831 return confidencebound;
20832}
20833
20834/** check if the current pseudo cost relative error in a direction violates the given threshold. The Relative
20835 * Error is calculated at a specific confidence level
20836 */
20838 SCIP_VAR* var, /**< variable in question */
20839 SCIP_SET* set, /**< global SCIP settings */
20840 SCIP_STAT* stat, /**< problem statistics */
20841 SCIP_Real threshold, /**< threshold for relative errors to be considered reliable (enough) */
20842 SCIP_CONFIDENCELEVEL clevel /**< a given confidence level */
20843 )
20844{
20845 SCIP_Real downsize;
20846 SCIP_Real upsize;
20847 SCIP_Real size;
20848 SCIP_Real relerrorup;
20849 SCIP_Real relerrordown;
20850 SCIP_Real relerror;
20851
20852 /* check, if the pseudo cost score of the variable is reliable */
20855 size = MIN(downsize, upsize);
20856
20857 /* Pseudo costs relative error can only be reliable if both directions have been tried at least twice */
20858 if( size <= 1.9 )
20859 return FALSE;
20860
20861 /* use the relative error between the current mean pseudo cost value of the candidate and its upper
20862 * confidence interval bound at confidence level of 95% for individual variable reliability.
20863 * this is only possible if we have at least 2 measurements and therefore a valid variance estimate.
20864 */
20865 if( downsize >= 1.9 )
20866 {
20867 SCIP_Real normval;
20868
20870 normval = SCIPvarGetPseudocostCurrentRun(var, stat, -1.0);
20871 normval = MAX(1.0, normval);
20872
20873 relerrordown /= normval;
20874 }
20875 else
20876 relerrordown = 0.0;
20877
20878 if( upsize >= 1.9 )
20879 {
20880 SCIP_Real normval;
20881
20883 normval = SCIPvarGetPseudocostCurrentRun(var, stat, +1.0);
20884 normval = MAX(1.0, normval);
20885 relerrorup /= normval;
20886 }
20887 else
20888 relerrorup = 0.0;
20889
20890 /* consider the relative error threshold violated, if it is violated in at least one branching direction */
20891 relerror = MAX(relerrorup, relerrordown);
20892
20893 return (relerror <= threshold);
20894}
20895
20896/** check if variable pseudo-costs have a significant difference in location. The significance depends on
20897 * the choice of \p clevel and on the kind of tested hypothesis. The one-sided hypothesis, which
20898 * should be rejected, is that fracy * mu_y >= fracx * mu_x, where mu_y and mu_x denote the
20899 * unknown location means of the underlying pseudo-cost distributions of x and y.
20900 *
20901 * This method is applied best if variable x has a better pseudo-cost score than y. The method hypothesizes that y were actually
20902 * better than x (despite the current information), meaning that y can be expected to yield branching
20903 * decisions as least as good as x in the long run. If the method returns TRUE, the current history information is
20904 * sufficient to safely rely on the alternative hypothesis that x yields indeed a better branching score (on average)
20905 * than y.
20906 *
20907 * @note The order of x and y matters for the one-sided hypothesis
20908 *
20909 * @note set \p onesided to FALSE if you are not sure which variable is better. The hypothesis tested then reads
20910 * fracy * mu_y == fracx * mu_x vs the alternative hypothesis fracy * mu_y != fracx * mu_x.
20911 *
20912 * @return TRUE if the hypothesis can be safely rejected at the given confidence level
20913 */
20915 SCIP_SET* set, /**< global SCIP settings */
20916 SCIP_STAT* stat, /**< problem statistics */
20917 SCIP_VAR* varx, /**< variable x */
20918 SCIP_Real fracx, /**< the fractionality of variable x */
20919 SCIP_VAR* vary, /**< variable y */
20920 SCIP_Real fracy, /**< the fractionality of variable y */
20921 SCIP_BRANCHDIR dir, /**< branching direction */
20922 SCIP_CONFIDENCELEVEL clevel, /**< confidence level for rejecting hypothesis */
20923 SCIP_Bool onesided /**< should a one-sided hypothesis y >= x be tested? */
20924 )
20925{
20926 SCIP_Real meanx;
20927 SCIP_Real meany;
20928 SCIP_Real variancex;
20929 SCIP_Real variancey;
20930 SCIP_Real countx;
20931 SCIP_Real county;
20932 SCIP_Real tresult;
20933 SCIP_Real realdirection;
20934
20935 if( varx == vary )
20936 return FALSE;
20937
20938 countx = SCIPvarGetPseudocostCount(varx, dir);
20939 county = SCIPvarGetPseudocostCount(vary, dir);
20940
20941 /* if not at least 2 measurements were taken, return FALSE */
20942 if( countx <= 1.9 || county <= 1.9 )
20943 return FALSE;
20944
20945 realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
20946
20947 meanx = fracx * SCIPvarGetPseudocost(varx, stat, realdirection);
20948 meany = fracy * SCIPvarGetPseudocost(vary, stat, realdirection);
20949
20950 variancex = SQR(fracx) * SCIPvarGetPseudocostVariance(varx, dir, FALSE);
20951 variancey = SQR(fracy) * SCIPvarGetPseudocostVariance(vary, dir, FALSE);
20952
20953 /* if there is no variance, the means are taken from a constant distribution */
20954 if( SCIPsetIsFeasEQ(set, variancex + variancey, 0.0) )
20955 return (onesided ? SCIPsetIsFeasGT(set, meanx, meany) : !SCIPsetIsFeasEQ(set, meanx, meany));
20956
20957 tresult = SCIPcomputeTwoSampleTTestValue(meanx, meany, variancex, variancey, countx, county);
20958
20959 /* for the two-sided hypothesis, just take the absolute of t */
20960 if( !onesided )
20961 tresult = REALABS(tresult);
20962
20963 return (tresult >= SCIPstudentTGetCriticalValue(clevel, (int)(countx + county - 2)));
20964}
20965
20966/** tests at a given confidence level whether the variable pseudo-costs only have a small probability to
20967 * exceed a \p threshold. This is useful to determine if past observations provide enough evidence
20968 * to skip an expensive strong-branching step if there is already a candidate that has been proven to yield an improvement
20969 * of at least \p threshold.
20970 *
20971 * @note use \p clevel to adjust the level of confidence. For SCIP_CONFIDENCELEVEL_MIN, the method returns TRUE if
20972 * the estimated probability to exceed \p threshold is less than 25 %.
20973 *
20974 * @see SCIP_Confidencelevel for a list of available levels. The used probability limits refer to the one-sided levels
20975 * of confidence.
20976 *
20977 * @return TRUE if the variable pseudo-cost probabilistic model is likely to be smaller than \p threshold
20978 * at the given confidence level \p clevel.
20979 */
20981 SCIP_SET* set, /**< global SCIP settings */
20982 SCIP_STAT* stat, /**< problem statistics */
20983 SCIP_VAR* var, /**< variable x */
20984 SCIP_Real frac, /**< the fractionality of variable x */
20985 SCIP_Real threshold, /**< the threshold to test against */
20986 SCIP_BRANCHDIR dir, /**< branching direction */
20987 SCIP_CONFIDENCELEVEL clevel /**< confidence level for rejecting hypothesis */
20988 )
20989{
20990 SCIP_Real mean;
20991 SCIP_Real variance;
20992 SCIP_Real count;
20993 SCIP_Real realdirection;
20994 SCIP_Real probability;
20995 SCIP_Real problimit;
20996
20997 count = SCIPvarGetPseudocostCount(var, dir);
20998
20999 /* if not at least 2 measurements were taken, return FALSE */
21000 if( count <= 1.9 )
21001 return FALSE;
21002
21003 realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
21004
21005 mean = frac * SCIPvarGetPseudocost(var, stat, realdirection);
21006 variance = SQR(frac) * SCIPvarGetPseudocostVariance(var, dir, FALSE);
21007
21008 /* if mean is at least threshold, it has at least a 50% probability to exceed threshold, we therefore return FALSE */
21009 if( SCIPsetIsFeasGE(set, mean, threshold) )
21010 return FALSE;
21011
21012 /* if there is no variance, the means are taken from a constant distribution */
21013 if( SCIPsetIsFeasEQ(set, variance, 0.0) )
21014 return SCIPsetIsFeasLT(set, mean, threshold);
21015
21016 /* obtain probability of a normally distributed random variable at given mean and variance to yield at most threshold */
21017 probability = SCIPnormalCDF(mean, variance, threshold);
21018
21019 /* determine a probability limit corresponding to the given confidence level */
21020 switch( clevel )
21021 {
21023 problimit = 0.75;
21024 break;
21026 problimit = 0.875;
21027 break;
21029 problimit = 0.9;
21030 break;
21032 problimit = 0.95;
21033 break;
21035 problimit = 0.975;
21036 break;
21037 default:
21038 problimit = -1;
21039 SCIPerrorMessage("Confidence level set to unknown value <%d>", (int)clevel);
21040 SCIPABORT();
21041 break;
21042 }
21043
21044 return (probability >= problimit);
21045}
21046
21047/** find the corresponding history entry if already existing, otherwise create new entry */
21048static
21050 SCIP_VAR* var, /**< problem variable */
21051 SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
21052 BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
21053 SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
21054 SCIP_HISTORY** history /**< pointer to store the value based history, or NULL */
21055 )
21056{
21057 assert(var != NULL);
21058 assert(blkmem != NULL);
21059 assert(set != NULL);
21060 assert(history != NULL);
21061
21062 (*history) = NULL;
21063
21064 if( var->valuehistory == NULL )
21065 {
21066 SCIP_CALL( SCIPvaluehistoryCreate(&var->valuehistory, blkmem) );
21067 }
21068
21069 SCIP_CALL( SCIPvaluehistoryFind(var->valuehistory, blkmem, set, value, history) );
21070
21071 return SCIP_OKAY;
21072}
21073
21074/** check if value based history should be used */
21075static
21077 SCIP_VAR* var, /**< problem variable */
21078 SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
21079 SCIP_SET* set /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
21080 )
21081{
21082 /* check if the domain value is unknown (not specific) */
21083 if( value == SCIP_UNKNOWN ) /*lint !e777*/
21084 return FALSE;
21085
21086 assert(set != NULL);
21087
21088 /* check if value based history should be collected */
21089 if( !set->history_valuebased )
21090 return FALSE;
21091
21092 /* value based history is not collected for binary variable since the standard history already contains all information */
21094 return FALSE;
21095
21096 /* value based history is not collected for continuous variables */
21098 return FALSE;
21099
21100 return TRUE;
21101}
21102
21103/** increases VSIDS of the variable by the given weight */
21105 SCIP_VAR* var, /**< problem variable */
21106 BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
21107 SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
21108 SCIP_STAT* stat, /**< problem statistics */
21109 SCIP_BRANCHDIR dir, /**< branching direction */
21110 SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
21111 SCIP_Real weight /**< weight of this update in VSIDS */
21112 )
21113{
21114 assert(var != NULL);
21116
21117 /* check if history statistics should be collected for a variable */
21118 if( !stat->collectvarhistory )
21119 return SCIP_OKAY;
21120
21121 if( SCIPsetIsZero(set, weight) )
21122 return SCIP_OKAY;
21123
21124 switch( SCIPvarGetStatus(var) )
21125 {
21127 if( var->data.original.transvar == NULL )
21128 {
21129 SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
21130 return SCIP_INVALIDDATA;
21131 }
21132 SCIP_CALL( SCIPvarIncVSIDS(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
21133 return SCIP_OKAY;
21134
21137 {
21138 SCIPhistoryIncVSIDS(var->history, dir, weight);
21139 SCIPhistoryIncVSIDS(var->historycrun, dir, weight);
21140
21141 if( useValuehistory(var, value, set) )
21142 {
21143 SCIP_HISTORY* history;
21144
21145 SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
21146 assert(history != NULL);
21147
21148 SCIPhistoryIncVSIDS(history, dir, weight);
21149 SCIPsetDebugMsg(set, "variable (<%s> %s %g) + <%g> = <%g>\n", SCIPvarGetName(var), dir == SCIP_BRANCHDIR_UPWARDS ? ">=" : "<=",
21150 value, weight, SCIPhistoryGetVSIDS(history, dir));
21151 }
21152
21153 return SCIP_OKAY;
21154 }
21156 SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
21157 return SCIP_INVALIDDATA;
21158
21160 value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
21161
21162 if( var->data.aggregate.scalar > 0.0 )
21163 {
21164 SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
21165 }
21166 else
21167 {
21168 assert(var->data.aggregate.scalar < 0.0);
21169 SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
21170 }
21171 return SCIP_OKAY;
21172
21174 SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
21175 return SCIP_INVALIDDATA;
21176
21178 value = 1.0 - value;
21179
21180 SCIP_CALL( SCIPvarIncVSIDS(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
21181 return SCIP_OKAY;
21182
21183 default:
21184 SCIPerrorMessage("unknown variable status\n");
21185 return SCIP_INVALIDDATA;
21186 }
21187}
21188
21189/** scales the VSIDS of the variable by the given scalar */
21191 SCIP_VAR* var, /**< problem variable */
21192 SCIP_Real scalar /**< scalar to multiply the VSIDSs with */
21193 )
21194{
21195 assert(var != NULL);
21196
21197 switch( SCIPvarGetStatus(var) )
21198 {
21200 if( var->data.original.transvar == NULL )
21201 {
21202 SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
21203 return SCIP_INVALIDDATA;
21204 }
21205 SCIP_CALL( SCIPvarScaleVSIDS(var->data.original.transvar, scalar) );
21206 return SCIP_OKAY;
21207
21210 {
21211 SCIPhistoryScaleVSIDS(var->history, scalar);
21212 SCIPhistoryScaleVSIDS(var->historycrun, scalar);
21213 SCIPvaluehistoryScaleVSIDS(var->valuehistory, scalar);
21214
21215 return SCIP_OKAY;
21216 }
21218 SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
21219 return SCIP_INVALIDDATA;
21220
21222 SCIP_CALL( SCIPvarScaleVSIDS(var->data.aggregate.var, scalar) );
21223 return SCIP_OKAY;
21224
21226 SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
21227 return SCIP_INVALIDDATA;
21228
21230 SCIP_CALL( SCIPvarScaleVSIDS(var->negatedvar, scalar) );
21231 return SCIP_OKAY;
21232
21233 default:
21234 SCIPerrorMessage("unknown variable status\n");
21235 return SCIP_INVALIDDATA;
21236 }
21237}
21238
21239/** increases the number of active conflicts by one and the overall length of the variable by the given length */
21241 SCIP_VAR* var, /**< problem variable */
21242 BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
21243 SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
21244 SCIP_STAT* stat, /**< problem statistics */
21245 SCIP_BRANCHDIR dir, /**< branching direction */
21246 SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
21247 SCIP_Real length /**< length of the conflict */
21248 )
21249{
21250 assert(var != NULL);
21252
21253 /* check if history statistics should be collected for a variable */
21254 if( !stat->collectvarhistory )
21255 return SCIP_OKAY;
21256
21257 switch( SCIPvarGetStatus(var) )
21258 {
21260 if( var->data.original.transvar == NULL )
21261 {
21262 SCIPerrorMessage("cannot update conflict score of original untransformed variable\n");
21263 return SCIP_INVALIDDATA;
21264 }
21265 SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.original.transvar, blkmem, set, stat, dir, value, length) );
21266 return SCIP_OKAY;
21267
21270 {
21271 SCIPhistoryIncNActiveConflicts(var->history, dir, length);
21272 SCIPhistoryIncNActiveConflicts(var->historycrun, dir, length);
21273
21274 if( useValuehistory(var, value, set) )
21275 {
21276 SCIP_HISTORY* history;
21277
21278 SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
21279 assert(history != NULL);
21280
21281 SCIPhistoryIncNActiveConflicts(history, dir, length);
21282 }
21283
21284 return SCIP_OKAY;
21285 }
21287 SCIPerrorMessage("cannot update conflict score of a fixed variable\n");
21288 return SCIP_INVALIDDATA;
21289
21291 value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
21292
21293 if( var->data.aggregate.scalar > 0.0 )
21294 {
21295 SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, dir, value, length) );
21296 }
21297 else
21298 {
21299 assert(var->data.aggregate.scalar < 0.0);
21300 SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
21301 }
21302 return SCIP_OKAY;
21303
21305 SCIPerrorMessage("cannot update conflict score of a multi-aggregated variable\n");
21306 return SCIP_INVALIDDATA;
21307
21309 value = 1.0 - value;
21310
21311 SCIP_CALL( SCIPvarIncNActiveConflicts(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
21312 return SCIP_OKAY;
21313
21314 default:
21315 SCIPerrorMessage("unknown variable status\n");
21316 return SCIP_INVALIDDATA;
21317 }
21318}
21319
21320/** gets the number of active conflicts containing this variable in given direction */
21322 SCIP_VAR* var, /**< problem variable */
21323 SCIP_STAT* stat, /**< problem statistics */
21324 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
21325 )
21326{
21327 assert(var != NULL);
21328 assert(stat != NULL);
21330
21331 switch( SCIPvarGetStatus(var) )
21332 {
21334 if( var->data.original.transvar == NULL )
21335 return 0;
21336 else
21337 return SCIPvarGetNActiveConflicts(var->data.original.transvar, stat, dir);
21338
21341 return SCIPhistoryGetNActiveConflicts(var->history, dir);
21342
21344 return 0;
21345
21347 if( var->data.aggregate.scalar > 0.0 )
21348 return SCIPvarGetNActiveConflicts(var->data.aggregate.var, stat, dir);
21349 else
21350 return SCIPvarGetNActiveConflicts(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
21351
21353 return 0;
21354
21356 return SCIPvarGetNActiveConflicts(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
21357
21358 default:
21359 SCIPerrorMessage("unknown variable status\n");
21360 SCIPABORT();
21361 return 0; /*lint !e527*/
21362 }
21363}
21364
21365/** gets the number of active conflicts containing this variable in given direction
21366 * in the current run
21367 */
21369 SCIP_VAR* var, /**< problem variable */
21370 SCIP_STAT* stat, /**< problem statistics */
21371 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
21372 )
21373{
21374 assert(var != NULL);
21375 assert(stat != NULL);
21377
21378 switch( SCIPvarGetStatus(var) )
21379 {
21381 if( var->data.original.transvar == NULL )
21382 return 0;
21383 else
21384 return SCIPvarGetNActiveConflictsCurrentRun(var->data.original.transvar, stat, dir);
21385
21388 return SCIPhistoryGetNActiveConflicts(var->historycrun, dir);
21389
21391 return 0;
21392
21394 if( var->data.aggregate.scalar > 0.0 )
21395 return SCIPvarGetNActiveConflictsCurrentRun(var->data.aggregate.var, stat, dir);
21396 else
21397 return SCIPvarGetNActiveConflictsCurrentRun(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
21398
21400 return 0;
21401
21403 return SCIPvarGetNActiveConflictsCurrentRun(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
21404
21405 default:
21406 SCIPerrorMessage("unknown variable status\n");
21407 SCIPABORT();
21408 return 0; /*lint !e527*/
21409 }
21410}
21411
21412/** gets the average conflict length in given direction due to branching on the variable */
21414 SCIP_VAR* var, /**< problem variable */
21415 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
21416 )
21417{
21418 assert(var != NULL);
21420
21421 switch( SCIPvarGetStatus(var) )
21422 {
21424 if( var->data.original.transvar == NULL )
21425 return 0.0;
21426 else
21427 return SCIPvarGetAvgConflictlength(var->data.original.transvar, dir);
21428
21431 return SCIPhistoryGetAvgConflictlength(var->history, dir);
21433 return 0.0;
21434
21436 if( var->data.aggregate.scalar > 0.0 )
21437 return SCIPvarGetAvgConflictlength(var->data.aggregate.var, dir);
21438 else
21439 return SCIPvarGetAvgConflictlength(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
21440
21442 return 0.0;
21443
21445 return SCIPvarGetAvgConflictlength(var->negatedvar, SCIPbranchdirOpposite(dir));
21446
21447 default:
21448 SCIPerrorMessage("unknown variable status\n");
21449 SCIPABORT();
21450 return 0.0; /*lint !e527*/
21451 }
21452}
21453
21454/** gets the average conflict length in given direction due to branching on the variable
21455 * in the current run
21456 */
21458 SCIP_VAR* var, /**< problem variable */
21459 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
21460 )
21461{
21462 assert(var != NULL);
21464
21465 switch( SCIPvarGetStatus(var) )
21466 {
21468 if( var->data.original.transvar == NULL )
21469 return 0.0;
21470 else
21471 return SCIPvarGetAvgConflictlengthCurrentRun(var->data.original.transvar, dir);
21472
21475 return SCIPhistoryGetAvgConflictlength(var->historycrun, dir);
21476
21478 return 0.0;
21479
21481 if( var->data.aggregate.scalar > 0.0 )
21482 return SCIPvarGetAvgConflictlengthCurrentRun(var->data.aggregate.var, dir);
21483 else
21484 return SCIPvarGetAvgConflictlengthCurrentRun(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
21485
21487 return 0.0;
21488
21491
21492 default:
21493 SCIPerrorMessage("unknown variable status\n");
21494 SCIPABORT();
21495 return 0.0; /*lint !e527*/
21496 }
21497}
21498
21499/** increases the number of branchings counter of the variable */
21501 SCIP_VAR* var, /**< problem variable */
21502 BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
21503 SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
21504 SCIP_STAT* stat, /**< problem statistics */
21505 SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
21506 SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
21507 int depth /**< depth at which the bound change took place */
21508 )
21509{
21510 assert(var != NULL);
21511 assert(stat != NULL);
21513
21514 /* check if history statistics should be collected for a variable */
21515 if( !stat->collectvarhistory )
21516 return SCIP_OKAY;
21517
21518 switch( SCIPvarGetStatus(var) )
21519 {
21521 if( var->data.original.transvar == NULL )
21522 {
21523 SCIPerrorMessage("cannot update branching counter of original untransformed variable\n");
21524 return SCIP_INVALIDDATA;
21525 }
21526 SCIP_CALL( SCIPvarIncNBranchings(var->data.original.transvar, blkmem, set, stat, dir, value, depth) );
21527 return SCIP_OKAY;
21528
21531 {
21532 SCIPhistoryIncNBranchings(var->history, dir, depth);
21533 SCIPhistoryIncNBranchings(var->historycrun, dir, depth);
21536
21537 if( useValuehistory(var, value, set) )
21538 {
21539 SCIP_HISTORY* history;
21540
21541 SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
21542 assert(history != NULL);
21543
21544 SCIPhistoryIncNBranchings(history, dir, depth);
21545 }
21546
21547 return SCIP_OKAY;
21548 }
21550 SCIPerrorMessage("cannot update branching counter of a fixed variable\n");
21551 return SCIP_INVALIDDATA;
21552
21554 value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
21555
21556 if( var->data.aggregate.scalar > 0.0 )
21557 {
21558 SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, dir, value, depth) );
21559 }
21560 else
21561 {
21562 assert(var->data.aggregate.scalar < 0.0);
21563 SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
21564 }
21565 return SCIP_OKAY;
21566
21568 SCIPerrorMessage("cannot update branching counter of a multi-aggregated variable\n");
21569 return SCIP_INVALIDDATA;
21570
21572 value = 1.0 - value;
21573
21574 SCIP_CALL( SCIPvarIncNBranchings(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
21575 return SCIP_OKAY;
21576
21577 default:
21578 SCIPerrorMessage("unknown variable status\n");
21579 return SCIP_INVALIDDATA;
21580 }
21581}
21582
21583/** increases the inference sum of the variable by the given weight */
21585 SCIP_VAR* var, /**< problem variable */
21586 BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
21587 SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
21588 SCIP_STAT* stat, /**< problem statistics */
21589 SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
21590 SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
21591 SCIP_Real weight /**< weight of this update in inference score */
21592 )
21593{
21594 assert(var != NULL);
21595 assert(stat != NULL);
21597
21598 /* check if history statistics should be collected for a variable */
21599 if( !stat->collectvarhistory )
21600 return SCIP_OKAY;
21601
21602 switch( SCIPvarGetStatus(var) )
21603 {
21605 if( var->data.original.transvar == NULL )
21606 {
21607 SCIPerrorMessage("cannot update inference counter of original untransformed variable\n");
21608 return SCIP_INVALIDDATA;
21609 }
21610 SCIP_CALL( SCIPvarIncInferenceSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
21611 return SCIP_OKAY;
21612
21615 {
21616 SCIPhistoryIncInferenceSum(var->history, dir, weight);
21617 SCIPhistoryIncInferenceSum(var->historycrun, dir, weight);
21618 SCIPhistoryIncInferenceSum(stat->glbhistory, dir, weight);
21619 SCIPhistoryIncInferenceSum(stat->glbhistorycrun, dir, weight);
21620
21621 if( useValuehistory(var, value, set) )
21622 {
21623 SCIP_HISTORY* history;
21624
21625 SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
21626 assert(history != NULL);
21627
21628 SCIPhistoryIncInferenceSum(history, dir, weight);
21629 }
21630
21631 return SCIP_OKAY;
21632 }
21634 SCIPerrorMessage("cannot update inference counter of a fixed variable\n");
21635 return SCIP_INVALIDDATA;
21636
21638 value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
21639
21640 if( var->data.aggregate.scalar > 0.0 )
21641 {
21642 SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
21643 }
21644 else
21645 {
21646 assert(var->data.aggregate.scalar < 0.0);
21647 SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
21648 }
21649 return SCIP_OKAY;
21650
21652 SCIPerrorMessage("cannot update inference counter of a multi-aggregated variable\n");
21653 return SCIP_INVALIDDATA;
21654
21656 value = 1.0 - value;
21657
21658 SCIP_CALL( SCIPvarIncInferenceSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
21659 return SCIP_OKAY;
21660
21661 default:
21662 SCIPerrorMessage("unknown variable status\n");
21663 return SCIP_INVALIDDATA;
21664 }
21665}
21666
21667/** increases the cutoff sum of the variable by the given weight */
21669 SCIP_VAR* var, /**< problem variable */
21670 BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
21671 SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
21672 SCIP_STAT* stat, /**< problem statistics */
21673 SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
21674 SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
21675 SCIP_Real weight /**< weight of this update in cutoff score */
21676 )
21677{
21678 assert(var != NULL);
21679 assert(stat != NULL);
21681
21682 /* check if history statistics should be collected for a variable */
21683 if( !stat->collectvarhistory )
21684 return SCIP_OKAY;
21685
21686 switch( SCIPvarGetStatus(var) )
21687 {
21689 if( var->data.original.transvar == NULL )
21690 {
21691 SCIPerrorMessage("cannot update cutoff sum of original untransformed variable\n");
21692 return SCIP_INVALIDDATA;
21693 }
21694 SCIP_CALL( SCIPvarIncCutoffSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
21695 return SCIP_OKAY;
21696
21699 {
21700 SCIPhistoryIncCutoffSum(var->history, dir, weight);
21701 SCIPhistoryIncCutoffSum(var->historycrun, dir, weight);
21702 SCIPhistoryIncCutoffSum(stat->glbhistory, dir, weight);
21703 SCIPhistoryIncCutoffSum(stat->glbhistorycrun, dir, weight);
21704
21705 if( useValuehistory(var, value, set) )
21706 {
21707 SCIP_HISTORY* history;
21708
21709 SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
21710 assert(history != NULL);
21711
21712 SCIPhistoryIncCutoffSum(history, dir, weight);
21713 }
21714
21715 return SCIP_OKAY;
21716 }
21718 SCIPerrorMessage("cannot update cutoff sum of a fixed variable\n");
21719 return SCIP_INVALIDDATA;
21720
21722 value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
21723
21724 if( var->data.aggregate.scalar > 0.0 )
21725 {
21726 SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
21727 }
21728 else
21729 {
21730 assert(var->data.aggregate.scalar < 0.0);
21731 SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
21732 }
21733 return SCIP_OKAY;
21734
21736 SCIPerrorMessage("cannot update cutoff sum of a multi-aggregated variable\n");
21737 return SCIP_INVALIDDATA;
21738
21740 value = 1.0 - value;
21741
21742 SCIP_CALL( SCIPvarIncCutoffSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
21743 return SCIP_OKAY;
21744
21745 default:
21746 SCIPerrorMessage("unknown variable status\n");
21747 return SCIP_INVALIDDATA;
21748 }
21749}
21750
21751/** returns the number of times, a bound of the variable was changed in given direction due to branching */
21753 SCIP_VAR* var, /**< problem variable */
21754 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
21755 )
21756{
21757 assert(var != NULL);
21759
21760 switch( SCIPvarGetStatus(var) )
21761 {
21763 if( var->data.original.transvar == NULL )
21764 return 0;
21765 else
21766 return SCIPvarGetNBranchings(var->data.original.transvar, dir);
21767
21770 return SCIPhistoryGetNBranchings(var->history, dir);
21771
21773 return 0;
21774
21776 if( var->data.aggregate.scalar > 0.0 )
21777 return SCIPvarGetNBranchings(var->data.aggregate.var, dir);
21778 else
21779 return SCIPvarGetNBranchings(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
21780
21782 return 0;
21783
21785 return SCIPvarGetNBranchings(var->negatedvar, SCIPbranchdirOpposite(dir));
21786
21787 default:
21788 SCIPerrorMessage("unknown variable status\n");
21789 SCIPABORT();
21790 return 0; /*lint !e527*/
21791 }
21792}
21793
21794/** returns the number of times, a bound of the variable was changed in given direction due to branching
21795 * in the current run
21796 */
21798 SCIP_VAR* var, /**< problem variable */
21799 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
21800 )
21801{
21802 assert(var != NULL);
21804
21805 switch( SCIPvarGetStatus(var) )
21806 {
21808 if( var->data.original.transvar == NULL )
21809 return 0;
21810 else
21811 return SCIPvarGetNBranchingsCurrentRun(var->data.original.transvar, dir);
21812
21815 return SCIPhistoryGetNBranchings(var->historycrun, dir);
21816
21818 return 0;
21819
21821 if( var->data.aggregate.scalar > 0.0 )
21822 return SCIPvarGetNBranchingsCurrentRun(var->data.aggregate.var, dir);
21823 else
21824 return SCIPvarGetNBranchingsCurrentRun(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
21825
21827 return 0;
21828
21831
21832 default:
21833 SCIPerrorMessage("unknown variable status\n");
21834 SCIPABORT();
21835 return 0; /*lint !e527*/
21836 }
21837}
21838
21839/** returns the average depth of bound changes in given direction due to branching on the variable */
21841 SCIP_VAR* var, /**< problem variable */
21842 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
21843 )
21844{
21845 assert(var != NULL);
21847
21848 switch( SCIPvarGetStatus(var) )
21849 {
21851 if( var->data.original.transvar == NULL )
21852 return 0.0;
21853 else
21854 return SCIPvarGetAvgBranchdepth(var->data.original.transvar, dir);
21855
21858 return SCIPhistoryGetAvgBranchdepth(var->history, dir);
21859
21861 return 0.0;
21862
21864 if( var->data.aggregate.scalar > 0.0 )
21865 return SCIPvarGetAvgBranchdepth(var->data.aggregate.var, dir);
21866 else
21867 return SCIPvarGetAvgBranchdepth(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
21868
21870 return 0.0;
21871
21873 return SCIPvarGetAvgBranchdepth(var->negatedvar, SCIPbranchdirOpposite(dir));
21874
21875 default:
21876 SCIPerrorMessage("unknown variable status\n");
21877 SCIPABORT();
21878 return 0.0; /*lint !e527*/
21879 }
21880}
21881
21882/** returns the average depth of bound changes in given direction due to branching on the variable
21883 * in the current run
21884 */
21886 SCIP_VAR* var, /**< problem variable */
21887 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
21888 )
21889{
21890 assert(var != NULL);
21892
21893 switch( SCIPvarGetStatus(var) )
21894 {
21896 if( var->data.original.transvar == NULL )
21897 return 0.0;
21898 else
21899 return SCIPvarGetAvgBranchdepthCurrentRun(var->data.original.transvar, dir);
21900
21903 return SCIPhistoryGetAvgBranchdepth(var->historycrun, dir);
21904
21906 return 0.0;
21907
21909 if( var->data.aggregate.scalar > 0.0 )
21910 return SCIPvarGetAvgBranchdepthCurrentRun(var->data.aggregate.var, dir);
21911 else
21912 return SCIPvarGetAvgBranchdepthCurrentRun(var->data.aggregate.var,
21914
21916 return 0.0;
21917
21919 return SCIPvarGetAvgBranchdepthCurrentRun(var->negatedvar,
21921
21922 default:
21923 SCIPerrorMessage("unknown variable status\n");
21924 SCIPABORT();
21925 return 0.0; /*lint !e527*/
21926 }
21927}
21928
21929/** returns the variable's VSIDS score */
21931 SCIP_VAR* var, /**< problem variable */
21932 SCIP_STAT* stat, /**< problem statistics */
21933 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
21934 )
21935{
21936 assert(var != NULL);
21937 assert(stat != NULL);
21939
21941 return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
21942
21943 switch( SCIPvarGetStatus(var) )
21944 {
21946 if( var->data.original.transvar == NULL )
21947 return 0.0;
21948 else
21949 return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
21950
21953 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE); /* column case already handled in if condition above */
21954 return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
21955
21957 return 0.0;
21958
21960 if( var->data.aggregate.scalar > 0.0 )
21961 return SCIPvarGetVSIDS(var->data.aggregate.var, stat, dir);
21962 else
21963 /* coverity[overrun-local] */
21964 return SCIPvarGetVSIDS(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
21965
21967 return 0.0;
21968
21970 /* coverity[overrun-local] */
21971 return SCIPvarGetVSIDS(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
21972
21973 default:
21974 SCIPerrorMessage("unknown variable status\n");
21975 SCIPABORT();
21976 return 0.0; /*lint !e527*/
21977 }
21978}
21979
21980/** returns the variable's VSIDS score only using conflicts of the current run */
21982 SCIP_VAR* var, /**< problem variable */
21983 SCIP_STAT* stat, /**< problem statistics */
21984 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
21985 )
21986{
21987 assert(var != NULL);
21988 assert(stat != NULL);
21990
21992 {
21993 SCIPerrorMessage("invalid branching direction %d when asking for VSIDS value\n", dir);
21994 return SCIP_INVALID;
21995 }
21996
21997 switch( SCIPvarGetStatus(var) )
21998 {
22000 if( var->data.original.transvar == NULL )
22001 return 0.0;
22002 else
22003 return SCIPvarGetVSIDSCurrentRun(var->data.original.transvar, stat, dir);
22004
22007 return SCIPhistoryGetVSIDS(var->historycrun, dir)/stat->vsidsweight;
22008
22010 return 0.0;
22011
22013 if( var->data.aggregate.scalar > 0.0 )
22014 return SCIPvarGetVSIDSCurrentRun(var->data.aggregate.var, stat, dir);
22015 else
22016 return SCIPvarGetVSIDSCurrentRun(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
22017
22019 return 0.0;
22020
22022 return SCIPvarGetVSIDSCurrentRun(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
22023
22024 default:
22025 SCIPerrorMessage("unknown variable status\n");
22026 SCIPABORT();
22027 return 0.0; /*lint !e527*/
22028 }
22029}
22030
22031/** returns the number of inferences branching on this variable in given direction triggered */
22033 SCIP_VAR* var, /**< problem variable */
22034 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
22035 )
22036{
22037 assert(var != NULL);
22039
22040 switch( SCIPvarGetStatus(var) )
22041 {
22043 if( var->data.original.transvar == NULL )
22044 return 0.0;
22045 else
22046 return SCIPvarGetInferenceSum(var->data.original.transvar, dir);
22047
22050 return SCIPhistoryGetInferenceSum(var->history, dir);
22051
22053 return 0.0;
22054
22056 if( var->data.aggregate.scalar > 0.0 )
22057 return SCIPvarGetInferenceSum(var->data.aggregate.var, dir);
22058 else
22059 return SCIPvarGetInferenceSum(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
22060
22062 return 0.0;
22063
22065 return SCIPvarGetInferenceSum(var->negatedvar, SCIPbranchdirOpposite(dir));
22066
22067 default:
22068 SCIPerrorMessage("unknown variable status\n");
22069 SCIPABORT();
22070 return 0.0; /*lint !e527*/
22071 }
22072}
22073
22074/** returns the number of inferences branching on this variable in given direction triggered
22075 * in the current run
22076 */
22078 SCIP_VAR* var, /**< problem variable */
22079 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
22080 )
22081{
22082 assert(var != NULL);
22084
22085 switch( SCIPvarGetStatus(var) )
22086 {
22088 if( var->data.original.transvar == NULL )
22089 return 0.0;
22090 else
22091 return SCIPvarGetInferenceSumCurrentRun(var->data.original.transvar, dir);
22092
22095 return SCIPhistoryGetInferenceSum(var->historycrun, dir);
22096
22098 return 0.0;
22099
22101 if( var->data.aggregate.scalar > 0.0 )
22102 return SCIPvarGetInferenceSumCurrentRun(var->data.aggregate.var, dir);
22103 else
22104 return SCIPvarGetInferenceSumCurrentRun(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
22105
22107 return 0.0;
22108
22111
22112 default:
22113 SCIPerrorMessage("unknown variable status\n");
22114 SCIPABORT();
22115 return 0.0; /*lint !e527*/
22116 }
22117}
22118
22119/** returns the average number of inferences found after branching on the variable in given direction */
22121 SCIP_VAR* var, /**< problem variable */
22122 SCIP_STAT* stat, /**< problem statistics */
22123 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
22124 )
22125{
22126 assert(var != NULL);
22127 assert(stat != NULL);
22129
22130 switch( SCIPvarGetStatus(var) )
22131 {
22133 if( var->data.original.transvar == NULL )
22134 return SCIPhistoryGetAvgInferences(stat->glbhistory, dir);
22135 else
22136 return SCIPvarGetAvgInferences(var->data.original.transvar, stat, dir);
22137
22140 if( SCIPhistoryGetNBranchings(var->history, dir) > 0 )
22141 return SCIPhistoryGetAvgInferences(var->history, dir);
22142 else
22143 {
22144 int nimpls;
22145 int ncliques;
22146
22148 ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
22149 return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistory, dir); /*lint !e790*/
22150 }
22151
22153 return 0.0;
22154
22156 if( var->data.aggregate.scalar > 0.0 )
22157 return SCIPvarGetAvgInferences(var->data.aggregate.var, stat, dir);
22158 else
22159 return SCIPvarGetAvgInferences(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
22160
22162 return 0.0;
22163
22165 return SCIPvarGetAvgInferences(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
22166
22167 default:
22168 SCIPerrorMessage("unknown variable status\n");
22169 SCIPABORT();
22170 return 0.0; /*lint !e527*/
22171 }
22172}
22173
22174/** returns the average number of inferences found after branching on the variable in given direction
22175 * in the current run
22176 */
22178 SCIP_VAR* var, /**< problem variable */
22179 SCIP_STAT* stat, /**< problem statistics */
22180 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
22181 )
22182{
22183 assert(var != NULL);
22184 assert(stat != NULL);
22186
22187 switch( SCIPvarGetStatus(var) )
22188 {
22190 if( var->data.original.transvar == NULL )
22192 else
22193 return SCIPvarGetAvgInferencesCurrentRun(var->data.original.transvar, stat, dir);
22194
22197 if( SCIPhistoryGetNBranchings(var->historycrun, dir) > 0 )
22198 return SCIPhistoryGetAvgInferences(var->historycrun, dir);
22199 else
22200 {
22201 int nimpls;
22202 int ncliques;
22203
22205 ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
22206 return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir); /*lint !e790*/
22207 }
22208
22210 return 0.0;
22211
22213 if( var->data.aggregate.scalar > 0.0 )
22214 return SCIPvarGetAvgInferencesCurrentRun(var->data.aggregate.var, stat, dir);
22215 else
22216 return SCIPvarGetAvgInferencesCurrentRun(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
22217
22219 return 0.0;
22220
22222 return SCIPvarGetAvgInferencesCurrentRun(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
22223
22224 default:
22225 SCIPerrorMessage("unknown variable status\n");
22226 SCIPABORT();
22227 return 0.0; /*lint !e527*/
22228 }
22229}
22230
22231/** returns the number of cutoffs branching on this variable in given direction produced */
22233 SCIP_VAR* var, /**< problem variable */
22234 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
22235 )
22236{
22237 assert(var != NULL);
22239
22240 switch( SCIPvarGetStatus(var) )
22241 {
22243 if( var->data.original.transvar == NULL )
22244 return 0;
22245 else
22246 return SCIPvarGetCutoffSum(var->data.original.transvar, dir);
22247
22250 return SCIPhistoryGetCutoffSum(var->history, dir);
22251
22253 return 0;
22254
22256 if( var->data.aggregate.scalar > 0.0 )
22257 return SCIPvarGetCutoffSum(var->data.aggregate.var, dir);
22258 else
22259 return SCIPvarGetCutoffSum(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
22260
22262 return 0;
22263
22265 return SCIPvarGetCutoffSum(var->negatedvar, SCIPbranchdirOpposite(dir));
22266
22267 default:
22268 SCIPerrorMessage("unknown variable status\n");
22269 SCIPABORT();
22270 return 0; /*lint !e527*/
22271 }
22272}
22273
22274/** returns the number of cutoffs branching on this variable in given direction produced in the current run */
22276 SCIP_VAR* var, /**< problem variable */
22277 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
22278 )
22279{
22280 assert(var != NULL);
22282
22283 switch( SCIPvarGetStatus(var) )
22284 {
22286 if( var->data.original.transvar == NULL )
22287 return 0;
22288 else
22289 return SCIPvarGetCutoffSumCurrentRun(var->data.original.transvar, dir);
22290
22293 return SCIPhistoryGetCutoffSum(var->historycrun, dir);
22294
22296 return 0;
22297
22299 if( var->data.aggregate.scalar > 0.0 )
22300 return SCIPvarGetCutoffSumCurrentRun(var->data.aggregate.var, dir);
22301 else
22302 return SCIPvarGetCutoffSumCurrentRun(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
22303
22305 return 0;
22306
22309
22310 default:
22311 SCIPerrorMessage("unknown variable status\n");
22312 SCIPABORT();
22313 return 0; /*lint !e527*/
22314 }
22315}
22316
22317/** returns the average number of cutoffs found after branching on the variable in given direction */
22319 SCIP_VAR* var, /**< problem variable */
22320 SCIP_STAT* stat, /**< problem statistics */
22321 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
22322 )
22323{
22324 assert(var != NULL);
22325 assert(stat != NULL);
22327
22328 switch( SCIPvarGetStatus(var) )
22329 {
22331 if( var->data.original.transvar == NULL )
22332 return SCIPhistoryGetAvgCutoffs(stat->glbhistory, dir);
22333 else
22334 return SCIPvarGetAvgCutoffs(var->data.original.transvar, stat, dir);
22335
22338 return SCIPhistoryGetNBranchings(var->history, dir) > 0
22339 ? SCIPhistoryGetAvgCutoffs(var->history, dir)
22341
22343 return 0.0;
22344
22346 if( var->data.aggregate.scalar > 0.0 )
22347 return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, dir);
22348 else
22349 return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
22350
22352 return 0.0;
22353
22355 return SCIPvarGetAvgCutoffs(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
22356
22357 default:
22358 SCIPerrorMessage("unknown variable status\n");
22359 SCIPABORT();
22360 return 0.0; /*lint !e527*/
22361 }
22362}
22363
22364/** returns the average number of cutoffs found after branching on the variable in given direction in the current run */
22366 SCIP_VAR* var, /**< problem variable */
22367 SCIP_STAT* stat, /**< problem statistics */
22368 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
22369 )
22370{
22371 assert(var != NULL);
22372 assert(stat != NULL);
22374
22375 switch( SCIPvarGetStatus(var) )
22376 {
22378 if( var->data.original.transvar == NULL )
22379 return SCIPhistoryGetAvgCutoffs(stat->glbhistorycrun, dir);
22380 else
22381 return SCIPvarGetAvgCutoffsCurrentRun(var->data.original.transvar, stat, dir);
22382
22385 return SCIPhistoryGetNBranchings(var->historycrun, dir) > 0
22386 ? SCIPhistoryGetAvgCutoffs(var->historycrun, dir)
22388
22390 return 0.0;
22391
22393 if( var->data.aggregate.scalar > 0.0 )
22394 return SCIPvarGetAvgCutoffsCurrentRun(var->data.aggregate.var, stat, dir);
22395 else
22396 return SCIPvarGetAvgCutoffsCurrentRun(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
22397
22399 return 0.0;
22400
22402 return SCIPvarGetAvgCutoffsCurrentRun(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
22403
22404 default:
22405 SCIPerrorMessage("unknown variable status\n");
22406 SCIPABORT();
22407 return 0.0; /*lint !e527*/
22408 }
22409}
22410
22411/** returns the variable's average GMI efficacy score value generated from simplex tableau rows of this variable */
22413 SCIP_VAR* var, /**< problem variable */
22414 SCIP_STAT* stat /**< problem statistics */
22415 )
22416{
22417 assert(var != NULL);
22418 assert(stat != NULL);
22419
22420 switch( SCIPvarGetStatus(var) )
22421 {
22423 if( var->data.original.transvar == NULL )
22424 return 0.0;
22425 else
22426 return SCIPvarGetAvgGMIScore(var->data.original.transvar, stat);
22427
22430 return SCIPhistoryGetAvgGMIeff(var->history);
22431
22433 return 0.0;
22434
22436 return SCIPvarGetAvgGMIScore(var->data.aggregate.var, stat);
22437
22439 return 0.0;
22440
22442 return SCIPvarGetAvgGMIScore(var->negatedvar, stat);
22443
22444 default:
22445 SCIPerrorMessage("unknown variable status\n");
22446 SCIPABORT();
22447 return 0.0; /*lint !e527*/
22448 }
22449}
22450
22451/** increase the variable's GMI efficacy scores generated from simplex tableau rows of this variable */
22453 SCIP_VAR* var, /**< problem variable */
22454 SCIP_STAT* stat, /**< problem statistics */
22455 SCIP_Real gmieff /**< efficacy of last GMI cut produced when variable was frac and basic */
22456 )
22457{
22458 assert(var != NULL);
22459 assert(stat != NULL);
22460 assert(gmieff >= 0);
22461
22462 switch( SCIPvarGetStatus(var) )
22463 {
22465 if( var->data.original.transvar != NULL )
22466 SCIP_CALL( SCIPvarIncGMIeffSum(var->data.original.transvar, stat, gmieff) );
22467 return SCIP_OKAY;
22468
22471 SCIPhistoryIncGMIeffSum(var->history, gmieff);
22472 return SCIP_OKAY;
22473
22475 return SCIP_INVALIDDATA;
22476
22478 SCIP_CALL( SCIPvarIncGMIeffSum(var->data.aggregate.var, stat, gmieff) );
22479 return SCIP_OKAY;
22480
22482 SCIP_CALL( SCIPvarIncGMIeffSum(var->negatedvar, stat, gmieff) );
22483 return SCIP_OKAY;
22484
22486 return SCIP_INVALIDDATA;
22487
22488 default:
22489 SCIPerrorMessage("unknown variable status\n");
22490 SCIPABORT();
22491 return SCIP_INVALIDDATA; /*lint !e527*/
22492 }
22493}
22494
22495/** returns the variable's last GMI efficacy score value generated from a simplex tableau row of this variable */
22497 SCIP_VAR* var, /**< problem variable */
22498 SCIP_STAT* stat /**< problem statistics */
22499 )
22500{
22501 assert(var != NULL);
22502 assert(stat != NULL);
22503
22504 switch( SCIPvarGetStatus(var) )
22505 {
22507 if( var->data.original.transvar != NULL )
22508 return SCIPvarGetLastGMIScore(var->data.original.transvar, stat);
22509 return 0.0;
22510
22513 return SCIPhistoryGetLastGMIeff(var->history);
22514
22516 return 0.0;
22517
22519 return SCIPvarGetLastGMIScore(var->data.aggregate.var, stat);
22520
22522 return 0.0;
22523
22525 return SCIPvarGetLastGMIScore(var->negatedvar, stat);
22526
22527 default:
22528 SCIPerrorMessage("unknown variable status\n");
22529 SCIPABORT();
22530 return 0.0; /*lint !e527*/
22531 }
22532}
22533
22534
22535/** sets the variable's last GMI efficacy score value generated from a simplex tableau row of this variable */
22537 SCIP_VAR* var, /**< problem variable */
22538 SCIP_STAT* stat, /**< problem statistics */
22539 SCIP_Real gmieff /**< efficacy of last GMI cut produced when variable was frac and basic */
22540 )
22541{
22542 assert(var != NULL);
22543 assert(stat != NULL);
22544 assert(gmieff >= 0);
22545
22546 switch( SCIPvarGetStatus(var) )
22547 {
22549 if( var->data.original.transvar != NULL )
22550 SCIP_CALL( SCIPvarSetLastGMIScore(var->data.original.transvar, stat, gmieff) );
22551 return SCIP_OKAY;
22552
22555 SCIPhistorySetLastGMIeff(var->history, gmieff);
22556 return SCIP_OKAY;
22557
22559 return SCIP_INVALIDDATA;
22560
22562 SCIP_CALL( SCIPvarSetLastGMIScore(var->data.aggregate.var, stat, gmieff) );
22563 return SCIP_OKAY;
22564
22566 SCIP_CALL( SCIPvarSetLastGMIScore(var->negatedvar, stat, gmieff) );
22567 return SCIP_OKAY;
22568
22570 return SCIP_INVALIDDATA;
22571
22572 default:
22573 SCIPerrorMessage("unknown variable status\n");
22574 SCIPABORT();
22575 return SCIP_INVALIDDATA; /*lint !e527*/
22576 }
22577}
22578
22579
22580
22581/*
22582 * information methods for bound changes
22583 */
22584
22585/** creates an artificial bound change information object with depth = INT_MAX and pos = -1 */
22587 SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
22588 BMS_BLKMEM* blkmem, /**< block memory */
22589 SCIP_VAR* var, /**< active variable that changed the bounds */
22590 SCIP_BOUNDTYPE boundtype, /**< type of bound for var: lower or upper bound */
22591 SCIP_Real oldbound, /**< old value for bound */
22592 SCIP_Real newbound /**< new value for bound */
22593 )
22594{
22595 assert(bdchginfo != NULL);
22596
22597 SCIP_ALLOC( BMSallocBlockMemory(blkmem, bdchginfo) );
22598 (*bdchginfo)->oldbound = oldbound;
22599 (*bdchginfo)->newbound = newbound;
22600 (*bdchginfo)->var = var;
22601 (*bdchginfo)->inferencedata.var = var;
22602 (*bdchginfo)->inferencedata.reason.prop = NULL;
22603 (*bdchginfo)->inferencedata.info = 0;
22604 (*bdchginfo)->bdchgidx.depth = INT_MAX;
22605 (*bdchginfo)->bdchgidx.pos = -1;
22606 (*bdchginfo)->pos = 0;
22607 (*bdchginfo)->boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
22608 (*bdchginfo)->boundtype = boundtype; /*lint !e641*/
22609 (*bdchginfo)->inferboundtype = boundtype; /*lint !e641*/
22610 (*bdchginfo)->redundant = FALSE;
22611
22612 return SCIP_OKAY;
22613}
22614
22615/** frees a bound change information object */
22617 SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
22618 BMS_BLKMEM* blkmem /**< block memory */
22619 )
22620{
22621 assert(bdchginfo != NULL);
22622
22623 BMSfreeBlockMemory(blkmem, bdchginfo);
22624}
22625
22626/** returns the bound change information for the last lower bound change on given active problem variable before or
22627 * after the bound change with the given index was applied;
22628 * returns NULL, if no change to the lower bound was applied up to this point of time
22629 */
22631 SCIP_VAR* var, /**< active problem variable */
22632 SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
22633 SCIP_Bool after /**< should the bound change with given index be included? */
22634 )
22635{
22636 int i;
22637
22638 assert(var != NULL);
22640
22641 /* search the correct bound change information for the given bound change index */
22642 if( after )
22643 {
22644 for( i = var->nlbchginfos-1; i >= 0; --i )
22645 {
22646 assert(var->lbchginfos[i].var == var);
22647 assert((SCIP_BOUNDTYPE)var->lbchginfos[i].boundtype == SCIP_BOUNDTYPE_LOWER);
22648 assert(var->lbchginfos[i].pos == i);
22649
22650 /* if we reached the (due to global bounds) redundant bound changes, return NULL */
22651 if( var->lbchginfos[i].redundant )
22652 return NULL;
22653 assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
22654
22655 /* if we reached the bound change index, return the current bound change info */
22656 if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->lbchginfos[i].bdchgidx) )
22657 return &var->lbchginfos[i];
22658 }
22659 }
22660 else
22661 {
22662 for( i = var->nlbchginfos-1; i >= 0; --i )
22663 {
22664 assert(var->lbchginfos[i].var == var);
22665 assert((SCIP_BOUNDTYPE)var->lbchginfos[i].boundtype == SCIP_BOUNDTYPE_LOWER);
22666 assert(var->lbchginfos[i].pos == i);
22667
22668 /* if we reached the (due to global bounds) redundant bound changes, return NULL */
22669 if( var->lbchginfos[i].redundant )
22670 return NULL;
22671 assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
22672
22673 /* if we reached the bound change index, return the current bound change info */
22674 if( SCIPbdchgidxIsEarlier(&var->lbchginfos[i].bdchgidx, bdchgidx) )
22675 return &var->lbchginfos[i];
22676 }
22677 }
22678
22679 return NULL;
22680}
22681
22682/** returns the bound change information for the last upper bound change on given active problem variable before or
22683 * after the bound change with the given index was applied;
22684 * returns NULL, if no change to the upper bound was applied up to this point of time
22685 */
22687 SCIP_VAR* var, /**< active problem variable */
22688 SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
22689 SCIP_Bool after /**< should the bound change with given index be included? */
22690 )
22691{
22692 int i;
22693
22694 assert(var != NULL);
22696
22697 /* search the correct bound change information for the given bound change index */
22698 if( after )
22699 {
22700 for( i = var->nubchginfos-1; i >= 0; --i )
22701 {
22702 assert(var->ubchginfos[i].var == var);
22703 assert((SCIP_BOUNDTYPE)var->ubchginfos[i].boundtype == SCIP_BOUNDTYPE_UPPER);
22704 assert(var->ubchginfos[i].pos == i);
22705
22706 /* if we reached the (due to global bounds) redundant bound changes, return NULL */
22707 if( var->ubchginfos[i].redundant )
22708 return NULL;
22709 assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
22710
22711 /* if we reached the bound change index, return the current bound change info */
22712 if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->ubchginfos[i].bdchgidx) )
22713 return &var->ubchginfos[i];
22714 }
22715 }
22716 else
22717 {
22718 for( i = var->nubchginfos-1; i >= 0; --i )
22719 {
22720 assert(var->ubchginfos[i].var == var);
22721 assert((SCIP_BOUNDTYPE)var->ubchginfos[i].boundtype == SCIP_BOUNDTYPE_UPPER);
22722 assert(var->ubchginfos[i].pos == i);
22723
22724 /* if we reached the (due to global bounds) redundant bound changes, return NULL */
22725 if( var->ubchginfos[i].redundant )
22726 return NULL;
22727 assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
22728
22729 /* if we reached the bound change index, return the current bound change info */
22730 if( SCIPbdchgidxIsEarlier(&var->ubchginfos[i].bdchgidx, bdchgidx) )
22731 return &var->ubchginfos[i];
22732 }
22733 }
22734
22735 return NULL;
22736}
22737
22738/** returns the bound change information for the last lower or upper bound change on given active problem variable
22739 * before or after the bound change with the given index was applied;
22740 * returns NULL, if no change to the lower/upper bound was applied up to this point of time
22741 */
22743 SCIP_VAR* var, /**< active problem variable */
22744 SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
22745 SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
22746 SCIP_Bool after /**< should the bound change with given index be included? */
22747 )
22748{
22749 if( boundtype == SCIP_BOUNDTYPE_LOWER )
22750 return SCIPvarGetLbchgInfo(var, bdchgidx, after);
22751 else
22752 {
22753 assert(boundtype == SCIP_BOUNDTYPE_UPPER);
22754 return SCIPvarGetUbchgInfo(var, bdchgidx, after);
22755 }
22756}
22757
22758/** bound change index representing the initial time before any bound changes took place */
22760
22761/** bound change index representing the presolving stage */
22763
22764/** returns the last bound change index, at which the bounds of the given variable were tightened */
22766 SCIP_VAR* var /**< problem variable */
22767 )
22768{
22769 SCIP_BDCHGIDX* lbchgidx;
22770 SCIP_BDCHGIDX* ubchgidx;
22771
22772 assert(var != NULL);
22773
22775
22776 /* check, if variable is original without transformed variable */
22777 if( var == NULL )
22778 return &initbdchgidx;
22779
22780 /* check, if variable was fixed in presolving */
22781 if( !SCIPvarIsActive(var) )
22782 return &presolvebdchgidx;
22783
22785
22786 /* get depths of last bound change information for the lower and upper bound */
22787 lbchgidx = (var->nlbchginfos > 0 && !var->lbchginfos[var->nlbchginfos-1].redundant
22788 ? &var->lbchginfos[var->nlbchginfos-1].bdchgidx : &initbdchgidx);
22789 ubchgidx = (var->nubchginfos > 0 && !var->ubchginfos[var->nubchginfos-1].redundant
22790 ? &var->ubchginfos[var->nubchginfos-1].bdchgidx : &initbdchgidx);
22791
22792 if( SCIPbdchgidxIsEarlierNonNull(lbchgidx, ubchgidx) )
22793 return ubchgidx;
22794 else
22795 return lbchgidx;
22796}
22797
22798/** returns the last depth level, at which the bounds of the given variable were tightened;
22799 * returns -2, if the variable's bounds are still the global bounds
22800 * returns -1, if the variable was fixed in presolving
22801 */
22803 SCIP_VAR* var /**< problem variable */
22804 )
22805{
22806 SCIP_BDCHGIDX* bdchgidx;
22807
22808 bdchgidx = SCIPvarGetLastBdchgIndex(var);
22809 assert(bdchgidx != NULL);
22810
22811 return bdchgidx->depth;
22812}
22813
22814/** returns at which depth in the tree a bound change was applied to the variable that conflicts with the
22815 * given bound; returns -1 if the bound does not conflict with the current local bounds of the variable
22816 */
22818 SCIP_VAR* var, /**< problem variable */
22819 SCIP_SET* set, /**< global SCIP settings */
22820 SCIP_BOUNDTYPE boundtype, /**< bound type of the conflicting bound */
22821 SCIP_Real bound /**< conflicting bound */
22822 )
22823{
22824 int i;
22825
22826 assert(var != NULL);
22827 assert(set != NULL);
22828 assert(var->scip == set->scip);
22829
22830 if( boundtype == SCIP_BOUNDTYPE_LOWER )
22831 {
22832 /* check if the bound is in conflict with the current local bounds */
22833 if( SCIPsetIsLE(set, bound, var->locdom.ub) )
22834 return -1;
22835
22836 /* check if the bound is in conflict with the global bound */
22837 if( SCIPsetIsGT(set, bound, var->glbdom.ub) )
22838 return 0;
22839
22840 /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
22841 assert(var->nubchginfos > 0);
22842 assert(SCIPsetIsGT(set, bound, var->ubchginfos[var->nubchginfos-1].newbound));
22843
22844 /* search for the first conflicting bound change */
22845 for( i = var->nubchginfos-1; i > 0 && SCIPsetIsGT(set, bound, var->ubchginfos[i-1].newbound); --i )
22846 {
22847 assert(var->ubchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
22848 assert((SCIP_BOUNDTYPE)var->ubchginfos[i].boundtype == SCIP_BOUNDTYPE_UPPER);
22849 }
22850 assert(SCIPsetIsGT(set, bound, var->ubchginfos[i].newbound)); /* bound change i is conflicting */
22851 assert(i == 0 || SCIPsetIsLE(set, bound, var->ubchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
22852
22853 /* return the depth at which the first conflicting bound change took place */
22854 return var->ubchginfos[i].bdchgidx.depth;
22855 }
22856 else
22857 {
22858 assert(boundtype == SCIP_BOUNDTYPE_UPPER);
22859
22860 /* check if the bound is in conflict with the current local bounds */
22861 if( SCIPsetIsGE(set, bound, var->locdom.lb) )
22862 return -1;
22863
22864 /* check if the bound is in conflict with the global bound */
22865 if( SCIPsetIsLT(set, bound, var->glbdom.lb) )
22866 return 0;
22867
22868 /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
22869 assert(var->nlbchginfos > 0);
22870 assert(SCIPsetIsLT(set, bound, var->lbchginfos[var->nlbchginfos-1].newbound));
22871
22872 /* search for the first conflicting bound change */
22873 for( i = var->nlbchginfos-1; i > 0 && SCIPsetIsLT(set, bound, var->lbchginfos[i-1].newbound); --i )
22874 {
22875 assert(var->lbchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
22876 assert((SCIP_BOUNDTYPE)var->lbchginfos[i].boundtype == SCIP_BOUNDTYPE_LOWER);
22877 }
22878 assert(SCIPsetIsLT(set, bound, var->lbchginfos[i].newbound)); /* bound change i is conflicting */
22879 assert(i == 0 || SCIPsetIsGE(set, bound, var->lbchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
22880
22881 /* return the depth at which the first conflicting bound change took place */
22882 return var->lbchginfos[i].bdchgidx.depth;
22883 }
22884}
22885
22886/** returns whether the first binary variable was fixed earlier than the second one;
22887 * returns FALSE, if the first variable is not fixed, and returns TRUE, if the first variable is fixed, but the
22888 * second one is not fixed
22889 */
22891 SCIP_VAR* var1, /**< first binary variable */
22892 SCIP_VAR* var2 /**< second binary variable */
22893 )
22894{
22895 SCIP_BDCHGIDX* bdchgidx1;
22896 SCIP_BDCHGIDX* bdchgidx2;
22897
22898 assert(var1 != NULL);
22899 assert(var2 != NULL);
22900 assert(SCIPvarIsBinary(var1));
22901 assert(SCIPvarIsBinary(var2));
22902
22903 var1 = SCIPvarGetProbvar(var1);
22904 var2 = SCIPvarGetProbvar(var2);
22905 assert(var1 != NULL);
22906 assert(var2 != NULL);
22907
22908 /* check, if variables are globally fixed */
22909 if( !SCIPvarIsActive(var2) || var2->glbdom.lb > 0.5 || var2->glbdom.ub < 0.5 )
22910 return FALSE;
22911 if( !SCIPvarIsActive(var1) || var1->glbdom.lb > 0.5 || var1->glbdom.ub < 0.5 )
22912 return TRUE;
22913
22916 assert(SCIPvarIsBinary(var1));
22917 assert(SCIPvarIsBinary(var2));
22918 assert(var1->nlbchginfos + var1->nubchginfos <= 1);
22919 assert(var2->nlbchginfos + var2->nubchginfos <= 1);
22920 assert(var1->nlbchginfos == 0 || !var1->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
22921 assert(var1->nubchginfos == 0 || !var1->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
22922 assert(var2->nlbchginfos == 0 || !var2->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
22923 assert(var2->nubchginfos == 0 || !var2->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
22924
22925 if( var1->nlbchginfos == 1 )
22926 bdchgidx1 = &var1->lbchginfos[0].bdchgidx;
22927 else if( var1->nubchginfos == 1 )
22928 bdchgidx1 = &var1->ubchginfos[0].bdchgidx;
22929 else
22930 bdchgidx1 = NULL;
22931
22932 if( var2->nlbchginfos == 1 )
22933 bdchgidx2 = &var2->lbchginfos[0].bdchgidx;
22934 else if( var2->nubchginfos == 1 )
22935 bdchgidx2 = &var2->ubchginfos[0].bdchgidx;
22936 else
22937 bdchgidx2 = NULL;
22938
22939 return SCIPbdchgidxIsEarlier(bdchgidx1, bdchgidx2);
22940}
22941
22942/** for a given array of variables, this function counts the numbers of variables for each variable and implied type combination */
22944 SCIP_VAR** vars, /**< array of variables to count the types for */
22945 int nvars, /**< number of variables in the array */
22946 int* nbinvars, /**< pointer to store number of binary variables or NULL if not needed */
22947 int* nintvars, /**< pointer to store number of integer variables or NULL if not needed */
22948 int* nbinimplvars, /**< pointer to store number of binary implied integral vars or NULL if not needed */
22949 int* nintimplvars, /**< pointer to store number of integer implied integral vars or NULL if not needed */
22950 int* ncontimplvars, /**< pointer to store number of continuous implied integral vars or NULL if not needed */
22951 int* ncontvars /**< pointer to store number of continuous variables or NULL if not needed */
22952 )
22953{
22954 assert(vars != NULL || nvars == 0);
22955 int binvars = 0;
22956 int binimplvars = 0;
22957 int intvars = 0;
22958 int intimplvars = 0;
22959 int contvars = 0;
22960 int contimplvars = 0;
22961 int v;
22962
22963 for( v = 0; v < nvars; ++v )
22964 {
22966 switch( SCIPvarGetType(vars[v]) )
22967 {
22969 if( implied )
22970 ++binimplvars;
22971 else
22972 ++binvars;
22973 break;
22975 if( implied )
22976 ++intimplvars;
22977 else
22978 ++intvars;
22979 break;
22981 if( implied )
22982 ++contimplvars;
22983 else
22984 ++contvars;
22985 break;
22986 default:
22987 SCIPerrorMessage("unknown variable type\n");
22988 SCIPABORT();
22989 } /*lint !e788*/
22990 }
22991 if( nbinvars != NULL )
22992 *nbinvars = binvars;
22993 if( nintvars != NULL )
22994 *nintvars = intvars;
22995 if( nbinimplvars != NULL )
22996 *nbinimplvars = binimplvars;
22997 if( nintimplvars != NULL )
22998 *nintimplvars = intimplvars;
22999 if( ncontimplvars != NULL )
23000 *ncontimplvars = contimplvars;
23001 if( ncontvars != NULL )
23002 *ncontvars = contvars;
23003}
23004
23005/*
23006 * Hash functions
23007 */
23008
23009/** gets the key (i.e. the name) of the given variable */
23010SCIP_DECL_HASHGETKEY(SCIPhashGetKeyVar)
23011{ /*lint --e{715}*/
23012 SCIP_VAR* var = (SCIP_VAR*)elem;
23013
23014 assert(var != NULL);
23015 return var->name;
23016}
23017
23018
23019
23020
23021/*
23022 * simple functions implemented as defines
23023 */
23024
23025/* In debug mode, the following methods are implemented as function calls to ensure
23026 * type validity.
23027 * In optimized mode, the methods are implemented as defines to improve performance.
23028 * However, we want to have them in the library anyways, so we have to undef the defines.
23029 */
23030
23031#undef SCIPboundchgGetNewbound
23032#undef SCIPboundchgGetLPSolVal
23033#undef SCIPboundchgGetVar
23034#undef SCIPboundchgGetBoundchgtype
23035#undef SCIPboundchgGetBoundtype
23036#undef SCIPboundchgIsRedundant
23037#undef SCIPdomchgGetNBoundchgs
23038#undef SCIPdomchgGetBoundchg
23039#undef SCIPholelistGetLeft
23040#undef SCIPholelistGetRight
23041#undef SCIPholelistGetNext
23042#undef SCIPvarGetName
23043#undef SCIPvarGetNUses
23044#undef SCIPvarGetData
23045#undef SCIPvarSetData
23046#undef SCIPvarSetDelorigData
23047#undef SCIPvarSetTransData
23048#undef SCIPvarSetDeltransData
23049#undef SCIPvarGetStatus
23050#undef SCIPvarIsOriginal
23051#undef SCIPvarIsTransformed
23052#undef SCIPvarIsNegated
23053#undef SCIPvarGetType
23054#undef SCIPvarIsBinary
23055#undef SCIPvarIsIntegral
23056#undef SCIPvarIsImpliedIntegral
23057#undef SCIPvarIsNonimpliedIntegral
23058#undef SCIPvarIsInitial
23059#undef SCIPvarIsRemovable
23060#undef SCIPvarIsDeleted
23061#undef SCIPvarIsDeletable
23062#undef SCIPvarMarkDeletable
23063#undef SCIPvarMarkNotDeletable
23064#undef SCIPvarIsActive
23065#undef SCIPvarGetIndex
23066#undef SCIPvarGetProbindex
23067#undef SCIPvarGetTransVar
23068#undef SCIPvarGetCol
23069#undef SCIPvarIsInLP
23070#undef SCIPvarGetMinAggrCoef
23071#undef SCIPvarGetMaxAggrCoef
23072#undef SCIPvarGetAggrVar
23073#undef SCIPvarGetAggrScalar
23074#undef SCIPvarGetAggrConstant
23075#undef SCIPvarGetMultaggrNVars
23076#undef SCIPvarGetMultaggrVars
23077#undef SCIPvarGetMultaggrScalars
23078#undef SCIPvarGetMultaggrConstant
23079#undef SCIPvarGetNegatedVar
23080#undef SCIPvarGetNegationVar
23081#undef SCIPvarGetNegationConstant
23082#undef SCIPvarGetObj
23083#undef SCIPvarGetLbOriginal
23084#undef SCIPvarGetUbOriginal
23085#undef SCIPvarGetHolelistOriginal
23086#undef SCIPvarGetLbGlobal
23087#undef SCIPvarGetUbGlobal
23088#undef SCIPvarGetHolelistGlobal
23089#undef SCIPvarGetBestBoundGlobal
23090#undef SCIPvarGetWorstBoundGlobal
23091#undef SCIPvarGetLbLocal
23092#undef SCIPvarGetUbLocal
23093#undef SCIPvarGetHolelistLocal
23094#undef SCIPvarGetBestBoundLocal
23095#undef SCIPvarGetWorstBoundLocal
23096#undef SCIPvarGetBestBoundType
23097#undef SCIPvarGetWorstBoundType
23098#undef SCIPvarGetLbLazy
23099#undef SCIPvarGetUbLazy
23100#undef SCIPvarGetBranchFactor
23101#undef SCIPvarGetBranchPriority
23102#undef SCIPvarGetBranchDirection
23103#undef SCIPvarGetNVlbs
23104#undef SCIPvarGetVlbVars
23105#undef SCIPvarGetVlbCoefs
23106#undef SCIPvarGetVlbConstants
23107#undef SCIPvarGetNVubs
23108#undef SCIPvarGetVubVars
23109#undef SCIPvarGetVubCoefs
23110#undef SCIPvarGetVubConstants
23111#undef SCIPvarGetNImpls
23112#undef SCIPvarGetImplVars
23113#undef SCIPvarGetImplTypes
23114#undef SCIPvarGetImplBounds
23115#undef SCIPvarGetImplIds
23116#undef SCIPvarGetNCliques
23117#undef SCIPvarGetCliques
23118#undef SCIPvarGetLPSol
23119#undef SCIPvarGetNLPSol
23120#undef SCIPvarGetBdchgInfoLb
23121#undef SCIPvarGetNBdchgInfosLb
23122#undef SCIPvarGetBdchgInfoUb
23123#undef SCIPvarGetNBdchgInfosUb
23124#undef SCIPvarGetValuehistory
23125#undef SCIPvarGetPseudoSol
23126#undef SCIPvarCatchEvent
23127#undef SCIPvarDropEvent
23128#undef SCIPvarGetVSIDS
23129#undef SCIPvarGetCliqueComponentIdx
23130#undef SCIPvarIsRelaxationOnly
23131#undef SCIPvarMarkRelaxationOnly
23132#undef SCIPbdchgidxGetPos
23133#undef SCIPbdchgidxGetDepth
23134#undef SCIPbdchgidxIsEarlierNonNull
23135#undef SCIPbdchgidxIsEarlier
23136#undef SCIPbdchginfoGetOldbound
23137#undef SCIPbdchginfoGetNewbound
23138#undef SCIPbdchginfoGetVar
23139#undef SCIPbdchginfoGetChgtype
23140#undef SCIPbdchginfoGetBoundtype
23141#undef SCIPbdchginfoGetDepth
23142#undef SCIPbdchginfoGetPos
23143#undef SCIPbdchginfoGetIdx
23144#undef SCIPbdchginfoGetInferVar
23145#undef SCIPbdchginfoGetInferCons
23146#undef SCIPbdchginfoGetInferProp
23147#undef SCIPbdchginfoGetInferInfo
23148#undef SCIPbdchginfoGetInferBoundtype
23149#undef SCIPbdchginfoIsRedundant
23150#undef SCIPbdchginfoHasInferenceReason
23151#undef SCIPbdchginfoIsTighter
23152
23153
23154/** returns the new value of the bound in the bound change data */
23156 SCIP_BOUNDCHG* boundchg /**< bound change data */
23157 )
23158{
23159 assert(boundchg != NULL);
23160
23161 return boundchg->newbound;
23162}
23163
23164/** returns the lp solution value in the branching data of the bound change data */
23166 SCIP_BOUNDCHG* boundchg /**< bound change data */
23167 )
23168{
23169 assert(boundchg != NULL);
23170
23171 return boundchg->data.branchingdata.lpsolval;
23172}
23173
23174/** returns the variable of the bound change in the bound change data */
23176 SCIP_BOUNDCHG* boundchg /**< bound change data */
23177 )
23178{
23179 assert(boundchg != NULL);
23180
23181 return boundchg->var;
23182}
23183
23184/** returns the bound change type of the bound change in the bound change data */
23186 SCIP_BOUNDCHG* boundchg /**< bound change data */
23187 )
23188{
23189 assert(boundchg != NULL);
23190
23191 return (SCIP_BOUNDCHGTYPE)(boundchg->boundchgtype);
23192}
23193
23194/** returns the bound type of the bound change in the bound change data */
23196 SCIP_BOUNDCHG* boundchg /**< bound change data */
23197 )
23198{
23199 assert(boundchg != NULL);
23200
23201 return (SCIP_BOUNDTYPE)(boundchg->boundtype);
23202}
23203
23204/** returns whether the bound change is redundant due to a more global bound that is at least as strong */
23206 SCIP_BOUNDCHG* boundchg /**< bound change data */
23207 )
23208{
23209 assert(boundchg != NULL);
23210
23211 return boundchg->redundant;
23212}
23213
23214/** returns the number of bound changes in the domain change data */
23216 SCIP_DOMCHG* domchg /**< domain change data */
23217 )
23218{
23219 return domchg != NULL ? domchg->domchgbound.nboundchgs : 0;
23220}
23221
23222/** returns a particular bound change in the domain change data */
23224 SCIP_DOMCHG* domchg, /**< domain change data */
23225 int pos /**< position of the bound change in the domain change data */
23226 )
23227{
23228 assert(domchg != NULL);
23229 assert(0 <= pos && pos < (int)domchg->domchgbound.nboundchgs);
23230
23231 return &domchg->domchgbound.boundchgs[pos];
23232}
23233
23234/** returns left bound of open interval in hole */
23236 SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
23237 )
23238{
23239 assert(holelist != NULL);
23240
23241 return holelist->hole.left;
23242}
23243
23244/** returns right bound of open interval in hole */
23246 SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
23247 )
23248{
23249 assert(holelist != NULL);
23250
23251 return holelist->hole.right;
23252}
23253
23254/** returns next hole in list */
23256 SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
23257 )
23258{
23259 assert(holelist != NULL);
23260
23261 return holelist->next;
23262}
23263
23264/** returns the name of the variable
23265 *
23266 * @note to change the name of a variable, use SCIPchgVarName() from scip.h
23267 */
23268const char* SCIPvarGetName(
23269 SCIP_VAR* var /**< problem variable */
23270 )
23271{
23272 assert(var != NULL);
23273
23274 return var->name;
23275}
23276
23277/** gets number of times, the variable is currently captured */
23279 SCIP_VAR* var /**< problem variable */
23280 )
23281{
23282 assert(var != NULL);
23283
23284 return var->nuses;
23285}
23286
23287/** returns the user data of the variable */
23289 SCIP_VAR* var /**< problem variable */
23290 )
23291{
23292 assert(var != NULL);
23293
23294 return var->vardata;
23295}
23296
23297/** sets the user data for the variable */
23299 SCIP_VAR* var, /**< problem variable */
23300 SCIP_VARDATA* vardata /**< user variable data */
23301 )
23302{
23303 assert(var != NULL);
23304
23305 var->vardata = vardata;
23306}
23307
23308/** sets method to free user data for the original variable */
23310 SCIP_VAR* var, /**< problem variable */
23311 SCIP_DECL_VARDELORIG ((*vardelorig)) /**< frees user data of original variable */
23312 )
23313{
23314 assert(var != NULL);
23316
23317 var->vardelorig = vardelorig;
23318}
23319
23320/** sets method to transform user data of the variable */
23322 SCIP_VAR* var, /**< problem variable */
23323 SCIP_DECL_VARTRANS ((*vartrans)) /**< creates transformed user data by transforming original user data */
23324 )
23325{
23326 assert(var != NULL);
23328
23329 var->vartrans = vartrans;
23330}
23331
23332/** sets method to free transformed user data for the variable */
23334 SCIP_VAR* var, /**< problem variable */
23335 SCIP_DECL_VARDELTRANS ((*vardeltrans)) /**< frees user data of transformed variable */
23336 )
23337{
23338 assert(var != NULL);
23339
23340 var->vardeltrans = vardeltrans;
23341}
23342
23343/** sets method to copy this variable into sub-SCIPs */
23345 SCIP_VAR* var, /**< problem variable */
23346 SCIP_DECL_VARCOPY ((*varcopy)) /**< copy method of the variable */
23347 )
23348{
23349 assert(var != NULL);
23350
23351 var->varcopy = varcopy;
23352}
23353
23354/** sets the initial flag of a variable; only possible for original or loose variables */
23356 SCIP_VAR* var, /**< problem variable */
23357 SCIP_Bool initial /**< initial flag */
23358 )
23359{
23360 assert(var != NULL);
23361
23363 return SCIP_INVALIDCALL;
23364
23365 var->initial = initial;
23366
23367 return SCIP_OKAY;
23368}
23369
23370/** sets the removable flag of a variable; only possible for original or loose variables */
23372 SCIP_VAR* var, /**< problem variable */
23373 SCIP_Bool removable /**< removable flag */
23374 )
23375{
23376 assert(var != NULL);
23377
23379 return SCIP_INVALIDCALL;
23380
23381 var->removable = removable;
23382
23383 return SCIP_OKAY;
23384}
23385
23386/** gets status of variable */
23388 SCIP_VAR* var /**< problem variable */
23389 )
23390{
23391 assert(var != NULL);
23392
23393 return (SCIP_VARSTATUS)(var->varstatus);
23394}
23395
23396/** returns the status of the exact variable data */
23398 SCIP_VAR* var /**< scip variable */
23399 )
23400{
23401 assert(var != NULL);
23402 assert(var->exactdata != NULL);
23403
23404 return var->exactdata->varstatusexact;
23405}
23406
23407/** returns whether the variable has exact variable data */
23409 SCIP_VAR* var /**< scip variable */
23410 )
23411{
23412 assert(var != NULL);
23413
23414 return (var->exactdata != NULL);
23415}
23416
23417/** returns whether the variable belongs to the original problem */
23419 SCIP_VAR* var /**< problem variable */
23420 )
23421{
23422 assert(var != NULL);
23424
23427 && SCIPvarGetStatus(var->negatedvar) == SCIP_VARSTATUS_ORIGINAL));
23428}
23429
23430/** returns whether the variable belongs to the transformed problem */
23432 SCIP_VAR* var /**< problem variable */
23433 )
23434{
23435 assert(var != NULL);
23437
23440 || SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_ORIGINAL));
23441}
23442
23443/** returns whether the variable was created by negation of a different variable */
23445 SCIP_VAR* var /**< problem variable */
23446 )
23447{
23448 assert(var != NULL);
23449
23451}
23452
23453/** gets type of variable */
23455 SCIP_VAR* var /**< problem variable */
23456 )
23457{
23458 assert(var != NULL);
23459
23460 return (SCIP_VARTYPE)(var->vartype);
23461}
23462
23463/** gets the implied integral type of the variable */
23465 SCIP_VAR* var /**< problem variable */
23466 )
23467{
23468 assert(var != NULL);
23469
23470 return (SCIP_IMPLINTTYPE)(var->varimpltype);
23471}
23472
23473/** returns TRUE if the variable is of binary type; this is the case if:
23474 * (1) variable type is binary
23475 * (2) variable type is integer or implicit integer and
23476 * (i) the lazy lower bound or the global lower bound is greater than or equal to zero
23477 * (ii) the lazy upper bound or the global upper bound is less than or equal to one
23478 */
23480 SCIP_VAR* var /**< problem variable */
23481 )
23482{
23483 assert(var != NULL);
23484
23487 && MAX(var->glbdom.lb, var->lazylb) >= 0.0 && MIN(var->glbdom.ub, var->lazyub) <= 1.0));
23488}
23489
23490/** returns whether variable is of integral type (binary, integer, or implied integral of any type) */
23492 SCIP_VAR* var /**< problem variable */
23493 )
23494{
23496}
23497
23498/** returns whether variable is implied integral (weakly or strongly) */
23500 SCIP_VAR* var /**< problem variable */
23501 )
23502{
23504}
23505
23506/** returns TRUE if the variable is integral, but not implied integral. */
23508 SCIP_VAR* var /**< problem variable */
23509 )
23510{
23512}
23513
23514/** returns whether variable's column should be present in the initial root LP */
23516 SCIP_VAR* var /**< problem variable */
23517 )
23518{
23519 assert(var != NULL);
23520
23521 return var->initial;
23522}
23523
23524/** returns whether variable's column is removable from the LP (due to aging or cleanup) */
23526 SCIP_VAR* var /**< problem variable */
23527 )
23528{
23529 assert(var != NULL);
23530
23531 return var->removable;
23532}
23533
23534/** returns whether the variable was deleted from the problem */
23536 SCIP_VAR* var /**< problem variable */
23537 )
23538{
23539 assert(var != NULL);
23540
23541 return var->deleted;
23542}
23543
23544/** marks the variable to be deletable, i.e., it may be deleted completely from the problem;
23545 * method can only be called before the variable is added to the problem by SCIPaddVar() or SCIPaddPricedVar()
23546 */
23548 SCIP_VAR* var /**< problem variable */
23549 )
23550{
23551 assert(var != NULL);
23552 assert(var->probindex == -1);
23553
23554 var->deletable = TRUE;
23555}
23556
23557/** marks the variable to be not deletable from the problem */
23559 SCIP_VAR* var
23560 )
23561{
23562 assert(var != NULL);
23563
23564 var->deletable = FALSE;
23565}
23566
23567/** marks variable to be deleted from global structures (cliques etc.) when cleaning up
23568 *
23569 * @note: this is not equivalent to marking the variable itself for deletion, this is done by using SCIPvarMarkDeletable()
23570 */
23572 SCIP_VAR* var /**< problem variable */
23573 )
23574{
23575 assert(var != NULL);
23576
23577 var->delglobalstructs = TRUE;
23578}
23579
23580/** returns whether the variable was flagged for deletion from global structures (cliques etc.) */
23582 SCIP_VAR* var /**< problem variable */
23583 )
23584{
23585 assert(var != NULL);
23586
23587 return var->delglobalstructs;
23588}
23589
23590/** returns whether a variable has been introduced to define a relaxation
23591 *
23592 * These variables are only valid for the current SCIP solve round,
23593 * they are not contained in any (checked) constraints, but may be used
23594 * in cutting planes, for example.
23595 * Relaxation-only variables are not copied by SCIPcopyVars and cuts
23596 * that contain these variables are not added as linear constraints when
23597 * restarting or transferring information from a copied SCIP to a SCIP.
23598 * Also conflicts with relaxation-only variables are not generated at
23599 * the moment.
23600 */
23602 SCIP_VAR* var /**< problem variable */
23603 )
23604{
23605 assert(var != NULL);
23606
23607 return var->relaxationonly;
23608}
23609
23610/** marks that this variable has only been introduced to define a relaxation
23611 *
23612 * The variable must not have a coefficient in the objective and must be deletable.
23613 * If it is not marked deletable, it will be marked as deletable, which is only possible
23614 * before the variable is added to a problem.
23615 *
23616 * @see SCIPvarIsRelaxationOnly
23617 * @see SCIPvarMarkDeletable
23618 */
23620 SCIP_VAR* var /**< problem variable */
23621 )
23622{
23623 assert(var != NULL);
23624 assert(SCIPvarGetObj(var) == 0.0);
23625
23626 if( !SCIPvarIsDeletable(var) )
23628
23629 var->relaxationonly = TRUE;
23630}
23631
23632/** returns whether variable is allowed to be deleted completely from the problem */
23634 SCIP_VAR* var
23635 )
23636{
23637 assert(var != NULL);
23638
23639 return var->deletable;
23640}
23641
23642/** returns whether variable is an active (neither fixed nor aggregated) variable */
23644 SCIP_VAR* var /**< problem variable */
23645 )
23646{
23647 assert(var != NULL);
23648
23649 return (var->probindex >= 0);
23650}
23651
23652/** gets unique index of variable */
23654 SCIP_VAR* var /**< problem variable */
23655 )
23656{
23657 assert(var != NULL);
23658
23659 return var->index;
23660}
23661
23662/** gets position of variable in problem, or -1 if variable is not active */
23664 SCIP_VAR* var /**< problem variable */
23665 )
23666{
23667 assert(var != NULL);
23668
23669 return var->probindex;
23670}
23671
23672/** gets transformed variable of ORIGINAL variable */
23674 SCIP_VAR* var /**< problem variable */
23675 )
23676{
23677 assert(var != NULL);
23679
23680 return var->data.original.transvar;
23681}
23682
23683/** gets column of COLUMN variable */
23685 SCIP_VAR* var /**< problem variable */
23686 )
23687{
23688 assert(var != NULL);
23690
23691 return var->data.col;
23692}
23693
23694/** gets exact column of COLUMN variable */
23696 SCIP_VAR* var /**< problem variable */
23697 )
23698{
23699 assert(var != NULL);
23700 assert(var->exactdata != NULL);
23702
23703 return var->exactdata->colexact;
23704}
23705
23706/** returns whether the variable is a COLUMN variable that is member of the current LP */
23708 SCIP_VAR* var /**< problem variable */
23709 )
23710{
23711 assert(var != NULL);
23712
23713 return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN && SCIPcolIsInLP(var->data.col));
23714}
23715
23716/** gets minimal absolute coefficient of a loose variable in (multi)aggregations of other variables */
23718 SCIP_VAR* var /**< problem variable */
23719 )
23720{
23722
23723 return var->data.loose.minaggrcoef;
23724}
23725
23726/** gets lower bound on absolute coefficient of a loose variable in (multi)aggregations of other variables */
23728 SCIP_VAR* var /**< problem variable */
23729 )
23730{
23732
23733 return var->data.loose.maxaggrcoef;
23734}
23735
23736/** gets upper bound on absolute coefficient of a loose variable in (multi)aggregations of other variables */
23738 SCIP_VAR* var /**< problem variable */
23739 )
23740{
23741 assert(var != NULL);
23743 assert(!var->donotaggr);
23744
23745 return var->data.aggregate.var;
23746}
23747
23748/** gets aggregation scalar a of an aggregated variable x = a*y + c */
23750 SCIP_VAR* var /**< problem variable */
23751 )
23752{
23753 assert(var != NULL);
23755 assert(!var->donotaggr);
23756
23757 return var->data.aggregate.scalar;
23758}
23759
23760/** gets aggregation scalar a of an aggregated variable x = a*y + c */
23762 SCIP_VAR* var /**< problem variable */
23763 )
23764{
23765 assert(var != NULL);
23767
23768 return var->exactdata->aggregate.scalar;
23769}
23770
23771/** gets aggregation constant c of an aggregated variable x = a*y + c */
23773 SCIP_VAR* var /**< problem variable */
23774 )
23775{
23776 assert(var != NULL);
23778 assert(!var->donotaggr);
23779
23780 return var->data.aggregate.constant;
23781}
23782
23783/** gets aggregation constant c of an aggregated variable x = a*y + c */
23785 SCIP_VAR* var /**< problem variable */
23786 )
23787{
23788 assert(var != NULL);
23790
23791 return var->exactdata->aggregate.constant;
23792}
23793
23794/** gets number n of aggregation variables of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
23796 SCIP_VAR* var /**< problem variable */
23797 )
23798{
23799 assert(var != NULL);
23801 assert(!var->donotmultaggr);
23802
23803 return var->data.multaggr.nvars;
23804}
23805
23806/** gets vector of aggregation variables y of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
23808 SCIP_VAR* var /**< problem variable */
23809 )
23810{
23811 assert(var != NULL);
23813 assert(!var->donotmultaggr);
23814
23815 return var->data.multaggr.vars;
23816}
23817
23818/** gets vector of aggregation scalars a of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
23820 SCIP_VAR* var /**< problem variable */
23821 )
23822{
23823 assert(var != NULL);
23825 assert(!var->donotmultaggr);
23826
23827 return var->data.multaggr.scalars;
23828}
23829
23830/** gets vector of exact aggregation scalars a of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
23832 SCIP_VAR* var /**< problem variable */
23833 )
23834{
23835 assert(var != NULL);
23837 assert(!var->donotmultaggr);
23838 assert(var->exactdata != NULL);
23839
23840 return var->exactdata->multaggr.scalars;
23841}
23842
23843/** gets aggregation constant c of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
23845 SCIP_VAR* var /**< problem variable */
23846 )
23847{
23848 assert(var != NULL);
23850 assert(!var->donotmultaggr);
23851
23852 return var->data.multaggr.constant;
23853}
23854
23855/** gets exact aggregation constant c of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
23857 SCIP_VAR* var /**< problem variable */
23858 )
23859{
23860 assert(var != NULL);
23862 assert(!var->donotmultaggr);
23863 assert(var->exactdata != NULL);
23864
23865 return var->exactdata->multaggr.constant;
23866}
23867
23868/** gets the negation of the given variable; may return NULL, if no negation is existing yet */
23870 SCIP_VAR* var /**< negated problem variable */
23871 )
23872{
23873 assert(var != NULL);
23874
23875 return var->negatedvar;
23876}
23877
23878/** gets the negation variable x of a negated variable x' = offset - x */
23880 SCIP_VAR* var /**< negated problem variable */
23881 )
23882{
23883 assert(var != NULL);
23885
23886 return var->negatedvar;
23887}
23888
23889/** gets the negation offset of a negated variable x' = offset - x */
23891 SCIP_VAR* var /**< negated problem variable */
23892 )
23893{
23894 assert(var != NULL);
23896
23897 return var->data.negate.constant;
23898}
23899
23900/** gets objective function value of variable */
23902 SCIP_VAR* var /**< problem variable */
23903 )
23904{
23905 assert(var != NULL);
23906
23907 return var->obj;
23908}
23909
23910/** gets exact objective function value of variable */
23912 SCIP_VAR* var /**< problem variable */
23913 )
23914{
23915 assert(var != NULL);
23916 assert(var->exactdata != NULL);
23917
23918 return var->exactdata->obj;
23919}
23920
23921/** gets exact objective function value of variable */
23923 SCIP_VAR* var /**< problem variable */
23924 )
23925{
23926 assert(var != NULL);
23927 assert(var->exactdata != NULL);
23928
23929 return var->exactdata->objinterval;
23930}
23931
23932/** gets the unchanged objective function value of a variable (ignoring temproray changes performed in probing mode) */
23934 SCIP_VAR* var /**< problem variable */
23935 )
23936{
23937 assert(var != NULL);
23938
23939 return var->unchangedobj;
23940}
23941
23942/** gets corresponding objective value of active, fixed, or multi-aggregated problem variable of given variable
23943 * e.g. obj(x) = 1 this method returns for ~x the value -1
23944 */
23946 SCIP_VAR* var, /**< problem variable */
23947 SCIP_Real* aggrobj /**< pointer to store the aggregated objective value */
23948 )
23949{
23950 SCIP_VAR* probvar = var;
23951 SCIP_Real mult = 1.0;
23952
23953 assert(probvar != NULL);
23954 assert(aggrobj != NULL);
23955
23956 while( probvar != NULL )
23957 {
23958 switch( SCIPvarGetStatus(probvar) )
23959 {
23963 (*aggrobj) = mult * SCIPvarGetObj(probvar);
23964 return SCIP_OKAY;
23965
23967 assert(SCIPvarGetObj(probvar) == 0.0);
23968 (*aggrobj) = 0.0;
23969 return SCIP_OKAY;
23970
23972 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
23973 if ( probvar->data.multaggr.nvars == 1 )
23974 {
23975 assert( probvar->data.multaggr.vars != NULL );
23976 assert( probvar->data.multaggr.scalars != NULL );
23977 assert( probvar->data.multaggr.vars[0] != NULL );
23978 mult *= probvar->data.multaggr.scalars[0];
23979 probvar = probvar->data.multaggr.vars[0];
23980 break;
23981 }
23982 else
23983 {
23984 SCIP_Real tmpobj;
23985 int v;
23986
23987 (*aggrobj) = 0.0;
23988
23989 for( v = probvar->data.multaggr.nvars - 1; v >= 0; --v )
23990 {
23991 SCIP_CALL( SCIPvarGetAggregatedObj(probvar->data.multaggr.vars[v], &tmpobj) );
23992 (*aggrobj) += probvar->data.multaggr.scalars[v] * tmpobj;
23993 }
23994 return SCIP_OKAY;
23995 }
23996
23997 case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
23998 assert(probvar->data.aggregate.var != NULL);
23999 mult *= probvar->data.aggregate.scalar;
24000 probvar = probvar->data.aggregate.var;
24001 break;
24002
24003 case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
24004 assert(probvar->negatedvar != NULL);
24006 assert(probvar->negatedvar->negatedvar == probvar);
24007 mult *= -1.0;
24008 probvar = probvar->negatedvar;
24009 break;
24010
24011 default:
24012 SCIPABORT();
24013 return SCIP_INVALIDDATA; /*lint !e527*/
24014 }
24015 }
24016
24017 return SCIP_INVALIDDATA;
24018}
24019
24020/** gets original lower bound of original problem variable (i.e. the bound set in problem creation) */
24022 SCIP_VAR* var /**< original problem variable */
24023 )
24024{
24025 assert(var != NULL);
24027
24029 return var->data.original.origdom.lb;
24030 else
24031 {
24033 assert(var->negatedvar != NULL);
24035
24036 return var->data.negate.constant - var->negatedvar->data.original.origdom.ub;
24037 }
24038}
24039
24040/** gets exact original lower bound of original problem variable (i.e. the bound set in problem creation) */
24042 SCIP_VAR* var /**< original problem variable */
24043 )
24044{
24045 assert(var != NULL);
24047 assert(var->exactdata != NULL);
24048
24050 return var->exactdata->origdom.lb;
24051 else
24052 {
24054 assert(var->negatedvar != NULL);
24056
24057 SCIPerrorMessage("negated var not implemented yet for rational data \n");
24058 SCIPABORT();
24059 return NULL;
24060 }
24061}
24062
24063/** gets original upper bound of original problem variable (i.e. the bound set in problem creation) */
24065 SCIP_VAR* var /**< original problem variable */
24066 )
24067{
24068 assert(var != NULL);
24070
24072 return var->data.original.origdom.ub;
24073 else
24074 {
24076 assert(var->negatedvar != NULL);
24078
24079 return var->data.negate.constant - var->negatedvar->data.original.origdom.lb;
24080 }
24081}
24082
24083/** gets exact original upper bound of original problem variable (i.e. the bound set in problem creation) */
24085 SCIP_VAR* var /**< original problem variable */
24086 )
24087{
24088 assert(var != NULL);
24090 assert(var->exactdata != NULL);
24091
24093 return var->exactdata->origdom.ub;
24094 else
24095 {
24097 assert(var->negatedvar != NULL);
24099
24100 SCIPerrorMessage("negated var not implemented yet for rational data \n");
24101 SCIPABORT();
24102 return NULL;
24103 }
24104}
24105
24106/** gets the original hole list of an original variable */
24108 SCIP_VAR* var /**< problem variable */
24109 )
24110{
24111 assert(var != NULL);
24113
24115 return var->data.original.origdom.holelist;
24116
24117 return NULL;
24118}
24119
24120/** gets global lower bound of variable */
24122 SCIP_VAR* var /**< problem variable */
24123 )
24124{
24125 assert(var != NULL);
24126
24127 return var->glbdom.lb;
24128}
24129
24130/** gets exact global lower bound of variable */
24132 SCIP_VAR* var /**< problem variable */
24133 )
24134{
24135 assert(var != NULL);
24136 assert(var->exactdata != NULL);
24137 assert(var->exactdata->glbdom.lb != NULL);
24138
24139 return var->exactdata->glbdom.lb;
24140}
24141
24142/** gets global upper bound of variable */
24144 SCIP_VAR* var /**< problem variable */
24145 )
24146{
24147 assert(var != NULL);
24148
24149 return var->glbdom.ub;
24150}
24151
24152/** gets exact global upper bound of variable */
24154 SCIP_VAR* var /**< problem variable */
24155 )
24156{
24157 assert(var != NULL);
24158 assert(var->exactdata != NULL);
24159 assert(var->exactdata->glbdom.ub != NULL);
24160
24161 return var->exactdata->glbdom.ub;
24162}
24163
24164/** gets the global hole list of an active variable */
24166 SCIP_VAR* var /**< problem variable */
24167 )
24168{
24169 assert(var != NULL);
24170
24171 return var->glbdom.holelist;
24172}
24173
24174/** gets best global bound of variable with respect to the objective function */
24176 SCIP_VAR* var /**< problem variable */
24177 )
24178{
24179 assert(var != NULL);
24180
24181 if( var->obj >= 0.0 )
24182 return var->glbdom.lb;
24183 else
24184 return var->glbdom.ub;
24185}
24186
24187/** gets best exact global bound of variable with respect to the objective function */
24189 SCIP_VAR* var /**< problem variable */
24190 )
24191{
24192 assert(var != NULL);
24193 assert(var->exactdata != NULL);
24194 assert(var->exactdata->glbdom.lb != NULL);
24195 assert(var->exactdata->glbdom.ub != NULL);
24196 assert(var->exactdata->obj != NULL);
24197
24198 if( !SCIPrationalIsNegative(var->exactdata->obj) )
24199 return var->exactdata->glbdom.lb;
24200 else
24201 return var->exactdata->glbdom.ub;
24202}
24203
24204/** gets worst global bound of variable with respect to the objective function */
24206 SCIP_VAR* var /**< problem variable */
24207 )
24208{
24209 assert(var != NULL);
24210
24211 if( var->obj >= 0.0 )
24212 return var->glbdom.ub;
24213 else
24214 return var->glbdom.lb;
24215}
24216
24217/** gets worst exact global bound of variable with respect to the objective function */
24219 SCIP_VAR* var /**< problem variable */
24220 )
24221{
24222 assert(var != NULL);
24223 assert(var->exactdata != NULL);
24224 assert(var->exactdata->glbdom.lb != NULL);
24225 assert(var->exactdata->glbdom.ub != NULL);
24226 assert(var->exactdata->obj != NULL);
24227
24228 if( !SCIPrationalIsNegative(var->exactdata->obj) )
24229 return var->exactdata->glbdom.ub;
24230 else
24231 return var->exactdata->glbdom.lb;
24232}
24233
24234/** gets current lower bound of variable */
24236 SCIP_VAR* var /**< problem variable */
24237 )
24238{
24239 assert(var != NULL);
24240
24241 return var->locdom.lb;
24242}
24243
24244/** gets current exact lower bound of variable */
24246 SCIP_VAR* var /**< problem variable */
24247 )
24248{
24249 assert(var != NULL);
24250 assert(var->exactdata != NULL);
24251 assert(var->exactdata->locdom.lb != NULL);
24252
24253 return var->exactdata->locdom.lb;
24254}
24255
24257 SCIP_VAR* var, /**< problem variable */
24258 SCIP_RATIONAL* output /**< output rational */
24259 )
24260{
24261 assert(var != NULL);
24262 assert(var->exactdata != NULL);
24263 assert(var->exactdata->locdom.lb != NULL);
24264 SCIPrationalSetFraction(output, (SCIP_Longint) (floor(var->locdom.lb)), 1LL);
24265 SCIPrationalMax(output, output, var->exactdata->locdom.lb);
24266}
24267
24268/** gets current upper bound of variable */
24270 SCIP_VAR* var /**< problem variable */
24271 )
24272{
24273 assert(var != NULL);
24274
24275 return var->locdom.ub;
24276}
24277
24278/** gets current exact upper bound of variable */
24280 SCIP_VAR* var /**< problem variable */
24281 )
24282{
24283 assert(var != NULL);
24284 assert(var->exactdata != NULL);
24285 assert(var->exactdata->locdom.ub != NULL);
24286
24287 return var->exactdata->locdom.ub;
24288}
24289
24291 SCIP_VAR* var, /**< problem variable */
24292 SCIP_RATIONAL* output /**< output rational */
24293 )
24294{
24295 assert(var != NULL);
24296 assert(var->exactdata != NULL);
24297 assert(var->exactdata->locdom.ub != NULL);
24298 SCIPrationalSetFraction(output, (SCIP_Longint) (ceil(var->locdom.ub)), 1LL);
24299 SCIPrationalMin(output, output, var->exactdata->locdom.ub);
24300}
24301
24302/** gets the current hole list of an active variable */
24304 SCIP_VAR* var /**< problem variable */
24305 )
24306{
24307 assert(var != NULL);
24308
24309 return var->locdom.holelist;
24310}
24311
24312/** gets best local bound of variable with respect to the objective function */
24314 SCIP_VAR* var /**< problem variable */
24315 )
24316{
24317 assert(var != NULL);
24318
24319 if( var->obj >= 0.0 )
24320 return var->locdom.lb;
24321 else
24322 return var->locdom.ub;
24323}
24324
24325/** gets best exact local bound of variable with respect to the objective function */
24327 SCIP_VAR* var /**< problem variable */
24328 )
24329{
24330 assert(var != NULL);
24331 assert(var->exactdata != NULL);
24332 assert(var->exactdata->locdom.lb != NULL);
24333 assert(var->exactdata->locdom.ub != NULL);
24334 assert(var->exactdata->obj != NULL);
24335
24336 if( !SCIPrationalIsNegative(var->exactdata->obj) )
24337 return var->exactdata->locdom.lb;
24338 else
24339 return var->exactdata->locdom.ub;
24340}
24341
24342/** gets worst local bound of variable with respect to the objective function */
24344 SCIP_VAR* var /**< problem variable */
24345 )
24346{
24347 assert(var != NULL);
24348
24349 if( var->obj >= 0.0 )
24350 return var->locdom.ub;
24351 else
24352 return var->locdom.lb;
24353}
24354
24355/** gets worst exact local bound of variable with respect to the objective function */
24357 SCIP_VAR* var /**< problem variable */
24358 )
24359{
24360 assert(var != NULL);
24361 assert(var->exactdata != NULL);
24362 assert(var->exactdata->locdom.lb != NULL);
24363 assert(var->exactdata->locdom.ub != NULL);
24364 assert(var->exactdata->obj != NULL);
24365
24366 if( !SCIPrationalIsNegative(var->exactdata->obj) )
24367 return var->exactdata->locdom.ub;
24368 else
24369 return var->exactdata->locdom.lb;
24370}
24371
24372/** gets type (lower or upper) of best bound of variable with respect to the objective function */
24374 SCIP_VAR* var /**< problem variable */
24375 )
24376{
24377 assert(var != NULL);
24378
24379 if( var->obj >= 0.0 )
24380 return SCIP_BOUNDTYPE_LOWER;
24381 else
24382 return SCIP_BOUNDTYPE_UPPER;
24383}
24384
24385/** gets type (lower or upper) of best bound of variable with respect to the objective function */
24387 SCIP_VAR* var /**< problem variable */
24388 )
24389{
24390 assert(var != NULL);
24391 assert(var->exactdata != NULL);
24392 assert(var->exactdata->obj != NULL);
24393
24394 if( !SCIPrationalIsNegative(var->exactdata->obj) )
24395 return SCIP_BOUNDTYPE_LOWER;
24396 else
24397 return SCIP_BOUNDTYPE_UPPER;
24398}
24399
24400/** gets type (lower or upper) of worst bound of variable with respect to the objective function */
24402 SCIP_VAR* var /**< problem variable */
24403 )
24404{
24405 assert(var != NULL);
24406
24407 if( var->obj >= 0.0 )
24408 return SCIP_BOUNDTYPE_UPPER;
24409 else
24410 return SCIP_BOUNDTYPE_LOWER;
24411}
24412
24413/** gets type (lower or upper) of worst bound of variable with respect to the objective function */
24415 SCIP_VAR* var /**< problem variable */
24416 )
24417{
24418 assert(var != NULL);
24419 assert(var->exactdata != NULL);
24420 assert(var->exactdata->obj != NULL);
24421
24422 if( !SCIPrationalIsNegative(var->exactdata->obj) )
24423 return SCIP_BOUNDTYPE_UPPER;
24424 else
24425 return SCIP_BOUNDTYPE_LOWER;
24426}
24427
24428/** gets lazy lower bound of variable, returns -infinity if the variable has no lazy lower bound */
24430 SCIP_VAR* var /**< problem variable */
24431 )
24432{
24433 assert(var != NULL);
24434
24435 return var->lazylb;
24436}
24437
24438/** gets lazy upper bound of variable, returns infinity if the variable has no lazy upper bound */
24440 SCIP_VAR* var /**< problem variable */
24441 )
24442{
24443 assert(var != NULL);
24444
24445 return var->lazyub;
24446}
24447
24448/** gets the branch factor of the variable; this value can be used in the branching methods to scale the score
24449 * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
24450 */
24452 SCIP_VAR* var /**< problem variable */
24453 )
24454{
24455 assert(var != NULL);
24456
24457 return var->branchfactor;
24458}
24459
24460/** gets the branch priority of the variable; variables with higher priority should always be preferred to variables
24461 * with lower priority
24462 */
24464 SCIP_VAR* var /**< problem variable */
24465 )
24466{
24467 assert(var != NULL);
24468
24469 return var->branchpriority;
24470}
24471
24472/** gets the preferred branch direction of the variable (downwards, upwards, or auto) */
24474 SCIP_VAR* var /**< problem variable */
24475 )
24476{
24477 assert(var != NULL);
24478
24479 return (SCIP_BRANCHDIR)var->branchdirection;
24480}
24481
24482/** gets number of variable lower bounds x >= b_i*z_i + d_i of given variable x */
24484 SCIP_VAR* var /**< problem variable */
24485 )
24486{
24487 assert(var != NULL);
24488
24489 return SCIPvboundsGetNVbds(var->vlbs);
24490}
24491
24492/** gets array with bounding variables z_i in variable lower bounds x >= b_i*z_i + d_i of given variable x;
24493 * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
24494 */
24496 SCIP_VAR* var /**< problem variable */
24497 )
24498{
24499 assert(var != NULL);
24500
24501 return SCIPvboundsGetVars(var->vlbs);
24502}
24503
24504/** gets array with bounding coefficients b_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
24506 SCIP_VAR* var /**< problem variable */
24507 )
24508{
24509 assert(var != NULL);
24510
24511 return SCIPvboundsGetCoefs(var->vlbs);
24512}
24513
24514/** gets array with bounding constants d_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
24516 SCIP_VAR* var /**< problem variable */
24517 )
24518{
24519 assert(var != NULL);
24520
24521 return SCIPvboundsGetConstants(var->vlbs);
24522}
24523
24524/** gets number of variable upper bounds x <= b_i*z_i + d_i of given variable x */
24526 SCIP_VAR* var /**< problem variable */
24527 )
24528{
24529 assert(var != NULL);
24530
24531 return SCIPvboundsGetNVbds(var->vubs);
24532}
24533
24534/** gets array with bounding variables z_i in variable upper bounds x <= b_i*z_i + d_i of given variable x;
24535 * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
24536 */
24538 SCIP_VAR* var /**< problem variable */
24539 )
24540{
24541 assert(var != NULL);
24542
24543 return SCIPvboundsGetVars(var->vubs);
24544}
24545
24546/** gets array with bounding coefficients b_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
24548 SCIP_VAR* var /**< problem variable */
24549 )
24550{
24551 assert(var != NULL);
24552
24553 return SCIPvboundsGetCoefs(var->vubs);
24554}
24555
24556/** gets array with bounding constants d_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
24558 SCIP_VAR* var /**< problem variable */
24559 )
24560{
24561 assert(var != NULL);
24562
24563 return SCIPvboundsGetConstants(var->vubs);
24564}
24565
24566/** gets number of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
24567 * there are no implications for nonbinary variable x
24568 */
24570 SCIP_VAR* var, /**< active problem variable */
24571 SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
24572 )
24573{
24574 assert(var != NULL);
24576
24577 return SCIPimplicsGetNImpls(var->implics, varfixing);
24578}
24579
24580/** gets array with implication variables y of implications y <= b or y >= b for x == 0 or x == 1 of given active
24581 * problem variable x, there are no implications for nonbinary variable x;
24582 * the implications are sorted such that implications with binary implied variables precede the ones with non-binary
24583 * implied variables, and as a second criteria, the implied variables are sorted by increasing variable index
24584 * (see SCIPvarGetIndex())
24585 */
24587 SCIP_VAR* var, /**< active problem variable */
24588 SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
24589 )
24590{
24591 assert(var != NULL);
24593
24594 return SCIPimplicsGetVars(var->implics, varfixing);
24595}
24596
24597/** gets array with implication types of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
24598 * variable x (SCIP_BOUNDTYPE_UPPER if y <= b, SCIP_BOUNDTYPE_LOWER if y >= b),
24599 * there are no implications for nonbinary variable x
24600 */
24602 SCIP_VAR* var, /**< active problem variable */
24603 SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
24604 )
24605{
24606 assert(var != NULL);
24608
24609 return SCIPimplicsGetTypes(var->implics, varfixing);
24610}
24611
24612/** gets array with implication bounds b of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
24613 * variable x, there are no implications for nonbinary variable x
24614 */
24616 SCIP_VAR* var, /**< active problem variable */
24617 SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
24618 )
24619{
24620 assert(var != NULL);
24622
24623 return SCIPimplicsGetBounds(var->implics, varfixing);
24624}
24625
24626/** Gets array with unique ids of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
24627 * there are no implications for nonbinary variable x.
24628 * If an implication is a shortcut, i.e., it was added as part of the transitive closure of another implication,
24629 * its id is negative, otherwise it is nonnegative.
24630 */
24632 SCIP_VAR* var, /**< active problem variable */
24633 SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
24634 )
24635{
24636 assert(var != NULL);
24638
24639 return SCIPimplicsGetIds(var->implics, varfixing);
24640}
24641
24642/** gets number of cliques, the active variable is contained in */
24644 SCIP_VAR* var, /**< active problem variable */
24645 SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
24646 )
24647{
24648 assert(var != NULL);
24649
24650 return SCIPcliquelistGetNCliques(var->cliquelist, varfixing);
24651}
24652
24653/** gets array of cliques, the active variable is contained in */
24655 SCIP_VAR* var, /**< active problem variable */
24656 SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
24657 )
24658{
24659 assert(var != NULL);
24660
24661 return SCIPcliquelistGetCliques(var->cliquelist, varfixing);
24662}
24663
24664/** gets primal LP solution value of variable */
24666 SCIP_VAR* var /**< problem variable */
24667 )
24668{
24669 assert(var != NULL);
24670
24672 return SCIPcolGetPrimsol(var->data.col);
24673 else
24674 return SCIPvarGetLPSol_rec(var);
24675}
24676
24677/** gets exact primal LP solution value of variable */
24679 SCIP_VAR* var, /**< problem variable */
24680 SCIP_RATIONAL* res /**< resulting value */
24681 )
24682{
24683 assert(var != NULL);
24684
24686 SCIPrationalSetRational(res, SCIPcolExactGetPrimsol(var->exactdata->colexact));
24687 else
24689}
24690
24691/** gets primal NLP solution value of variable */
24693 SCIP_VAR* var /**< problem variable */
24694 )
24695{
24696 assert(var != NULL);
24697
24699 return var->nlpsol;
24700 else
24701 return SCIPvarGetNLPSol_rec(var);
24702}
24703
24704/** return lower bound change info at requested position */
24706 SCIP_VAR* var, /**< problem variable */
24707 int pos /**< requested position */
24708 )
24709{
24710 assert(pos >= 0);
24711 assert(pos < var->nlbchginfos);
24712
24713 return &var->lbchginfos[pos];
24714}
24715
24716/** gets the number of lower bound change info array */
24718 SCIP_VAR* var /**< problem variable */
24719 )
24720{
24721 return var->nlbchginfos;
24722}
24723
24724/** return upper bound change info at requested position */
24726 SCIP_VAR* var, /**< problem variable */
24727 int pos /**< requested position */
24728 )
24729{
24730 assert(pos >= 0);
24731 assert(pos < var->nubchginfos);
24732
24733 return &var->ubchginfos[pos];
24734}
24735
24736/** gets the number upper bound change info array */
24738 SCIP_VAR* var /**< problem variable */
24739 )
24740{
24741 assert(var != NULL);
24742
24743 return var->nubchginfos;
24744}
24745
24746/** returns the value based history for the variable */
24748 SCIP_VAR* var /**< problem variable */
24749 )
24750{
24751 assert(var != NULL);
24752
24753 return var->valuehistory;
24754}
24755
24756/** gets pseudo solution value of variable */
24758 SCIP_VAR* var /**< problem variable */
24759 )
24760{
24761 assert(var != NULL);
24762
24765 else
24767}
24768
24769/** gets exact pseudo solution value of variable */
24771 SCIP_VAR* var /**< problem variable */
24772 )
24773{
24774 assert(var != NULL);
24775
24778 else
24780}
24781
24782/** returns the variable's VSIDS score */
24784 SCIP_VAR* var, /**< problem variable */
24785 SCIP_STAT* stat, /**< problem statistics */
24786 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
24787 )
24788{
24789 assert(var != NULL);
24790
24792 return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
24793 else
24794 return SCIPvarGetVSIDS_rec(var, stat, dir);
24795}
24796
24797/** includes event handler with given data in variable's event filter */
24799 SCIP_VAR* var, /**< problem variable */
24800 BMS_BLKMEM* blkmem, /**< block memory */
24801 SCIP_SET* set, /**< global SCIP settings */
24802 SCIP_EVENTTYPE eventtype, /**< event type to catch */
24803 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
24804 SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
24805 int* filterpos /**< pointer to store position of event filter entry, or NULL */
24806 )
24807{
24808 assert(var != NULL);
24809 assert(set != NULL);
24810 assert(var->scip == set->scip);
24811 assert(var->eventfilter != NULL);
24812 assert((eventtype & ~SCIP_EVENTTYPE_VARCHANGED) == 0);
24813 assert((eventtype & SCIP_EVENTTYPE_VARCHANGED) != 0);
24815
24816 SCIPsetDebugMsg(set, "catch event of type 0x%" SCIP_EVENTTYPE_FORMAT " of variable <%s> with handler %p and data %p\n",
24817 eventtype, var->name, (void*)eventhdlr, (void*)eventdata);
24818
24819 SCIP_CALL( SCIPeventfilterAdd(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
24820
24821 return SCIP_OKAY;
24822}
24823
24824/** deletes event handler with given data from variable's event filter */
24826 SCIP_VAR* var, /**< problem variable */
24827 BMS_BLKMEM* blkmem, /**< block memory */
24828 SCIP_SET* set, /**< global SCIP settings */
24829 SCIP_EVENTTYPE eventtype, /**< event type mask of dropped event */
24830 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
24831 SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
24832 int filterpos /**< position of event filter entry returned by SCIPvarCatchEvent(), or -1 */
24833 )
24834{
24835 assert(var != NULL);
24836 assert(set != NULL);
24837 assert(var->scip == set->scip);
24838 assert(var->eventfilter != NULL);
24840
24841 SCIPsetDebugMsg(set, "drop event of variable <%s> with handler %p and data %p\n", var->name, (void*)eventhdlr,
24842 (void*)eventdata);
24843
24844 SCIP_CALL( SCIPeventfilterDel(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
24845
24846 return SCIP_OKAY;
24847}
24848
24849/** returns the position of the bound change index */
24851 SCIP_BDCHGIDX* bdchgidx /**< bound change index */
24852 )
24853{
24854 assert(bdchgidx != NULL);
24855
24856 return bdchgidx->pos;
24857}
24858
24859/** returns the depth of the bound change index */
24861 SCIP_BDCHGIDX* bdchgidx /**< bound change index */
24862 )
24863{
24864 assert(bdchgidx != NULL);
24865
24866 return bdchgidx->depth;
24867}
24868
24869/** returns whether first bound change index belongs to an earlier applied bound change than second one */
24871 SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index */
24872 SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index */
24873 )
24874{
24875 assert(bdchgidx1 != NULL);
24876 assert(bdchgidx1->depth >= -2);
24877 assert(bdchgidx1->pos >= 0);
24878 assert(bdchgidx2 != NULL);
24879 assert(bdchgidx2->depth >= -2);
24880 assert(bdchgidx2->pos >= 0);
24881
24882 return (bdchgidx1->depth < bdchgidx2->depth)
24883 || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
24884}
24885
24886/** returns whether first bound change index belongs to an earlier applied bound change than second one;
24887 * if a bound change index is NULL, the bound change index represents the current time, i.e. the time after the
24888 * last bound change was applied to the current node
24889 */
24891 SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index, or NULL */
24892 SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index, or NULL */
24893 )
24894{
24895 assert(bdchgidx1 == NULL || bdchgidx1->depth >= -2);
24896 assert(bdchgidx1 == NULL || bdchgidx1->pos >= 0);
24897 assert(bdchgidx2 == NULL || bdchgidx2->depth >= -2);
24898 assert(bdchgidx2 == NULL || bdchgidx2->pos >= 0);
24899
24900 if( bdchgidx1 == NULL )
24901 return FALSE;
24902 else if( bdchgidx2 == NULL )
24903 return TRUE;
24904 else
24905 return (bdchgidx1->depth < bdchgidx2->depth)
24906 || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
24907}
24908
24909/** returns old bound that was overwritten for given bound change information */
24911 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
24912 )
24913{
24914 assert(bdchginfo != NULL);
24915
24916 return bdchginfo->oldbound;
24917}
24918
24919/** returns new bound installed for given bound change information */
24921 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
24922 )
24923{
24924 assert(bdchginfo != NULL);
24925
24926 return bdchginfo->newbound;
24927}
24928
24929/** returns variable that belongs to the given bound change information */
24931 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
24932 )
24933{
24934 assert(bdchginfo != NULL);
24935
24936 return bdchginfo->var;
24937}
24938
24939/** returns whether the bound change information belongs to a branching decision or a deduction */
24941 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
24942 )
24943{
24944 assert(bdchginfo != NULL);
24945
24946 return (SCIP_BOUNDCHGTYPE)(bdchginfo->boundchgtype);
24947}
24948
24949/** returns whether the bound change information belongs to a lower or upper bound change */
24951 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
24952 )
24953{
24954 assert(bdchginfo != NULL);
24955
24956 return (SCIP_BOUNDTYPE)(bdchginfo->boundtype);
24957}
24958
24959/** returns depth level of given bound change information */
24961 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
24962 )
24963{
24964 assert(bdchginfo != NULL);
24965
24966 return bdchginfo->bdchgidx.depth;
24967}
24968
24969/** returns bound change position in its depth level of given bound change information */
24971 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
24972 )
24973{
24974 assert(bdchginfo != NULL);
24975
24976 return bdchginfo->bdchgidx.pos;
24977}
24978
24979/** returns bound change index of given bound change information */
24981 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
24982 )
24983{
24984 assert(bdchginfo != NULL);
24985
24986 return &bdchginfo->bdchgidx;
24987}
24988
24989/** returns inference variable of given bound change information */
24991 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
24992 )
24993{
24994 assert(bdchginfo != NULL);
24997
24998 return bdchginfo->inferencedata.var;
24999}
25000
25001/** returns inference constraint of given bound change information */
25003 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
25004 )
25005{
25006 assert(bdchginfo != NULL);
25008 assert(bdchginfo->inferencedata.reason.cons != NULL);
25009
25010 return bdchginfo->inferencedata.reason.cons;
25011}
25012
25013/** returns inference propagator of given bound change information, or NULL if no propagator was responsible */
25015 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
25016 )
25017{
25018 assert(bdchginfo != NULL);
25020
25021 return bdchginfo->inferencedata.reason.prop;
25022}
25023
25024/** returns inference user information of given bound change information */
25026 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
25027 )
25028{
25029 assert(bdchginfo != NULL);
25032
25033 return bdchginfo->inferencedata.info;
25034}
25035
25036/** returns inference bound of inference variable of given bound change information */
25038 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
25039 )
25040{
25041 assert(bdchginfo != NULL);
25044
25045 return (SCIP_BOUNDTYPE)(bdchginfo->inferboundtype);
25046}
25047
25048/** returns the relaxed bound change type */
25050 SCIP_BDCHGINFO* bdchginfo /**< bound change to add to the conflict set */
25051 )
25052{
25053 return ((SCIP_BOUNDTYPE)(bdchginfo->boundtype) == SCIP_BOUNDTYPE_LOWER ? bdchginfo->var->conflictrelaxedlb : bdchginfo->var->conflictrelaxedub);
25054}
25055
25056
25057/** returns whether the bound change information belongs to a redundant bound change */
25059 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
25060 )
25061{
25062 assert(bdchginfo != NULL);
25063 assert(bdchginfo->redundant == (bdchginfo->oldbound == bdchginfo->newbound)); /*lint !e777*/
25064
25065 return bdchginfo->redundant;
25066}
25067
25068/** returns whether the bound change has an inference reason (constraint or propagator), that can be resolved */
25070 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
25071 )
25072{
25073 assert(bdchginfo != NULL);
25074
25077 && bdchginfo->inferencedata.reason.prop != NULL);
25078}
25079
25080/** for two bound change informations belonging to the same variable and bound, returns whether the first bound change
25081 * has a tighter new bound as the second bound change
25082 */
25084 SCIP_BDCHGINFO* bdchginfo1, /**< first bound change information */
25085 SCIP_BDCHGINFO* bdchginfo2 /**< second bound change information */
25086 )
25087{
25088 assert(bdchginfo1 != NULL);
25089 assert(bdchginfo2 != NULL);
25090 assert(bdchginfo1->var == bdchginfo2->var);
25091 assert(bdchginfo1->boundtype == bdchginfo2->boundtype);
25092
25093 return (SCIPbdchginfoGetBoundtype(bdchginfo1) == SCIP_BOUNDTYPE_LOWER
25094 ? bdchginfo1->newbound > bdchginfo2->newbound
25095 : bdchginfo1->newbound < bdchginfo2->newbound);
25096}
25097
25098/** returns position of variable in certificate */
25100 SCIP_VAR* var /**< variable to get index for */
25101 )
25102{
25103 assert(var != NULL);
25104 assert(var->exactdata != NULL);
25105
25106 return var->exactdata->certificateindex;
25107}
25108
25109/** sets index of variable in certificate */
25111 SCIP_VAR* var, /**< variable to set index for */
25112 int certidx /**< the index */
25113 )
25114{
25115 assert(var != NULL);
25116 assert(var->exactdata != NULL);
25117 assert(certidx >= 0);
25118
25119 var->exactdata->certificateindex = certidx;
25120}
25121
25122/** sets index of variable in certificate */
25124 SCIP_VAR* var, /**< variable to set index for */
25125 SCIP_Longint certidx /**< the index */
25126 )
25127{
25128 assert(var != NULL);
25129 assert(var->exactdata != NULL);
25130 assert(certidx >= 0);
25131
25132 var->exactdata->glbdom.ubcertificateidx = certidx;
25133 var->exactdata->locdom.ubcertificateidx = certidx;
25134}
25135
25136/** sets index of variable in certificate */
25138 SCIP_VAR* var, /**< variable to set index for */
25139 SCIP_Longint certidx /**< the index */
25140 )
25141{
25142 assert(var != NULL);
25143 assert(var->exactdata != NULL);
25144 assert(certidx >= 0);
25145
25146 var->exactdata->locdom.ubcertificateidx = certidx;
25147}
25148
25149/** sets index of variable in certificate */
25151 SCIP_VAR* var, /**< variable to set index for */
25152 SCIP_Longint certidx /**< the index */
25153 )
25154{
25155 assert(var != NULL);
25156 assert(var->exactdata != NULL);
25157 assert(certidx >= 0);
25158
25159 var->exactdata->locdom.lbcertificateidx = certidx;
25160}
25161
25162/** sets index of variable in certificate */
25164 SCIP_VAR* var, /**< variable to set index for */
25165 SCIP_Longint certidx /**< the index */
25166 )
25167{
25168 assert(var != NULL);
25169 assert(var->exactdata != NULL);
25170 assert(certidx >= 0);
25171
25172 var->exactdata->glbdom.lbcertificateidx = certidx;
25173 var->exactdata->locdom.lbcertificateidx = certidx;
25174}
25175
25176/** returns index of variable bound in vipr certificate */
25178 SCIP_VAR* var /**< variable to get index for */
25179 )
25180{
25181 assert(var->exactdata != NULL);
25182 assert(var->exactdata->locdom.lbcertificateidx != -1);
25183 assert(var->exactdata->locdom.lbcertificateidx <= SCIPcertificateGetCurrentIndex(SCIPgetCertificate(var->scip)) && var->exactdata->locdom.lbcertificateidx >= 0);
25184
25185 return var->exactdata->locdom.lbcertificateidx;
25186}
25187
25188/** returns index of variable bound in vipr certificate */
25190 SCIP_VAR* var /**< variable to get index for */
25191 )
25192{
25193 assert(var->exactdata != NULL);
25194 assert(var->exactdata->locdom.ubcertificateidx != -1);
25195 assert(var->exactdata->locdom.ubcertificateidx <= SCIPcertificateGetCurrentIndex(SCIPgetCertificate(var->scip)) && var->exactdata->locdom.ubcertificateidx >= 0);
25196
25197 return var->exactdata->locdom.ubcertificateidx;
25198}
25199
25200/** returns index of variable bound in vipr certificate */
25202 SCIP_VAR* var /**< variable to get index for */
25203 )
25204{
25205 assert(var->exactdata != NULL);
25206 assert(var->exactdata->glbdom.lbcertificateidx != -1);
25207 assert(var->exactdata->glbdom.lbcertificateidx <= SCIPcertificateGetCurrentIndex(SCIPgetCertificate(var->scip)) && var->exactdata->glbdom.lbcertificateidx >= 0);
25208
25209 return var->exactdata->glbdom.lbcertificateidx;
25210}
25211
25212/** returns index of variable bound in vipr certificate */
25214 SCIP_VAR* var /**< variable to get index for */
25215 )
25216{
25217 assert(var->exactdata != NULL);
25218 assert(var->exactdata->glbdom.ubcertificateidx != -1);
25219 assert(var->exactdata->glbdom.ubcertificateidx <= SCIPcertificateGetCurrentIndex(SCIPgetCertificate(var->scip)) && var->exactdata->glbdom.ubcertificateidx >= 0);
25220
25221 return var->exactdata->glbdom.ubcertificateidx;
25222}
static long bound
static GRAPHNODE ** active
SCIP_CERTIFICATE * SCIPgetCertificate(SCIP *scip)
SCIP_RETCODE SCIPcertificateSetLastBoundIndex(SCIP_CERTIFICATE *certificate, SCIP_Longint index)
SCIP_Longint SCIPcertificateGetLastBoundIndex(SCIP_CERTIFICATE *certificate)
SCIP_Bool SCIPcertificateIsEnabled(SCIP_CERTIFICATE *certificate)
SCIP_Longint SCIPcertificateGetCurrentIndex(SCIP_CERTIFICATE *certificate)
SCIP_Bool SCIPcertificateEnsureLastBoundInfoConsistent(SCIP_CERTIFICATE *certificate, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_Real newbound, SCIP_Bool needsglobal)
methods for certificate output
SCIP_VAR * a
SCIP_VAR ** b
void SCIPconsCapture(SCIP_CONS *cons)
Definition cons.c:6431
SCIP_RETCODE SCIPconsRelease(SCIP_CONS **cons, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition cons.c:6443
internal methods for constraints and constraint handlers
#define MAX_CLIQUELENGTH
#define MAXABSVBCOEF
#define MAXDNOM
#define SCIPdebugCheckLbGlobal(scip, var, lb)
Definition debug.h:298
#define SCIPdebugCheckImplic(set, var, varfixing, implvar, impltype, implbound)
Definition debug.h:305
#define SCIPdebugCheckUbGlobal(scip, var, ub)
Definition debug.h:299
#define SCIPdebugCheckVbound(set, var, vbtype, vbvar, vbcoef, vbconstant)
Definition debug.h:304
#define SCIPdebugCheckAggregation(set, var, aggrvars, scalars, constant, naggrvars)
Definition debug.h:306
#define SCIP_DEFAULT_INFINITY
Definition def.h:170
#define NULL
Definition def.h:255
#define SCIP_MAXSTRLEN
Definition def.h:276
#define SCIP_Longint
Definition def.h:148
#define EPSISINT(x, eps)
Definition def.h:202
#define SCIP_REAL_MAX
Definition def.h:165
#define SCIP_INVALID
Definition def.h:185
#define SCIP_INTERVAL_INFINITY
Definition def.h:187
#define SCIP_Bool
Definition def.h:98
#define EPSLE(x, y, eps)
Definition def.h:192
#define MIN(x, y)
Definition def.h:231
#define SCIP_ALLOC(x)
Definition def.h:373
#define SCIP_Real
Definition def.h:163
#define SCIP_UNKNOWN
Definition def.h:186
#define ABS(x)
Definition def.h:223
#define SQR(x)
Definition def.h:206
#define EPSEQ(x, y, eps)
Definition def.h:190
#define TRUE
Definition def.h:100
#define FALSE
Definition def.h:101
#define MAX(x, y)
Definition def.h:227
#define SCIP_CALL_ABORT(x)
Definition def.h:341
#define SCIPABORT()
Definition def.h:334
#define SCIP_REAL_MIN
Definition def.h:166
#define REALABS(x)
Definition def.h:189
#define EPSZ(x, eps)
Definition def.h:195
#define SCIP_CALL(x)
Definition def.h:362
SCIP_RETCODE SCIPeventCreateLbChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition event.c:752
SCIP_RETCODE SCIPeventCreateVarFixed(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition event.c:634
SCIP_RETCODE SCIPeventCreateUbChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition event.c:780
SCIP_RETCODE SCIPeventCreateVarUnlocked(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition event.c:656
SCIP_RETCODE SCIPeventAddExactObjChg(SCIP_EVENT *event, BMS_BLKMEM *blkmem, SCIP_RATIONAL *oldobj, SCIP_RATIONAL *newobj)
Definition event.c:827
SCIP_RETCODE SCIPeventCreateObjChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldobj, SCIP_Real newobj)
Definition event.c:677
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:2561
SCIP_RETCODE SCIPeventfilterFree(SCIP_EVENTFILTER **eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition event.c:2167
SCIP_Bool SCIPeventqueueIsDelayed(SCIP_EVENTQUEUE *eventqueue)
Definition event.c:2933
SCIP_RETCODE SCIPeventAddExactBdChg(SCIP_EVENT *event, BMS_BLKMEM *blkmem, SCIP_RATIONAL *oldbound, SCIP_RATIONAL *newbound)
Definition event.c:808
SCIP_RETCODE SCIPeventCreateGholeAdded(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real left, SCIP_Real right)
Definition event.c:845
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:2300
SCIP_RETCODE SCIPeventfilterCreate(SCIP_EVENTFILTER **eventfilter, BMS_BLKMEM *blkmem)
Definition event.c:2142
SCIP_RETCODE SCIPeventProcess(SCIP_EVENT *event, SCIP_SET *set, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter)
Definition event.c:1804
SCIP_RETCODE SCIPeventCreateImplAdded(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition event.c:933
SCIP_RETCODE SCIPeventChgType(SCIP_EVENT *event, SCIP_EVENTTYPE eventtype)
Definition event.c:1204
SCIP_RETCODE SCIPeventCreateImplTypeChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_IMPLINTTYPE oldtype, SCIP_IMPLINTTYPE newtype)
Definition event.c:975
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:2207
SCIP_RETCODE SCIPeventCreateGubChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition event.c:727
SCIP_RETCODE SCIPeventCreateGlbChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition event.c:702
SCIP_RETCODE SCIPeventCreateTypeChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_VARTYPE oldtype, SCIP_VARTYPE newtype)
Definition event.c:952
internal methods for managing events
const char * SCIPgetProbName(SCIP *scip)
Definition scip_prob.c:1242
int SCIPgetNTotalVars(SCIP *scip)
Definition scip_prob.c:3064
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition misc.c:3143
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition misc.c:3466
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition misc.c:9197
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition misc.c:9449
SCIP_Bool SCIPrealToRational(SCIP_Real val, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Longint *numerator, SCIP_Longint *denominator)
Definition misc.c:9470
SCIP_Bool SCIPisCertified(SCIP *scip)
SCIP_Bool SCIPshouldCertificateTrackBounds(SCIP *scip)
SCIP_Real SCIPcolGetObj(SCIP_COL *col)
Definition lp.c:17336
SCIP_Real SCIPcolGetLb(SCIP_COL *col)
Definition lp.c:17346
SCIP_Real SCIPcolGetPrimsol(SCIP_COL *col)
Definition lp.c:17379
SCIP_Real SCIPcolGetUb(SCIP_COL *col)
Definition lp.c:17356
SCIP_Bool SCIPcolIsInLP(SCIP_COL *col)
Definition lp.c:17509
SCIP_BASESTAT SCIPcolGetBasisStatus(SCIP_COL *col)
Definition lp.c:17414
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition cons.c:8393
void SCIPintervalSet(SCIP_INTERVAL *resultant, SCIP_Real value)
struct SCIP_Interval SCIP_INTERVAL
void SCIPintervalMulScalar(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_Real operand2)
void SCIPintervalAddScalar(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_Real operand2)
void SCIPintervalSetRational(SCIP_INTERVAL *resultant, SCIP_RATIONAL *value)
SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
Definition tree.c:8513
SCIP_NODE * SCIPnodeGetParent(SCIP_NODE *node)
Definition tree.c:8812
SCIP_Bool SCIPinProbing(SCIP *scip)
const char * SCIPpropGetName(SCIP_PROP *prop)
Definition prop.c:951
SCIP_Bool SCIPrationalIsLTReal(SCIP_RATIONAL *rat, SCIP_Real real)
SCIP_Bool SCIPrationalIsFpRepresentable(SCIP_RATIONAL *rational)
void SCIPrationalMin(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
SCIP_Bool SCIPrationalRoundLong(SCIP_Longint *res, SCIP_RATIONAL *src, SCIP_ROUNDMODE_RAT roundmode)
SCIP_RETCODE SCIPrationalCreateBlock(BMS_BLKMEM *blkmem, SCIP_RATIONAL **rational)
Definition rational.cpp:109
SCIP_RETCODE SCIPrationalCreate(SCIP_RATIONAL **rational)
Definition rational.cpp:95
void SCIPrationalMult(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
void SCIPrationalInvert(SCIP_RATIONAL *res, SCIP_RATIONAL *op)
void SCIPrationalSetInfinity(SCIP_RATIONAL *res)
Definition rational.cpp:619
void SCIPrationalAdd(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
Definition rational.cpp:936
SCIP_Real SCIPrationalGetReal(SCIP_RATIONAL *rational)
SCIP_Bool SCIPrationalIsString(const char *desc)
Definition rational.cpp:653
void SCIPrationalFreeBlock(BMS_BLKMEM *mem, SCIP_RATIONAL **rational)
Definition rational.cpp:462
#define SCIPrationalDebugMessage
Definition rational.h:641
void SCIPrationalRoundInteger(SCIP_RATIONAL *res, SCIP_RATIONAL *src, SCIP_ROUNDMODE_RAT roundmode)
void SCIPrationalDiv(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
SCIP_Bool SCIPrationalIsAbsInfinity(SCIP_RATIONAL *rational)
SCIP_Bool SCIPrationalIsLT(SCIP_RATIONAL *rat1, SCIP_RATIONAL *rat2)
void SCIPrationalSetReal(SCIP_RATIONAL *res, SCIP_Real real)
Definition rational.cpp:604
SCIP_Bool SCIPrationalIsGT(SCIP_RATIONAL *rat1, SCIP_RATIONAL *rat2)
SCIP_RETCODE SCIPrationalCopyBlock(BMS_BLKMEM *mem, SCIP_RATIONAL **result, SCIP_RATIONAL *src)
Definition rational.cpp:152
void SCIPrationalFreeBuffer(BMS_BUFMEM *bufmem, SCIP_RATIONAL **rational)
Definition rational.cpp:474
SCIP_RETCODE SCIPrationalCopyBlockArray(BMS_BLKMEM *mem, SCIP_RATIONAL ***target, SCIP_RATIONAL **src, int len)
Definition rational.cpp:250
void SCIPrationalDiff(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
Definition rational.cpp:984
SCIP_RETCODE SCIPrationalCopyBufferArray(BMS_BUFMEM *mem, SCIP_RATIONAL ***result, SCIP_RATIONAL **src, int len)
Definition rational.cpp:268
SCIP_Bool SCIPrationalIsPositive(SCIP_RATIONAL *rational)
SCIP_Longint SCIPrationalDenominator(SCIP_RATIONAL *rational)
int SCIPrationalGetSign(const SCIP_RATIONAL *rational)
SCIP_RETCODE SCIPrationalCreateBuffer(BMS_BUFMEM *bufmem, SCIP_RATIONAL **rational)
Definition rational.cpp:124
void SCIPrationalAddProd(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
SCIP_Bool SCIPrationalIsZero(SCIP_RATIONAL *rational)
void SCIPrationalSetRational(SCIP_RATIONAL *res, SCIP_RATIONAL *src)
Definition rational.cpp:570
void SCIPrationalSetString(SCIP_RATIONAL *res, const char *desc)
Definition rational.cpp:717
SCIP_Bool SCIPrationalIsIntegral(SCIP_RATIONAL *rational)
void SCIPrationalMax(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
SCIP_Bool SCIPrationalIsGE(SCIP_RATIONAL *rat1, SCIP_RATIONAL *rat2)
void SCIPrationalCanonicalize(SCIP_RATIONAL *rational)
Definition rational.cpp:539
void SCIPrationalMessage(SCIP_MESSAGEHDLR *msg, FILE *file, SCIP_RATIONAL *rational)
void SCIPrationalSetNegInfinity(SCIP_RATIONAL *res)
Definition rational.cpp:631
void SCIPrationalSetFraction(SCIP_RATIONAL *res, SCIP_Longint nom, SCIP_Longint denom)
Definition rational.cpp:583
void SCIPrationalNegate(SCIP_RATIONAL *res, SCIP_RATIONAL *op)
SCIP_Bool SCIPrationalIsNegative(SCIP_RATIONAL *rational)
void SCIPrationalDiffReal(SCIP_RATIONAL *res, SCIP_RATIONAL *rat, SCIP_Real real)
SCIP_Bool SCIPrationalIsInfinity(SCIP_RATIONAL *rational)
void SCIPrationalFreeBlockArray(BMS_BLKMEM *mem, SCIP_RATIONAL ***ratblockarray, int size)
Definition rational.cpp:502
SCIP_Real SCIPrationalRoundReal(SCIP_RATIONAL *rational, SCIP_ROUNDMODE_RAT roundmode)
SCIP_Longint SCIPrationalNumerator(SCIP_RATIONAL *rational)
SCIP_Bool SCIPrationalIsEQReal(SCIP_RATIONAL *rat, SCIP_Real real)
SCIP_RETCODE SCIPrationalCreateBufferArray(BMS_BUFMEM *mem, SCIP_RATIONAL ***rational, int size)
Definition rational.cpp:215
SCIP_Bool SCIPrationalIsNegInfinity(SCIP_RATIONAL *rational)
void SCIPrationalFree(SCIP_RATIONAL **rational)
Definition rational.cpp:451
void SCIPrationalDiffProdReal(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_Real op2)
SCIP_Bool SCIPrationalIsGTReal(SCIP_RATIONAL *rat, SCIP_Real real)
SCIP_RETCODE SCIPrationalReallocBlockArray(BMS_BLKMEM *mem, SCIP_RATIONAL ***result, int oldlen, int newlen)
Definition rational.cpp:345
SCIP_Bool SCIPrationalIsEQ(SCIP_RATIONAL *rat1, SCIP_RATIONAL *rat2)
void SCIPrationalDiffProd(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
SCIP_RETCODE SCIPrationalReallocBufferArray(BMS_BUFMEM *mem, SCIP_RATIONAL ***result, int oldlen, int newlen)
Definition rational.cpp:315
void SCIPrationalMultReal(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_Real op2)
void SCIPrationalFreeBufferArray(BMS_BUFMEM *mem, SCIP_RATIONAL ***ratbufarray, int size)
Definition rational.cpp:519
SCIP_Bool SCIPrationalIsLE(SCIP_RATIONAL *rat1, SCIP_RATIONAL *rat2)
void SCIPrationalAddProdReal(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_Real op2)
SCIP_Longint SCIPgetNLPIterations(SCIP *scip)
SCIP_NODE * SCIPgetFocusNode(SCIP *scip)
Definition scip_tree.c:72
int SCIPgetDepth(SCIP *scip)
Definition scip_tree.c:672
SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition var.c:23515
SCIP_Real SCIPvarGetLPSol_rec(SCIP_VAR *var)
Definition var.c:18706
int SCIPvarCompareActiveAndNegated(SCIP_VAR *var1, SCIP_VAR *var2)
Definition var.c:17237
SCIP_Longint SCIPvarGetUbCertificateIndexLocal(SCIP_VAR *var)
Definition var.c:25189
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition var.c:18321
void SCIPvarSetLbCertificateIndexGlobal(SCIP_VAR *var, SCIP_Longint certidx)
Definition var.c:25163
SCIP_HOLELIST * SCIPvarGetHolelistLocal(SCIP_VAR *var)
Definition var.c:24303
int SCIPvarGetNVlbs(SCIP_VAR *var)
Definition var.c:24483
SCIP_RETCODE SCIPvarGetProbvarBound(SCIP_VAR **var, SCIP_Real *bound, SCIP_BOUNDTYPE *boundtype)
Definition var.c:17802
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition var.c:23535
SCIP_Real SCIPvarGetNegationConstant(SCIP_VAR *var)
Definition var.c:23890
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition var.c:23684
SCIP_Bool SCIPbdchginfoIsRedundant(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:25058
SCIP_Real SCIPvarGetAvgBranchdepthCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:21885
SCIP_Bool SCIPvarMayRoundUp(SCIP_VAR *var)
Definition var.c:4484
SCIP_Real SCIPvarGetMultaggrConstant(SCIP_VAR *var)
Definition var.c:23844
SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
Definition var.c:24373
void SCIPvarSetTransData(SCIP_VAR *var,)
Definition var.c:23321
void SCIPvarsGetProbvar(SCIP_VAR **vars, int nvars)
Definition var.c:17531
SCIP_BOUNDTYPE SCIPvarGetWorstBoundTypeExact(SCIP_VAR *var)
Definition var.c:24414
SCIP_Real SCIPvarGetSol(SCIP_VAR *var, SCIP_Bool getlpval)
Definition var.c:19008
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition var.c:23869
SCIP_Real * SCIPvarGetVlbCoefs(SCIP_VAR *var)
Definition var.c:24505
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition var.c:23643
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition var.c:23479
SCIP_Longint SCIPvarGetUbCertificateIndexGlobal(SCIP_VAR *var)
Definition var.c:25213
SCIP_BOUNDTYPE SCIPboundchgGetBoundtype(SCIP_BOUNDCHG *boundchg)
Definition var.c:23195
SCIP_Real SCIPholelistGetRight(SCIP_HOLELIST *holelist)
Definition var.c:23245
void SCIPvarSetDelorigData(SCIP_VAR *var,)
Definition var.c:23309
SCIP_Real SCIPvarGetAvgBranchdepth(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:21840
SCIP_Real SCIPvarGetBestBoundGlobal(SCIP_VAR *var)
Definition var.c:24175
SCIP_Bool SCIPbdchgidxIsEarlier(SCIP_BDCHGIDX *bdchgidx1, SCIP_BDCHGIDX *bdchgidx2)
Definition var.c:24890
SCIP_RATIONAL * SCIPvarGetBestBoundGlobalExact(SCIP_VAR *var)
Definition var.c:24188
SCIP_Bool SCIPvarWasFixedEarlier(SCIP_VAR *var1, SCIP_VAR *var2)
Definition var.c:22890
SCIP_BDCHGIDX * SCIPbdchginfoGetIdx(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:24980
SCIP_VAR * SCIPboundchgGetVar(SCIP_BOUNDCHG *boundchg)
Definition var.c:23175
void SCIPvarSetCertificateIndex(SCIP_VAR *var, int certidx)
Definition var.c:25110
SCIP_RATIONAL * SCIPvarGetAggrScalarExact(SCIP_VAR *var)
Definition var.c:23761
SCIP_Bool SCIPvarHasImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition var.c:16442
SCIP_BOUNDCHG * SCIPdomchgGetBoundchg(SCIP_DOMCHG *domchg, int pos)
Definition var.c:23223
int SCIPvarGetNImpls(SCIP_VAR *var, SCIP_Bool varfixing)
Definition var.c:24569
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition var.c:23387
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition var.c:4386
SCIP_BOUNDCHGTYPE SCIPboundchgGetBoundchgtype(SCIP_BOUNDCHG *boundchg)
Definition var.c:23185
SCIP_Real SCIPvarGetInferenceSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:22032
SCIP_Real SCIPvarGetAggrConstant(SCIP_VAR *var)
Definition var.c:23772
SCIP_Bool SCIPvarIsImpliedIntegral(SCIP_VAR *var)
Definition var.c:23499
SCIP_RETCODE SCIPvarGetAggregatedObj(SCIP_VAR *var, SCIP_Real *aggrobj)
Definition var.c:23945
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition var.c:24269
int SCIPvarGetNLocksDown(SCIP_VAR *var)
Definition var.c:4449
SCIP_Real SCIPvarGetBestRootSol(SCIP_VAR *var)
Definition var.c:19481
SCIP_HOLELIST * SCIPholelistGetNext(SCIP_HOLELIST *holelist)
Definition var.c:23255
SCIP_Real SCIPvarGetLbOriginal(SCIP_VAR *var)
Definition var.c:24021
SCIP_BDCHGINFO * SCIPvarGetLbchgInfo(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition var.c:22630
SCIP_RATIONAL * SCIPvarGetAggrConstantExact(SCIP_VAR *var)
Definition var.c:23784
SCIP_RATIONAL * SCIPvarGetPseudoSolExact(SCIP_VAR *var)
Definition var.c:24770
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition var.c:23431
void SCIPvarMarkDeletable(SCIP_VAR *var)
Definition var.c:23547
void SCIPvarGetImplicVarBounds(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_Real *lb, SCIP_Real *ub)
Definition var.c:16477
SCIP_PROP * SCIPbdchginfoGetInferProp(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:25014
int SCIPvarGetCertificateIndex(SCIP_VAR *var)
Definition var.c:25099
SCIP_Bool SCIPvarIsNonimpliedIntegral(SCIP_VAR *var)
Definition var.c:23507
SCIP_Real SCIPboundchgGetNewbound(SCIP_BOUNDCHG *boundchg)
Definition var.c:23155
SCIP_Bool SCIPvarMayRoundDown(SCIP_VAR *var)
Definition var.c:4473
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition var.c:23901
SCIP_Real SCIPvarGetAggrScalar(SCIP_VAR *var)
Definition var.c:23749
SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
Definition var.c:17551
void SCIPvarMarkRelaxationOnly(SCIP_VAR *var)
Definition var.c:23619
SCIP_RETCODE SCIPvarGetOrigvarSumExact(SCIP_VAR **var, SCIP_RATIONAL *scalar, SCIP_RATIONAL *constant)
Definition var.c:18410
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition var.c:23454
SCIP_BOUNDTYPE SCIPvarGetBestBoundTypeExact(SCIP_VAR *var)
Definition var.c:24386
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition var.c:24143
SCIP_RETCODE SCIPvarSetInitial(SCIP_VAR *var, SCIP_Bool initial)
Definition var.c:23355
SCIP_VAR ** SCIPvarGetImplVars(SCIP_VAR *var, SCIP_Bool varfixing)
Definition var.c:24586
void SCIPvarSetBestRootSol(SCIP_VAR *var, SCIP_Real rootsol, SCIP_Real rootredcost, SCIP_Real rootlpobjval)
Definition var.c:19613
SCIP_VARSTATUS SCIPvarGetStatusExact(SCIP_VAR *var)
Definition var.c:23397
SCIP_RATIONAL * SCIPvarGetWorstBoundLocalExact(SCIP_VAR *var)
Definition var.c:24356
int SCIPbdchginfoGetDepth(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:24960
int SCIPbdchginfoGetInferInfo(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:25025
int SCIPvarGetIndex(SCIP_VAR *var)
Definition var.c:23653
SCIP_INTERVAL SCIPvarGetObjInterval(SCIP_VAR *var)
Definition var.c:23922
SCIP_CONS * SCIPbdchginfoGetInferCons(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:25002
SCIP_Real SCIPvarGetNLPSol_rec(SCIP_VAR *var)
Definition var.c:18860
SCIP_BDCHGIDX * SCIPvarGetLastBdchgIndex(SCIP_VAR *var)
Definition var.c:22765
SCIP_COLEXACT * SCIPvarGetColExact(SCIP_VAR *var)
Definition var.c:23695
void SCIPvarGetLPSolExact_rec(SCIP_VAR *var, SCIP_RATIONAL *res)
Definition var.c:18785
int SCIPbdchginfoGetPos(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:24970
SCIP_Real SCIPvarGetWorstBoundLocal(SCIP_VAR *var)
Definition var.c:24343
int SCIPvarGetNUses(SCIP_VAR *var)
Definition var.c:23278
SCIP_RATIONAL * SCIPvarGetLbOriginalExact(SCIP_VAR *var)
Definition var.c:24041
SCIP_RATIONAL * SCIPvarGetUbOriginalExact(SCIP_VAR *var)
Definition var.c:24084
int SCIPdomchgGetNBoundchgs(SCIP_DOMCHG *domchg)
Definition var.c:23215
SCIP_Longint SCIPvarGetLbCertificateIndexGlobal(SCIP_VAR *var)
Definition var.c:25201
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition var.c:23663
const char * SCIPvarGetName(SCIP_VAR *var)
Definition var.c:23268
SCIP_Bool SCIPvarIsExact(SCIP_VAR *var)
Definition var.c:23408
SCIP_RETCODE SCIPvarGetProbvarBoundExact(SCIP_VAR **var, SCIP_RATIONAL *bound, SCIP_BOUNDTYPE *boundtype)
Definition var.c:17895
SCIP_Real SCIPvarGetUbOriginal(SCIP_VAR *var)
Definition var.c:24064
SCIP_Real SCIPvarGetWorstBoundGlobal(SCIP_VAR *var)
Definition var.c:24205
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:24930
SCIP_Bool SCIPvarHasBinaryImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_Bool implvarfixing)
Definition var.c:16462
void SCIPvarMarkDeleteGlobalStructures(SCIP_VAR *var)
Definition var.c:23571
SCIP_Real * SCIPvarGetVlbConstants(SCIP_VAR *var)
Definition var.c:24515
SCIP_Real SCIPvarGetRootSol(SCIP_VAR *var)
Definition var.c:19116
SCIP_RATIONAL * SCIPvarGetMultaggrConstantExact(SCIP_VAR *var)
Definition var.c:23856
int * SCIPvarGetImplIds(SCIP_VAR *var, SCIP_Bool varfixing)
Definition var.c:24631
SCIP_Real SCIPvarGetBestBoundLocal(SCIP_VAR *var)
Definition var.c:24313
int SCIPvarGetNVubs(SCIP_VAR *var)
Definition var.c:24525
SCIP_RATIONAL * SCIPvarGetUbLocalExact(SCIP_VAR *var)
Definition var.c:24279
SCIP_Real SCIPvarGetBranchFactor(SCIP_VAR *var)
Definition var.c:24451
void SCIPvarSetUbCertificateIndexGlobal(SCIP_VAR *var, SCIP_Longint certidx)
Definition var.c:25123
SCIP_Real SCIPvarGetAvgSol(SCIP_VAR *var)
Definition var.c:19828
SCIP_Bool SCIPvarIsDeletable(SCIP_VAR *var)
Definition var.c:23633
SCIP_Real SCIPbdchginfoGetOldbound(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:24910
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition var.c:23491
SCIP_Bool SCIPvarIsTransformedOrigvar(SCIP_VAR *var)
Definition var.c:18498
SCIP_Real SCIPvarGetUbLazy(SCIP_VAR *var)
Definition var.c:24439
SCIP_Real SCIPvarGetPseudoSol(SCIP_VAR *var)
Definition var.c:24757
SCIP_BRANCHDIR SCIPvarGetBranchDirection(SCIP_VAR *var)
Definition var.c:24473
SCIP_BOUNDTYPE SCIPbdchginfoGetInferBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:25037
void SCIPvarSetData(SCIP_VAR *var, SCIP_VARDATA *vardata)
Definition var.c:23298
SCIP_Real * SCIPvarGetImplBounds(SCIP_VAR *var, SCIP_Bool varfixing)
Definition var.c:24615
void SCIPvarSetDeltransData(SCIP_VAR *var,)
Definition var.c:23333
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition var.c:24665
SCIP_BDCHGINFO * SCIPvarGetBdchgInfo(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition var.c:22742
void SCIPvarGetSolExact(SCIP_VAR *var, SCIP_RATIONAL *res, SCIP_Bool getlpval)
Definition var.c:19020
SCIP_VARDATA * SCIPvarGetData(SCIP_VAR *var)
Definition var.c:23288
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition var.c:23807
SCIP_Bool SCIPbdchginfoIsTighter(SCIP_BDCHGINFO *bdchginfo1, SCIP_BDCHGINFO *bdchginfo2)
Definition var.c:25083
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition var.c:23795
SCIP_RETCODE SCIPvarSetRemovable(SCIP_VAR *var, SCIP_Bool removable)
Definition var.c:23371
SCIP_Longint SCIPvarGetLbCertificateIndexLocal(SCIP_VAR *var)
Definition var.c:25177
SCIP_HOLELIST * SCIPvarGetHolelistOriginal(SCIP_VAR *var)
Definition var.c:24107
SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
Definition var.c:23525
int SCIPvarGetNCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition var.c:24643
SCIP_BOUNDCHGTYPE SCIPbdchginfoGetChgtype(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:24940
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition var.c:24235
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition var.c:23444
SCIP_VAR * SCIPbdchginfoGetInferVar(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:24990
SCIP_RATIONAL * SCIPvarGetBestBoundLocalExact(SCIP_VAR *var)
Definition var.c:24326
SCIP_Bool SCIPbdchginfoHasInferenceReason(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:25069
SCIP_RATIONAL * SCIPvarGetLbGlobalExact(SCIP_VAR *var)
Definition var.c:24131
SCIP_Bool SCIPboundchgIsRedundant(SCIP_BOUNDCHG *boundchg)
Definition var.c:23205
SCIP_Longint SCIPvarGetNBranchings(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:21752
SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
Definition var.c:23601
SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition var.c:23879
SCIP_RETCODE SCIPvarGetProbvarHole(SCIP_VAR **var, SCIP_Real *left, SCIP_Real *right)
Definition var.c:17991
SCIP_VAR ** SCIPvarGetVlbVars(SCIP_VAR *var)
Definition var.c:24495
SCIP_BDCHGINFO * SCIPvarGetUbchgInfo(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition var.c:22686
SCIP_Real SCIPholelistGetLeft(SCIP_HOLELIST *holelist)
Definition var.c:23235
SCIP_RATIONAL ** SCIPvarGetMultaggrScalarsExact(SCIP_VAR *var)
Definition var.c:23831
SCIP_Real SCIPvarGetMaxAggrCoef(SCIP_VAR *var)
Definition var.c:23727
int SCIPvarGetBranchPriority(SCIP_VAR *var)
Definition var.c:24463
SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
Definition var.c:23418
SCIP_CLIQUE ** SCIPvarGetCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition var.c:24654
SCIP_Real SCIPvarGetMinAggrCoef(SCIP_VAR *var)
Definition var.c:23717
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition var.c:24121
void SCIPvarMarkNotDeletable(SCIP_VAR *var)
Definition var.c:23558
SCIP_Real SCIPvarGetBestRootRedcost(SCIP_VAR *var)
Definition var.c:19548
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoLb(SCIP_VAR *var, int pos)
Definition var.c:24705
SCIP_RATIONAL * SCIPvarGetLbLocalExact(SCIP_VAR *var)
Definition var.c:24245
SCIP_IMPLINTTYPE SCIPvarGetImplType(SCIP_VAR *var)
Definition var.c:23464
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition var.c:17275
void SCIPvarsCountTypes(SCIP_VAR **vars, int nvars, int *nbinvars, int *nintvars, int *nbinimplvars, int *nintimplvars, int *ncontimplvars, int *ncontvars)
Definition var.c:22943
SCIP_Real SCIPvarGetCutoffSumCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:22275
SCIP_Real SCIPvarGetBestRootLPObjval(SCIP_VAR *var)
Definition var.c:19582
SCIP_RETCODE SCIPvarGetProbvarBinary(SCIP_VAR **var, SCIP_Bool *negated)
Definition var.c:17643
SCIP_Longint SCIPvarGetNBranchingsCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:21797
SCIP_Real * SCIPvarGetVubConstants(SCIP_VAR *var)
Definition var.c:24557
int SCIPvarGetNLocksUp(SCIP_VAR *var)
Definition var.c:4462
SCIP_VAR * SCIPvarGetTransVar(SCIP_VAR *var)
Definition var.c:23673
SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
Definition var.c:24692
SCIP_VAR ** SCIPvarGetVubVars(SCIP_VAR *var)
Definition var.c:24537
int SCIPvarGetNBdchgInfosUb(SCIP_VAR *var)
Definition var.c:24737
SCIP_BOUNDTYPE SCIPbdchginfoGetBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:24950
SCIP_VALUEHISTORY * SCIPvarGetValuehistory(SCIP_VAR *var)
Definition var.c:24747
SCIP_BOUNDTYPE SCIPvarGetWorstBoundType(SCIP_VAR *var)
Definition var.c:24401
void SCIPvarSetCopyData(SCIP_VAR *var,)
Definition var.c:23344
SCIP_Real SCIPvarGetInferenceSumCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:22077
SCIP_Bool SCIPvarsHaveCommonClique(SCIP_VAR *var1, SCIP_Bool value1, SCIP_VAR *var2, SCIP_Bool value2, SCIP_Bool regardimplics)
Definition var.c:16808
SCIP_Bool SCIPbdchgidxIsEarlierNonNull(SCIP_BDCHGIDX *bdchgidx1, SCIP_BDCHGIDX *bdchgidx2)
Definition var.c:24870
SCIP_Real * SCIPvarGetVubCoefs(SCIP_VAR *var)
Definition var.c:24547
SCIP_HOLELIST * SCIPvarGetHolelistGlobal(SCIP_VAR *var)
Definition var.c:24165
void SCIPvarGetLPSolExact(SCIP_VAR *var, SCIP_RATIONAL *res)
Definition var.c:24678
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:24920
SCIP_RATIONAL * SCIPvarGetWorstBoundGlobalExact(SCIP_VAR *var)
Definition var.c:24218
SCIP_Real SCIPboundchgGetLPSolVal(SCIP_BOUNDCHG *boundchg)
Definition var.c:23165
int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition var.c:4328
SCIP_RATIONAL * SCIPvarGetObjExact(SCIP_VAR *var)
Definition var.c:23911
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoUb(SCIP_VAR *var, int pos)
Definition var.c:24725
int SCIPvarGetNBdchgInfosLb(SCIP_VAR *var)
Definition var.c:24717
SCIP_BOUNDTYPE * SCIPvarGetImplTypes(SCIP_VAR *var, SCIP_Bool varfixing)
Definition var.c:24601
int SCIPvarGetLastBdchgDepth(SCIP_VAR *var)
Definition var.c:22802
SCIP_RETCODE SCIPvarsGetProbvarBinary(SCIP_VAR ***vars, SCIP_Bool **negatedarr, int nvars)
Definition var.c:17611
SCIP_RATIONAL * SCIPvarGetUbGlobalExact(SCIP_VAR *var)
Definition var.c:24153
SCIP_Real SCIPvarGetUnchangedObj(SCIP_VAR *var)
Definition var.c:23933
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition var.c:23819
SCIP_Real SCIPvarGetCutoffSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:22232
SCIP_Real SCIPvarGetLbLazy(SCIP_VAR *var)
Definition var.c:24429
SCIP_Bool SCIPvarIsInLP(SCIP_VAR *var)
Definition var.c:23707
SCIP_VAR * SCIPvarGetAggrVar(SCIP_VAR *var)
Definition var.c:23737
SCIP_Real SCIPnormalCDF(SCIP_Real mean, SCIP_Real variance, SCIP_Real value)
Definition misc.c:200
SCIP_Real SCIPcomputeTwoSampleTTestValue(SCIP_Real meanx, SCIP_Real meany, SCIP_Real variancex, SCIP_Real variancey, SCIP_Real countx, SCIP_Real county)
Definition misc.c:127
SCIP_Real SCIPstudentTGetCriticalValue(SCIP_CONFIDENCELEVEL clevel, int df)
Definition misc.c:110
SCIP_Bool SCIPsortedvecFindPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), void *val, int len, int *pos)
void SCIPsortPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
void SCIPsortPtrPtr(void **ptrarray1, void **ptrarray2, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition misc.c:10827
SCIP_Bool SCIPstrToRealValue(const char *str, SCIP_Real *value, char **endptr)
Definition misc.c:10955
void SCIPstrCopySection(const char *str, char startchar, char endchar, char *token, int size, char **endptr)
Definition misc.c:10985
SCIP_RETCODE SCIPskipSpace(char **s)
Definition misc.c:10816
SCIP_RETCODE SCIPvaluehistoryCreate(SCIP_VALUEHISTORY **valuehistory, BMS_BLKMEM *blkmem)
Definition history.c:323
SCIP_RETCODE SCIPvaluehistoryFind(SCIP_VALUEHISTORY *valuehistory, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real value, SCIP_HISTORY **history)
Definition history.c:364
void SCIPvaluehistoryFree(SCIP_VALUEHISTORY **valuehistory, BMS_BLKMEM *blkmem)
Definition history.c:342
void SCIPvaluehistoryScaleVSIDS(SCIP_VALUEHISTORY *valuehistory, SCIP_Real scalar)
Definition history.c:409
return SCIP_OKAY
int c
int depth
SCIP_Bool cutoff
static SCIP_SOL * sol
SCIP_Real obj
assert(minobj< SCIPgetCutoffbound(scip))
int nvars
SCIP_VAR * var
SCIP_Real primsol
SCIP_Real frac
SCIP_Real newobj
SCIP_Real oldobj
static SCIP_VAR ** vars
SCIP_Real * rootsol
void SCIPhistoryReset(SCIP_HISTORY *history)
Definition history.c:78
SCIP_Real SCIPhistoryGetPseudocost(SCIP_HISTORY *history, SCIP_Real solvaldelta)
Definition history.c:529
SCIP_Real SCIPhistoryGetAvgInferences(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:790
SCIP_Longint SCIPhistoryGetNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:690
SCIP_Longint SCIPhistoryGetNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:764
SCIP_Real SCIPhistoryGetAvgConflictlength(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:703
SCIP_Real SCIPhistoryGetAvgCutoffs(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:816
SCIP_RETCODE SCIPhistoryCreate(SCIP_HISTORY **history, BMS_BLKMEM *blkmem)
Definition history.c:51
SCIP_Real SCIPhistoryGetAncPseudocostCount(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:596
void SCIPhistorySetLastGMIeff(SCIP_HISTORY *history, SCIP_Real gmieff)
Definition history.c:907
void SCIPhistoryUpdateAncPseudocost(SCIP_HISTORY *history, SCIP_SET *set, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition history.c:255
void SCIPhistoryIncInferenceSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition history.c:732
SCIP_Real SCIPhistoryGetAncPseudocost(SCIP_HISTORY *history, SCIP_Real solvaldelta)
Definition history.c:543
SCIP_Real SCIPhistoryGetCutoffSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:803
SCIP_Real SCIPhistoryGetPseudocostCount(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:581
SCIP_Real SCIPhistoryGetPseudocostVariance(SCIP_HISTORY *history, SCIP_BRANCHDIR direction)
Definition history.c:557
void SCIPhistoryIncNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real length)
Definition history.c:674
void SCIPhistoryScaleVSIDS(SCIP_HISTORY *history, SCIP_Real scalar)
Definition history.c:649
void SCIPhistoryIncCutoffSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition history.c:748
void SCIPhistoryIncNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, int depth)
Definition history.c:716
void SCIPhistoryUpdatePseudocost(SCIP_HISTORY *history, SCIP_SET *set, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition history.c:191
SCIP_Real SCIPhistoryGetVSIDS(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:661
SCIP_Real SCIPhistoryGetAvgBranchdepth(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:829
SCIP_Real SCIPhistoryGetLastGMIeff(SCIP_HISTORY *history)
Definition history.c:897
SCIP_Real SCIPhistoryGetAvgGMIeff(SCIP_HISTORY *history)
Definition history.c:874
SCIP_Real SCIPhistoryGetInferenceSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:777
void SCIPhistoryFree(SCIP_HISTORY **history, BMS_BLKMEM *blkmem)
Definition history.c:66
void SCIPhistoryUnite(SCIP_HISTORY *history, SCIP_HISTORY *addhistory, SCIP_Bool switcheddirs)
Definition history.c:117
void SCIPhistoryIncGMIeffSum(SCIP_HISTORY *history, SCIP_Real gmieff)
Definition history.c:884
SCIP_BRANCHDIR SCIPbranchdirOpposite(SCIP_BRANCHDIR dir)
Definition history.c:520
void SCIPhistoryIncVSIDS(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition history.c:635
internal methods for branching and inference history
SCIP_VAR ** SCIPimplicsGetVars(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition implics.c:3335
void SCIPcliqueDelVar(SCIP_CLIQUE *clique, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Bool value)
Definition implics.c:1285
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_EVENTFILTER *eventfilter, SCIP_VAR **vars, SCIP_Bool *values, int nvars, SCIP_Bool isequation, SCIP_Bool *infeasible, int *nbdchgs)
Definition implics.c:2377
void SCIPcliquelistRemoveFromCliques(SCIP_CLIQUELIST *cliquelist, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Bool irrelevantvar)
Definition implics.c:1683
void SCIPvboundsFree(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem)
Definition implics.c:73
SCIP_Real * SCIPvboundsGetCoefs(SCIP_VBOUNDS *vbounds)
Definition implics.c:3310
void SCIPvboundsShrink(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem, int newnvbds)
Definition implics.c:333
SCIP_VAR ** SCIPcliqueGetVars(SCIP_CLIQUE *clique)
Definition implics.c:3384
SCIP_CLIQUE ** SCIPcliquelistGetCliques(SCIP_CLIQUELIST *cliquelist, SCIP_Bool value)
Definition implics.c:3459
SCIP_Bool SCIPcliquelistsHaveCommonClique(SCIP_CLIQUELIST *cliquelist1, SCIP_Bool value1, SCIP_CLIQUELIST *cliquelist2, SCIP_Bool value2)
Definition implics.c:1605
SCIP_Real * SCIPimplicsGetBounds(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition implics.c:3353
void SCIPcliquelistCheck(SCIP_CLIQUELIST *cliquelist, SCIP_VAR *var)
Definition implics.c:3468
SCIP_VAR ** SCIPvboundsGetVars(SCIP_VBOUNDS *vbounds)
Definition implics.c:3302
int SCIPcliqueGetNVars(SCIP_CLIQUE *clique)
Definition implics.c:3374
SCIP_Bool * SCIPcliqueGetValues(SCIP_CLIQUE *clique)
Definition implics.c:3396
SCIP_RETCODE SCIPvboundsDel(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem, SCIP_VAR *vbdvar, SCIP_Bool negativecoef)
Definition implics.c:288
int * SCIPimplicsGetIds(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition implics.c:3365
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 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
void SCIPcliquelistFree(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem)
Definition implics.c:1441
int SCIPimplicsGetNImpls(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition implics.c:3326
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_BOUNDTYPE * SCIPimplicsGetTypes(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition implics.c:3344
int SCIPcliquelistGetNCliques(SCIP_CLIQUELIST *cliquelist, SCIP_Bool value)
Definition implics.c:3450
SCIP_RETCODE SCIPcliquelistDel(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition implics.c:1527
SCIP_Bool SCIPcliqueIsCleanedUp(SCIP_CLIQUE *clique)
Definition implics.c:3430
void SCIPimplicsGetVarImplicPoss(SCIP_IMPLICS *implics, SCIP_Bool varfixing, SCIP_VAR *implvar, int *lowerimplicpos, int *upperimplicpos)
Definition implics.c:916
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 * SCIPvboundsGetConstants(SCIP_VBOUNDS *vbounds)
Definition implics.c:3318
int SCIPvboundsGetNVbds(SCIP_VBOUNDS *vbounds)
Definition implics.c:3294
SCIP_Bool SCIPimplicsContainsImpl(SCIP_IMPLICS *implics, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition implics.c:933
void SCIPimplicsFree(SCIP_IMPLICS **implics, BMS_BLKMEM *blkmem)
Definition implics.c:451
SCIP_RETCODE SCIPcliquelistAdd(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition implics.c:1482
methods for implications, variable bounds, and cliques
SCIP_Bool SCIPlpIsSolBasic(SCIP_LP *lp)
Definition lp.c:18241
SCIP_RETCODE SCIPcolChgUb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newub)
Definition lp.c:3997
SCIP_RETCODE SCIPcolFree(SCIP_COL **col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition lp.c:3572
SCIP_RETCODE SCIPcolChgLb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newlb)
Definition lp.c:3952
void SCIPlpDecNLoosevars(SCIP_LP *lp)
Definition lp.c:14686
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:5856
SCIP_RETCODE SCIPcolChgObj(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newobj)
Definition lp.c:3893
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:5744
SCIP_Bool SCIPlpDiving(SCIP_LP *lp)
Definition lp.c:18251
SCIP_Real SCIPcolGetRedcost(SCIP_COL *col, SCIP_STAT *stat, SCIP_LP *lp)
Definition lp.c:4147
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:3473
SCIP_RETCODE SCIPlpUpdateVarLoose(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition lp.c:14665
static const SCIP_Real scalars[]
Definition lp.c:5959
SCIP_RETCODE SCIPlpUpdateVarColumn(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition lp.c:14541
internal methods for LP management
SCIP_RETCODE SCIPlpExactUpdateVarColumn(SCIP_LPEXACT *lpexact, SCIP_SET *set, SCIP_VAR *var)
Definition lpexact.c:6663
SCIP_RETCODE SCIProwExactIncCoef(SCIP_ROWEXACT *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LPEXACT *lpexact, SCIP_COLEXACT *col, SCIP_RATIONAL *incval)
Definition lpexact.c:5321
void SCIPlpExactDecNLoosevars(SCIP_LPEXACT *lpexact)
Definition lpexact.c:6770
SCIP_RATIONAL * SCIPcolExactGetPrimsol(SCIP_COLEXACT *col)
Definition lpexact.c:6039
SCIP_Bool SCIPlpExactDiving(SCIP_LPEXACT *lpexact)
Definition lpexact.c:8423
SCIP_RETCODE SCIPcolExactFree(SCIP_COLEXACT **col, BMS_BLKMEM *blkmem)
Definition lpexact.c:2754
SCIP_RETCODE SCIPcolExactChgUb(SCIP_COLEXACT *col, SCIP_SET *set, SCIP_LPEXACT *lpexact, SCIP_RATIONAL *newub)
Definition lpexact.c:3093
SCIP_RETCODE SCIProwExactAddConstant(SCIP_ROWEXACT *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_LPEXACT *lpexact, SCIP_RATIONAL *addval)
Definition lpexact.c:5416
SCIP_RETCODE SCIPcolExactCreate(SCIP_COLEXACT **col, SCIP_COL *fpcol, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var, int len, SCIP_ROWEXACT **rows, SCIP_RATIONAL **vals, SCIP_Bool removable)
Definition lpexact.c:2410
SCIP_RETCODE SCIPcolExactChgLb(SCIP_COLEXACT *col, SCIP_SET *set, SCIP_LPEXACT *lpexact, SCIP_RATIONAL *newlb)
Definition lpexact.c:3048
internal methods for exact LP management
#define BMSreallocBlockMemorySize(mem, ptr, oldsize, newsize)
Definition memory.h:456
#define BMSduplicateBlockMemoryArray(mem, ptr, source, num)
Definition memory.h:462
#define BMSfreeBlockMemory(mem, ptr)
Definition memory.h:465
#define BMSallocBlockMemory(mem, ptr)
Definition memory.h:451
#define BMSfreeBlockMemoryArrayNull(mem, ptr, num)
Definition memory.h:468
#define BMSfreeBlockMemorySize(mem, ptr, size)
Definition memory.h:469
#define BMSallocBlockMemoryArray(mem, ptr, num)
Definition memory.h:454
#define BMScopyMemoryArray(ptr, source, num)
Definition memory.h:134
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition memory.h:467
#define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
Definition memory.h:458
#define BMSallocBlockMemorySize(mem, ptr, size)
Definition memory.h:453
struct BMS_BlkMem BMS_BLKMEM
Definition memory.h:437
void SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr,...)
Definition message.c:618
void SCIPmessagePrintWarning(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
Definition message.c:427
real eps
SCIP_RETCODE SCIPprimalUpdateObjoffsetExact(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp)
Definition primal.c:646
SCIP_RETCODE SCIPprimalUpdateObjoffset(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp)
Definition primal.c:590
internal methods for collecting primal CIP solutions and primal informations
void SCIPprobUpdateNObjVars(SCIP_PROB *prob, SCIP_SET *set, SCIP_Real oldobj, SCIP_Real newobj)
Definition prob.c:1871
int SCIPprobGetNContVars(SCIP_PROB *prob)
Definition prob.c:2901
SCIP_RETCODE SCIPprobVarChangedStatus(SCIP_PROB *prob, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_BRANCHCAND *branchcand, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var)
Definition prob.c:1409
const char * SCIPprobGetName(SCIP_PROB *prob)
Definition prob.c:2856
void SCIPprobAddObjoffset(SCIP_PROB *prob, SCIP_Real addval)
Definition prob.c:1666
SCIP_RETCODE SCIPprobAddVar(SCIP_PROB *prob, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_VAR *var)
Definition prob.c:1096
int SCIPprobGetNVars(SCIP_PROB *prob)
Definition prob.c:2865
SCIP_VAR ** SCIPprobGetVars(SCIP_PROB *prob)
Definition prob.c:2910
SCIP_Bool SCIPprobIsTransformed(SCIP_PROB *prob)
Definition prob.c:2800
void SCIPprobAddObjoffsetExact(SCIP_PROB *prob, SCIP_RATIONAL *addval)
Definition prob.c:1682
internal methods for storing and manipulating the main problem
public methods for managing constraints
public methods for branching and inference history structure
public methods for implications, variable bounds, and cliques
public methods for LP management
public methods for message output
#define SCIPerrorMessage
Definition pub_message.h:64
#define SCIPdebugMessage
Definition pub_message.h:96
public data structures and miscellaneous methods
methods for sorting joint arrays of various types
public methods for propagators
public methods for problem variables
void SCIPrelaxationSolObjAdd(SCIP_RELAXATION *relaxation, SCIP_Real val)
Definition relax.c:864
internal methods for relaxators
SCIP callable library.
public methods for certified solving
public methods for exact solving
public methods for global and local (sub)problems
public methods for the probing mode
SCIP_Bool SCIPsetIsDualfeasZero(SCIP_SET *set, SCIP_Real val)
Definition set.c:7292
SCIP_Real SCIPsetFloor(SCIP_SET *set, SCIP_Real val)
Definition set.c:6716
SCIP_Bool SCIPsetIsFeasPositive(SCIP_SET *set, SCIP_Real val)
Definition set.c:7076
SCIP_Bool SCIPsetIsGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:6617
SCIP_Real SCIPsetFeasCeil(SCIP_SET *set, SCIP_Real val)
Definition set.c:7136
SCIP_Bool SCIPsetIsFeasNegative(SCIP_SET *set, SCIP_Real val)
Definition set.c:7087
SCIP_Real SCIPsetFeastol(SCIP_SET *set)
Definition set.c:6422
SCIP_Real SCIPsetCeil(SCIP_SET *set, SCIP_Real val)
Definition set.c:6728
SCIP_Bool SCIPsetIsFeasGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:7017
SCIP_Bool SCIPsetIsFeasLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:6993
SCIP_Bool SCIPsetIsFeasEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:6945
SCIP_Bool SCIPsetIsPositive(SCIP_SET *set, SCIP_Real val)
Definition set.c:6648
SCIP_Bool SCIPsetIsLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:6577
SCIP_Real SCIPsetFeasFloor(SCIP_SET *set, SCIP_Real val)
Definition set.c:7124
SCIP_Bool SCIPsetIsDualfeasNegative(SCIP_SET *set, SCIP_Real val)
Definition set.c:7314
SCIP_Real SCIPsetEpsilon(SCIP_SET *set)
Definition set.c:6402
SCIP_Bool SCIPsetIsEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:6537
SCIP_Bool SCIPsetIsFeasZero(SCIP_SET *set, SCIP_Real val)
Definition set.c:7065
SCIP_STAGE SCIPsetGetStage(SCIP_SET *set)
Definition set.c:3197
SCIP_Bool SCIPsetIsFeasLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:6969
SCIP_Real SCIPsetInfinity(SCIP_SET *set)
Definition set.c:6380
SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:6557
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition set.c:6515
SCIP_Bool SCIPsetIsSumZero(SCIP_SET *set, SCIP_Real val)
Definition set.c:6864
SCIP_Bool SCIPsetIsDualfeasPositive(SCIP_SET *set, SCIP_Real val)
Definition set.c:7303
SCIP_Bool SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:6597
SCIP_Bool SCIPsetIsIntegral(SCIP_SET *set, SCIP_Real val)
Definition set.c:6670
SCIP_Bool SCIPsetIsZero(SCIP_SET *set, SCIP_Real val)
Definition set.c:6637
SCIP_Bool SCIPsetIsFeasGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:7041
SCIP_Real SCIPsetGetHugeValue(SCIP_SET *set)
Definition set.c:6392
SCIP_Real SCIPsetRound(SCIP_SET *set, SCIP_Real val)
Definition set.c:6740
int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
Definition set.c:6080
SCIP_Bool SCIPsetIsFeasIntegral(SCIP_SET *set, SCIP_Real val)
Definition set.c:7098
SCIP_Bool SCIPsetIsNegative(SCIP_SET *set, SCIP_Real val)
Definition set.c:6659
internal methods for global SCIP settings
#define SCIPsetFreeBufferArray(set, ptr)
Definition set.h:1782
#define SCIPsetFreeCleanBufferArray(set, ptr)
Definition set.h:1789
#define SCIPsetAllocBufferArray(set, ptr, num)
Definition set.h:1775
#define SCIPsetAllocCleanBufferArray(set, ptr, num)
Definition set.h:1786
#define SCIPsetDuplicateBufferArray(set, ptr, source, num)
Definition set.h:1777
#define SCIPsetDebugMsg
Definition set.h:1811
#define SCIPsetReallocBufferArray(set, ptr, num)
Definition set.h:1779
SCIP_Real SCIPsolGetVal(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var)
Definition sol.c:1912
internal methods for storing primal CIP solutions
SCIP_RETCODE SCIPstatUpdateVarRootLPBestEstimate(SCIP_STAT *stat, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldrootpscostscore)
Definition stat.c:871
internal methods for problem statistics
#define SCIPstatIncrement(stat, set, field)
Definition stat.h:260
SCIP_RATIONAL * scalar
Definition struct_var.h:218
SCIP_RATIONAL * constant
Definition struct_var.h:219
SCIP_VAR * var
Definition struct_var.h:212
SCIP_Real scalar
Definition struct_var.h:210
SCIP_Real constant
Definition struct_var.h:211
SCIP_BDCHGIDX bdchgidx
Definition struct_var.h:127
SCIP_Real newbound
Definition struct_var.h:123
SCIP_INFERENCEDATA inferencedata
Definition struct_var.h:126
unsigned int boundchgtype
Definition struct_var.h:129
unsigned int boundtype
Definition struct_var.h:130
SCIP_VAR * var
Definition struct_var.h:125
unsigned int redundant
Definition struct_var.h:132
unsigned int inferboundtype
Definition struct_var.h:131
SCIP_Real oldbound
Definition struct_var.h:122
SCIP_RATIONAL * newboundexact
Definition struct_var.h:97
union SCIP_BoundChg::@126301315365336333353356203157377037022074222233 data
SCIP_Longint certificateindex
Definition struct_var.h:103
SCIP_Real newbound
Definition struct_var.h:96
unsigned int applied
Definition struct_var.h:108
unsigned int boundtype
Definition struct_var.h:106
SCIP_INFERENCEDATA inferencedata
Definition struct_var.h:101
unsigned int redundant
Definition struct_var.h:109
SCIP_VAR * var
Definition struct_var.h:104
SCIP_BRANCHINGDATA branchingdata
Definition struct_var.h:100
unsigned int inferboundtype
Definition struct_var.h:107
unsigned int boundchgtype
Definition struct_var.h:105
SCIP_HOLECHG * holechgs
Definition struct_var.h:149
SCIP_BOUNDCHG * boundchgs
Definition struct_var.h:140
unsigned int nboundchgs
Definition struct_var.h:138
SCIP_BOUNDCHG * boundchgs
Definition struct_var.h:158
SCIP_HOLECHG * holechgs
Definition struct_var.h:159
unsigned int nboundchgs
Definition struct_var.h:156
unsigned int domchgtype
Definition struct_var.h:157
SCIP_RATIONAL * ub
Definition struct_var.h:185
SCIP_RATIONAL * lb
Definition struct_var.h:184
SCIP_Real lb
Definition struct_var.h:176
SCIP_Real ub
Definition struct_var.h:177
SCIP_HOLELIST * holelist
Definition struct_var.h:178
SCIP_HOLELIST ** ptr
Definition struct_var.h:70
SCIP_HOLELIST * oldlist
Definition struct_var.h:72
SCIP_HOLELIST * newlist
Definition struct_var.h:71
SCIP_Real right
Definition struct_var.h:57
SCIP_Real left
Definition struct_var.h:56
SCIP_HOLELIST * next
Definition struct_var.h:64
SCIP_HOLE hole
Definition struct_var.h:63
SCIP_Real sup
SCIP_Real inf
SCIP_Real minaggrcoef
Definition struct_var.h:203
SCIP_Real maxaggrcoef
Definition struct_var.h:204
SCIP_LPEXACT * lpexact
Definition struct_lp.h:309
SCIP_Bool divingobjchg
Definition struct_lp.h:387
SCIP_RATIONAL ** scalars
Definition struct_var.h:236
SCIP_RATIONAL * constant
Definition struct_var.h:235
SCIP_VAR ** vars
Definition struct_var.h:227
SCIP_Real * scalars
Definition struct_var.h:226
SCIP_Real constant
Definition struct_var.h:242
SCIP_VAR * transvar
Definition struct_var.h:194
SCIP_OBJSENSE objsense
Definition struct_prob.h:92
SCIP_Real objscale
Definition struct_prob.h:51
SCIP_ROW * fprow
char * name
Definition struct_lp.h:229
SCIP_VAR * lastbranchvar
SCIP_Longint lpcount
SCIP_HISTORY * glbhistory
int nrootboundchgs
int nrootintfixingsrun
int nrootintfixings
SCIP_Real vsidsweight
SCIP_BRANCHDIR lastbranchdir
int nrootboundchgsrun
SCIP_Bool collectvarhistory
SCIP_HISTORY * glbhistorycrun
SCIP_Real lastbranchvalue
SCIP_INTERVAL objinterval
Definition struct_var.h:249
SCIP_DOMEXACT glbdom
Definition struct_var.h:251
SCIP_RATIONAL * obj
Definition struct_var.h:248
SCIP_DOMEXACT origdom
Definition struct_var.h:252
SCIP_COLEXACT * colexact
Definition struct_var.h:255
SCIP_MULTAGGREXACT multaggr
Definition struct_var.h:254
SCIP_VARSTATUS varstatusexact
Definition struct_var.h:256
SCIP_AGGREGATEEXACT aggregate
Definition struct_var.h:253
SCIP_DOMEXACT locdom
Definition struct_var.h:250
SCIP_Real lazylb
Definition struct_var.h:277
SCIP_VARDATA * vardata
Definition struct_var.h:296
int nubchginfos
Definition struct_var.h:325
SCIP_Real lazyub
Definition struct_var.h:278
SCIP_ORIGINAL original
Definition struct_var.h:283
SCIP_VBOUNDS * vlbs
Definition struct_var.h:299
SCIP_AGGREGATE aggregate
Definition struct_var.h:286
SCIP_IMPLICS * implics
Definition struct_var.h:301
SCIP_VAR ** parentvars
Definition struct_var.h:297
SCIP_BDCHGINFO * lbchginfos
Definition struct_var.h:304
SCIP_VAR * negatedvar
Definition struct_var.h:298
SCIP * scip
Definition struct_var.h:345
int nlocksdown[NLOCKTYPES]
Definition struct_var.h:319
SCIP_HISTORY * historycrun
Definition struct_var.h:307
unsigned int donotmultaggr
Definition struct_var.h:335
SCIP_DOM glbdom
Definition struct_var.h:279
SCIP_Real branchfactor
Definition struct_var.h:265
SCIP_Real conflictrelaxedub
Definition struct_var.h:276
SCIP_BDCHGINFO * ubchginfos
Definition struct_var.h:305
char * name
Definition struct_var.h:291
union SCIP_Var::@062351145146014100220174313010263165251013276204 data
SCIP_Real conflictrelaxedlb
Definition struct_var.h:275
SCIP_VARDATAEXACT * exactdata
Definition struct_var.h:290
unsigned int initial
Definition struct_var.h:330
SCIP_DOM locdom
Definition struct_var.h:280
unsigned int removable
Definition struct_var.h:331
SCIP_CLIQUELIST * cliquelist
Definition struct_var.h:302
SCIP_MULTAGGR multaggr
Definition struct_var.h:287
SCIP_Real obj
Definition struct_var.h:263
int nlocksup[NLOCKTYPES]
Definition struct_var.h:320
int nlbchginfos
Definition struct_var.h:323
unsigned int branchdirection
Definition struct_var.h:340
SCIP_HISTORY * history
Definition struct_var.h:306
SCIP_VBOUNDS * vubs
Definition struct_var.h:300
int nparentvars
Definition struct_var.h:317
unsigned int donotaggr
Definition struct_var.h:334
SCIP_LOOSE loose
Definition struct_var.h:284
SCIP_NEGATE negate
Definition struct_var.h:285
SCIP_Longint closestvblpcount
Definition struct_var.h:309
int branchpriority
Definition struct_var.h:321
datastructures for managing events
data structures for LP management
data structures for exact LP management
datastructures for storing and manipulating the main problem
SCIP main data structure.
datastructures for global SCIP settings
datastructures for problem statistics
datastructures for problem variables
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_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype, SCIP_Bool probingchange)
Definition tree.c:2539
SCIP_NODE * SCIPtreeGetRootNode(SCIP_TREE *tree)
Definition tree.c:9559
internal methods for branch and bound tree
struct SCIP_BranchCand SCIP_BRANCHCAND
Definition type_branch.h:55
struct SCIP_Certificate SCIP_CERTIFICATE
struct SCIP_Cons SCIP_CONS
Definition type_cons.h:63
#define SCIP_EVENTTYPE_GHOLEADDED
Definition type_event.h:81
struct SCIP_Eventhdlr SCIP_EVENTHDLR
Definition type_event.h:159
#define SCIP_EVENTTYPE_GUBCHANGED
Definition type_event.h:76
struct SCIP_EventData SCIP_EVENTDATA
Definition type_event.h:179
struct SCIP_EventFilter SCIP_EVENTFILTER
Definition type_event.h:180
struct SCIP_EventQueue SCIP_EVENTQUEUE
Definition type_event.h:181
#define SCIP_EVENTTYPE_FORMAT
Definition type_event.h:157
#define SCIP_EVENTTYPE_GLBCHANGED
Definition type_event.h:75
#define SCIP_EVENTTYPE_VARCHANGED
Definition type_event.h:132
#define SCIP_EVENTTYPE_LBCHANGED
Definition type_event.h:123
#define SCIP_EVENTTYPE_UBCHANGED
Definition type_event.h:124
#define SCIP_EVENTTYPE_LHOLEADDED
Definition type_event.h:83
uint64_t SCIP_EVENTTYPE
Definition type_event.h:156
struct SCIP_Event SCIP_EVENT
Definition type_event.h:161
struct SCIP_History SCIP_HISTORY
@ SCIP_BRANCHDIR_DOWNWARDS
@ SCIP_BRANCHDIR_AUTO
@ SCIP_BRANCHDIR_UPWARDS
struct SCIP_ValueHistory SCIP_VALUEHISTORY
enum SCIP_BranchDir SCIP_BRANCHDIR
struct SCIP_Clique SCIP_CLIQUE
struct SCIP_CliqueTable SCIP_CLIQUETABLE
struct SCIP_Row SCIP_ROW
Definition type_lp.h:105
struct SCIP_Lp SCIP_LP
Definition type_lp.h:111
@ SCIP_BOUNDTYPE_UPPER
Definition type_lp.h:58
@ SCIP_BOUNDTYPE_LOWER
Definition type_lp.h:57
struct SCIP_Col SCIP_COL
Definition type_lp.h:99
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition type_lp.h:60
struct SCIP_LpExact SCIP_LPEXACT
struct SCIP_RowExact SCIP_ROWEXACT
struct SCIP_ColExact SCIP_COLEXACT
@ SCIP_BASESTAT_UPPER
Definition type_lpi.h:93
@ SCIP_BASESTAT_LOWER
Definition type_lpi.h:91
enum SCIP_BaseStat SCIP_BASESTAT
Definition type_lpi.h:96
struct SCIP_Messagehdlr SCIP_MESSAGEHDLR
struct SCIP_HashMap SCIP_HASHMAP
Definition type_misc.h:106
#define SCIP_DECL_SORTPTRCOMP(x)
Definition type_misc.h:189
#define SCIP_DECL_HASHKEYEQ(x)
Definition type_misc.h:195
#define SCIP_DECL_HASHGETKEY(x)
Definition type_misc.h:192
#define SCIP_DECL_HASHKEYVAL(x)
Definition type_misc.h:198
@ SCIP_CONFIDENCELEVEL_MAX
Definition type_misc.h:51
@ SCIP_CONFIDENCELEVEL_MEDIUM
Definition type_misc.h:49
@ SCIP_CONFIDENCELEVEL_HIGH
Definition type_misc.h:50
@ SCIP_CONFIDENCELEVEL_MIN
Definition type_misc.h:47
@ SCIP_CONFIDENCELEVEL_LOW
Definition type_misc.h:48
enum SCIP_Confidencelevel SCIP_CONFIDENCELEVEL
Definition type_misc.h:53
struct SCIP_Primal SCIP_PRIMAL
Definition type_primal.h:39
struct SCIP_Prob SCIP_PROB
Definition type_prob.h:52
enum SCIP_Objsense SCIP_OBJSENSE
Definition type_prob.h:50
struct SCIP_Prop SCIP_PROP
Definition type_prop.h:51
struct SCIP_Rational SCIP_RATIONAL
@ SCIP_R_ROUND_UPWARDS
@ SCIP_R_ROUND_DOWNWARDS
struct SCIP_Relaxation SCIP_RELAXATION
Definition type_relax.h:51
struct SCIP_Reopt SCIP_REOPT
Definition type_reopt.h:39
@ SCIP_DIDNOTRUN
Definition type_result.h:42
@ SCIP_SUCCESS
Definition type_result.h:58
enum SCIP_Result SCIP_RESULT
Definition type_result.h:61
@ SCIP_INVALIDRESULT
@ SCIP_READERROR
@ SCIP_INVALIDDATA
@ SCIP_INVALIDCALL
@ SCIP_ERROR
enum SCIP_Retcode SCIP_RETCODE
struct Scip SCIP
Definition type_scip.h:39
struct SCIP_Set SCIP_SET
Definition type_set.h:71
@ SCIP_STAGE_PROBLEM
Definition type_set.h:45
@ SCIP_STAGE_PRESOLVING
Definition type_set.h:49
@ SCIP_STAGE_INITSOLVE
Definition type_set.h:52
@ SCIP_STAGE_SOLVING
Definition type_set.h:53
@ SCIP_STAGE_TRANSFORMING
Definition type_set.h:46
@ SCIP_STAGE_PRESOLVED
Definition type_set.h:51
struct SCIP_Sol SCIP_SOL
Definition type_sol.h:57
struct SCIP_Stat SCIP_STAT
Definition type_stat.h:66
struct SCIP_Node SCIP_NODE
Definition type_tree.h:63
struct SCIP_Tree SCIP_TREE
Definition type_tree.h:65
struct SCIP_VarData SCIP_VARDATA
Definition type_var.h:167
struct SCIP_Var SCIP_VAR
Definition type_var.h:166
enum SCIP_BoundchgType SCIP_BOUNDCHGTYPE
Definition type_var.h:135
struct SCIP_DomChgBoth SCIP_DOMCHGBOTH
Definition type_var.h:147
#define NLOCKTYPES
Definition type_var.h:138
enum SCIP_ImplintType SCIP_IMPLINTTYPE
Definition type_var.h:117
@ SCIP_IMPLINTTYPE_NONE
Definition type_var.h:90
@ SCIP_IMPLINTTYPE_STRONG
Definition type_var.h:106
@ SCIP_IMPLINTTYPE_WEAK
Definition type_var.h:91
#define SCIP_DECL_VARDELORIG(x)
Definition type_var.h:180
struct SCIP_HoleChg SCIP_HOLECHG
Definition type_var.h:155
union SCIP_DomChg SCIP_DOMCHG
Definition type_var.h:149
@ SCIP_DOMCHGTYPE_DYNAMIC
Definition type_var.h:122
@ SCIP_DOMCHGTYPE_BOUND
Definition type_var.h:124
@ SCIP_DOMCHGTYPE_BOTH
Definition type_var.h:123
struct SCIP_BoundChg SCIP_BOUNDCHG
Definition type_var.h:150
struct SCIP_BdChgIdx SCIP_BDCHGIDX
Definition type_var.h:151
struct SCIP_DomChgDyn SCIP_DOMCHGDYN
Definition type_var.h:148
#define SCIP_DECL_VARTRANS(x)
Definition type_var.h:200
#define SCIP_DEPRECATED_VARTYPE_IMPLINT
Definition type_var.h:79
struct SCIP_DomChgBound SCIP_DOMCHGBOUND
Definition type_var.h:146
struct SCIP_Holelist SCIP_HOLELIST
Definition type_var.h:157
@ SCIP_VARTYPE_INTEGER
Definition type_var.h:65
@ SCIP_VARTYPE_CONTINUOUS
Definition type_var.h:71
@ SCIP_VARTYPE_BINARY
Definition type_var.h:64
@ SCIP_BOUNDCHGTYPE_PROPINFER
Definition type_var.h:133
@ SCIP_BOUNDCHGTYPE_BRANCHING
Definition type_var.h:131
@ SCIP_BOUNDCHGTYPE_CONSINFER
Definition type_var.h:132
@ SCIP_VARSTATUS_ORIGINAL
Definition type_var.h:51
@ SCIP_VARSTATUS_FIXED
Definition type_var.h:54
@ SCIP_VARSTATUS_COLUMN
Definition type_var.h:53
@ SCIP_VARSTATUS_MULTAGGR
Definition type_var.h:56
@ SCIP_VARSTATUS_NEGATED
Definition type_var.h:57
@ SCIP_VARSTATUS_AGGREGATED
Definition type_var.h:55
@ SCIP_VARSTATUS_LOOSE
Definition type_var.h:52
struct SCIP_BdChgInfo SCIP_BDCHGINFO
Definition type_var.h:152
#define SCIP_DECL_VARCOPY(x)
Definition type_var.h:243
#define SCIP_DECL_VARDELTRANS(x)
Definition type_var.h:213
struct SCIP_Dom SCIP_DOM
Definition type_var.h:158
enum SCIP_LockType SCIP_LOCKTYPE
Definition type_var.h:144
@ SCIP_LOCKTYPE_MODEL
Definition type_var.h:141
enum SCIP_Vartype SCIP_VARTYPE
Definition type_var.h:73
enum SCIP_Varstatus SCIP_VARSTATUS
Definition type_var.h:59
SCIP_DOMCHGBOUND domchgbound
Definition struct_var.h:168
SCIP_DOMCHGDYN domchgdyn
Definition struct_var.h:170
SCIP_DOMCHGBOTH domchgboth
Definition struct_var.h:169
SCIP_Real SCIPvarGetObjLP(SCIP_VAR *var)
Definition var.c:18523
SCIP_Real SCIPvarGetPseudocost(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition var.c:20438
SCIP_RETCODE SCIPvarsGetActiveVars(SCIP_SET *set, SCIP_VAR **vars, int *nvars, int varssize, int *requiredsize)
Definition var.c:17339
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_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, int naggvars, SCIP_VAR **aggvars, SCIP_Real *scalars, SCIP_Real constant, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition var.c:8056
SCIP_RETCODE SCIPvarTryAggregateVarsExact(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_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_RATIONAL *scalarx, SCIP_RATIONAL *scalary, SCIP_RATIONAL *rhs, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition var.c:7864
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_RATIONAL *lbexact, SCIP_RATIONAL *ubexact, SCIP_RATIONAL *objexact, SCIP_VARTYPE *vartype, SCIP_IMPLINTTYPE *impltype, SCIP_Real *lazylb, SCIP_Real *lazyub, SCIP_RATIONAL *lazylbexact, SCIP_RATIONAL *lazyubexact, SCIP_Bool local, char **endptr, SCIP_Bool *success)
Definition var.c:2972
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:21500
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:10295
static SCIP_RETCODE varFreeExactData(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition var.c:3604
static SCIP_RETCODE varEnsureUbchginfosSize(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition var.c:459
SCIP_RETCODE SCIPdomchgAddBoundchg(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_VAR *var, SCIP_Real newbound, SCIP_RATIONAL *newboundexact, 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:1734
SCIP_RETCODE SCIPvarChgLbLazy(SCIP_VAR *var, SCIP_SET *set, SCIP_Real lazylb)
Definition var.c:11772
static SCIP_RETCODE domchgEnsureBoundchgsSize(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition var.c:1540
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_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool value, SCIP_Bool *infeasible, int *nbdchgs)
Definition var.c:16513
static SCIP_RETCODE varEventGubChangedExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_RATIONAL *oldbound, SCIP_RATIONAL *newbound)
Definition var.c:10410
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:12231
SCIP_Real SCIPvarGetPseudocostCount(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:20581
SCIP_RETCODE SCIPvarResetBounds(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat)
Definition var.c:14535
void SCIPbdchginfoFree(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem)
Definition var.c:22616
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:230
SCIP_RETCODE SCIPvarGetTransformed(SCIP_VAR *origvar, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **transvar)
Definition var.c:4581
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:9420
static SCIP_RETCODE varProcessChgBranchPriority(SCIP_VAR *var, int branchpriority)
Definition var.c:16964
void SCIPvarGetUbLocalExactMinimal(SCIP_VAR *var, SCIP_RATIONAL *output)
Definition var.c:24290
SCIP_Real SCIPvarGetPseudocostVariance(SCIP_VAR *var, SCIP_BRANCHDIR dir, SCIP_Bool onlycurrentrun)
Definition var.c:20745
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:1181
SCIP_Real SCIPvarGetImplRedcost(SCIP_VAR *var, SCIP_SET *set, SCIP_Bool varfixing, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_LP *lp)
Definition var.c:19234
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_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool *infeasible, int *nbdchgs)
Definition var.c:14725
SCIP_RETCODE SCIPvarSetLastGMIScore(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real gmieff)
Definition var.c:22536
static SCIP_RETCODE parseBounds(SCIP_SET *set, const char *str, char *type, SCIP_Real *lb, SCIP_Real *ub, SCIP_RATIONAL *lbexact, SCIP_RATIONAL *ubexact, char **endptr)
Definition var.c:2926
void SCIPvarInitSolve(SCIP_VAR *var)
Definition var.c:3846
SCIP_RETCODE SCIPvarChgUbGlobalExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LPEXACT *lpexact, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_RATIONAL *newbound)
Definition var.c:11619
SCIP_Real SCIPvarGetAncPseudocostCountCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:20671
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:21584
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_EVENTFILTER *eventfilter, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_Bool implvarfixing, SCIP_Bool *infeasible, int *nbdchgs)
Definition var.c:15034
SCIP_RETCODE SCIPvarChgLbGlobalExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LPEXACT *lpexact, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_RATIONAL *newbound)
Definition var.c:11322
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_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *aggvar, SCIP_Real scalar, SCIP_Real constant, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition var.c:6174
SCIP_RETCODE SCIPvarChgBdGlobalExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LPEXACT *lpexact, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_RATIONAL *newbound, SCIP_BOUNDTYPE boundtype)
Definition var.c:11849
static void printBounds(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, FILE *file, SCIP_Real lb, SCIP_Real ub, const char *name)
Definition var.c:3859
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_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_Real scalarx, SCIP_Real scalary, SCIP_Real rhs, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition var.c:7688
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:21104
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:12044
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:485
SCIP_RETCODE SCIPvarChgUbLocalExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LPEXACT *lpexact, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_RATIONAL *newbound)
Definition var.c:13113
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:1640
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:14298
SCIP_Real SCIPvarGetAvgCutoffs(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition var.c:22318
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:845
SCIP_RETCODE SCIPvarGetProbvarSumExact(SCIP_VAR **var, SCIP_RATIONAL *scalar, SCIP_RATIONAL *constant)
Definition var.c:18206
SCIP_RETCODE SCIPdomchgMakeStatic(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition var.c:1451
static void checkImplic(SCIP_SET *set, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool *redundant, SCIP_Bool *infeasible)
Definition var.c:14694
SCIP_RETCODE SCIPvarGetMultaggrUbLocalExact(SCIP_VAR *var, SCIP_SET *set, SCIP_RATIONAL *result)
Definition var.c:13787
static SCIP_VAR * varGetActiveVar(SCIP_VAR *var)
Definition var.c:8795
SCIP_RETCODE SCIPvarUpdatePseudocost(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition var.c:20275
void SCIPvarSetLbCertificateIndexLocal(SCIP_VAR *var, SCIP_Longint certidx)
Definition var.c:25150
SCIP_RETCODE SCIPvarTransform(SCIP_VAR *origvar, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_OBJSENSE objsense, SCIP_VAR **transvar)
Definition var.c:4494
SCIP_RETCODE SCIPvarAddHoleOriginal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real left, SCIP_Real right)
Definition var.c:13998
static SCIP_RETCODE varProcessChgLbLocalExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LPEXACT *lpexact, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_RATIONAL *newbound)
Definition var.c:12431
SCIP_RETCODE SCIPvarAddCliqueToList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition var.c:16726
int SCIPbdchgidxGetDepth(SCIP_BDCHGIDX *bdchgidx)
Definition var.c:24860
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:9350
static SCIP_RETCODE varFree(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition var.c:3656
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:14179
SCIP_Real SCIPvarGetAvgInferencesCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition var.c:22177
static SCIP_RETCODE varEventImplAdded(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition var.c:14576
SCIP_RETCODE SCIPvarRelease(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition var.c:3787
void SCIPvarGetClosestVub(SCIP_VAR *var, SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *closestvub, int *closestvubidx)
Definition var.c:19964
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:21240
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_IMPLINTTYPE impltype, 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:2325
SCIP_RETCODE SCIPvarRemove(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_CLIQUETABLE *cliquetable, SCIP_SET *set, SCIP_Bool final, SCIP_Bool keepimplics)
Definition var.c:9123
void SCIPvarAdjustLb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *lb)
Definition var.c:9911
static SCIP_RATIONAL * SCIPvarGetPseudoSolExact_rec(SCIP_VAR *var)
Definition var.c:18976
void SCIPvarAdjustLbExact(SCIP_VAR *var, SCIP_SET *set, SCIP_RATIONAL *lb)
Definition var.c:9928
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:24825
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:11179
SCIP_RETCODE SCIPvarSetNLPSol(SCIP_VAR *var, SCIP_SET *set, SCIP_Real solval)
Definition var.c:19772
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:2751
SCIP_Real SCIPvarCalcPscostConfidenceBound(SCIP_VAR *var, SCIP_SET *set, SCIP_BRANCHDIR dir, SCIP_Bool onlycurrentrun, SCIP_CONFIDENCELEVEL clevel)
Definition var.c:20799
static SCIP_BDCHGIDX presolvebdchgidx
Definition var.c:22762
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:11877
SCIP_Bool SCIPvarIsPscostRelerrorReliable(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real threshold, SCIP_CONFIDENCELEVEL clevel)
Definition var.c:20837
static SCIP_RETCODE parseValue(SCIP_SET *set, const char *str, SCIP_Real *value, SCIP_RATIONAL *valueexact)
Definition var.c:2872
SCIP_RETCODE SCIPvarChgLbOriginal(SCIP_VAR *var, SCIP_SET *set, SCIP_Real newbound)
Definition var.c:10029
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:20036
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_EVENTFILTER *eventfilter, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool transitive, SCIP_Bool *infeasible, int *nbdchgs)
Definition var.c:15108
SCIP_Real SCIPvarGetLbLP(SCIP_VAR *var, SCIP_SET *set)
Definition var.c:18569
static SCIP_RETCODE tryAggregateIntVarsExact(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_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_RATIONAL *scalarx, SCIP_RATIONAL *scalary, SCIP_RATIONAL *rhs, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition var.c:7421
void SCIPvarAdjustBd(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real *bd)
Definition var.c:10013
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:11953
SCIP_RETCODE SCIPvarChgObjDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newobj)
Definition var.c:9848
SCIP_RETCODE SCIPdomchgFree(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition var.c:1348
SCIP_RETCODE SCIPvarColumnExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LPEXACT *lp)
Definition var.c:4646
SCIP_Real SCIPvarGetRelaxSolTransVar(SCIP_VAR *var)
Definition var.c:19761
SCIP_RETCODE SCIPvarPrint(SCIP_VAR *var, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition var.c:3953
SCIP_Real SCIPvarGetAvgGMIScore(SCIP_VAR *var, SCIP_STAT *stat)
Definition var.c:22412
SCIP_Real SCIPvarGetVSIDS(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition var.c:24783
SCIP_RETCODE SCIPvarAddObjExact(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_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_RATIONAL *addobj)
Definition var.c:9705
static SCIP_RETCODE varEventVarFixed(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, int fixeventtype)
Definition var.c:4725
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:21668
SCIP_Real SCIPvarGetMultaggrLbLocal(SCIP_VAR *var, SCIP_SET *set)
Definition var.c:13575
static SCIP_RETCODE varNegateExactData(SCIP_VAR *negvar, SCIP_VAR *origvar, BMS_BLKMEM *blkmem)
Definition var.c:8934
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:20914
void SCIPvarCapture(SCIP_VAR *var)
Definition var.c:3762
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:10372
SCIP_RETCODE SCIPvarChgBranchDirection(SCIP_VAR *var, SCIP_BRANCHDIR branchdirection)
Definition var.c:17151
SCIP_Real SCIPvarGetPseudocostCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition var.c:20534
SCIP_RETCODE SCIPdomchgAddHolechg(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HOLELIST **ptr, SCIP_HOLELIST *newlist, SCIP_HOLELIST *oldlist)
Definition var.c:1839
void SCIPvarStoreRootSol(SCIP_VAR *var, SCIP_Bool roothaslp)
Definition var.c:19035
void SCIPvarGetLbLocalExactMaximal(SCIP_VAR *var, SCIP_RATIONAL *output)
Definition var.c:24256
static void adjustedLbExact(SCIP_SET *set, SCIP_Bool isintegral, SCIP_RATIONAL *lb)
Definition var.c:1921
static SCIP_RETCODE domchgEnsureHolechgsSize(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition var.c:1567
static SCIP_RETCODE varEnsureLbchginfosSize(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition var.c:433
static SCIP_RETCODE varProcessChgLbGlobalExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LPEXACT *lpexact, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_RATIONAL *newbound)
Definition var.c:10894
SCIP_Bool SCIPvarDoNotAggr(SCIP_VAR *var)
Definition var.c:8844
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:9243
SCIP_RETCODE SCIPvarFlattenAggregationGraph(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition var.c:5989
void SCIPvarAdjustUbExact(SCIP_VAR *var, SCIP_SET *set, SCIP_RATIONAL *ub)
Definition var.c:9979
SCIP_Longint SCIPvarGetNActiveConflicts(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition var.c:21321
SCIP_RETCODE SCIPvarChgLbExactDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LPEXACT *lpexact, SCIP_RATIONAL *newbound)
Definition var.c:13366
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_IMPLINTTYPE impltype, 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:2487
void SCIPvarUpdateBestRootSol(SCIP_VAR *var, SCIP_SET *set, SCIP_Real rootsol, SCIP_Real rootredcost, SCIP_Real rootlpobjval)
Definition var.c:19046
static SCIP_Real adjustedLbExactFloat(SCIP_Bool isintegral, SCIP_Real lb)
Definition var.c:1908
SCIP_RETCODE SCIPvarFixExact(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_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_RATIONAL *fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition var.c:4987
SCIP_Real SCIPvarGetVSIDS_rec(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition var.c:21930
SCIP_RETCODE SCIPvarChgImplType(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_EVENTQUEUE *eventqueue, SCIP_IMPLINTTYPE impltype)
Definition var.c:9302
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:13250
static SCIP_RETCODE boundchgApplyExact(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:635
SCIP_RETCODE SCIPvarScaleVSIDS(SCIP_VAR *var, SCIP_Real scalar)
Definition var.c:21190
static SCIP_RETCODE findValuehistoryEntry(SCIP_VAR *var, SCIP_Real value, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HISTORY **history)
Definition var.c:21049
SCIP_Real SCIPvarGetAvgConflictlength(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:21413
static SCIP_Real adjustedLb(SCIP_SET *set, SCIP_Bool isintegral, SCIP_Real lb)
Definition var.c:1888
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:10701
SCIP_Real SCIPvarGetPseudocostCountCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:20626
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:11476
SCIP_RETCODE SCIPvarMultiaggregateExact(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_LPEXACT *lpexact, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, int naggvars, SCIP_VAR **aggvars, SCIP_RATIONAL **scalars, SCIP_RATIONAL *constant, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition var.c:8416
static void overwriteMultAggrWithExactData(SCIP_SET *set, SCIP_VAR *var)
Definition var.c:1986
SCIP_RETCODE SCIPvarChgUbOriginalExact(SCIP_VAR *var, SCIP_SET *set, SCIP_RATIONAL *newbound)
Definition var.c:10221
static SCIP_RETCODE varProcessChgUbGlobalExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LPEXACT *lpexact, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_RATIONAL *newbound)
Definition var.c:11036
static SCIP_RETCODE varUpdateAggregationBoundsExact(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_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *aggvar, SCIP_RATIONAL *scalar, SCIP_RATIONAL *constant, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition var.c:6366
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_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_VAR *aggvar, SCIP_Real scalar, SCIP_Real constant, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition var.c:6599
static SCIP_RETCODE varEnsureParentvarsSize(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition var.c:3479
static SCIP_Real adjustedUb(SCIP_SET *set, SCIP_Bool isintegral, SCIP_Real ub)
Definition var.c:1937
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_IMPLINTTYPE impltype, 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:2531
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:3357
SCIP_Real SCIPvarGetUbLP(SCIP_VAR *var, SCIP_SET *set)
Definition var.c:18639
SCIP_RETCODE SCIPvarColumn(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_LP *lp)
Definition var.c:4612
SCIP_Real SCIPvarGetAncPseudocost(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition var.c:20485
SCIP_RETCODE SCIPvarChgUbOriginal(SCIP_VAR *var, SCIP_SET *set, SCIP_Real newbound)
Definition var.c:10162
SCIP_RETCODE SCIPvarChgUbDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newbound)
Definition var.c:13423
static void domMerge(SCIP_DOM *dom, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real *newlb, SCIP_Real *newub)
Definition var.c:274
SCIP_Real SCIPvarGetAvgInferences(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition var.c:22120
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_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_Real addobj)
Definition var.c:9590
int SCIPvarGetConflictingBdchgDepth(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real bound)
Definition var.c:22817
static SCIP_RETCODE varEventVarUnlocked(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition var.c:4179
static void adjustedUbExact(SCIP_SET *set, SCIP_Bool isintegral, SCIP_RATIONAL *ub)
Definition var.c:1970
SCIP_RETCODE SCIPvarChgUbExactDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LPEXACT *lpexact, SCIP_RATIONAL *newbound)
Definition var.c:13513
SCIP_Real SCIPvarGetMultaggrUbGlobal(SCIP_VAR *var, SCIP_SET *set)
Definition var.c:13937
static SCIP_RETCODE varEventLbChangedExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LPEXACT *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_RATIONAL *oldbound, SCIP_RATIONAL *newbound)
Definition var.c:11915
void SCIPvarGetClosestVlb(SCIP_VAR *var, SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *closestvlb, int *closestvlbidx)
Definition var.c:19889
SCIP_RETCODE SCIPvarChgUbLazy(SCIP_VAR *var, SCIP_SET *set, SCIP_Real lazyub)
Definition var.c:11795
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:14596
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_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_Real scalarx, SCIP_Real scalary, SCIP_Real rhs, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition var.c:7183
SCIP_RETCODE SCIPvarChgLbOriginalExact(SCIP_VAR *var, SCIP_SET *set, SCIP_RATIONAL *newbound)
Definition var.c:10088
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:20980
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:1675
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:1059
void SCIPvarMarkDeleted(SCIP_VAR *var)
Definition var.c:9160
#define MAXIMPLSCLOSURE
Definition var.c:83
static SCIP_RETCODE varSetName(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_STAT *stat, const char *name)
Definition var.c:2294
void SCIPvarMergeHistories(SCIP_VAR *targetvar, SCIP_VAR *othervar, SCIP_STAT *stat)
Definition var.c:6116
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_EVENTFILTER *eventfilter, SCIP_VAR *vlbvar, SCIP_Real vlbcoef, SCIP_Real vlbconstant, SCIP_Bool transitive, SCIP_Bool *infeasible, int *nbdchgs)
Definition var.c:15317
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:10449
static void varUpdateMinMaxAggrCoef(SCIP_VAR *var, SCIP_VAR *aggvar, SCIP_Real aggscalar)
Definition var.c:6147
static void printHolelist(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, SCIP_HOLELIST *holelist, const char *name)
Definition var.c:3919
void SCIPdomchgAddCurrentCertificateIndex(SCIP_DOMCHG *domchg, SCIP_CERTIFICATE *certificate)
Definition var.c:1714
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:560
SCIP_RETCODE SCIPvarUpdateAncPseudocost(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition var.c:20375
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:24798
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:14426
SCIP_Bool SCIPvarIsMarkedDeleteGlobalStructures(SCIP_VAR *var)
Definition var.c:23581
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:1591
SCIP_RETCODE SCIPvarDelClique(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition var.c:16765
static SCIP_RETCODE varEventObjChangedExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_EVENTQUEUE *eventqueue, SCIP_RATIONAL *oldobj, SCIP_RATIONAL *newobj)
Definition var.c:9386
SCIP_Real SCIPvarGetRelaxSol(SCIP_VAR *var, SCIP_SET *set)
Definition var.c:19689
SCIP_RETCODE SCIPvarDelCliqueFromList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition var.c:16748
int SCIPbdchgidxGetPos(SCIP_BDCHGIDX *bdchgidx)
Definition var.c:24850
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:11820
static SCIP_Bool useValuehistory(SCIP_VAR *var, SCIP_Real value, SCIP_SET *set)
Definition var.c:21076
SCIP_RETCODE SCIPvarsAddClique(SCIP_VAR **vars, SCIP_Bool *values, int nvars, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_CLIQUE *clique)
Definition var.c:16688
SCIP_RETCODE SCIPvarMarkDoNotAggr(SCIP_VAR *var)
Definition var.c:9171
static SCIP_RETCODE varProcessChgBranchFactor(SCIP_VAR *var, SCIP_SET *set, SCIP_Real branchfactor)
Definition var.c:16829
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:12716
SCIP_RETCODE SCIPvarLoose(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *prob, SCIP_LP *lp)
Definition var.c:4680
static SCIP_RETCODE varFreeParents(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition var.c:3531
static SCIP_BDCHGIDX initbdchgidx
Definition var.c:22759
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_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool value, SCIP_CLIQUE *clique, SCIP_Bool *infeasible, int *nbdchgs)
Definition var.c:16602
static SCIP_RETCODE varProcessChgUbLocalExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LPEXACT *lpexact, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_RATIONAL *newbound)
Definition var.c:12573
SCIP_RETCODE SCIPvarChgBranchPriority(SCIP_VAR *var, int branchpriority)
Definition var.c:17020
SCIP_RETCODE SCIPvarChgLbLocalExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LPEXACT *lpexact, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_RATIONAL *newbound)
Definition var.c:12846
static SCIP_RETCODE domchgCreate(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem)
Definition var.c:1327
SCIP_RETCODE SCIPvarMarkDoNotMultaggr(SCIP_VAR *var)
Definition var.c:9207
static SCIP_RETCODE holelistCreate(SCIP_HOLELIST **holelist, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real left, SCIP_Real right)
Definition var.c:158
static SCIP_Real adjustedUbExactFloat(SCIP_Bool isintegral, SCIP_Real lb)
Definition var.c:1957
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:4200
SCIP_RETCODE SCIPvarNegate(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **negvar)
Definition var.c:8980
SCIP_Real SCIPvarGetMultaggrUbLocal(SCIP_VAR *var, SCIP_SET *set)
Definition var.c:13723
SCIP_RETCODE SCIPbdchginfoCreate(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_Real oldbound, SCIP_Real newbound)
Definition var.c:22586
SCIP_Real SCIPvarGetMinPseudocostScore(SCIP_VAR *var, SCIP_STAT *stat, SCIP_SET *set, SCIP_Real solval)
Definition var.c:20714
SCIP_RETCODE SCIPvarGetProbvarSum(SCIP_VAR **var, SCIP_SET *set, SCIP_Real *scalar, SCIP_Real *constant)
Definition var.c:18076
SCIP_Bool SCIPvarIsAggrCoefAcceptable(SCIP_SET *set, SCIP_VAR *var, SCIP_Real scalar)
Definition var.c:8910
SCIP_RETCODE SCIPvarAddExactData(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_RATIONAL *lb, SCIP_RATIONAL *ub, SCIP_RATIONAL *obj)
Definition var.c:2578
SCIP_RETCODE SCIPvarIncGMIeffSum(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real gmieff)
Definition var.c:22452
static void holelistFree(SCIP_HOLELIST **holelist, BMS_BLKMEM *blkmem)
Definition var.c:182
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:10522
SCIP_Real SCIPvarGetLastGMIScore(SCIP_VAR *var, SCIP_STAT *stat)
Definition var.c:22496
void SCIPvarAdjustUb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *ub)
Definition var.c:9962
SCIP_Real SCIPbdchginfoGetRelaxedBound(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:25049
static SCIP_Real getImplVarRedcost(SCIP_VAR *var, SCIP_SET *set, SCIP_Bool varfixing, SCIP_STAT *stat, SCIP_LP *lp)
Definition var.c:19181
SCIP_RETCODE SCIPvarGetActiveRepresentatives(SCIP_SET *set, SCIP_VAR **vars, SCIP_Real *scalars, int *nvars, int varssize, SCIP_Real *constant, int *requiredsize)
Definition var.c:5180
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_EVENTFILTER *eventfilter, 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:14825
SCIP_RETCODE SCIPvarChgLbDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newbound)
Definition var.c:13276
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_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition var.c:4820
static SCIP_Real SCIPvarGetPseudoSol_rec(SCIP_VAR *var)
Definition var.c:18908
SCIP_Real SCIPvarGetAvgConflictlengthCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:21457
SCIP_RETCODE SCIPvarCopyExactData(BMS_BLKMEM *blkmem, SCIP_VAR *targetvar, SCIP_VAR *sourcevar, SCIP_Bool negateobj)
Definition var.c:2686
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:12984
static SCIP_RETCODE domchgMakeDynamic(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem)
Definition var.c:1399
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:3234
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_EVENTFILTER *eventfilter, SCIP_VAR *vubvar, SCIP_Real vubcoef, SCIP_Real vubconstant, SCIP_Bool transitive, SCIP_Bool *infeasible, int *nbdchgs)
Definition var.c:15784
SCIP_Real SCIPvarGetVSIDSCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition var.c:21981
static void varIncRootboundchgs(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat)
Definition var.c:10481
void SCIPvarSetNamePointer(SCIP_VAR *var, const char *name)
Definition var.c:9103
SCIP_RETCODE SCIPvarAggregateExact(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_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_VAR *aggvar, SCIP_RATIONAL *scalar, SCIP_RATIONAL *constant, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition var.c:6909
static SCIP_RETCODE holelistDuplicate(SCIP_HOLELIST **target, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HOLELIST *source)
Definition var.c:208
SCIP_RETCODE SCIPvarChgName(SCIP_VAR *var, BMS_BLKMEM *blkmem, const char *name)
Definition var.c:3828
void SCIPvarSetHistory(SCIP_VAR *var, SCIP_HISTORY *history, SCIP_STAT *stat)
Definition var.c:6132
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:14050
void SCIPvarSetUbCertificateIndexLocal(SCIP_VAR *var, SCIP_Longint certidx)
Definition var.c:25137
void SCIPvarAdjustUbExactFloat(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *ub)
Definition var.c:9996
void SCIPvarSetProbindex(SCIP_VAR *var, int probindex)
Definition var.c:9088
static SCIP_RETCODE varAddParent(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_VAR *parentvar)
Definition var.c:3503
SCIP_Real SCIPvarGetMultaggrLbGlobal(SCIP_VAR *var, SCIP_SET *set)
Definition var.c:13871
SCIP_RETCODE SCIPvarSetRelaxSol(SCIP_VAR *var, SCIP_SET *set, SCIP_RELAXATION *relaxation, SCIP_Real solval, SCIP_Bool updateobj)
Definition var.c:19628
void SCIPvarAdjustLbExactFloat(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *lb)
Definition var.c:9945
SCIP_RETCODE SCIPvarChgBranchFactor(SCIP_VAR *var, SCIP_SET *set, SCIP_Real branchfactor)
Definition var.c:16893
static SCIP_RETCODE boundchgReleaseData(SCIP_BOUNDCHG *boundchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition var.c:1290
static SCIP_RETCODE varEventUbChangedExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LPEXACT *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_RATIONAL *oldbound, SCIP_RATIONAL *newbound)
Definition var.c:11991
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_EVENTFILTER *eventfilter, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool transitive, SCIP_Bool *infeasible, int *nbdchgs)
Definition var.c:16242
SCIP_Longint SCIPvarGetNActiveConflictsCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition var.c:21368
static SCIP_RETCODE boundchgCaptureData(SCIP_BOUNDCHG *boundchg)
Definition var.c:1258
SCIP_RETCODE SCIPvarChgObjExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PROB *prob, SCIP_PRIMAL *primal, SCIP_LPEXACT *lp, SCIP_EVENTQUEUE *eventqueue, SCIP_RATIONAL *newobj)
Definition var.c:9495
static SCIP_RETCODE varEventGlbChangedExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_RATIONAL *oldbound, SCIP_RATIONAL *newbound)
Definition var.c:10333
static SCIP_RETCODE varProcessChgBranchDirection(SCIP_VAR *var, SCIP_BRANCHDIR branchdirection)
Definition var.c:17084
SCIP_Real SCIPvarGetAvgCutoffsCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition var.c:22365
SCIP_Bool SCIPvarDoNotMultaggr(SCIP_VAR *var)
Definition var.c:8877
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:2006
SCIP_RETCODE SCIPvarGetMultaggrLbLocalExact(SCIP_VAR *var, SCIP_SET *set, SCIP_RATIONAL *result)
Definition var.c:13639
static void printBoundsExact(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, SCIP_RATIONAL *lb, SCIP_RATIONAL *ub, const char *name)
Definition var.c:3889
static void varSetProbindex(SCIP_VAR *var, int probindex)
Definition var.c:9072
SCIP_RETCODE SCIPvarGetActiveRepresentativesExact(SCIP_SET *set, SCIP_VAR **vars, SCIP_RATIONAL **scalars, int *nvars, int varssize, SCIP_RATIONAL *constant, int *requiredsize, SCIP_Bool mergemultiples)
Definition var.c:5511
SCIP_RETCODE SCIPvarAddToRowExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *prob, SCIP_LPEXACT *lpexact, SCIP_ROWEXACT *rowexact, SCIP_RATIONAL *val)
Definition var.c:20136
internal methods for problem variables