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-2023 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file var.c
26 * @ingroup OTHER_CFILES
27 * @brief methods for problem variables
28 * @author Tobias Achterberg
29 * @author Timo Berthold
30 * @author Gerald Gamrath
31 * @author Stefan Heinz
32 * @author Marc Pfetsch
33 * @author Michael Winkler
34 * @author Kati Wolter
35 * @author Stefan Vigerske
36 *
37 * @todo Possibly implement the access of bounds of multi-aggregated variables by accessing the
38 * corresponding linear constraint if it exists. This seems to require some work, since the linear
39 * constraint has to be stored. Moreover, it has even to be created in case the original constraint
40 * was deleted after multi-aggregation, but the bounds of the multi-aggregated variable should be
41 * changed. This has to be done with care in order to not loose the performance gains of
42 * multi-aggregation.
43 */
44
45/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
46
47#include "scip/cons.h"
48#include "scip/event.h"
49#include "scip/history.h"
50#include "scip/implics.h"
51#include "scip/lp.h"
52#include "scip/primal.h"
53#include "scip/prob.h"
54#include "scip/pub_cons.h"
55#include "scip/pub_history.h"
56#include "scip/pub_implics.h"
57#include "scip/pub_lp.h"
58#include "scip/pub_message.h"
59#include "scip/pub_misc.h"
60#include "scip/pub_misc_sort.h"
61#include "scip/pub_prop.h"
62#include "scip/pub_var.h"
63#include "scip/relax.h"
64#include "scip/set.h"
65#include "scip/sol.h"
66#include "scip/stat.h"
67#include "scip/struct_event.h"
68#include "scip/struct_lp.h"
69#include "scip/struct_prob.h"
70#include "scip/struct_set.h"
71#include "scip/struct_stat.h"
72#include "scip/struct_var.h"
73#include "scip/tree.h"
74#include "scip/var.h"
75#include <string.h>
76
77#define MAXIMPLSCLOSURE 100 /**< maximal number of descendants of implied variable for building closure
78 * in implication graph */
79#define MAXABSVBCOEF 1e+5 /**< maximal absolute coefficient in variable bounds added due to implications */
80
81
82/*
83 * Debugging variable release and capture
84 *
85 * Define DEBUGUSES_VARNAME to the name of the variable for which to print
86 * a backtrace when it is captured and released.
87 * Optionally define DEBUGUSES_PROBNAME to the name of a SCIP problem to consider.
88 * Have DEBUGUSES_NOADDR2LINE defined if you do not have addr2line installed on your system.
89 */
90/* #define DEBUGUSES_VARNAME "t_t_b7" */
91/* #define DEBUGUSES_PROBNAME "t_st_e35_rens" */
92/* #define DEBUGUSES_NOADDR2LINE */
93
94#ifdef DEBUGUSES_VARNAME
95#include <execinfo.h>
96#include <stdio.h>
97#include <stdlib.h>
98#include "scip/struct_scip.h"
99
100/** obtains a backtrace and prints it to stdout. */
101static
102void print_backtrace(void)
103{
104 void* array[10];
105 char** strings;
106 int size;
107 int i;
108
109 size = backtrace(array, 10);
111 if( strings == NULL )
112 return;
113
114 /* skip first entry, which is the print_backtrace function */
115 for( i = 1; i < size; ++i )
116 {
117 /* if string is something like
118 * /path/to/scip/bin/../lib/shared/libscip-7.0.1.3.linux.x86_64.gnu.dbg.so(+0x2675dd3)
119 * (that is, no function name because it is a inlined function), then call
120 * addr2line -e <libname> <addr> to get func and code line
121 * dladdr() may be an alternative
122 */
123 char* openpar;
124 char* closepar = NULL;
125#ifndef DEBUGUSES_NOADDR2LINE
126 openpar = strchr(strings[i], '(');
127 if( openpar != NULL && openpar[1] == '+' )
128 closepar = strchr(openpar+2, ')');
129#endif
130 if( closepar != NULL )
131 {
132 char cmd[SCIP_MAXSTRLEN];
133 (void) SCIPsnprintf(cmd, SCIP_MAXSTRLEN, "addr2line -f -p -e \"%.*s\" %.*s", openpar - strings[i], strings[i], closepar-openpar-1, openpar+1);
134 printf(" ");
135 fflush(stdout);
136 system(cmd);
137 }
138 else
139 printf(" %s\n", strings[i]);
140 }
141
142 free(strings);
143}
144#endif
145
146/*
147 * hole, holelist, and domain methods
148 */
149
150/** creates a new holelist element */
151static
153 SCIP_HOLELIST** holelist, /**< pointer to holelist to create */
154 BMS_BLKMEM* blkmem, /**< block memory for target holelist */
155 SCIP_SET* set, /**< global SCIP settings */
156 SCIP_Real left, /**< left bound of open interval in new hole */
157 SCIP_Real right /**< right bound of open interval in new hole */
158 )
159{
160 assert(holelist != NULL);
161 assert(blkmem != NULL);
162 assert(SCIPsetIsLT(set, left, right));
163
164 SCIPsetDebugMsg(set, "create hole list element (%.15g,%.15g) in blkmem %p\n", left, right, (void*)blkmem);
165
166 SCIP_ALLOC( BMSallocBlockMemory(blkmem, holelist) );
167 (*holelist)->hole.left = left;
168 (*holelist)->hole.right = right;
169 (*holelist)->next = NULL;
170
171 return SCIP_OKAY;
172}
173
174/** frees all elements in the holelist */
175static
177 SCIP_HOLELIST** holelist, /**< pointer to holelist to free */
178 BMS_BLKMEM* blkmem /**< block memory for target holelist */
179 )
180{
181 assert(holelist != NULL);
182 assert(blkmem != NULL);
183
184 while( *holelist != NULL )
185 {
186 SCIP_HOLELIST* next;
187
188 SCIPdebugMessage("free hole list element (%.15g,%.15g) in blkmem %p\n",
189 (*holelist)->hole.left, (*holelist)->hole.right, (void*)blkmem);
190
191 next = (*holelist)->next;
192 BMSfreeBlockMemory(blkmem, holelist);
193 assert(*holelist == NULL);
194
195 *holelist = next;
196 }
197 assert(*holelist == NULL);
198}
199
200/** duplicates a list of holes */
201static
203 SCIP_HOLELIST** target, /**< pointer to target holelist */
204 BMS_BLKMEM* blkmem, /**< block memory for target holelist */
205 SCIP_SET* set, /**< global SCIP settings */
206 SCIP_HOLELIST* source /**< holelist to duplicate */
207 )
208{
209 assert(target != NULL);
210
211 while( source != NULL )
212 {
213 assert(source->next == NULL || SCIPsetIsGE(set, source->next->hole.left, source->hole.right));
214 SCIP_CALL( holelistCreate(target, blkmem, set, source->hole.left, source->hole.right) );
215 source = source->next;
216 target = &(*target)->next;
217 }
218
219 return SCIP_OKAY;
220}
221
222/** adds a hole to the domain */
223static
225 SCIP_DOM* dom, /**< domain to add hole to */
226 BMS_BLKMEM* blkmem, /**< block memory */
227 SCIP_SET* set, /**< global SCIP settings */
228 SCIP_Real left, /**< left bound of open interval in new hole */
229 SCIP_Real right, /**< right bound of open interval in new hole */
230 SCIP_Bool* added /**< pointer to store whether the hole was added (variable didn't had that hole before), or NULL */
231 )
232{
234 SCIP_HOLELIST* next;
235
236 assert(dom != NULL);
237 assert(added != NULL);
238
239 /* search for the position of the new hole */
240 insertpos = &dom->holelist;
241 while( *insertpos != NULL && (*insertpos)->hole.left < left )
242 insertpos = &(*insertpos)->next;
243
244 /* check if new hole already exists in the hole list or is a sub hole of an existing one */
245 if( *insertpos != NULL && (*insertpos)->hole.left == left && (*insertpos)->hole.right >= right ) /*lint !e777 */
246 {
247 SCIPsetDebugMsg(set, "new hole (%.15g,%.15g) is redundant through known hole (%.15g,%.15g)\n",
248 left, right, (*insertpos)->hole.left, (*insertpos)->hole.right);
249 *added = FALSE;
250 return SCIP_OKAY;
251 }
252
253 /* add hole */
254 *added = TRUE;
255
256 next = *insertpos;
257 SCIP_CALL( holelistCreate(insertpos, blkmem, set, left, right) );
258 (*insertpos)->next = next;
259
260 return SCIP_OKAY;
261}
262
263/** merges overlapping holes into single holes, computes and moves lower and upper bound, respectively */
264/**@todo the domMerge() method is currently called if a lower or an upper bound locally or globally changed; this could
265 * be more efficient if performed with the knowledge if it was a lower or an upper bound which triggered this
266 * merge */
267static
269 SCIP_DOM* dom, /**< domain to merge */
270 BMS_BLKMEM* blkmem, /**< block memory */
271 SCIP_SET* set, /**< global SCIP settings */
272 SCIP_Real* newlb, /**< pointer to store new lower bound */
273 SCIP_Real* newub /**< pointer to store new upper bound */
274 )
275{
278 SCIP_Real* lastrightptr;
279
280 assert(dom != NULL);
281 assert(SCIPsetIsLE(set, dom->lb, dom->ub));
282
283#ifndef NDEBUG
284 {
285 /* check if the holelist is sorted w.r.t. to the left interval bounds */
286 SCIP_Real lastleft;
287
288 holelistptr = &dom->holelist;
289
291
292 while( *holelistptr != NULL )
293 {
294 if( (*holelistptr)->next != NULL )
295 {
296 assert( SCIPsetIsLE(set, lastleft, (*holelistptr)->hole.left) );
297 lastleft = (*holelistptr)->hole.left;
298 }
299
300 holelistptr = &(*holelistptr)->next;
301 }
302 }
303#endif
304
305 SCIPsetDebugMsg(set, "merge hole list\n");
306
307 holelistptr = &dom->holelist;
308 lastrightptr = &dom->lb; /* lower bound is the right bound of the hole (-infinity,lb) */
310
311 while( *holelistptr != NULL )
312 {
313 SCIPsetDebugMsg(set, "check hole (%.15g,%.15g) last right interval was <%.15g>\n", (*holelistptr)->hole.left, (*holelistptr)->hole.right, *lastrightptr);
314
315 /* check that the hole is not empty */
316 assert(SCIPsetIsLT(set, (*holelistptr)->hole.left, (*holelistptr)->hole.right));
317
318 if( SCIPsetIsGE(set, (*holelistptr)->hole.left, dom->ub) )
319 {
320 /* the remaining holes start behind the upper bound: remove them */
321 SCIPsetDebugMsg(set, "remove remaining hole since upper bound <%.15g> is less then the left hand side of the current hole\n", dom->ub);
322 holelistFree(holelistptr, blkmem);
324
325 /* unlink this hole from the previous hole */
326 *lastnextptr = NULL;
327 }
328 else if( SCIPsetIsGT(set, (*holelistptr)->hole.right, dom->ub) )
329 {
330 /* the hole overlaps the upper bound: decrease upper bound, remove this hole and all remaining holes */
331 SCIPsetDebugMsg(set, "upper bound <%.15g> lays in current hole; store new upper bound and remove this and all remaining holes\n", dom->ub);
332
333 assert(SCIPsetIsLT(set, (*holelistptr)->hole.left, dom->ub));
334
335 /* adjust upper bound */
336 dom->ub = (*holelistptr)->hole.left;
337
338 if(newub != NULL )
339 *newub = (*holelistptr)->hole.left;
340
341 /* remove remaining hole list */
342 holelistFree(holelistptr, blkmem);
344
345 /* unlink this hole from the previous hole */
346 *lastnextptr = NULL;
347 }
348 else if( SCIPsetIsGT(set, *lastrightptr, (*holelistptr)->hole.left) )
349 {
350 /* the right bound of the last hole is greater than the left bound of this hole: increase the right bound of
351 * the last hole, delete this hole */
353
354 if( SCIPsetIsEQ(set, *lastrightptr, dom->lb ) )
355 {
356 /* the reason for the overlap results from the lower bound hole (-infinity,lb); therefore, we can increase
357 * the lower bound */
358 SCIPsetDebugMsg(set, "lower bound <%.15g> lays in current hole; store new lower bound and remove hole\n", dom->lb);
359 *lastrightptr = MAX(*lastrightptr, (*holelistptr)->hole.right);
360
361 /* adjust lower bound */
362 dom->lb = *lastrightptr;
363
364 if(newlb != NULL )
366 }
367 else
368 {
369 SCIPsetDebugMsg(set, "current hole overlaps with the previous one (...,%.15g); merge to (...,%.15g)\n",
370 *lastrightptr, MAX(*lastrightptr, (*holelistptr)->hole.right) );
371 *lastrightptr = MAX(*lastrightptr, (*holelistptr)->hole.right);
372 }
373 nextholelist = (*holelistptr)->next;
374 (*holelistptr)->next = NULL;
375 holelistFree(holelistptr, blkmem);
376
377 /* connect the linked list after removing the hole */
379
380 /* get next hole */
382 }
383 else
384 {
385 /* the holes do not overlap: update lastholelist and lastrightptr */
386 lastrightptr = &(*holelistptr)->hole.right;
387 lastnextptr = &(*holelistptr)->next;
388
389 /* get next hole */
390 holelistptr = &(*holelistptr)->next;
391 }
392 }
393
394#ifndef NDEBUG
395 {
396 /* check that holes are merged */
397 SCIP_Real lastright;
398
399 lastright = dom->lb; /* lower bound is the right bound of the hole (-infinity,lb) */
400 holelistptr = &dom->holelist;
401
402 while( *holelistptr != NULL )
403 {
404 /* check the the last right interval is smaller or equal to the current left interval (none overlapping) */
405 assert( SCIPsetIsLE(set, lastright, (*holelistptr)->hole.left) );
406
407 /* check the hole property (check that the hole is not empty) */
408 assert( SCIPsetIsLT(set, (*holelistptr)->hole.left, (*holelistptr)->hole.right) );
409 lastright = (*holelistptr)->hole.right;
410
411 /* get next hole */
412 holelistptr = &(*holelistptr)->next;
413 }
414
415 /* check the the last right interval is smaller or equal to the upper bound (none overlapping) */
417 }
418#endif
419}
420
421/*
422 * domain change methods
423 */
424
425/** ensures, that bound change info array for lower bound changes can store at least num entries */
426static
428 SCIP_VAR* var, /**< problem variable */
429 BMS_BLKMEM* blkmem, /**< block memory */
430 SCIP_SET* set, /**< global SCIP settings */
431 int num /**< minimum number of entries to store */
432 )
433{
434 assert(var != NULL);
437
438 if( num > var->lbchginfossize )
439 {
440 int newsize;
441
445 }
446 assert(num <= var->lbchginfossize);
447
448 return SCIP_OKAY;
449}
450
451/** ensures, that bound change info array for upper bound changes can store at least num entries */
452static
454 SCIP_VAR* var, /**< problem variable */
455 BMS_BLKMEM* blkmem, /**< block memory */
456 SCIP_SET* set, /**< global SCIP settings */
457 int num /**< minimum number of entries to store */
458 )
459{
460 assert(var != NULL);
463
464 if( num > var->ubchginfossize )
465 {
466 int newsize;
467
471 }
472 assert(num <= var->ubchginfossize);
473
474 return SCIP_OKAY;
475}
476
477/** adds domain change info to the variable's lower bound change info array */
478static
480 SCIP_VAR* var, /**< problem variable */
481 BMS_BLKMEM* blkmem, /**< block memory */
482 SCIP_SET* set, /**< global SCIP settings */
483 SCIP_Real oldbound, /**< old value for bound */
484 SCIP_Real newbound, /**< new value for bound */
485 int depth, /**< depth in the tree, where the bound change takes place */
486 int pos, /**< position of the bound change in its bound change array */
487 SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself) */
488 SCIP_CONS* infercons, /**< constraint that inferred this bound change, or NULL */
489 SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
490 int inferinfo, /**< user information for inference to help resolving the conflict */
491 SCIP_BOUNDTYPE inferboundtype, /**< type of bound for inference var: lower or upper bound */
492 SCIP_BOUNDCHGTYPE boundchgtype /**< bound change type: branching decision or inferred bound change */
493 )
494{
495 assert(var != NULL);
496 assert(SCIPsetIsLT(set, oldbound, newbound));
499 assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, oldbound, 0.0));
500 assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, 1.0));
501 assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
502 assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
503 assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
504
505 SCIPsetDebugMsg(set, "adding lower bound change info to var <%s>[%g,%g]: depth=%d, pos=%d, infer%s=<%s>, inferinfo=%d, %g -> %g\n",
506 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, depth, pos, infercons != NULL ? "cons" : "prop",
507 infercons != NULL ? SCIPconsGetName(infercons) : (inferprop != NULL ? SCIPpropGetName(inferprop) : "-"), inferinfo,
508 oldbound, newbound);
509
511 var->lbchginfos[var->nlbchginfos].oldbound = oldbound;
512 var->lbchginfos[var->nlbchginfos].newbound = newbound;
516 var->lbchginfos[var->nlbchginfos].pos = var->nlbchginfos; /*lint !e732*/
517 var->lbchginfos[var->nlbchginfos].boundchgtype = boundchgtype; /*lint !e641*/
520 var->lbchginfos[var->nlbchginfos].inferboundtype = inferboundtype; /*lint !e641*/
522 var->lbchginfos[var->nlbchginfos].inferencedata.info = inferinfo;
523
524 /**@note The "pos" data member of the bound change info has a size of 27 bits */
525 assert(var->nlbchginfos < 1 << 27);
526
527 switch( boundchgtype )
528 {
530 break;
532 assert(infercons != NULL);
533 var->lbchginfos[var->nlbchginfos].inferencedata.reason.cons = infercons;
534 break;
536 var->lbchginfos[var->nlbchginfos].inferencedata.reason.prop = inferprop;
537 break;
538 default:
539 SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
540 return SCIP_INVALIDDATA;
541 }
542
543 var->nlbchginfos++;
544
548
549 return SCIP_OKAY;
550}
551
552/** adds domain change info to the variable's upper bound change info array */
553static
555 SCIP_VAR* var, /**< problem variable */
556 BMS_BLKMEM* blkmem, /**< block memory */
557 SCIP_SET* set, /**< global SCIP settings */
558 SCIP_Real oldbound, /**< old value for bound */
559 SCIP_Real newbound, /**< new value for bound */
560 int depth, /**< depth in the tree, where the bound change takes place */
561 int pos, /**< position of the bound change in its bound change array */
562 SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself) */
563 SCIP_CONS* infercons, /**< constraint that inferred this bound change, or NULL */
564 SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
565 int inferinfo, /**< user information for inference to help resolving the conflict */
566 SCIP_BOUNDTYPE inferboundtype, /**< type of bound for inference var: lower or upper bound */
567 SCIP_BOUNDCHGTYPE boundchgtype /**< bound change type: branching decision or inferred bound change */
568 )
569{
570 assert(var != NULL);
571 assert(SCIPsetIsGT(set, oldbound, newbound));
574 assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, oldbound, 1.0));
575 assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, 0.0));
576 assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
577 assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
578 assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
579
580 SCIPsetDebugMsg(set, "adding upper bound change info to var <%s>[%g,%g]: depth=%d, pos=%d, infer%s=<%s>, inferinfo=%d, %g -> %g\n",
581 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, depth, pos, infercons != NULL ? "cons" : "prop",
582 infercons != NULL ? SCIPconsGetName(infercons) : (inferprop != NULL ? SCIPpropGetName(inferprop) : "-"), inferinfo,
583 oldbound, newbound);
584
586 var->ubchginfos[var->nubchginfos].oldbound = oldbound;
587 var->ubchginfos[var->nubchginfos].newbound = newbound;
591 var->ubchginfos[var->nubchginfos].pos = var->nubchginfos; /*lint !e732*/
592 var->ubchginfos[var->nubchginfos].boundchgtype = boundchgtype; /*lint !e641*/
595 var->ubchginfos[var->nubchginfos].inferboundtype = inferboundtype; /*lint !e641*/
597 var->ubchginfos[var->nubchginfos].inferencedata.info = inferinfo;
598
599 /**@note The "pos" data member of the bound change info has a size of 27 bits */
600 assert(var->nubchginfos < 1 << 27);
601
602 switch( boundchgtype )
603 {
605 break;
607 assert(infercons != NULL);
608 var->ubchginfos[var->nubchginfos].inferencedata.reason.cons = infercons;
609 break;
611 var->ubchginfos[var->nubchginfos].inferencedata.reason.prop = inferprop;
612 break;
613 default:
614 SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
615 return SCIP_INVALIDDATA;
616 }
617
618 var->nubchginfos++;
619
623
624 return SCIP_OKAY;
625}
626
627/** applies single bound change */
629 SCIP_BOUNDCHG* boundchg, /**< bound change to apply */
630 BMS_BLKMEM* blkmem, /**< block memory */
631 SCIP_SET* set, /**< global SCIP settings */
632 SCIP_STAT* stat, /**< problem statistics */
633 SCIP_LP* lp, /**< current LP data */
634 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
635 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
636 int depth, /**< depth in the tree, where the bound change takes place */
637 int pos, /**< position of the bound change in its bound change array */
638 SCIP_Bool* cutoff /**< pointer to store whether an infeasible bound change was detected */
639 )
640{
641 SCIP_VAR* var;
642
643 assert(boundchg != NULL);
644 assert(stat != NULL);
645 assert(depth > 0);
646 assert(pos >= 0);
647 assert(cutoff != NULL);
648
649 *cutoff = FALSE;
650
651 /* ignore redundant bound changes */
652 if( boundchg->redundant )
653 return SCIP_OKAY;
654
655 var = boundchg->var;
656 assert(var != NULL);
659
660 /* apply bound change */
661 switch( boundchg->boundtype )
662 {
664 /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
665 if( SCIPsetIsGT(set, boundchg->newbound, var->locdom.lb) )
666 {
667 if( SCIPsetIsLE(set, boundchg->newbound, var->locdom.ub) )
668 {
669 /* add the bound change info to the variable's bound change info array */
670 switch( boundchg->boundchgtype )
671 {
673 SCIPsetDebugMsg(set, " -> branching: new lower bound of <%s>[%g,%g]: %g\n",
675 SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
677 stat->lastbranchvar = var;
679 stat->lastbranchvalue = boundchg->newbound;
680 break;
681
683 assert(boundchg->data.inferencedata.reason.cons != NULL);
684 SCIPsetDebugMsg(set, " -> constraint <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
685 SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
687 SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
688 boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
689 boundchg->data.inferencedata.info,
691 break;
692
694 SCIPsetDebugMsg(set, " -> propagator <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
695 boundchg->data.inferencedata.reason.prop != NULL
696 ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
698 SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
699 boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
700 boundchg->data.inferencedata.info,
702 break;
703
704 default:
705 SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
706 return SCIP_INVALIDDATA;
707 }
708
709 /* change local bound of variable */
710 SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, boundchg->newbound) );
711 }
712 else
713 {
714 SCIPsetDebugMsg(set, " -> cutoff: new lower bound of <%s>[%g,%g]: %g\n",
716 *cutoff = TRUE;
717 boundchg->redundant = TRUE; /* bound change has not entered the lbchginfos array of the variable! */
718 }
719 }
720 else
721 {
722 /* mark bound change to be inactive */
723 SCIPsetDebugMsg(set, " -> inactive %s: new lower bound of <%s>[%g,%g]: %g\n",
724 (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
726 boundchg->redundant = TRUE;
727 }
728 break;
729
731 /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
732 if( SCIPsetIsLT(set, boundchg->newbound, var->locdom.ub) )
733 {
734 if( SCIPsetIsGE(set, boundchg->newbound, var->locdom.lb) )
735 {
736 /* add the bound change info to the variable's bound change info array */
737 switch( boundchg->boundchgtype )
738 {
740 SCIPsetDebugMsg(set, " -> branching: new upper bound of <%s>[%g,%g]: %g\n",
742 SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
744 stat->lastbranchvar = var;
746 stat->lastbranchvalue = boundchg->newbound;
747 break;
748
750 assert(boundchg->data.inferencedata.reason.cons != NULL);
751 SCIPsetDebugMsg(set, " -> constraint <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
752 SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
754 SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
755 boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
756 boundchg->data.inferencedata.info,
758 break;
759
761 SCIPsetDebugMsg(set, " -> propagator <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
762 boundchg->data.inferencedata.reason.prop != NULL
763 ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
765 SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
766 boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
767 boundchg->data.inferencedata.info,
769 break;
770
771 default:
772 SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
773 return SCIP_INVALIDDATA;
774 }
775
776 /* change local bound of variable */
777 SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, boundchg->newbound) );
778 }
779 else
780 {
781 SCIPsetDebugMsg(set, " -> cutoff: new upper bound of <%s>[%g,%g]: %g\n",
783 *cutoff = TRUE;
784 boundchg->redundant = TRUE; /* bound change has not entered the ubchginfos array of the variable! */
785 }
786 }
787 else
788 {
789 /* mark bound change to be inactive */
790 SCIPsetDebugMsg(set, " -> inactive %s: new upper bound of <%s>[%g,%g]: %g\n",
791 (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
793 boundchg->redundant = TRUE;
794 }
795 break;
796
797 default:
798 SCIPerrorMessage("unknown bound type\n");
799 return SCIP_INVALIDDATA;
800 }
801
802 /* update the branching and inference history */
803 if( !boundchg->applied && !boundchg->redundant )
804 {
805 assert(var == boundchg->var);
806
808 {
809 SCIP_CALL( SCIPvarIncNBranchings(var, blkmem, set, stat,
812 }
813 else if( stat->lastbranchvar != NULL )
814 {
815 /**@todo if last branching variable is unknown, retrieve it from the nodes' boundchg arrays */
816 SCIP_CALL( SCIPvarIncInferenceSum(stat->lastbranchvar, blkmem, set, stat, stat->lastbranchdir, stat->lastbranchvalue, 1.0) );
817 }
818 boundchg->applied = TRUE;
819 }
820
821 return SCIP_OKAY;
822}
823
824/** undoes single bound change */
826 SCIP_BOUNDCHG* boundchg, /**< bound change to remove */
827 BMS_BLKMEM* blkmem, /**< block memory */
828 SCIP_SET* set, /**< global SCIP settings */
829 SCIP_STAT* stat, /**< problem statistics */
830 SCIP_LP* lp, /**< current LP data */
831 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
832 SCIP_EVENTQUEUE* eventqueue /**< event queue */
833 )
834{
835 SCIP_VAR* var;
836
837 assert(boundchg != NULL);
838 assert(stat != NULL);
839
840 /* ignore redundant bound changes */
841 if( boundchg->redundant )
842 return SCIP_OKAY;
843
844 var = boundchg->var;
845 assert(var != NULL);
847
848 /* undo bound change: apply the previous bound change of variable */
849 switch( boundchg->boundtype )
850 {
852 var->nlbchginfos--;
853 assert(var->nlbchginfos >= 0);
856 assert( SCIPsetIsFeasLE(set, boundchg->newbound, var->locdom.lb) ); /* current lb might be larger to intermediate global bound change */
857
858 SCIPsetDebugMsg(set, "removed lower bound change info of var <%s>[%g,%g]: depth=%d, pos=%d, %g -> %g\n",
862
863 /* reinstall the previous local bound */
864 SCIP_CALL( SCIPvarChgLbLocal(boundchg->var, blkmem, set, stat, lp, branchcand, eventqueue,
866
867 /* in case all bound changes are removed the local bound should match the global bound */
869
870 break;
871
873 var->nubchginfos--;
874 assert(var->nubchginfos >= 0);
877 assert( SCIPsetIsFeasGE(set, boundchg->newbound, var->locdom.ub) ); /* current ub might be smaller to intermediate global bound change */
878
879 SCIPsetDebugMsg(set, "removed upper bound change info of var <%s>[%g,%g]: depth=%d, pos=%d, %g -> %g\n",
883
884 /* reinstall the previous local bound */
885 SCIP_CALL( SCIPvarChgUbLocal(boundchg->var, blkmem, set, stat, lp, branchcand, eventqueue,
887
888 /* in case all bound changes are removed the local bound should match the global bound */
890
891 break;
892
893 default:
894 SCIPerrorMessage("unknown bound type\n");
895 return SCIP_INVALIDDATA;
896 }
897
898 /* update last branching variable */
900 {
901 stat->lastbranchvar = NULL;
903 }
904
905 return SCIP_OKAY;
906}
907
908/** applies single bound change to the global problem by changing the global bound of the corresponding variable */
909static
911 SCIP_BOUNDCHG* boundchg, /**< bound change to apply */
912 BMS_BLKMEM* blkmem, /**< block memory */
913 SCIP_SET* set, /**< global SCIP settings */
914 SCIP_STAT* stat, /**< problem statistics */
915 SCIP_LP* lp, /**< current LP data */
916 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
917 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
918 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
919 SCIP_Bool* cutoff /**< pointer to store whether an infeasible bound change was detected */
920 )
921{
922 SCIP_VAR* var;
923 SCIP_Real newbound;
924 SCIP_BOUNDTYPE boundtype;
925
926 assert(boundchg != NULL);
927 assert(cutoff != NULL);
928
929 *cutoff = FALSE;
930
931 /* ignore redundant bound changes */
932 if( boundchg->redundant )
933 return SCIP_OKAY;
934
938
939 /* check if the bound change is redundant which can happen due to a (better) global bound change which was performed
940 * after that bound change was applied
941 *
942 * @note a global bound change is not captured by the redundant member of the bound change data structure
943 */
944 if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasLE(set, newbound, SCIPvarGetLbGlobal(var)))
945 || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasGE(set, newbound, SCIPvarGetUbGlobal(var))) )
946 {
947 return SCIP_OKAY;
948 }
949
950 SCIPsetDebugMsg(set, "applying global bound change: <%s>[%g,%g] %s %g\n",
952 boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", newbound);
953
954 /* check for cutoff */
955 if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGT(set, newbound, SCIPvarGetUbGlobal(var)))
956 || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLT(set, newbound, SCIPvarGetLbGlobal(var))) )
957 {
958 *cutoff = TRUE;
959 return SCIP_OKAY;
960 }
961
962 /* apply bound change */
963 SCIP_CALL( SCIPvarChgBdGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound, boundtype) );
964
965 return SCIP_OKAY;
966}
967
968/** captures branching and inference data of bound change */
969static
971 SCIP_BOUNDCHG* boundchg /**< bound change to remove */
972 )
973{
974 assert(boundchg != NULL);
975
976 /* capture variable associated with the bound change */
977 assert(boundchg->var != NULL);
979
980 switch( boundchg->boundchgtype )
981 {
984 break;
985
987 assert(boundchg->data.inferencedata.var != NULL);
988 assert(boundchg->data.inferencedata.reason.cons != NULL);
989 SCIPconsCapture(boundchg->data.inferencedata.reason.cons);
990 break;
991
992 default:
993 SCIPerrorMessage("invalid bound change type\n");
994 return SCIP_INVALIDDATA;
995 }
996
997 return SCIP_OKAY;
998}
999
1000/** releases branching and inference data of bound change */
1001static
1003 SCIP_BOUNDCHG* boundchg, /**< bound change to remove */
1004 BMS_BLKMEM* blkmem, /**< block memory */
1005 SCIP_SET* set, /**< global SCIP settings */
1006 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1007 SCIP_LP* lp /**< current LP data */
1008
1009 )
1010{
1011 assert(boundchg != NULL);
1012
1013 switch( boundchg->boundchgtype )
1014 {
1017 break;
1018
1020 assert(boundchg->data.inferencedata.var != NULL);
1021 assert(boundchg->data.inferencedata.reason.cons != NULL);
1022 SCIP_CALL( SCIPconsRelease(&boundchg->data.inferencedata.reason.cons, blkmem, set) );
1023 break;
1024
1025 default:
1026 SCIPerrorMessage("invalid bound change type\n");
1027 return SCIP_INVALIDDATA;
1028 }
1029
1030 /* release variable */
1031 assert(boundchg->var != NULL);
1032 SCIP_CALL( SCIPvarRelease(&boundchg->var, blkmem, set, eventqueue, lp) );
1033
1034 return SCIP_OKAY;
1035}
1036
1037/** creates empty domain change data with dynamic arrays */
1038static
1040 SCIP_DOMCHG** domchg, /**< pointer to domain change data */
1041 BMS_BLKMEM* blkmem /**< block memory */
1042 )
1043{
1044 assert(domchg != NULL);
1045 assert(blkmem != NULL);
1046
1047 SCIP_ALLOC( BMSallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN)) );
1048 (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1049 (*domchg)->domchgdyn.nboundchgs = 0;
1050 (*domchg)->domchgdyn.boundchgs = NULL;
1051 (*domchg)->domchgdyn.nholechgs = 0;
1052 (*domchg)->domchgdyn.holechgs = NULL;
1053 (*domchg)->domchgdyn.boundchgssize = 0;
1054 (*domchg)->domchgdyn.holechgssize = 0;
1055
1056 return SCIP_OKAY;
1057}
1058
1059/** frees domain change data */
1061 SCIP_DOMCHG** domchg, /**< pointer to domain change */
1062 BMS_BLKMEM* blkmem, /**< block memory */
1063 SCIP_SET* set, /**< global SCIP settings */
1064 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1065 SCIP_LP* lp /**< current LP data */
1066 )
1067{
1068 assert(domchg != NULL);
1069 assert(blkmem != NULL);
1070
1071 if( *domchg != NULL )
1072 {
1073 int i;
1074
1075 /* release variables, branching and inference data associated with the bound changes */
1076 for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1077 {
1078 SCIP_CALL( boundchgReleaseData(&(*domchg)->domchgbound.boundchgs[i], blkmem, set, eventqueue, lp) );
1079 }
1080
1081 /* free memory for bound and hole changes */
1082 switch( (*domchg)->domchgdyn.domchgtype )
1083 {
1085 BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgbound.boundchgs, (*domchg)->domchgbound.nboundchgs);
1086 BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOUND));
1087 break;
1089 BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgboth.boundchgs, (*domchg)->domchgboth.nboundchgs);
1090 BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgboth.holechgs, (*domchg)->domchgboth.nholechgs);
1091 BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH));
1092 break;
1094 BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.boundchgs, (*domchg)->domchgdyn.boundchgssize);
1095 BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.holechgs, (*domchg)->domchgdyn.holechgssize);
1096 BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN));
1097 break;
1098 default:
1099 SCIPerrorMessage("invalid domain change type\n");
1100 return SCIP_INVALIDDATA;
1101 }
1102 }
1103
1104 return SCIP_OKAY;
1105}
1106
1107/** converts a static domain change data into a dynamic one */
1108static
1110 SCIP_DOMCHG** domchg, /**< pointer to domain change data */
1111 BMS_BLKMEM* blkmem /**< block memory */
1112 )
1113{
1114 assert(domchg != NULL);
1115 assert(blkmem != NULL);
1116
1117 SCIPdebugMessage("making domain change data %p pointing to %p dynamic\n", (void*)domchg, (void*)*domchg);
1118
1119 if( *domchg == NULL )
1120 {
1121 SCIP_CALL( domchgCreate(domchg, blkmem) );
1122 }
1123 else
1124 {
1125 switch( (*domchg)->domchgdyn.domchgtype )
1126 {
1128 SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOUND), sizeof(SCIP_DOMCHGDYN)) );
1129 (*domchg)->domchgdyn.nholechgs = 0;
1130 (*domchg)->domchgdyn.holechgs = NULL;
1131 (*domchg)->domchgdyn.boundchgssize = (int) (*domchg)->domchgdyn.nboundchgs;
1132 (*domchg)->domchgdyn.holechgssize = 0;
1133 (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1134 break;
1136 SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH), sizeof(SCIP_DOMCHGDYN)) );
1137 (*domchg)->domchgdyn.boundchgssize = (int) (*domchg)->domchgdyn.nboundchgs;
1138 (*domchg)->domchgdyn.holechgssize = (*domchg)->domchgdyn.nholechgs;
1139 (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1140 break;
1142 break;
1143 default:
1144 SCIPerrorMessage("invalid domain change type\n");
1145 return SCIP_INVALIDDATA;
1146 }
1147 }
1148#ifndef NDEBUG
1149 {
1150 int i;
1151 for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1152 assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1153 || EPSISINT((*domchg)->domchgbound.boundchgs[i].newbound, 1e-06));
1154 }
1155#endif
1156
1157 return SCIP_OKAY;
1158}
1159
1160/** converts a dynamic domain change data into a static one, using less memory than for a dynamic one */
1162 SCIP_DOMCHG** domchg, /**< pointer to domain change data */
1163 BMS_BLKMEM* blkmem, /**< block memory */
1164 SCIP_SET* set, /**< global SCIP settings */
1165 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1166 SCIP_LP* lp /**< current LP data */
1167 )
1168{
1169 assert(domchg != NULL);
1170 assert(blkmem != NULL);
1171
1172 SCIPsetDebugMsg(set, "making domain change data %p pointing to %p static\n", (void*)domchg, (void*)*domchg);
1173
1174 if( *domchg != NULL )
1175 {
1176 switch( (*domchg)->domchgdyn.domchgtype )
1177 {
1179 if( (*domchg)->domchgbound.nboundchgs == 0 )
1180 {
1181 SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1182 }
1183 break;
1185 if( (*domchg)->domchgboth.nholechgs == 0 )
1186 {
1187 if( (*domchg)->domchgbound.nboundchgs == 0 )
1188 {
1189 SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1190 }
1191 else
1192 {
1193 SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH), sizeof(SCIP_DOMCHGBOUND)) );
1194 (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOUND; /*lint !e641*/
1195 }
1196 }
1197 break;
1199 if( (*domchg)->domchgboth.nholechgs == 0 )
1200 {
1201 if( (*domchg)->domchgbound.nboundchgs == 0 )
1202 {
1203 SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1204 }
1205 else
1206 {
1207 /* shrink dynamic size arrays to their minimal sizes */
1208 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.boundchgs, \
1209 (*domchg)->domchgdyn.boundchgssize, (*domchg)->domchgdyn.nboundchgs) ); /*lint !e571*/
1210 BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.holechgs, (*domchg)->domchgdyn.holechgssize);
1211
1212 /* convert into static domain change */
1213 SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN), sizeof(SCIP_DOMCHGBOUND)) );
1214 (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOUND; /*lint !e641*/
1215 }
1216 }
1217 else
1218 {
1219 /* shrink dynamic size arrays to their minimal sizes */
1220 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.boundchgs, \
1221 (*domchg)->domchgdyn.boundchgssize, (*domchg)->domchgdyn.nboundchgs) ); /*lint !e571*/
1222 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.holechgs, \
1223 (*domchg)->domchgdyn.holechgssize, (*domchg)->domchgdyn.nholechgs) );
1224
1225 /* convert into static domain change */
1226 SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN), sizeof(SCIP_DOMCHGBOTH)) );
1227 (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOTH; /*lint !e641*/
1228 }
1229 break;
1230 default:
1231 SCIPerrorMessage("invalid domain change type\n");
1232 return SCIP_INVALIDDATA;
1233 }
1234#ifndef NDEBUG
1235 if( *domchg != NULL )
1236 {
1237 int i;
1238 for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1239 assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1240 || SCIPsetIsFeasIntegral(set, (*domchg)->domchgbound.boundchgs[i].newbound));
1241 }
1242#endif
1243 }
1244
1245 return SCIP_OKAY;
1246}
1247
1248/** ensures, that boundchgs array can store at least num entries */
1249static
1251 SCIP_DOMCHG* domchg, /**< domain change data structure */
1252 BMS_BLKMEM* blkmem, /**< block memory */
1253 SCIP_SET* set, /**< global SCIP settings */
1254 int num /**< minimum number of entries to store */
1255 )
1256{
1257 assert(domchg != NULL);
1258 assert(domchg->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1259
1260 if( num > domchg->domchgdyn.boundchgssize )
1261 {
1262 int newsize;
1263
1267 }
1268 assert(num <= domchg->domchgdyn.boundchgssize);
1269
1270 return SCIP_OKAY;
1271}
1272
1273/** ensures, that holechgs array can store at least num additional entries */
1274static
1276 SCIP_DOMCHG* domchg, /**< domain change data structure */
1277 BMS_BLKMEM* blkmem, /**< block memory */
1278 SCIP_SET* set, /**< global SCIP settings */
1279 int num /**< minimum number of additional entries to store */
1280 )
1281{
1282 assert(domchg != NULL);
1283 assert(domchg->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1284
1285 if( num > domchg->domchgdyn.holechgssize )
1286 {
1287 int newsize;
1288
1291 domchg->domchgdyn.holechgssize = newsize;
1292 }
1293 assert(num <= domchg->domchgdyn.holechgssize);
1294
1295 return SCIP_OKAY;
1296}
1297
1298/** applies domain change */
1300 SCIP_DOMCHG* domchg, /**< domain change to apply */
1301 BMS_BLKMEM* blkmem, /**< block memory */
1302 SCIP_SET* set, /**< global SCIP settings */
1303 SCIP_STAT* stat, /**< problem statistics */
1304 SCIP_LP* lp, /**< current LP data */
1305 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1306 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1307 int depth, /**< depth in the tree, where the domain change takes place */
1308 SCIP_Bool* cutoff /**< pointer to store whether an infeasible domain change was detected */
1309 )
1310{
1311 int i;
1312
1313 assert(cutoff != NULL);
1314
1315 *cutoff = FALSE;
1316
1317 SCIPsetDebugMsg(set, "applying domain changes at %p in depth %d\n", (void*)domchg, depth);
1318
1319 if( domchg == NULL )
1320 return SCIP_OKAY;
1321
1322 /* apply bound changes */
1323 for( i = 0; i < (int)domchg->domchgbound.nboundchgs; ++i )
1324 {
1325 SCIP_CALL( SCIPboundchgApply(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp,
1326 branchcand, eventqueue, depth, i, cutoff) );
1327 if( *cutoff )
1328 break;
1329 }
1330 SCIPsetDebugMsg(set, " -> %u bound changes (cutoff %u)\n", domchg->domchgbound.nboundchgs, *cutoff);
1331
1332 /* mark all bound changes after a cutoff redundant */
1333 for( ; i < (int)domchg->domchgbound.nboundchgs; ++i )
1335
1336 /* apply holelist changes */
1337 if( domchg->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_BOUND ) /*lint !e641*/
1338 {
1339 for( i = 0; i < domchg->domchgboth.nholechgs; ++i )
1340 *(domchg->domchgboth.holechgs[i].ptr) = domchg->domchgboth.holechgs[i].newlist;
1341 SCIPsetDebugMsg(set, " -> %d hole changes\n", domchg->domchgboth.nholechgs);
1342 }
1343
1344 return SCIP_OKAY;
1345}
1346
1347/** undoes domain change */
1349 SCIP_DOMCHG* domchg, /**< domain change to remove */
1350 BMS_BLKMEM* blkmem, /**< block memory */
1351 SCIP_SET* set, /**< global SCIP settings */
1352 SCIP_STAT* stat, /**< problem statistics */
1353 SCIP_LP* lp, /**< current LP data */
1354 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1355 SCIP_EVENTQUEUE* eventqueue /**< event queue */
1356 )
1357{
1358 int i;
1359
1360 SCIPsetDebugMsg(set, "undoing domain changes at %p\n", (void*)domchg);
1361 if( domchg == NULL )
1362 return SCIP_OKAY;
1363
1364 /* undo holelist changes */
1365 if( domchg->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_BOUND ) /*lint !e641*/
1366 {
1367 for( i = domchg->domchgboth.nholechgs-1; i >= 0; --i )
1368 *(domchg->domchgboth.holechgs[i].ptr) = domchg->domchgboth.holechgs[i].oldlist;
1369 SCIPsetDebugMsg(set, " -> %d hole changes\n", domchg->domchgboth.nholechgs);
1370 }
1371
1372 /* undo bound changes */
1373 for( i = domchg->domchgbound.nboundchgs-1; i >= 0; --i )
1374 {
1375 SCIP_CALL( SCIPboundchgUndo(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp, branchcand, eventqueue) );
1376 }
1377 SCIPsetDebugMsg(set, " -> %u bound changes\n", domchg->domchgbound.nboundchgs);
1378
1379 return SCIP_OKAY;
1380}
1381
1382/** applies domain change to the global problem */
1384 SCIP_DOMCHG* domchg, /**< domain change to apply */
1385 BMS_BLKMEM* blkmem, /**< block memory */
1386 SCIP_SET* set, /**< global SCIP settings */
1387 SCIP_STAT* stat, /**< problem statistics */
1388 SCIP_LP* lp, /**< current LP data */
1389 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1390 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1391 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1392 SCIP_Bool* cutoff /**< pointer to store whether an infeasible domain change was detected */
1393 )
1394{
1395 int i;
1396
1397 assert(cutoff != NULL);
1398
1399 *cutoff = FALSE;
1400
1401 if( domchg == NULL )
1402 return SCIP_OKAY;
1403
1404 SCIPsetDebugMsg(set, "applying domain changes at %p to the global problem\n", (void*)domchg);
1405
1406 /* apply bound changes */
1407 for( i = 0; i < (int)domchg->domchgbound.nboundchgs; ++i )
1408 {
1409 SCIP_CALL( boundchgApplyGlobal(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp,
1410 branchcand, eventqueue, cliquetable, cutoff) );
1411 if( *cutoff )
1412 break;
1413 }
1414 SCIPsetDebugMsg(set, " -> %u global bound changes\n", domchg->domchgbound.nboundchgs);
1415
1416 /**@todo globally apply holelist changes - how can this be done without confusing pointer updates? */
1417
1418 return SCIP_OKAY;
1419}
1420
1421/** adds bound change to domain changes */
1423 SCIP_DOMCHG** domchg, /**< pointer to domain change data structure */
1424 BMS_BLKMEM* blkmem, /**< block memory */
1425 SCIP_SET* set, /**< global SCIP settings */
1426 SCIP_VAR* var, /**< variable to change the bounds for */
1427 SCIP_Real newbound, /**< new value for bound */
1428 SCIP_BOUNDTYPE boundtype, /**< type of bound for var: lower or upper bound */
1429 SCIP_BOUNDCHGTYPE boundchgtype, /**< type of bound change: branching decision or inference */
1430 SCIP_Real lpsolval, /**< solval of variable in last LP on path to node, or SCIP_INVALID if unknown */
1431 SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself), or NULL */
1432 SCIP_CONS* infercons, /**< constraint that deduced the bound change, or NULL */
1433 SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
1434 int inferinfo, /**< user information for inference to help resolving the conflict */
1435 SCIP_BOUNDTYPE inferboundtype /**< type of bound for inference var: lower or upper bound */
1436 )
1437{
1439
1440 assert(domchg != NULL);
1441 assert(var != NULL);
1444 assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, boundtype == SCIP_BOUNDTYPE_LOWER ? 1.0 : 0.0));
1445 assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
1446 assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
1447 assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
1448
1449 SCIPsetDebugMsg(set, "adding %s bound change <%s: %g> of variable <%s> to domain change at %p pointing to %p\n",
1450 boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
1451 newbound, var->name, (void*)domchg, (void*)*domchg);
1452
1453 /* if domain change data doesn't exist, create it;
1454 * if domain change is static, convert it into dynamic change
1455 */
1456 if( *domchg == NULL )
1457 {
1458 SCIP_CALL( domchgCreate(domchg, blkmem) );
1459 }
1460 else if( (*domchg)->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_DYNAMIC ) /*lint !e641*/
1461 {
1462 SCIP_CALL( domchgMakeDynamic(domchg, blkmem) );
1463 }
1464 assert(*domchg != NULL && (*domchg)->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1465
1466 /* get memory for additional bound change */
1467 SCIP_CALL( domchgEnsureBoundchgsSize(*domchg, blkmem, set, (*domchg)->domchgdyn.nboundchgs+1) );
1468
1469 /* fill in the bound change data */
1470 boundchg = &(*domchg)->domchgdyn.boundchgs[(*domchg)->domchgdyn.nboundchgs];
1471 boundchg->var = var;
1472 switch( boundchgtype )
1473 {
1475 boundchg->data.branchingdata.lpsolval = lpsolval;
1476 break;
1478 assert(infercons != NULL);
1479 boundchg->data.inferencedata.var = infervar;
1480 boundchg->data.inferencedata.reason.cons = infercons;
1481 boundchg->data.inferencedata.info = inferinfo;
1482 break;
1484 boundchg->data.inferencedata.var = infervar;
1485 boundchg->data.inferencedata.reason.prop = inferprop;
1486 boundchg->data.inferencedata.info = inferinfo;
1487 break;
1488 default:
1489 SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
1490 return SCIP_INVALIDDATA;
1491 }
1492
1493 boundchg->newbound = newbound;
1494 boundchg->boundchgtype = boundchgtype; /*lint !e641*/
1495 boundchg->boundtype = boundtype; /*lint !e641*/
1496 boundchg->inferboundtype = inferboundtype; /*lint !e641*/
1497 boundchg->applied = FALSE;
1498 boundchg->redundant = FALSE;
1499 (*domchg)->domchgdyn.nboundchgs++;
1500
1501 /* capture branching and inference data associated with the bound changes */
1503
1504#ifdef SCIP_DISABLED_CODE /* expensive debug check */
1505#ifdef SCIP_MORE_DEBUG
1506 {
1507 int i;
1508 for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1509 assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1510 || SCIPsetIsFeasIntegral(set, (*domchg)->domchgbound.boundchgs[i].newbound));
1511 }
1512#endif
1513#endif
1514
1515 return SCIP_OKAY;
1516}
1517
1518/** adds hole change to domain changes */
1520 SCIP_DOMCHG** domchg, /**< pointer to domain change data structure */
1521 BMS_BLKMEM* blkmem, /**< block memory */
1522 SCIP_SET* set, /**< global SCIP settings */
1523 SCIP_HOLELIST** ptr, /**< changed list pointer */
1524 SCIP_HOLELIST* newlist, /**< new value of list pointer */
1525 SCIP_HOLELIST* oldlist /**< old value of list pointer */
1526 )
1527{
1529
1530 assert(domchg != NULL);
1531 assert(ptr != NULL);
1532
1533 /* if domain change data doesn't exist, create it;
1534 * if domain change is static, convert it into dynamic change
1535 */
1536 if( *domchg == NULL )
1537 {
1538 SCIP_CALL( domchgCreate(domchg, blkmem) );
1539 }
1540 else if( (*domchg)->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_DYNAMIC ) /*lint !e641*/
1541 {
1542 SCIP_CALL( domchgMakeDynamic(domchg, blkmem) );
1543 }
1544 assert(*domchg != NULL && (*domchg)->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1545
1546 /* get memory for additional hole change */
1547 SCIP_CALL( domchgEnsureHolechgsSize(*domchg, blkmem, set, (*domchg)->domchgdyn.nholechgs+1) );
1548
1549 /* fill in the hole change data */
1550 holechg = &(*domchg)->domchgdyn.holechgs[(*domchg)->domchgdyn.nholechgs];
1551 holechg->ptr = ptr;
1552 holechg->newlist = newlist;
1553 holechg->oldlist = oldlist;
1554 (*domchg)->domchgdyn.nholechgs++;
1555
1556 return SCIP_OKAY;
1557}
1558
1559
1560
1561
1562/*
1563 * methods for variables
1564 */
1565
1566/** returns adjusted lower bound value, which is rounded for integral variable types */
1567static
1568SCIP_Real adjustedLb(
1569 SCIP_SET* set, /**< global SCIP settings */
1570 SCIP_VARTYPE vartype, /**< type of variable */
1571 SCIP_Real lb /**< lower bound to adjust */
1572 )
1573{
1574 if( lb < 0.0 && SCIPsetIsInfinity(set, -lb) )
1575 return -SCIPsetInfinity(set);
1576 else if( lb > 0.0 && SCIPsetIsInfinity(set, lb) )
1577 return SCIPsetInfinity(set);
1578 else if( vartype != SCIP_VARTYPE_CONTINUOUS )
1579 return SCIPsetFeasCeil(set, lb);
1580 else if( lb > 0.0 && lb < SCIPsetEpsilon(set) )
1581 return 0.0;
1582 else
1583 return lb;
1584}
1585
1586/** returns adjusted upper bound value, which is rounded for integral variable types */
1587static
1588SCIP_Real adjustedUb(
1589 SCIP_SET* set, /**< global SCIP settings */
1590 SCIP_VARTYPE vartype, /**< type of variable */
1591 SCIP_Real ub /**< upper bound to adjust */
1592 )
1593{
1594 if( ub > 0.0 && SCIPsetIsInfinity(set, ub) )
1595 return SCIPsetInfinity(set);
1596 else if( ub < 0.0 && SCIPsetIsInfinity(set, -ub) )
1597 return -SCIPsetInfinity(set);
1598 else if( vartype != SCIP_VARTYPE_CONTINUOUS )
1599 return SCIPsetFeasFloor(set, ub);
1601 return 0.0;
1602 else
1603 return ub;
1604}
1605
1606/** removes (redundant) cliques, implications and variable bounds of variable from all other variables' implications and variable
1607 * bounds arrays, and optionally removes them also from the variable itself
1608 */
1610 SCIP_VAR* var, /**< problem variable */
1611 BMS_BLKMEM* blkmem, /**< block memory */
1612 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1613 SCIP_SET* set, /**< global SCIP settings */
1614 SCIP_Bool irrelevantvar, /**< has the variable become irrelevant? */
1615 SCIP_Bool onlyredundant, /**< should only the redundant implications and variable bounds be removed? */
1616 SCIP_Bool removefromvar /**< should the implications and variable bounds be removed from the var itself? */
1617 )
1618{
1619 SCIP_Real lb;
1620 SCIP_Real ub;
1621
1622 assert(var != NULL);
1625
1626 lb = SCIPvarGetLbGlobal(var);
1627 ub = SCIPvarGetUbGlobal(var);
1628
1629 SCIPsetDebugMsg(set, "removing %s implications and vbounds of %s<%s>[%g,%g]\n",
1630 onlyredundant ? "redundant" : "all", irrelevantvar ? "irrelevant " : "", SCIPvarGetName(var), lb, ub);
1631
1632 /* remove implications of (fixed) binary variable */
1633 if( var->implics != NULL && (!onlyredundant || lb > 0.5 || ub < 0.5) )
1634 {
1635 SCIP_Bool varfixing;
1636
1638
1639 varfixing = FALSE;
1640 do
1641 {
1644 int nimpls;
1645 int i;
1646
1650
1651 for( i = 0; i < nimpls; i++ )
1652 {
1655
1656 implvar = implvars[i];
1657 impltype = impltypes[i];
1658 assert(implvar != var);
1659
1660 /* remove for all implications z == 0 / 1 ==> x <= p / x >= p (x not binary)
1661 * the following variable bound from x's variable bounds
1662 * x <= b*z+d (z in vubs of x) , for z == 0 / 1 ==> x <= p
1663 * x >= b*z+d (z in vlbs of x) , for z == 0 / 1 ==> x >= p
1664 */
1666 {
1667 if( implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1668 {
1669 SCIPsetDebugMsg(set, "deleting variable bound: <%s> == %u ==> <%s> <= %g\n",
1672 SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, varfixing) );
1673 implvar->closestvblpcount = -1;
1674 var->closestvblpcount = -1;
1675 }
1676 }
1677 else
1678 {
1679 if( implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1680 {
1681 SCIPsetDebugMsg(set, "deleting variable bound: <%s> == %u ==> <%s> >= %g\n",
1684 SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, !varfixing) );
1685 implvar->closestvblpcount = -1;
1686 var->closestvblpcount = -1;
1687 }
1688 }
1689 }
1691 }
1692 while( varfixing == TRUE );
1693
1694 if( removefromvar )
1695 {
1696 /* free the implications data structures */
1697 SCIPimplicsFree(&var->implics, blkmem);
1698 }
1699 }
1700
1701 /* remove the (redundant) variable lower bounds */
1702 if( var->vlbs != NULL )
1703 {
1704 SCIP_VAR** vars;
1705 SCIP_Real* coefs;
1706 SCIP_Real* constants;
1707 int nvbds;
1708 int newnvbds;
1709 int i;
1710
1713 coefs = SCIPvboundsGetCoefs(var->vlbs);
1714 constants = SCIPvboundsGetConstants(var->vlbs);
1715
1716 /* remove for all variable bounds x >= b*z+d the following implication from z's implications
1717 * z == ub ==> x >= b*ub + d , if b > 0
1718 * z == lb ==> x >= b*lb + d , if b < 0
1719 */
1720 newnvbds = 0;
1721 for( i = 0; i < nvbds; i++ )
1722 {
1724 SCIP_Real coef;
1725
1726 assert(newnvbds <= i);
1727
1728 implvar = vars[i];
1729 assert(implvar != NULL);
1730
1731 coef = coefs[i];
1732 assert(!SCIPsetIsZero(set, coef));
1733
1734 /* check, if we want to remove the variable bound */
1735 if( onlyredundant )
1736 {
1737 SCIP_Real vbound;
1738
1739 vbound = MAX(coef * SCIPvarGetUbGlobal(implvar), coef * SCIPvarGetLbGlobal(implvar)) + constants[i]; /*lint !e666*/
1740 if( SCIPsetIsFeasGT(set, vbound, lb) )
1741 {
1742 /* the variable bound is not redundant: keep it */
1743 if( removefromvar )
1744 {
1745 if( newnvbds < i )
1746 {
1748 coefs[newnvbds] = coef;
1749 constants[newnvbds] = constants[i];
1750 }
1751 newnvbds++;
1752 }
1753 continue;
1754 }
1755 }
1756
1757 /* remove the corresponding implication */
1758 if( implvar->implics != NULL ) /* variable may have been aggregated in the mean time */
1759 {
1760 SCIPsetDebugMsg(set, "deleting implication: <%s> == %d ==> <%s> >= %g\n",
1761 SCIPvarGetName(implvar), (coef > 0.0), SCIPvarGetName(var), MAX(coef, 0.0) + constants[i]);
1762 SCIP_CALL( SCIPimplicsDel(&implvar->implics, blkmem, set, (coef > 0.0), var, SCIP_BOUNDTYPE_LOWER) );
1763 }
1764 if( coef > 0.0 && implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1765 {
1766 SCIPsetDebugMsg(set, "deleting variable upper bound from <%s> involving variable %s\n",
1768 SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, FALSE) );
1769 implvar->closestvblpcount = -1;
1770 var->closestvblpcount = -1;
1771 }
1772 else if( coef < 0.0 && implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1773 {
1774 SCIPsetDebugMsg(set, "deleting variable lower bound from <%s> involving variable %s\n",
1776 SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, TRUE) );
1777 implvar->closestvblpcount = -1;
1778 var->closestvblpcount = -1;
1779 }
1780 }
1781
1782 if( removefromvar )
1783 {
1784 /* update the number of variable bounds */
1785 SCIPvboundsShrink(&var->vlbs, blkmem, newnvbds);
1786 var->closestvblpcount = -1;
1787 }
1788 }
1789
1790 /**@todo in general, variable bounds like x >= b*z + d corresponding to an implication like z = ub ==> x >= b*ub + d
1791 * might be missing because we only add variable bounds with reasonably small value of b. thus, we currently
1792 * cannot remove such variables x from z's implications.
1793 */
1794
1795 /* remove the (redundant) variable upper bounds */
1796 if( var->vubs != NULL )
1797 {
1798 SCIP_VAR** vars;
1799 SCIP_Real* coefs;
1800 SCIP_Real* constants;
1801 int nvbds;
1802 int newnvbds;
1803 int i;
1804
1807 coefs = SCIPvboundsGetCoefs(var->vubs);
1808 constants = SCIPvboundsGetConstants(var->vubs);
1809
1810 /* remove for all variable bounds x <= b*z+d the following implication from z's implications
1811 * z == lb ==> x <= b*lb + d , if b > 0
1812 * z == ub ==> x <= b*ub + d , if b < 0
1813 */
1814 newnvbds = 0;
1815 for( i = 0; i < nvbds; i++ )
1816 {
1818 SCIP_Real coef;
1819
1820 assert(newnvbds <= i);
1821
1822 implvar = vars[i];
1823 assert(implvar != NULL);
1824
1825 coef = coefs[i];
1826 assert(!SCIPsetIsZero(set, coef));
1827
1828 /* check, if we want to remove the variable bound */
1829 if( onlyredundant )
1830 {
1831 SCIP_Real vbound;
1832
1833 vbound = MIN(coef * SCIPvarGetUbGlobal(implvar), coef * SCIPvarGetLbGlobal(implvar)) + constants[i]; /*lint !e666*/
1834 if( SCIPsetIsFeasLT(set, vbound, ub) )
1835 {
1836 /* the variable bound is not redundant: keep it */
1837 if( removefromvar )
1838 {
1839 if( newnvbds < i )
1840 {
1842 coefs[newnvbds] = coefs[i];
1843 constants[newnvbds] = constants[i];
1844 }
1845 newnvbds++;
1846 }
1847 continue;
1848 }
1849 }
1850
1851 /* remove the corresponding implication */
1852 if( implvar->implics != NULL ) /* variable may have been aggregated in the mean time */
1853 {
1854 SCIPsetDebugMsg(set, "deleting implication: <%s> == %d ==> <%s> <= %g\n",
1855 SCIPvarGetName(implvar), (coef < 0.0), SCIPvarGetName(var), MIN(coef, 0.0) + constants[i]);
1856 SCIP_CALL( SCIPimplicsDel(&implvar->implics, blkmem, set, (coef < 0.0), var, SCIP_BOUNDTYPE_UPPER) );
1857 }
1858 if( coef < 0.0 && implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1859 {
1860 SCIPsetDebugMsg(set, "deleting variable upper bound from <%s> involving variable %s\n",
1862 SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, TRUE) );
1863 implvar->closestvblpcount = -1;
1864 var->closestvblpcount = -1;
1865 }
1866 else if( coef > 0.0 && implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1867 {
1868 SCIPsetDebugMsg(set, "deleting variable lower bound from <%s> involving variable %s\n",
1870 SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, FALSE) );
1871 implvar->closestvblpcount = -1;
1872 var->closestvblpcount = -1;
1873 }
1874 }
1875
1876 if( removefromvar )
1877 {
1878 /* update the number of variable bounds */
1879 SCIPvboundsShrink(&var->vubs, blkmem, newnvbds);
1880 var->closestvblpcount = -1;
1881 }
1882 }
1883
1884 /* remove the variable from all cliques */
1885 if( SCIPvarIsBinary(var) )
1887
1888 /**@todo variable bounds like x <= b*z + d with z general integer are not removed from x's vbd arrays, because
1889 * z has no link (like in the binary case) to x
1890 */
1891
1892 return SCIP_OKAY;
1893}
1894
1895/** sets the variable name */
1896static
1898 SCIP_VAR* var, /**< problem variable */
1899 BMS_BLKMEM* blkmem, /**< block memory */
1900 SCIP_STAT* stat, /**< problem statistics, or NULL */
1901 const char* name /**< name of variable, or NULL for automatic name creation */
1902 )
1903{
1904 assert(blkmem != NULL);
1905 assert(var != NULL);
1906
1907 if( name == NULL )
1908 {
1909 char s[SCIP_MAXSTRLEN];
1910
1911 assert(stat != NULL);
1912
1913 (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "_var%d_", stat->nvaridx);
1914 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->name, s, strlen(s)+1) );
1915 }
1916 else
1917 {
1918 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->name, name, strlen(name)+1) );
1919 }
1920
1921 return SCIP_OKAY;
1922}
1923
1924
1925/** creates variable; if variable is of integral type, fractional bounds are automatically rounded; an integer variable
1926 * with bounds zero and one is automatically converted into a binary variable
1927 */
1928static
1930 SCIP_VAR** var, /**< pointer to variable data */
1931 BMS_BLKMEM* blkmem, /**< block memory */
1932 SCIP_SET* set, /**< global SCIP settings */
1933 SCIP_STAT* stat, /**< problem statistics */
1934 const char* name, /**< name of variable, or NULL for automatic name creation */
1935 SCIP_Real lb, /**< lower bound of variable */
1936 SCIP_Real ub, /**< upper bound of variable */
1937 SCIP_Real obj, /**< objective function value */
1938 SCIP_VARTYPE vartype, /**< type of variable */
1939 SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
1940 SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
1941 SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
1942 SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
1943 SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
1944 SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
1945 SCIP_VARDATA* vardata /**< user data for this specific variable */
1946 )
1947{
1948 int i;
1949
1950 assert(var != NULL);
1951 assert(blkmem != NULL);
1952 assert(stat != NULL);
1953
1954 /* adjust bounds of variable */
1955 lb = adjustedLb(set, vartype, lb);
1956 ub = adjustedUb(set, vartype, ub);
1957
1958 /* convert [0,1]-integers into binary variables and check that binary variables have correct bounds */
1959 if( (SCIPsetIsEQ(set, lb, 0.0) || SCIPsetIsEQ(set, lb, 1.0))
1960 && (SCIPsetIsEQ(set, ub, 0.0) || SCIPsetIsEQ(set, ub, 1.0)) )
1961 {
1962 if( vartype == SCIP_VARTYPE_INTEGER )
1963 vartype = SCIP_VARTYPE_BINARY;
1964 }
1965 else
1966 {
1967 if( vartype == SCIP_VARTYPE_BINARY )
1968 {
1969 SCIPerrorMessage("invalid bounds [%.2g,%.2g] for binary variable <%s>\n", lb, ub, name);
1970 return SCIP_INVALIDDATA;
1971 }
1972 }
1973
1974 assert(vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, lb, 0.0) || SCIPsetIsEQ(set, lb, 1.0));
1975 assert(vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, ub, 0.0) || SCIPsetIsEQ(set, ub, 1.0));
1976
1978
1979 /* set variable's name */
1980 SCIP_CALL( varSetName(*var, blkmem, stat, name) );
1981
1982#ifndef NDEBUG
1983 (*var)->scip = set->scip;
1984#endif
1985 (*var)->obj = obj;
1986 (*var)->unchangedobj = obj;
1987 (*var)->branchfactor = 1.0;
1988 (*var)->rootsol = 0.0;
1989 (*var)->bestrootsol = 0.0;
1990 (*var)->bestrootredcost = 0.0;
1991 (*var)->bestrootlpobjval = SCIP_INVALID;
1992 (*var)->relaxsol = 0.0;
1993 (*var)->nlpsol = 0.0;
1994 (*var)->primsolavg = 0.5 * (lb + ub);
1995 (*var)->conflictlb = SCIP_REAL_MIN;
1996 (*var)->conflictub = SCIP_REAL_MAX;
1997 (*var)->conflictrelaxedlb = (*var)->conflictlb;
1998 (*var)->conflictrelaxedub = (*var)->conflictub;
1999 (*var)->lazylb = -SCIPsetInfinity(set);
2000 (*var)->lazyub = SCIPsetInfinity(set);
2001 (*var)->glbdom.holelist = NULL;
2002 (*var)->glbdom.lb = lb;
2003 (*var)->glbdom.ub = ub;
2004 (*var)->locdom.holelist = NULL;
2005 (*var)->locdom.lb = lb;
2006 (*var)->locdom.ub = ub;
2007 (*var)->varcopy = varcopy;
2008 (*var)->vardelorig = vardelorig;
2009 (*var)->vartrans = vartrans;
2010 (*var)->vardeltrans = vardeltrans;
2011 (*var)->vardata = vardata;
2012 (*var)->parentvars = NULL;
2013 (*var)->negatedvar = NULL;
2014 (*var)->vlbs = NULL;
2015 (*var)->vubs = NULL;
2016 (*var)->implics = NULL;
2017 (*var)->cliquelist = NULL;
2018 (*var)->eventfilter = NULL;
2019 (*var)->lbchginfos = NULL;
2020 (*var)->ubchginfos = NULL;
2021 (*var)->index = stat->nvaridx;
2022 (*var)->probindex = -1;
2023 (*var)->pseudocandindex = -1;
2024 (*var)->eventqueueindexobj = -1;
2025 (*var)->eventqueueindexlb = -1;
2026 (*var)->eventqueueindexub = -1;
2027 (*var)->parentvarssize = 0;
2028 (*var)->nparentvars = 0;
2029 (*var)->nuses = 0;
2030 (*var)->branchpriority = 0;
2031 (*var)->branchdirection = SCIP_BRANCHDIR_AUTO; /*lint !e641*/
2032 (*var)->lbchginfossize = 0;
2033 (*var)->nlbchginfos = 0;
2034 (*var)->ubchginfossize = 0;
2035 (*var)->nubchginfos = 0;
2036 (*var)->conflictlbcount = 0;
2037 (*var)->conflictubcount = 0;
2038 (*var)->closestvlbidx = -1;
2039 (*var)->closestvubidx = -1;
2040 (*var)->closestvblpcount = -1;
2041 (*var)->initial = initial;
2042 (*var)->removable = removable;
2043 (*var)->deleted = FALSE;
2044 (*var)->donotaggr = FALSE;
2045 (*var)->donotmultaggr = FALSE;
2046 (*var)->vartype = vartype; /*lint !e641*/
2047 (*var)->pseudocostflag = FALSE;
2048 (*var)->eventqueueimpl = FALSE;
2049 (*var)->deletable = FALSE;
2050 (*var)->delglobalstructs = FALSE;
2051 (*var)->relaxationonly = FALSE;
2052
2053 for( i = 0; i < NLOCKTYPES; i++ )
2054 {
2055 (*var)->nlocksdown[i] = 0;
2056 (*var)->nlocksup[i] = 0;
2057 }
2058
2059 stat->nvaridx++;
2060
2061 /* create branching and inference history entries */
2062 SCIP_CALL( SCIPhistoryCreate(&(*var)->history, blkmem) );
2063 SCIP_CALL( SCIPhistoryCreate(&(*var)->historycrun, blkmem) );
2064
2065 /* the value based history is only created on demand */
2066 (*var)->valuehistory = NULL;
2067
2068 return SCIP_OKAY;
2069}
2070
2071/** creates and captures an original problem variable; an integer variable with bounds
2072 * zero and one is automatically converted into a binary variable
2073 */
2075 SCIP_VAR** var, /**< pointer to variable data */
2076 BMS_BLKMEM* blkmem, /**< block memory */
2077 SCIP_SET* set, /**< global SCIP settings */
2078 SCIP_STAT* stat, /**< problem statistics */
2079 const char* name, /**< name of variable, or NULL for automatic name creation */
2080 SCIP_Real lb, /**< lower bound of variable */
2081 SCIP_Real ub, /**< upper bound of variable */
2082 SCIP_Real obj, /**< objective function value */
2083 SCIP_VARTYPE vartype, /**< type of variable */
2084 SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2085 SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2086 SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2087 SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2088 SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2089 SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2090 SCIP_VARDATA* vardata /**< user data for this specific variable */
2091 )
2092{
2093 assert(var != NULL);
2094 assert(blkmem != NULL);
2095 assert(stat != NULL);
2096
2097 /* create variable */
2098 SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2099 varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2100
2101 /* set variable status and data */
2102 (*var)->varstatus = SCIP_VARSTATUS_ORIGINAL; /*lint !e641*/
2103 (*var)->data.original.origdom.holelist = NULL;
2104 (*var)->data.original.origdom.lb = lb;
2105 (*var)->data.original.origdom.ub = ub;
2106 (*var)->data.original.transvar = NULL;
2107
2108 /* capture variable */
2110
2111 return SCIP_OKAY;
2112}
2113
2114/** creates and captures a loose variable belonging to the transformed problem; an integer variable with bounds
2115 * zero and one is automatically converted into a binary variable
2116 */
2118 SCIP_VAR** var, /**< pointer to variable data */
2119 BMS_BLKMEM* blkmem, /**< block memory */
2120 SCIP_SET* set, /**< global SCIP settings */
2121 SCIP_STAT* stat, /**< problem statistics */
2122 const char* name, /**< name of variable, or NULL for automatic name creation */
2123 SCIP_Real lb, /**< lower bound of variable */
2124 SCIP_Real ub, /**< upper bound of variable */
2125 SCIP_Real obj, /**< objective function value */
2126 SCIP_VARTYPE vartype, /**< type of variable */
2127 SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2128 SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2129 SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2130 SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2131 SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2132 SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2133 SCIP_VARDATA* vardata /**< user data for this specific variable */
2134 )
2135{
2136 assert(var != NULL);
2137 assert(blkmem != NULL);
2138
2139 /* create variable */
2140 SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2141 varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2142
2143 /* create event filter for transformed variable */
2144 SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
2145
2146 /* set variable status and data */
2147 (*var)->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
2148
2149 /* capture variable */
2151
2152 return SCIP_OKAY;
2153}
2154
2155/** copies and captures a variable from source to target SCIP; an integer variable with bounds zero and one is
2156 * automatically converted into a binary variable; in case the variable data cannot be copied the variable is not
2157 * copied at all
2158 */
2160 SCIP_VAR** var, /**< pointer to store the target variable */
2161 BMS_BLKMEM* blkmem, /**< block memory */
2162 SCIP_SET* set, /**< global SCIP settings */
2163 SCIP_STAT* stat, /**< problem statistics */
2164 SCIP* sourcescip, /**< source SCIP data structure */
2165 SCIP_VAR* sourcevar, /**< source variable */
2166 SCIP_HASHMAP* varmap, /**< a hashmap to store the mapping of source variables corresponding
2167 * target variables */
2168 SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
2169 * target constraints */
2170 SCIP_Bool global /**< should global or local bounds be used? */
2171 )
2172{
2175 SCIP_Real lb;
2176 SCIP_Real ub;
2177
2178 assert(set != NULL);
2179 assert(blkmem != NULL);
2180 assert(stat != NULL);
2181 assert(sourcescip != NULL);
2182 assert(sourcevar != NULL);
2183 assert(var != NULL);
2184 assert(set->stage == SCIP_STAGE_PROBLEM);
2185 assert(varmap != NULL);
2186 assert(consmap != NULL);
2187
2188 /** @todo copy hole lists */
2191
2193 targetdata = NULL;
2194
2196 {
2199 }
2200 else
2201 {
2204 }
2205
2206 /* creates and captures the variable in the target SCIP and initialize callback methods and variable data to NULL */
2210 NULL, NULL, NULL, NULL, NULL) );
2211 assert(*var != NULL);
2212
2213 /* directly copy donot(mult)aggr flag */
2214 (*var)->donotaggr = sourcevar->donotaggr;
2215 (*var)->donotmultaggr = sourcevar->donotmultaggr;
2216
2217 /* insert variable into mapping between source SCIP and the target SCIP */
2220
2221 /* in case there exists variable data and the variable data copy callback, try to copy variable data */
2222 if( sourcevar->vardata != NULL && sourcevar->varcopy != NULL )
2223 {
2224 SCIP_CALL( sourcevar->varcopy(set->scip, sourcescip, sourcevar, sourcevar->vardata,
2225 varmap, consmap, (*var), &targetdata, &result) );
2226
2227 /* evaluate result */
2229 {
2230 SCIPerrorMessage("variable data copying method returned invalid result <%d>\n", result);
2231 return SCIP_INVALIDRESULT;
2232 }
2233
2235
2236 /* if copying was successful, add the created variable data to the variable as well as all callback methods */
2237 if( result == SCIP_SUCCESS )
2238 {
2239 (*var)->varcopy = sourcevar->varcopy;
2240 (*var)->vardelorig = sourcevar->vardelorig;
2241 (*var)->vartrans = sourcevar->vartrans;
2242 (*var)->vardeltrans = sourcevar->vardeltrans;
2243 (*var)->vardata = targetdata;
2244 }
2245 }
2246
2247 /* we initialize histories of the variables by copying the source variable-information */
2248 if( set->history_allowtransfer )
2249 {
2251 }
2252
2253 /* in case the copying was successfully, add the created variable data to the variable as well as all callback
2254 * methods
2255 */
2256 if( result == SCIP_SUCCESS )
2257 {
2258 (*var)->varcopy = sourcevar->varcopy;
2259 (*var)->vardelorig = sourcevar->vardelorig;
2260 (*var)->vartrans = sourcevar->vartrans;
2261 (*var)->vardeltrans = sourcevar->vardeltrans;
2262 (*var)->vardata = targetdata;
2263 }
2264
2265 SCIPsetDebugMsg(set, "created copy <%s> of variable <%s>\n", SCIPvarGetName(*var), SCIPvarGetName(sourcevar));
2266
2267 return SCIP_OKAY;
2268}
2269
2270/** parse given string for a SCIP_Real bound */
2271static
2273 SCIP_SET* set, /**< global SCIP settings */
2274 const char* str, /**< string to parse */
2275 SCIP_Real* value, /**< pointer to store the parsed value */
2276 char** endptr /**< pointer to store the final string position if successfully parsed */
2277 )
2278{
2279 /* first check for infinity value */
2280 if( strncmp(str, "+inf", 4) == 0 )
2281 {
2282 *value = SCIPsetInfinity(set);
2283 (*endptr) = (char*)str + 4;
2284 }
2285 else if( strncmp(str, "-inf", 4) == 0 )
2286 {
2287 *value = -SCIPsetInfinity(set);
2288 (*endptr) = (char*)str + 4;
2289 }
2290 else
2291 {
2292 if( !SCIPstrToRealValue(str, value, endptr) )
2293 {
2294 SCIPerrorMessage("expected value: %s.\n", str);
2295 return SCIP_READERROR;
2296 }
2297 }
2298
2299 return SCIP_OKAY;
2300}
2301
2302/** parse the characters as bounds */
2303static
2305 SCIP_SET* set, /**< global SCIP settings */
2306 const char* str, /**< string to parse */
2307 char* type, /**< bound type (global, local, or lazy) */
2308 SCIP_Real* lb, /**< pointer to store the lower bound */
2309 SCIP_Real* ub, /**< pointer to store the upper bound */
2310 char** endptr /**< pointer to store the final string position if successfully parsed (or NULL if an error occured) */
2311 )
2312{
2313 char token[SCIP_MAXSTRLEN];
2314 char* tmpend;
2315
2316 SCIPsetDebugMsg(set, "parsing bounds: '%s'\n", str);
2317
2318 /* get bound type */
2319 SCIPstrCopySection(str, ' ', ' ', type, SCIP_MAXSTRLEN, endptr);
2320 if ( *endptr == str
2321 || ( strncmp(type, "original", 8) != 0 && strncmp(type, "global", 6) != 0 && strncmp(type, "local", 5) != 0 && strncmp(type, "lazy", 4) != 0 ) )
2322 {
2323 SCIPsetDebugMsg(set, "unkown bound type\n");
2324 *endptr = NULL;
2325 return SCIP_OKAY;
2326 }
2327
2328 SCIPsetDebugMsg(set, "parsed bound type <%s>\n", type);
2329
2330 /* get lower bound */
2331 SCIPstrCopySection(str, '[', ',', token, SCIP_MAXSTRLEN, endptr);
2332 str = *endptr;
2333 SCIP_CALL( parseValue(set, token, lb, &tmpend) );
2334
2335 /* get upper bound */
2336 SCIP_CALL( parseValue(set, str, ub, endptr) );
2337
2338 SCIPsetDebugMsg(set, "parsed bounds: [%g,%g]\n", *lb, *ub);
2339
2340 /* skip end of bounds */
2341 while ( **endptr != '\0' && (**endptr == ']' || **endptr == ',') )
2342 ++(*endptr);
2343
2344 return SCIP_OKAY;
2345}
2346
2347/** parses a given string for a variable informations */
2348static
2350 SCIP_SET* set, /**< global SCIP settings */
2351 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2352 const char* str, /**< string to parse */
2353 char* name, /**< pointer to store the variable name */
2354 SCIP_Real* lb, /**< pointer to store the lower bound */
2355 SCIP_Real* ub, /**< pointer to store the upper bound */
2356 SCIP_Real* obj, /**< pointer to store the objective coefficient */
2357 SCIP_VARTYPE* vartype, /**< pointer to store the variable type */
2358 SCIP_Real* lazylb, /**< pointer to store if the lower bound is lazy */
2359 SCIP_Real* lazyub, /**< pointer to store if the upper bound is lazy */
2360 SCIP_Bool local, /**< should the local bound be applied */
2361 char** endptr, /**< pointer to store the final string position if successfully */
2362 SCIP_Bool* success /**< pointer store if the paring process was successful */
2363 )
2364{
2365 SCIP_Real parsedlb;
2366 SCIP_Real parsedub;
2367 char token[SCIP_MAXSTRLEN];
2368 char* strptr;
2369 int i;
2370
2371 assert(lb != NULL);
2372 assert(ub != NULL);
2373 assert(obj != NULL);
2374 assert(vartype != NULL);
2375 assert(lazylb != NULL);
2376 assert(lazyub != NULL);
2377 assert(success != NULL);
2378
2379 (*success) = TRUE;
2380
2381 /* copy variable type */
2382 SCIPstrCopySection(str, '[', ']', token, SCIP_MAXSTRLEN, endptr);
2383 assert(*endptr != str);
2384 SCIPsetDebugMsg(set, "parsed variable type <%s>\n", token);
2385
2386 /* get variable type */
2387 if( strncmp(token, "binary", 3) == 0 )
2388 (*vartype) = SCIP_VARTYPE_BINARY;
2389 else if( strncmp(token, "integer", 3) == 0 )
2390 (*vartype) = SCIP_VARTYPE_INTEGER;
2391 else if( strncmp(token, "implicit", 3) == 0 )
2392 (*vartype) = SCIP_VARTYPE_IMPLINT;
2393 else if( strncmp(token, "continuous", 3) == 0 )
2394 (*vartype) = SCIP_VARTYPE_CONTINUOUS;
2395 else
2396 {
2397 SCIPmessagePrintWarning(messagehdlr, "unknown variable type\n");
2398 (*success) = FALSE;
2399 return SCIP_OKAY;
2400 }
2401
2402 /* move string pointer behind variable type */
2403 str = *endptr;
2404
2405 /* get variable name */
2406 SCIPstrCopySection(str, '<', '>', name, SCIP_MAXSTRLEN, endptr);
2407 assert(*endptr != str);
2408 SCIPsetDebugMsg(set, "parsed variable name <%s>\n", name);
2409
2410 /* move string pointer behind variable name */
2411 str = *endptr;
2412
2413 /* cut out objective coefficient */
2414 SCIPstrCopySection(str, '=', ',', token, SCIP_MAXSTRLEN, endptr);
2415
2416 /* move string pointer behind objective coefficient */
2417 str = *endptr;
2418
2419 /* get objective coefficient */
2420 if( !SCIPstrToRealValue(token, obj, endptr) )
2421 {
2422 *endptr = NULL;
2423 return SCIP_READERROR;
2424 }
2425
2426 SCIPsetDebugMsg(set, "parsed objective coefficient <%g>\n", *obj);
2427
2428 /* parse global/original bounds */
2429 SCIP_CALL( parseBounds(set, str, token, lb, ub, endptr) );
2430 if ( *endptr == NULL )
2431 {
2432 SCIPerrorMessage("Expected bound type: %s.\n", token);
2433 return SCIP_READERROR;
2434 }
2435 assert(strncmp(token, "global", 6) == 0 || strncmp(token, "original", 8) == 0);
2436
2437 /* initialize the lazy bound */
2438 *lazylb = -SCIPsetInfinity(set);
2439 *lazyub = SCIPsetInfinity(set);
2440
2441 /* store pointer */
2442 strptr = *endptr;
2443
2444 /* possibly parse optional local and lazy bounds */
2445 for( i = 0; i < 2 && *endptr != NULL && **endptr != '\0'; ++i )
2446 {
2447 /* start after previous bounds */
2448 strptr = *endptr;
2449
2450 /* parse global bounds */
2452
2453 /* stop if parsing of bounds failed */
2454 if( *endptr == NULL )
2455 break;
2456
2457 if( strncmp(token, "local", 5) == 0 && local )
2458 {
2459 *lb = parsedlb;
2460 *ub = parsedub;
2461 }
2462 else if( strncmp(token, "lazy", 4) == 0 )
2463 {
2464 *lazylb = parsedlb;
2465 *lazyub = parsedub;
2466 }
2467 }
2468
2469 /* restore pointer */
2470 if ( *endptr == NULL )
2471 *endptr = strptr;
2472
2473 /* check bounds for binary variables */
2474 if ( (*vartype) == SCIP_VARTYPE_BINARY )
2475 {
2476 if ( SCIPsetIsLT(set, *lb, 0.0) || SCIPsetIsGT(set, *ub, 1.0) )
2477 {
2478 SCIPerrorMessage("Parsed invalid bounds for binary variable <%s>: [%f, %f].\n", name, *lb, *ub);
2479 return SCIP_READERROR;
2480 }
2481 if ( !SCIPsetIsInfinity(set, -(*lazylb)) && !SCIPsetIsInfinity(set, *lazyub) &&
2482 ( SCIPsetIsLT(set, *lazylb, 0.0) || SCIPsetIsGT(set, *lazyub, 1.0) ) )
2483 {
2484 SCIPerrorMessage("Parsed invalid lazy bounds for binary variable <%s>: [%f, %f].\n", name, *lazylb, *lazyub);
2485 return SCIP_READERROR;
2486 }
2487 }
2488
2489 return SCIP_OKAY;
2490}
2491
2492/** parses variable information (in cip format) out of a string; if the parsing process was successful an original
2493 * variable is created and captured; if variable is of integral type, fractional bounds are automatically rounded; an
2494 * integer variable with bounds zero and one is automatically converted into a binary variable
2495 */
2497 SCIP_VAR** var, /**< pointer to variable data */
2498 BMS_BLKMEM* blkmem, /**< block memory */
2499 SCIP_SET* set, /**< global SCIP settings */
2500 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2501 SCIP_STAT* stat, /**< problem statistics */
2502 const char* str, /**< string to parse */
2503 SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2504 SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2505 SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2506 SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable */
2507 SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data */
2508 SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable */
2509 SCIP_VARDATA* vardata, /**< user data for this specific variable */
2510 char** endptr, /**< pointer to store the final string position if successfully */
2511 SCIP_Bool* success /**< pointer store if the paring process was successful */
2512 )
2513{
2514 char name[SCIP_MAXSTRLEN];
2515 SCIP_Real lb;
2516 SCIP_Real ub;
2517 SCIP_Real obj;
2518 SCIP_VARTYPE vartype;
2519 SCIP_Real lazylb;
2520 SCIP_Real lazyub;
2521
2522 assert(var != NULL);
2523 assert(blkmem != NULL);
2524 assert(stat != NULL);
2525 assert(endptr != NULL);
2526 assert(success != NULL);
2527
2528 /* parse string in cip format for variable information */
2529 SCIP_CALL( varParse(set, messagehdlr, str, name, &lb, &ub, &obj, &vartype, &lazylb, &lazyub, FALSE, endptr, success) );
2530
2531 if( *success ) /*lint !e774*/
2532 {
2533 /* create variable */
2534 SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2535 varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2536
2537 /* set variable status and data */
2538 (*var)->varstatus = SCIP_VARSTATUS_ORIGINAL; /*lint !e641*/
2539 (*var)->data.original.origdom.holelist = NULL;
2540 (*var)->data.original.origdom.lb = lb;
2541 (*var)->data.original.origdom.ub = ub;
2542 (*var)->data.original.transvar = NULL;
2543
2544 /* set lazy status of variable bounds */
2545 (*var)->lazylb = lazylb;
2546 (*var)->lazyub = lazyub;
2547
2548 /* capture variable */
2550 }
2551
2552 return SCIP_OKAY;
2553}
2554
2555/** parses variable information (in cip format) out of a string; if the parsing process was successful a loose variable
2556 * belonging to the transformed problem is created and captured; if variable is of integral type, fractional bounds are
2557 * automatically rounded; an integer variable with bounds zero and one is automatically converted into a binary
2558 * variable
2559 */
2561 SCIP_VAR** var, /**< pointer to variable data */
2562 BMS_BLKMEM* blkmem, /**< block memory */
2563 SCIP_SET* set, /**< global SCIP settings */
2564 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2565 SCIP_STAT* stat, /**< problem statistics */
2566 const char* str, /**< string to parse */
2567 SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2568 SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2569 SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2570 SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable */
2571 SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data */
2572 SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable */
2573 SCIP_VARDATA* vardata, /**< user data for this specific variable */
2574 char** endptr, /**< pointer to store the final string position if successfully */
2575 SCIP_Bool* success /**< pointer store if the paring process was successful */
2576 )
2577{
2578 char name[SCIP_MAXSTRLEN];
2579 SCIP_Real lb;
2580 SCIP_Real ub;
2581 SCIP_Real obj;
2582 SCIP_VARTYPE vartype;
2583 SCIP_Real lazylb;
2584 SCIP_Real lazyub;
2585
2586 assert(var != NULL);
2587 assert(blkmem != NULL);
2588 assert(endptr != NULL);
2589 assert(success != NULL);
2590
2591 /* parse string in cip format for variable information */
2592 SCIP_CALL( varParse(set, messagehdlr, str, name, &lb, &ub, &obj, &vartype, &lazylb, &lazyub, TRUE, endptr, success) );
2593
2594 if( *success ) /*lint !e774*/
2595 {
2596 /* create variable */
2597 SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2598 varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2599
2600 /* create event filter for transformed variable */
2601 SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
2602
2603 /* set variable status and data */
2604 (*var)->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
2605
2606 /* set lazy status of variable bounds */
2607 (*var)->lazylb = lazylb;
2608 (*var)->lazyub = lazyub;
2609
2610 /* capture variable */
2612 }
2613
2614 return SCIP_OKAY;
2615}
2616
2617/** ensures, that parentvars array of var can store at least num entries */
2618static
2620 SCIP_VAR* var, /**< problem variable */
2621 BMS_BLKMEM* blkmem, /**< block memory */
2622 SCIP_SET* set, /**< global SCIP settings */
2623 int num /**< minimum number of entries to store */
2624 )
2625{
2627
2628 if( num > var->parentvarssize )
2629 {
2630 int newsize;
2631
2635 }
2636 assert(num <= var->parentvarssize);
2637
2638 return SCIP_OKAY;
2639}
2640
2641/** adds variable to parent list of a variable and captures parent variable */
2642static
2644 SCIP_VAR* var, /**< variable to add parent to */
2645 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
2646 SCIP_SET* set, /**< global SCIP settings */
2647 SCIP_VAR* parentvar /**< parent variable to add */
2648 )
2649{
2650 assert(var != NULL);
2651 assert(parentvar != NULL);
2652
2653 /* the direct original counterpart must be stored as first parent */
2655
2656 SCIPsetDebugMsg(set, "adding parent <%s>[%p] to variable <%s>[%p] in slot %d\n",
2657 parentvar->name, (void*)parentvar, var->name, (void*)var, var->nparentvars);
2658
2660
2662 var->nparentvars++;
2663
2665
2666 return SCIP_OKAY;
2667}
2668
2669/** deletes and releases all variables from the parent list of a variable, frees the memory of parents array */
2670static
2672 SCIP_VAR** var, /**< pointer to variable */
2673 BMS_BLKMEM* blkmem, /**< block memory */
2674 SCIP_SET* set, /**< global SCIP settings */
2675 SCIP_EVENTQUEUE* eventqueue, /**< event queue (or NULL, if it's an original variable) */
2676 SCIP_LP* lp /**< current LP data (or NULL, if it's an original variable) */
2677 )
2678{
2680 int i;
2681
2682 SCIPsetDebugMsg(set, "free parents of <%s>\n", (*var)->name);
2683
2684 /* release the parent variables and remove the link from the parent variable to the child */
2685 for( i = 0; i < (*var)->nparentvars; ++i )
2686 {
2687 assert((*var)->parentvars != NULL);
2688 parentvar = (*var)->parentvars[i];
2689 assert(parentvar != NULL);
2690
2691 switch( SCIPvarGetStatus(parentvar) )
2692 {
2694 assert(parentvar->data.original.transvar == *var);
2695 assert(&parentvar->data.original.transvar != var);
2696 parentvar->data.original.transvar = NULL;
2697 break;
2698
2700 assert(parentvar->data.aggregate.var == *var);
2701 assert(&parentvar->data.aggregate.var != var);
2702 parentvar->data.aggregate.var = NULL;
2703 break;
2704
2705#if 0
2706 /* The following code is unclear: should the current variable be removed from its parents? */
2708 assert(parentvar->data.multaggr.vars != NULL);
2709 for( v = 0; v < parentvar->data.multaggr.nvars && parentvar->data.multaggr.vars[v] != *var; ++v )
2710 {}
2711 assert(v < parentvar->data.multaggr.nvars && parentvar->data.multaggr.vars[v] == *var);
2712 if( v < parentvar->data.multaggr.nvars-1 )
2713 {
2714 parentvar->data.multaggr.vars[v] = parentvar->data.multaggr.vars[parentvar->data.multaggr.nvars-1];
2715 parentvar->data.multaggr.scalars[v] = parentvar->data.multaggr.scalars[parentvar->data.multaggr.nvars-1];
2716 }
2717 parentvar->data.multaggr.nvars--;
2718 break;
2719#endif
2720
2722 assert(parentvar->negatedvar == *var);
2723 assert((*var)->negatedvar == parentvar);
2724 parentvar->negatedvar = NULL;
2725 (*var)->negatedvar = NULL;
2726 break;
2727
2728 default:
2729 SCIPerrorMessage("parent variable is neither ORIGINAL, AGGREGATED nor NEGATED\n");
2730 return SCIP_INVALIDDATA;
2731 } /*lint !e788*/
2732
2733 SCIP_CALL( SCIPvarRelease(&(*var)->parentvars[i], blkmem, set, eventqueue, lp) );
2734 }
2735
2736 /* free parentvars array */
2737 BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->parentvars, (*var)->parentvarssize);
2738
2739 return SCIP_OKAY;
2740}
2741
2742/** frees a variable */
2743static
2745 SCIP_VAR** var, /**< pointer to variable */
2746 BMS_BLKMEM* blkmem, /**< block memory */
2747 SCIP_SET* set, /**< global SCIP settings */
2748 SCIP_EVENTQUEUE* eventqueue, /**< event queue (may be NULL, if it's not a column variable) */
2749 SCIP_LP* lp /**< current LP data (may be NULL, if it's not a column variable) */
2750 )
2751{
2752 assert(var != NULL);
2753 assert(*var != NULL);
2754 assert(SCIPvarGetStatus(*var) != SCIP_VARSTATUS_COLUMN || &(*var)->data.col->var != var);
2755 assert((*var)->nuses == 0);
2756 assert((*var)->probindex == -1);
2757 assert((*var)->nlocksup[SCIP_LOCKTYPE_MODEL] == 0);
2758 assert((*var)->nlocksdown[SCIP_LOCKTYPE_MODEL] == 0);
2759
2760 SCIPsetDebugMsg(set, "free variable <%s> with status=%d\n", (*var)->name, SCIPvarGetStatus(*var));
2761
2762 switch( SCIPvarGetStatus(*var) )
2763 {
2765 assert((*var)->data.original.transvar == NULL); /* cannot free variable, if transformed variable is still existing */
2766 holelistFree(&(*var)->data.original.origdom.holelist, blkmem);
2767 assert((*var)->data.original.origdom.holelist == NULL);
2768 break;
2770 break;
2772 SCIP_CALL( SCIPcolFree(&(*var)->data.col, blkmem, set, eventqueue, lp) ); /* free corresponding LP column */
2773 break;
2776 break;
2778 BMSfreeBlockMemoryArray(blkmem, &(*var)->data.multaggr.vars, (*var)->data.multaggr.varssize);
2779 BMSfreeBlockMemoryArray(blkmem, &(*var)->data.multaggr.scalars, (*var)->data.multaggr.varssize);
2780 break;
2782 break;
2783 default:
2784 SCIPerrorMessage("unknown variable status\n");
2785 return SCIP_INVALIDDATA;
2786 }
2787
2788 /* release all parent variables and free the parentvars array */
2789 SCIP_CALL( varFreeParents(var, blkmem, set, eventqueue, lp) );
2790
2791 /* free user data */
2793 {
2794 if( (*var)->vardelorig != NULL )
2795 {
2796 SCIP_CALL( (*var)->vardelorig(set->scip, *var, &(*var)->vardata) );
2797 }
2798 }
2799 else
2800 {
2801 if( (*var)->vardeltrans != NULL )
2802 {
2803 SCIP_CALL( (*var)->vardeltrans(set->scip, *var, &(*var)->vardata) );
2804 }
2805 }
2806
2807 /* free event filter */
2808 if( (*var)->eventfilter != NULL )
2809 {
2810 SCIP_CALL( SCIPeventfilterFree(&(*var)->eventfilter, blkmem, set) );
2811 }
2812 assert((*var)->eventfilter == NULL);
2813
2814 /* free hole lists */
2815 holelistFree(&(*var)->glbdom.holelist, blkmem);
2816 holelistFree(&(*var)->locdom.holelist, blkmem);
2817 assert((*var)->glbdom.holelist == NULL);
2818 assert((*var)->locdom.holelist == NULL);
2819
2820 /* free variable bounds data structures */
2821 SCIPvboundsFree(&(*var)->vlbs, blkmem);
2822 SCIPvboundsFree(&(*var)->vubs, blkmem);
2823
2824 /* free implications data structures */
2825 SCIPimplicsFree(&(*var)->implics, blkmem);
2826
2827 /* free clique list data structures */
2828 SCIPcliquelistFree(&(*var)->cliquelist, blkmem);
2829
2830 /* free bound change information arrays */
2831 BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->lbchginfos, (*var)->lbchginfossize);
2832 BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->ubchginfos, (*var)->ubchginfossize);
2833
2834 /* free branching and inference history entries */
2835 SCIPhistoryFree(&(*var)->history, blkmem);
2836 SCIPhistoryFree(&(*var)->historycrun, blkmem);
2837 SCIPvaluehistoryFree(&(*var)->valuehistory, blkmem);
2838
2839 /* free variable data structure */
2840 BMSfreeBlockMemoryArray(blkmem, &(*var)->name, strlen((*var)->name)+1);
2841 BMSfreeBlockMemory(blkmem, var);
2842
2843 return SCIP_OKAY;
2844}
2845
2846/** increases usage counter of variable */
2848 SCIP_VAR* var /**< variable */
2849 )
2850{
2851 assert(var != NULL);
2852 assert(var->nuses >= 0);
2853
2854 SCIPdebugMessage("capture variable <%s> with nuses=%d\n", var->name, var->nuses);
2855 var->nuses++;
2856
2857#ifdef DEBUGUSES_VARNAME
2858 if( strcmp(var->name, DEBUGUSES_VARNAME) == 0
2862#endif
2863 )
2864 {
2865 printf("Captured variable " DEBUGUSES_VARNAME " in SCIP %p, now %d uses; captured at\n", (void*)var->scip, var->nuses);
2867 }
2868#endif
2869}
2870
2871/** decreases usage counter of variable, and frees memory if necessary */
2873 SCIP_VAR** var, /**< pointer to variable */
2874 BMS_BLKMEM* blkmem, /**< block memory */
2875 SCIP_SET* set, /**< global SCIP settings */
2876 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2877 SCIP_LP* lp /**< current LP data (or NULL, if it's an original variable) */
2878 )
2879{
2880 assert(var != NULL);
2881 assert(*var != NULL);
2882 assert((*var)->nuses >= 1);
2883 assert(blkmem != NULL);
2884 assert((*var)->scip == set->scip);
2885
2886 SCIPsetDebugMsg(set, "release variable <%s> with nuses=%d\n", (*var)->name, (*var)->nuses);
2887 (*var)->nuses--;
2888
2889#ifdef DEBUGUSES_VARNAME
2890 if( strcmp((*var)->name, DEBUGUSES_VARNAME) == 0
2892 && (((*var)->scip->transprob != NULL && strcmp(SCIPprobGetName((*var)->scip->transprob), DEBUGUSES_PROBNAME) == 0) ||
2893 strcmp(SCIPprobGetName((*var)->scip->origprob), DEBUGUSES_PROBNAME) == 0)
2894#endif
2895 )
2896 {
2897 printf("Released variable " DEBUGUSES_VARNAME " in SCIP %p, now %d uses; released at\n", (void*)(*var)->scip, (*var)->nuses);
2899 }
2900#endif
2901
2902 if( (*var)->nuses == 0 )
2903 {
2904 SCIP_CALL( varFree(var, blkmem, set, eventqueue, lp) );
2905 }
2906
2907 *var = NULL;
2908
2909 return SCIP_OKAY;
2910}
2911
2912/** change variable name */
2914 SCIP_VAR* var, /**< problem variable */
2915 BMS_BLKMEM* blkmem, /**< block memory */
2916 const char* name /**< name of variable */
2917 )
2918{
2919 assert(name != NULL);
2920
2921 /* remove old variable name */
2923
2924 /* set new variable name */
2925 SCIP_CALL( varSetName(var, blkmem, NULL, name) );
2926
2927 return SCIP_OKAY;
2928}
2929
2930/** initializes variable data structure for solving */
2932 SCIP_VAR* var /**< problem variable */
2933 )
2934{
2935 assert(var != NULL);
2936
2938 var->conflictlbcount = 0;
2939 var->conflictubcount = 0;
2940}
2941
2942/** outputs the given bounds into the file stream */
2943static
2945 SCIP_SET* set, /**< global SCIP settings */
2946 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2947 FILE* file, /**< output file (or NULL for standard output) */
2948 SCIP_Real lb, /**< lower bound */
2949 SCIP_Real ub, /**< upper bound */
2950 const char* name /**< bound type name */
2951 )
2952{
2953 assert(set != NULL);
2954
2955 SCIPmessageFPrintInfo(messagehdlr, file, ", %s=", name);
2956 if( SCIPsetIsInfinity(set, lb) )
2957 SCIPmessageFPrintInfo(messagehdlr, file, "[+inf,");
2958 else if( SCIPsetIsInfinity(set, -lb) )
2959 SCIPmessageFPrintInfo(messagehdlr, file, "[-inf,");
2960 else
2961 SCIPmessageFPrintInfo(messagehdlr, file, "[%.15g,", lb);
2962 if( SCIPsetIsInfinity(set, ub) )
2963 SCIPmessageFPrintInfo(messagehdlr, file, "+inf]");
2964 else if( SCIPsetIsInfinity(set, -ub) )
2965 SCIPmessageFPrintInfo(messagehdlr, file, "-inf]");
2966 else
2967 SCIPmessageFPrintInfo(messagehdlr, file, "%.15g]", ub);
2968}
2969
2970/** prints hole list to file stream */
2971static
2973 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2974 FILE* file, /**< output file (or NULL for standard output) */
2975 SCIP_HOLELIST* holelist, /**< hole list pointer to hole of interest */
2976 const char* name /**< hole type name */
2977 )
2978{ /*lint --e{715}*/
2979 SCIP_Real left;
2980 SCIP_Real right;
2981
2982 if( holelist == NULL )
2983 return;
2984
2985 left = SCIPholelistGetLeft(holelist);
2986 right = SCIPholelistGetRight(holelist);
2987
2988 /* display first hole */
2989 SCIPmessageFPrintInfo(messagehdlr, file, ", %s=(%g,%g)", name, left, right);
2990 holelist = SCIPholelistGetNext(holelist);
2991
2992 while(holelist != NULL )
2993 {
2994 left = SCIPholelistGetLeft(holelist);
2995 right = SCIPholelistGetRight(holelist);
2996
2997 /* display hole */
2998 SCIPmessageFPrintInfo(messagehdlr, file, "(%g,%g)", left, right);
2999
3000 /* get next hole */
3001 holelist = SCIPholelistGetNext(holelist);
3002 }
3003}
3004
3005/** outputs variable information into file stream */
3007 SCIP_VAR* var, /**< problem variable */
3008 SCIP_SET* set, /**< global SCIP settings */
3009 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3010 FILE* file /**< output file (or NULL for standard output) */
3011 )
3012{
3013 SCIP_HOLELIST* holelist;
3014 SCIP_Real lb;
3015 SCIP_Real ub;
3016 int i;
3017
3018 assert(var != NULL);
3019 assert(var->scip == set->scip);
3020
3021 /* type of variable */
3022 switch( SCIPvarGetType(var) )
3023 {
3025 SCIPmessageFPrintInfo(messagehdlr, file, " [binary]");
3026 break;
3028 SCIPmessageFPrintInfo(messagehdlr, file, " [integer]");
3029 break;
3031 SCIPmessageFPrintInfo(messagehdlr, file, " [implicit]");
3032 break;
3034 SCIPmessageFPrintInfo(messagehdlr, file, " [continuous]");
3035 break;
3036 default:
3037 SCIPerrorMessage("unknown variable type\n");
3038 SCIPABORT();
3039 return SCIP_ERROR; /*lint !e527*/
3040 }
3041
3042 /* name */
3043 SCIPmessageFPrintInfo(messagehdlr, file, " <%s>:", var->name);
3044
3045 /* objective value */
3046 SCIPmessageFPrintInfo(messagehdlr, file, " obj=%.15g", var->obj);
3047
3048 /* bounds (global bounds for transformed variables, original bounds for original variables) */
3050 {
3051 /* output original bound */
3054 printBounds(set, messagehdlr, file, lb, ub, "original bounds");
3055
3056 /* output lazy bound */
3057 lb = SCIPvarGetLbLazy(var);
3058 ub = SCIPvarGetUbLazy(var);
3059
3060 /* only display the lazy bounds if they are different from [-infinity,infinity] */
3061 if( !SCIPsetIsInfinity(set, -lb) || !SCIPsetIsInfinity(set, ub) )
3062 printBounds(set, messagehdlr, file, lb, ub, "lazy bounds");
3063
3064 holelist = SCIPvarGetHolelistOriginal(var);
3065 printHolelist(messagehdlr, file, holelist, "original holes");
3066 }
3067 else
3068 {
3069 /* output global bound */
3070 lb = SCIPvarGetLbGlobal(var);
3071 ub = SCIPvarGetUbGlobal(var);
3072 printBounds(set, messagehdlr, file, lb, ub, "global bounds");
3073
3074 /* output local bound */
3075 lb = SCIPvarGetLbLocal(var);
3076 ub = SCIPvarGetUbLocal(var);
3077 printBounds(set, messagehdlr, file, lb, ub, "local bounds");
3078
3079 /* output lazy bound */
3080 lb = SCIPvarGetLbLazy(var);
3081 ub = SCIPvarGetUbLazy(var);
3082
3083 /* only display the lazy bounds if they are different from [-infinity,infinity] */
3084 if( !SCIPsetIsInfinity(set, -lb) || !SCIPsetIsInfinity(set, ub) )
3085 printBounds(set, messagehdlr, file, lb, ub, "lazy bounds");
3086
3087 /* global hole list */
3088 holelist = SCIPvarGetHolelistGlobal(var);
3089 printHolelist(messagehdlr, file, holelist, "global holes");
3090
3091 /* local hole list */
3092 holelist = SCIPvarGetHolelistLocal(var);
3093 printHolelist(messagehdlr, file, holelist, "local holes");
3094 }
3095
3096 /* fixings and aggregations */
3097 switch( SCIPvarGetStatus(var) )
3098 {
3102 break;
3103
3105 SCIPmessageFPrintInfo(messagehdlr, file, ", fixed:");
3107 SCIPmessageFPrintInfo(messagehdlr, file, "+inf");
3108 else if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
3109 SCIPmessageFPrintInfo(messagehdlr, file, "-inf");
3110 else
3111 SCIPmessageFPrintInfo(messagehdlr, file, "%.15g", var->glbdom.lb);
3112 break;
3113
3115 SCIPmessageFPrintInfo(messagehdlr, file, ", aggregated:");
3117 SCIPmessageFPrintInfo(messagehdlr, file, " %.15g", var->data.aggregate.constant);
3118 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g<%s>", var->data.aggregate.scalar, SCIPvarGetName(var->data.aggregate.var));
3119 break;
3120
3122 SCIPmessageFPrintInfo(messagehdlr, file, ", aggregated:");
3124 SCIPmessageFPrintInfo(messagehdlr, file, " %.15g", var->data.multaggr.constant);
3125 for( i = 0; i < var->data.multaggr.nvars; ++i )
3126 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g<%s>", var->data.multaggr.scalars[i], SCIPvarGetName(var->data.multaggr.vars[i]));
3127 break;
3128
3130 SCIPmessageFPrintInfo(messagehdlr, file, ", negated: %.15g - <%s>", var->data.negate.constant, SCIPvarGetName(var->negatedvar));
3131 break;
3132
3133 default:
3134 SCIPerrorMessage("unknown variable status\n");
3135 SCIPABORT();
3136 return SCIP_ERROR; /*lint !e527*/
3137 }
3138
3139 SCIPmessageFPrintInfo(messagehdlr, file, "\n");
3140
3141 return SCIP_OKAY;
3142}
3143
3144/** issues a VARUNLOCKED event on the given variable */
3145static
3147 SCIP_VAR* var, /**< problem variable to change */
3148 BMS_BLKMEM* blkmem, /**< block memory */
3149 SCIP_SET* set, /**< global SCIP settings */
3150 SCIP_EVENTQUEUE* eventqueue /**< event queue */
3151 )
3152{
3154
3155 assert(var != NULL);
3157 assert(var->scip == set->scip);
3158
3159 /* issue VARUNLOCKED event on variable */
3161 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
3162
3163 return SCIP_OKAY;
3164}
3165
3166/** modifies lock numbers for rounding */
3168 SCIP_VAR* var, /**< problem variable */
3169 BMS_BLKMEM* blkmem, /**< block memory */
3170 SCIP_SET* set, /**< global SCIP settings */
3171 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3172 SCIP_LOCKTYPE locktype, /**< type of the variable locks */
3173 int addnlocksdown, /**< increase in number of rounding down locks */
3174 int addnlocksup /**< increase in number of rounding up locks */
3175 )
3176{
3178
3179 assert(var != NULL);
3180 assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
3181 assert(var->nlocksup[locktype] >= 0);
3182 assert(var->nlocksdown[locktype] >= 0);
3183 assert(var->scip == set->scip);
3184
3185 if( addnlocksdown == 0 && addnlocksup == 0 )
3186 return SCIP_OKAY;
3187
3188#ifdef SCIP_DEBUG
3189 SCIPsetDebugMsg(set, "add rounding locks %d/%d to variable <%s> (locks=%d/%d, type=%u)\n",
3191#endif
3192
3193 lockvar = var;
3194
3195 while( TRUE ) /*lint !e716 */
3196 {
3197 assert(lockvar != NULL);
3198
3199 switch( SCIPvarGetStatus(lockvar) )
3200 {
3202 if( lockvar->data.original.transvar != NULL )
3203 {
3204 lockvar = lockvar->data.original.transvar;
3205 break;
3206 }
3207 else
3208 {
3209 lockvar->nlocksdown[locktype] += addnlocksdown;
3210 lockvar->nlocksup[locktype] += addnlocksup;
3211
3212 assert(lockvar->nlocksdown[locktype] >= 0);
3213 assert(lockvar->nlocksup[locktype] >= 0);
3214
3215 return SCIP_OKAY;
3216 }
3220 lockvar->nlocksdown[locktype] += addnlocksdown;
3221 lockvar->nlocksup[locktype] += addnlocksup;
3222
3223 assert(lockvar->nlocksdown[locktype] >= 0);
3224 assert(lockvar->nlocksup[locktype] >= 0);
3225
3226 if( locktype == SCIP_LOCKTYPE_MODEL && lockvar->nlocksdown[locktype] <= 1
3227 && lockvar->nlocksup[locktype] <= 1 )
3228 {
3229 SCIP_CALL( varEventVarUnlocked(lockvar, blkmem, set, eventqueue) );
3230 }
3231
3232 return SCIP_OKAY;
3234 assert(!lockvar->donotaggr);
3235
3236 if( lockvar->data.aggregate.scalar < 0.0 )
3237 {
3238 int tmp = addnlocksup;
3239
3242 }
3243
3244 lockvar = lockvar->data.aggregate.var;
3245 break;
3247 {
3248 int v;
3249
3250 assert(!lockvar->donotmultaggr);
3251
3252 lockvar->nlocksdown[locktype] += addnlocksdown;
3253 lockvar->nlocksup[locktype] += addnlocksup;
3254
3255 assert(lockvar->nlocksdown[locktype] >= 0);
3256 assert(lockvar->nlocksup[locktype] >= 0);
3257
3258 for( v = lockvar->data.multaggr.nvars - 1; v >= 0; --v )
3259 {
3260 if( lockvar->data.multaggr.scalars[v] > 0.0 )
3261 {
3262 SCIP_CALL( SCIPvarAddLocks(lockvar->data.multaggr.vars[v], blkmem, set, eventqueue, locktype, addnlocksdown,
3263 addnlocksup) );
3264 }
3265 else
3266 {
3267 SCIP_CALL( SCIPvarAddLocks(lockvar->data.multaggr.vars[v], blkmem, set, eventqueue, locktype, addnlocksup,
3268 addnlocksdown) );
3269 }
3270 }
3271 return SCIP_OKAY;
3272 }
3274 {
3275 int tmp = addnlocksup;
3276
3277 assert(lockvar->negatedvar != NULL);
3279 assert(lockvar->negatedvar->negatedvar == lockvar);
3280
3283
3284 lockvar = lockvar->negatedvar;
3285 break;
3286 }
3287 default:
3288 SCIPerrorMessage("unknown variable status\n");
3289 return SCIP_INVALIDDATA;
3290 }
3291 }
3292}
3293
3294/** gets number of locks for rounding down of a special type */
3296 SCIP_VAR* var, /**< problem variable */
3297 SCIP_LOCKTYPE locktype /**< type of variable locks */
3298 )
3299{
3300 int nlocks;
3301 int i;
3302
3303 assert(var != NULL);
3304 assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
3305 assert(var->nlocksdown[locktype] >= 0);
3306
3307 switch( SCIPvarGetStatus(var) )
3308 {
3310 if( var->data.original.transvar != NULL )
3312 else
3313 return var->nlocksdown[locktype];
3314
3318 return var->nlocksdown[locktype];
3319
3321 assert(!var->donotaggr);
3322 if( var->data.aggregate.scalar > 0.0 )
3324 else
3326
3329 nlocks = 0;
3330 for( i = 0; i < var->data.multaggr.nvars; ++i )
3331 {
3332 if( var->data.multaggr.scalars[i] > 0.0 )
3334 else
3336 }
3337 return nlocks;
3338
3344
3345 default:
3346 SCIPerrorMessage("unknown variable status\n");
3347 SCIPABORT();
3348 return INT_MAX; /*lint !e527*/
3349 }
3350}
3351
3352/** gets number of locks for rounding up of a special type */
3354 SCIP_VAR* var, /**< problem variable */
3355 SCIP_LOCKTYPE locktype /**< type of variable locks */
3356 )
3357{
3358 int nlocks;
3359 int i;
3360
3361 assert(var != NULL);
3362 assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
3363 assert(var->nlocksup[locktype] >= 0);
3364
3365 switch( SCIPvarGetStatus(var) )
3366 {
3368 if( var->data.original.transvar != NULL )
3370 else
3371 return var->nlocksup[locktype];
3372
3376 return var->nlocksup[locktype];
3377
3379 assert(!var->donotaggr);
3380 if( var->data.aggregate.scalar > 0.0 )
3382 else
3384
3387 nlocks = 0;
3388 for( i = 0; i < var->data.multaggr.nvars; ++i )
3389 {
3390 if( var->data.multaggr.scalars[i] > 0.0 )
3392 else
3394 }
3395 return nlocks;
3396
3402
3403 default:
3404 SCIPerrorMessage("unknown variable status\n");
3405 SCIPABORT();
3406 return INT_MAX; /*lint !e527*/
3407 }
3408}
3409
3410/** gets number of locks for rounding down
3411 *
3412 * @note This method will always return variable locks of type model
3413 *
3414 * @note It is recommented to use SCIPvarGetNLocksDownType()
3415 */
3417 SCIP_VAR* var /**< problem variable */
3418 )
3419{
3421}
3422
3423/** gets number of locks for rounding up
3424 *
3425 * @note This method will always return variable locks of type model
3426 *
3427 * @note It is recommented to use SCIPvarGetNLocksUpType()
3428 */
3430 SCIP_VAR* var /**< problem variable */
3431 )
3432{
3434}
3435
3436/** is it possible, to round variable down and stay feasible?
3437 *
3438 * @note This method will always check w.r.t variable locks of type model
3439 */
3441 SCIP_VAR* var /**< problem variable */
3442 )
3443{
3445}
3446
3447/** is it possible, to round variable up and stay feasible?
3448 *
3449 * @note This method will always check w.r.t. variable locks of type model
3450 */
3452 SCIP_VAR* var /**< problem variable */
3453 )
3454{
3456}
3457
3458/** gets and captures transformed variable of a given variable; if the variable is not yet transformed,
3459 * a new transformed variable for this variable is created
3460 */
3462 SCIP_VAR* origvar, /**< original problem variable */
3463 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3464 SCIP_SET* set, /**< global SCIP settings */
3465 SCIP_STAT* stat, /**< problem statistics */
3466 SCIP_OBJSENSE objsense, /**< objective sense of original problem; transformed is always MINIMIZE */
3467 SCIP_VAR** transvar /**< pointer to store the transformed variable */
3468 )
3469{
3470 char name[SCIP_MAXSTRLEN];
3471
3472 assert(origvar != NULL);
3473 assert(origvar->scip == set->scip);
3475 assert(SCIPsetIsEQ(set, origvar->glbdom.lb, origvar->locdom.lb));
3476 assert(SCIPsetIsEQ(set, origvar->glbdom.ub, origvar->locdom.ub));
3477 assert(origvar->vlbs == NULL);
3478 assert(origvar->vubs == NULL);
3479 assert(transvar != NULL);
3480
3481 /* check if variable is already transformed */
3482 if( origvar->data.original.transvar != NULL )
3483 {
3484 *transvar = origvar->data.original.transvar;
3485 SCIPvarCapture(*transvar);
3486 }
3487 else
3488 {
3489 int i;
3490
3491 /* create transformed variable */
3492 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "t_%s", origvar->name);
3493 SCIP_CALL( SCIPvarCreateTransformed(transvar, blkmem, set, stat, name,
3494 origvar->glbdom.lb, origvar->glbdom.ub, (SCIP_Real)objsense * origvar->obj,
3495 SCIPvarGetType(origvar), origvar->initial, origvar->removable,
3496 origvar->vardelorig, origvar->vartrans, origvar->vardeltrans, origvar->varcopy, NULL) );
3497
3498 /* copy the branch factor and priority */
3499 (*transvar)->branchfactor = origvar->branchfactor;
3500 (*transvar)->branchpriority = origvar->branchpriority;
3501 (*transvar)->branchdirection = origvar->branchdirection; /*lint !e732*/
3502
3503 /* duplicate hole lists */
3504 SCIP_CALL( holelistDuplicate(&(*transvar)->glbdom.holelist, blkmem, set, origvar->glbdom.holelist) );
3505 SCIP_CALL( holelistDuplicate(&(*transvar)->locdom.holelist, blkmem, set, origvar->locdom.holelist) );
3506
3507 /* link original and transformed variable */
3508 origvar->data.original.transvar = *transvar;
3509 SCIP_CALL( varAddParent(*transvar, blkmem, set, origvar) );
3510
3511 /* copy rounding locks */
3512 for( i = 0; i < NLOCKTYPES; i++ )
3513 {
3514 (*transvar)->nlocksdown[i] = origvar->nlocksdown[i];
3515 (*transvar)->nlocksup[i] = origvar->nlocksup[i];
3516 assert((*transvar)->nlocksdown[i] >= 0);
3517 assert((*transvar)->nlocksup[i] >= 0);
3518 }
3519
3520 /* copy donot(mult)aggr status */
3521 (*transvar)->donotaggr = origvar->donotaggr;
3522 (*transvar)->donotmultaggr = origvar->donotmultaggr;
3523
3524 /* copy lazy bounds */
3525 (*transvar)->lazylb = origvar->lazylb;
3526 (*transvar)->lazyub = origvar->lazyub;
3527
3528 /* transfer eventual variable statistics; do not update global statistics, because this has been done
3529 * when original variable was created
3530 */
3531 SCIPhistoryUnite((*transvar)->history, origvar->history, FALSE);
3532
3533 /* transform user data */
3534 if( origvar->vartrans != NULL )
3535 {
3536 SCIP_CALL( origvar->vartrans(set->scip, origvar, origvar->vardata, *transvar, &(*transvar)->vardata) );
3537 }
3538 else
3539 (*transvar)->vardata = origvar->vardata;
3540 }
3541
3542 SCIPsetDebugMsg(set, "transformed variable: <%s>[%p] -> <%s>[%p]\n", origvar->name, (void*)origvar, (*transvar)->name, (void*)*transvar);
3543
3544 return SCIP_OKAY;
3545}
3546
3547/** gets corresponding transformed variable of an original or negated original variable */
3549 SCIP_VAR* origvar, /**< original problem variable */
3550 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3551 SCIP_SET* set, /**< global SCIP settings */
3552 SCIP_STAT* stat, /**< problem statistics */
3553 SCIP_VAR** transvar /**< pointer to store the transformed variable, or NULL if not existing yet */
3554 )
3555{
3556 assert(origvar != NULL);
3558 assert(origvar->scip == set->scip);
3559
3561 {
3562 assert(origvar->negatedvar != NULL);
3564
3565 if( origvar->negatedvar->data.original.transvar == NULL )
3566 *transvar = NULL;
3567 else
3568 {
3569 SCIP_CALL( SCIPvarNegate(origvar->negatedvar->data.original.transvar, blkmem, set, stat, transvar) );
3570 }
3571 }
3572 else
3573 *transvar = origvar->data.original.transvar;
3574
3575 return SCIP_OKAY;
3576}
3577
3578/** converts loose transformed variable into column variable, creates LP column */
3580 SCIP_VAR* var, /**< problem variable */
3581 BMS_BLKMEM* blkmem, /**< block memory */
3582 SCIP_SET* set, /**< global SCIP settings */
3583 SCIP_STAT* stat, /**< problem statistics */
3584 SCIP_PROB* prob, /**< problem data */
3585 SCIP_LP* lp /**< current LP data */
3586 )
3587{
3588 assert(var != NULL);
3590 assert(var->scip == set->scip);
3591
3592 SCIPsetDebugMsg(set, "creating column for variable <%s>\n", var->name);
3593
3594 /* switch variable status */
3595 var->varstatus = SCIP_VARSTATUS_COLUMN; /*lint !e641*/
3596
3597 /* create column of variable */
3598 SCIP_CALL( SCIPcolCreate(&var->data.col, blkmem, set, stat, var, 0, NULL, NULL, var->removable) );
3599
3600 if( var->probindex != -1 )
3601 {
3602 /* inform problem about the variable's status change */
3603 SCIP_CALL( SCIPprobVarChangedStatus(prob, blkmem, set, NULL, NULL, var) );
3604
3605 /* inform LP, that problem variable is now a column variable and no longer loose */
3607 }
3608
3609 return SCIP_OKAY;
3610}
3611
3612/** converts column transformed variable back into loose variable, frees LP column */
3614 SCIP_VAR* var, /**< problem variable */
3615 BMS_BLKMEM* blkmem, /**< block memory */
3616 SCIP_SET* set, /**< global SCIP settings */
3617 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3618 SCIP_PROB* prob, /**< problem data */
3619 SCIP_LP* lp /**< current LP data */
3620 )
3621{
3622 assert(var != NULL);
3624 assert(var->scip == set->scip);
3625 assert(var->data.col != NULL);
3626 assert(var->data.col->lppos == -1);
3627 assert(var->data.col->lpipos == -1);
3628
3629 SCIPsetDebugMsg(set, "deleting column for variable <%s>\n", var->name);
3630
3631 /* free column of variable */
3632 SCIP_CALL( SCIPcolFree(&var->data.col, blkmem, set, eventqueue, lp) );
3633
3634 /* switch variable status */
3635 var->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
3636
3637 if( var->probindex != -1 )
3638 {
3639 /* inform problem about the variable's status change */
3640 SCIP_CALL( SCIPprobVarChangedStatus(prob, blkmem, set, NULL, NULL, var) );
3641
3642 /* inform LP, that problem variable is now a loose variable and no longer a column */
3644 }
3645
3646 return SCIP_OKAY;
3647}
3648
3649/** issues a VARFIXED event on the given variable and all its parents (except ORIGINAL parents);
3650 * the event issuing on the parents is necessary, because unlike with bound changes, the parent variables
3651 * are not informed about a fixing of an active variable they are pointing to
3652 */
3653static
3655 SCIP_VAR* var, /**< problem variable to change */
3656 BMS_BLKMEM* blkmem, /**< block memory */
3657 SCIP_SET* set, /**< global SCIP settings */
3658 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3659 int fixeventtype /**< is this event a fixation(0), an aggregation(1), or a
3660 * multi-aggregation(2)
3661 */
3662 )
3663{
3665 SCIP_VARSTATUS varstatus;
3666 int i;
3667
3668 assert(var != NULL);
3669 assert(var->scip == set->scip);
3670 assert(0 <= fixeventtype && fixeventtype <= 2);
3671
3672 /* issue VARFIXED event on variable */
3674 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
3675
3676#ifndef NDEBUG
3677 for( i = var->nparentvars -1; i >= 0; --i )
3678 {
3680 }
3681#endif
3682
3683 switch( fixeventtype )
3684 {
3685 case 0:
3686 /* process all parents of a fixed variable */
3687 for( i = var->nparentvars - 1; i >= 0; --i )
3688 {
3689 varstatus = SCIPvarGetStatus(var->parentvars[i]);
3690
3691 assert(varstatus != SCIP_VARSTATUS_FIXED);
3692
3693 /* issue event on all not yet fixed parent variables, (that should already issued this event) except the original
3694 * one
3695 */
3696 if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3697 {
3698 SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3699 }
3700 }
3701 break;
3702 case 1:
3703 /* process all parents of a aggregated variable */
3704 for( i = var->nparentvars - 1; i >= 0; --i )
3705 {
3706 varstatus = SCIPvarGetStatus(var->parentvars[i]);
3707
3708 assert(varstatus != SCIP_VARSTATUS_FIXED);
3709
3710 /* issue event for not aggregated parent variable, because for these and its parents the var event was already
3711 * issued(, except the original one)
3712 *
3713 * @note that even before an aggregated parent variable, there might be variables, for which the vent was not
3714 * yet issued
3715 */
3716 if( varstatus == SCIP_VARSTATUS_AGGREGATED )
3717 continue;
3718
3719 if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3720 {
3721 SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3722 }
3723 }
3724 break;
3725 case 2:
3726 /* process all parents of a aggregated variable */
3727 for( i = var->nparentvars - 1; i >= 0; --i )
3728 {
3729 varstatus = SCIPvarGetStatus(var->parentvars[i]);
3730
3731 assert(varstatus != SCIP_VARSTATUS_FIXED);
3732
3733 /* issue event on all parent variables except the original one */
3734 if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3735 {
3736 SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3737 }
3738 }
3739 break;
3740 default:
3741 SCIPerrorMessage("unknown variable fixation event origin\n");
3742 return SCIP_INVALIDDATA;
3743 }
3744
3745 return SCIP_OKAY;
3746}
3747
3748/** converts variable into fixed variable */
3750 SCIP_VAR* var, /**< problem variable */
3751 BMS_BLKMEM* blkmem, /**< block memory */
3752 SCIP_SET* set, /**< global SCIP settings */
3753 SCIP_STAT* stat, /**< problem statistics */
3754 SCIP_PROB* transprob, /**< tranformed problem data */
3755 SCIP_PROB* origprob, /**< original problem data */
3756 SCIP_PRIMAL* primal, /**< primal data */
3757 SCIP_TREE* tree, /**< branch and bound tree */
3758 SCIP_REOPT* reopt, /**< reoptimization data structure */
3759 SCIP_LP* lp, /**< current LP data */
3760 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3761 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
3762 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3763 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
3764 SCIP_Real fixedval, /**< value to fix variable at */
3765 SCIP_Bool* infeasible, /**< pointer to store whether the fixing is infeasible */
3766 SCIP_Bool* fixed /**< pointer to store whether the fixing was performed (variable was unfixed) */
3767 )
3768{
3769 SCIP_Real obj;
3770 SCIP_Real childfixedval;
3771
3772 assert(var != NULL);
3773 assert(var->scip == set->scip);
3776 assert(infeasible != NULL);
3777 assert(fixed != NULL);
3778
3779 SCIPsetDebugMsg(set, "fix variable <%s>[%g,%g] to %g\n", var->name, var->glbdom.lb, var->glbdom.ub, fixedval);
3780
3781 *infeasible = FALSE;
3782 *fixed = FALSE;
3783
3785 {
3786 *infeasible = !SCIPsetIsFeasEQ(set, fixedval, var->locdom.lb);
3787 SCIPsetDebugMsg(set, " -> variable already fixed to %g (fixedval=%g): infeasible=%u\n", var->locdom.lb, fixedval, *infeasible);
3788 return SCIP_OKAY;
3789 }
3793 {
3794 SCIPsetDebugMsg(set, " -> fixing infeasible: locdom=[%g,%g], fixedval=%g\n", var->locdom.lb, var->locdom.ub, fixedval);
3795 *infeasible = TRUE;
3796 return SCIP_OKAY;
3797 }
3798
3799 switch( SCIPvarGetStatus(var) )
3800 {
3802 if( var->data.original.transvar == NULL )
3803 {
3804 SCIPerrorMessage("cannot fix an untransformed original variable\n");
3805 return SCIP_INVALIDDATA;
3806 }
3807 SCIP_CALL( SCIPvarFix(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
3808 lp, branchcand, eventfilter, eventqueue, cliquetable, fixedval, infeasible, fixed) );
3809 break;
3810
3812 assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
3813
3814 /* set the fixed variable's objective value to 0.0 */
3815 obj = var->obj;
3816 SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
3817
3818 /* since we change the variable type form loose to fixed, we have to adjust the number of loose
3819 * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
3820 * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
3821 * objective of this variable is set to zero
3822 */
3824
3825 /* change variable's bounds to fixed value (thereby removing redundant implications and variable bounds) */
3826 holelistFree(&var->glbdom.holelist, blkmem);
3827 holelistFree(&var->locdom.holelist, blkmem);
3828 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, fixedval) );
3829 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, fixedval) );
3830
3831 /* explicitly set variable's bounds, even if the fixed value is in epsilon range of the old bound */
3832 var->glbdom.lb = fixedval;
3833 var->glbdom.ub = fixedval;
3834 var->locdom.lb = fixedval;
3835 var->locdom.ub = fixedval;
3836
3837 /* delete implications and variable bounds information */
3838 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
3839 assert(var->vlbs == NULL);
3840 assert(var->vubs == NULL);
3841 assert(var->implics == NULL);
3842
3843 /* clear the history of the variable */
3846
3847 /* convert variable into fixed variable */
3848 var->varstatus = SCIP_VARSTATUS_FIXED; /*lint !e641*/
3849
3850 /* inform problem about the variable's status change */
3851 if( var->probindex != -1 )
3852 {
3853 SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
3854 }
3855
3856 /* reset the objective value of the fixed variable, thus adjusting the problem's objective offset */
3857 SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventfilter, eventqueue, obj) );
3858
3859 /* issue VARFIXED event */
3860 SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 0) );
3861
3862 *fixed = TRUE;
3863 break;
3864
3866 SCIPerrorMessage("cannot fix a column variable\n");
3867 return SCIP_INVALIDDATA;
3868
3870 SCIPerrorMessage("cannot fix a fixed variable again\n"); /*lint !e527*/
3871 SCIPABORT(); /* case is already handled in earlier if condition */
3872 return SCIP_INVALIDDATA; /*lint !e527*/
3873
3875 /* fix aggregation variable y in x = a*y + c, instead of fixing x directly */
3880 else
3882 SCIP_CALL( SCIPvarFix(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
3883 branchcand, eventfilter, eventqueue, cliquetable, childfixedval, infeasible, fixed) );
3884 break;
3885
3887 SCIPerrorMessage("cannot fix a multiple aggregated variable\n");
3888 SCIPABORT();
3889 return SCIP_INVALIDDATA; /*lint !e527*/
3890
3892 /* fix negation variable x in x' = offset - x, instead of fixing x' directly */
3897 SCIP_CALL( SCIPvarFix(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
3898 branchcand, eventfilter, eventqueue, cliquetable, var->data.negate.constant - fixedval, infeasible, fixed) );
3899 break;
3900
3901 default:
3902 SCIPerrorMessage("unknown variable status\n");
3903 return SCIP_INVALIDDATA;
3904 }
3905
3906 return SCIP_OKAY;
3907}
3908
3909/** transforms given variables, scalars and constant to the corresponding active variables, scalars and constant
3910 *
3911 * If the number of needed active variables is greater than the available slots in the variable array, nothing happens except
3912 * that the required size is stored in the corresponding variable; hence, if afterwards the required size is greater than the
3913 * available slots (varssize), nothing happens; otherwise, the active variable representation is stored in the arrays.
3914 *
3915 * The reason for this approach is that we cannot reallocate memory, since we do not know how the
3916 * memory has been allocated (e.g., by a C++ 'new' or SCIP functions).
3917 */
3919 SCIP_SET* set, /**< global SCIP settings */
3920 SCIP_VAR** vars, /**< variable array to get active variables */
3921 SCIP_Real* scalars, /**< scalars a_1, ..., a_n in linear sum a_1*x_1 + ... + a_n*x_n + c */
3922 int* nvars, /**< pointer to number of variables and values in vars and scalars array */
3923 int varssize, /**< available slots in vars and scalars array */
3924 SCIP_Real* constant, /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c */
3925 int* requiredsize, /**< pointer to store the required array size for the active variables */
3926 SCIP_Bool mergemultiples /**< should multiple occurrences of a var be replaced by a single coeff? */
3927 )
3928{
3930 SCIP_Real* activescalars;
3931 int nactivevars;
3932 SCIP_Real activeconstant;
3933 SCIP_Bool activeconstantinf;
3934 int activevarssize;
3935
3936 SCIP_VAR* var;
3937 SCIP_Real scalar;
3938 int v;
3939 int k;
3940
3941 SCIP_VAR** tmpvars;
3943 SCIP_Real* tmpscalars;
3944 SCIP_Real* multscalars;
3945 int tmpvarssize;
3946 int ntmpvars;
3947 int nmultvars;
3948
3950 SCIP_Real multscalar;
3951 SCIP_Real multconstant;
3952 int pos;
3953
3954 int noldtmpvars;
3955
3957 SCIP_Real* tmpscalars2;
3958 int tmpvarssize2;
3959 int ntmpvars2;
3960
3961 SCIP_Bool sortagain = FALSE;
3962
3963 assert(set != NULL);
3964 assert(nvars != NULL);
3965 assert(scalars != NULL || *nvars == 0);
3966 assert(constant != NULL);
3968 assert(*nvars <= varssize);
3969
3970 *requiredsize = 0;
3971
3972 if( *nvars == 0 )
3973 return SCIP_OKAY;
3974
3975 assert(vars != NULL);
3976
3977 /* handle the "easy" case of just one variable and avoid memory allocation if the variable is already active */
3978 if( *nvars == 1 && (vars[0]->varstatus == ((int) SCIP_VARSTATUS_COLUMN) || vars[0]->varstatus == ((int) SCIP_VARSTATUS_LOOSE)) )
3979 {
3980 *requiredsize = 1;
3981
3982 return SCIP_OKAY;
3983 }
3984
3985 nactivevars = 0;
3986 activeconstant = 0.0;
3988 activevarssize = (*nvars) * 2;
3989 ntmpvars = *nvars;
3990 tmpvarssize = *nvars;
3991
3992 tmpvarssize2 = 1;
3993
3994 /* allocate temporary memory */
4001
4002 /* to avoid unnecessary expanding of variable arrays while disaggregating several variables multiple times combine same variables
4003 * first, first get all corresponding variables with status loose, column, multaggr or fixed
4004 */
4005 for( v = ntmpvars - 1; v >= 0; --v )
4006 {
4007 var = tmpvars[v];
4008 scalar = tmpscalars[v];
4009
4010 assert(var != NULL);
4011 /* transforms given variable, scalar and constant to the corresponding active, fixed, or
4012 * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed
4013 * variable, "scalar" will be 0.0 and the value of the sum will be stored in "constant".
4014 */
4016 assert(var != NULL);
4017
4020
4022
4027
4028 tmpvars[v] = var;
4029 tmpscalars[v] = scalar;
4030 }
4032
4033 /* sort all variables to combine equal variables easily */
4035 ntmpvars = 0;
4036 for( v = 1; v < noldtmpvars; ++v )
4037 {
4038 /* combine same variables */
4039 if( SCIPvarCompare(tmpvars[v], tmpvars[ntmpvars]) == 0 )
4040 {
4042 }
4043 else
4044 {
4045 ++ntmpvars;
4046 if( v > ntmpvars )
4047 {
4049 tmpvars[ntmpvars] = tmpvars[v];
4050 }
4051 }
4052 }
4053 ++ntmpvars;
4054
4055#ifdef SCIP_MORE_DEBUG
4056 for( v = 1; v < ntmpvars; ++v )
4057 assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
4058#endif
4059
4060 /* collect for each variable the representation in active variables */
4061 while( ntmpvars >= 1 )
4062 {
4063 --ntmpvars;
4064 ntmpvars2 = 0;
4065 var = tmpvars[ntmpvars];
4066 scalar = tmpscalars[ntmpvars];
4067
4068 assert(var != NULL);
4069
4070 /* TODO: maybe we should test here on SCIPsetIsZero() instead of 0.0 */
4071 if( scalar == 0.0 )
4072 continue;
4073
4078
4079 switch( SCIPvarGetStatus(var) )
4080 {
4083 /* x = a*y + c */
4085 {
4086 activevarssize *= 2;
4090 }
4092 activescalars[nactivevars] = scalar;
4093 nactivevars++;
4094 break;
4095
4097 /* x = a_1*y_1 + ... + a_n*y_n + c */
4101 sortagain = TRUE;
4102
4104 {
4105 while( nmultvars + ntmpvars > tmpvarssize )
4106 tmpvarssize *= 2;
4110 }
4111
4112 if( nmultvars > tmpvarssize2 )
4113 {
4114 while( nmultvars > tmpvarssize2 )
4115 tmpvarssize2 *= 2;
4119 }
4120
4121 --nmultvars;
4122
4123 for( ; nmultvars >= 0; --nmultvars )
4124 {
4127 multconstant = 0;
4128
4129 assert(multvar != NULL);
4131 assert(multvar != NULL);
4132
4137
4138 if( !activeconstantinf )
4139 {
4140 assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
4141
4143 {
4144 assert(scalar != 0.0);
4145 if( scalar * multconstant > 0.0 )
4146 {
4149 }
4150 else
4151 {
4154 }
4155 }
4156 else
4157 activeconstant += scalar * multconstant;
4158 }
4159#ifndef NDEBUG
4160 else
4161 {
4162 assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
4164 assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
4166 }
4167#endif
4168
4169 if( SCIPsortedvecFindPtr((void**)tmpvars, SCIPvarComp, multvar, ntmpvars, &pos) )
4170 {
4171 assert(SCIPvarCompare(tmpvars[pos], multvar) == 0);
4172 tmpscalars[pos] += scalar * multscalar;
4173 }
4174 else
4175 {
4177 tmpscalars2[ntmpvars2] = scalar * multscalar;
4178 ++(ntmpvars2);
4180 }
4181 }
4182
4183 if( ntmpvars2 > 0 )
4184 {
4185 /* sort all variables to combine equal variables easily */
4187 pos = 0;
4188 for( v = 1; v < ntmpvars2; ++v )
4189 {
4190 /* combine same variables */
4191 if( SCIPvarCompare(tmpvars2[v], tmpvars2[pos]) == 0 )
4192 {
4193 tmpscalars2[pos] += tmpscalars2[v];
4194 }
4195 else
4196 {
4197 ++pos;
4198 if( v > pos )
4199 {
4200 tmpscalars2[pos] = tmpscalars2[v];
4201 tmpvars2[pos] = tmpvars2[v];
4202 }
4203 }
4204 }
4205 ntmpvars2 = pos + 1;
4206#ifdef SCIP_MORE_DEBUG
4207 for( v = 1; v < ntmpvars2; ++v )
4208 {
4209 assert(SCIPvarCompare(tmpvars2[v], tmpvars2[v-1]) > 0);
4210 }
4211 for( v = 1; v < ntmpvars; ++v )
4212 {
4213 assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
4214 }
4215#endif
4216 v = ntmpvars - 1;
4217 k = ntmpvars2 - 1;
4218 pos = ntmpvars + ntmpvars2 - 1;
4220
4221 while( v >= 0 && k >= 0 )
4222 {
4223 assert(pos >= 0);
4224 assert(SCIPvarCompare(tmpvars[v], tmpvars2[k]) != 0);
4225 if( SCIPvarCompare(tmpvars[v], tmpvars2[k]) >= 0 )
4226 {
4227 tmpvars[pos] = tmpvars[v];
4228 tmpscalars[pos] = tmpscalars[v];
4229 --v;
4230 }
4231 else
4232 {
4233 tmpvars[pos] = tmpvars2[k];
4234 tmpscalars[pos] = tmpscalars2[k];
4235 --k;
4236 }
4237 --pos;
4238 assert(pos >= 0);
4239 }
4240 while( v >= 0 )
4241 {
4242 assert(pos >= 0);
4243 tmpvars[pos] = tmpvars[v];
4244 tmpscalars[pos] = tmpscalars[v];
4245 --v;
4246 --pos;
4247 }
4248 while( k >= 0 )
4249 {
4250 assert(pos >= 0);
4251 tmpvars[pos] = tmpvars2[k];
4252 tmpscalars[pos] = tmpscalars2[k];
4253 --k;
4254 --pos;
4255 }
4256 }
4257#ifdef SCIP_MORE_DEBUG
4258 for( v = 1; v < ntmpvars; ++v )
4259 {
4260 assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
4261 }
4262#endif
4263
4264 if( !activeconstantinf )
4265 {
4266 assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
4267
4269
4271 {
4272 assert(scalar != 0.0);
4273 if( scalar * multconstant > 0.0 )
4274 {
4277 }
4278 else
4279 {
4282 }
4283 }
4284 else
4285 activeconstant += scalar * multconstant;
4286 }
4287#ifndef NDEBUG
4288 else
4289 {
4291 assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
4293 assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
4295 }
4296#endif
4297 break;
4298
4303 default:
4304 /* case x = c, but actually we should not be here, since SCIPvarGetProbvarSum() returns a scalar of 0.0 for
4305 * fixed variables and is handled already
4306 */
4309 }
4310 }
4311
4312 if( mergemultiples )
4313 {
4314 if( sortagain )
4315 {
4316 /* sort variable and scalar array by variable index */
4318
4319 /* eliminate duplicates and count required size */
4320 v = nactivevars - 1;
4321 while( v > 0 )
4322 {
4323 /* combine both variable since they are the same */
4324 if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
4325 {
4326 if( activescalars[v - 1] + activescalars[v] != 0.0 )
4327 {
4328 activescalars[v - 1] += activescalars[v];
4329 --nactivevars;
4332 }
4333 else
4334 {
4335 --nactivevars;
4338 --nactivevars;
4339 --v;
4342 }
4343 }
4344 --v;
4345 }
4346 }
4347 /* the variables were added in reverse order, we revert the order now;
4348 * this should not be necessary, but not doing this changes the behavior sometimes
4349 */
4350 else
4351 {
4353 SCIP_Real tmpscalar;
4354
4355 for( v = 0; v < nactivevars / 2; ++v )
4356 {
4357 tmpvar = activevars[v];
4359 activevars[v] = activevars[nactivevars - 1 - v];
4361 activevars[nactivevars - 1 - v] = tmpvar;
4363 }
4364 }
4365 }
4367
4368 if( varssize >= *requiredsize )
4369 {
4370 assert(vars != NULL);
4371
4372 *nvars = *requiredsize;
4373
4374 if( !SCIPsetIsInfinity(set, *constant) && !SCIPsetIsInfinity(set, -(*constant)) )
4375 {
4376 /* if the activeconstant is infinite, the constant pointer gets the same value, otherwise add the value */
4377 if( activeconstantinf )
4378 (*constant) = activeconstant;
4379 else
4380 (*constant) += activeconstant;
4381 }
4382#ifndef NDEBUG
4383 else
4384 {
4387 }
4388#endif
4389
4390 /* copy active variable and scalar array to the given arrays */
4391 for( v = 0; v < *nvars; ++v )
4392 {
4393 vars[v] = activevars[v];
4394 scalars[v] = activescalars[v]; /*lint !e613*/
4395 }
4396 }
4397
4398 assert(SCIPsetIsInfinity(set, *constant) == ((*constant) == SCIPsetInfinity(set))); /*lint !e777*/
4399 assert(SCIPsetIsInfinity(set, -(*constant)) == ((*constant) == -SCIPsetInfinity(set))); /*lint !e777*/
4400
4402 SCIPsetFreeBufferArray(set, &tmpvars);
4407
4408 return SCIP_OKAY;
4409}
4410
4411
4412/** flattens aggregation graph of multi-aggregated variable in order to avoid exponential recursion later on */
4414 SCIP_VAR* var, /**< problem variable */
4415 BMS_BLKMEM* blkmem, /**< block memory */
4416 SCIP_SET* set, /**< global SCIP settings */
4417 SCIP_EVENTQUEUE* eventqueue /**< event queue */
4418 )
4419{
4420 int nlocksup[NLOCKTYPES];
4421 int nlocksdown[NLOCKTYPES];
4422 SCIP_Real multconstant;
4423 int multvarssize;
4424 int nmultvars;
4425 int multrequiredsize;
4426 int i;
4427
4428 assert( var != NULL );
4430 assert(var->scip == set->scip);
4431
4432 /* in order to update the locks on the active representation of the multi-aggregated variable, we remove all locks
4433 * on the current representation now and re-add the locks once the variable graph has been flattened, which
4434 * may lead to duplicate occurences of the same variable being merged
4435 *
4436 * Here is an example. Assume we have the multi-aggregation z = x + y.
4437 * z occures with positive coefficient in a <= constraint c1, so it has an uplock from there.
4438 * When the multi-aggregation is performed, all locks are added to the active representation,
4439 * so x and y both get an uplock from c1. However, z was not yet replaced by x + y in c1.
4440 * Next, a negation y = 1 - x is identified. Again, locks are moved, so that the uplock of y originating
4441 * from c1 is added to x as a downlock. Thus, x has both an up- and downlock from c1.
4442 * The multi-aggregation changes to z = x + 1 - x, which corresponds to the locks.
4443 * However, before z is replaced by that sum, SCIPvarFlattenAggregationGraph() is called
4444 * which changes z = x + y = x + 1 - x = 1, since it merges multiple occurences of the same variable.
4445 * The up- and downlock of x, however, is not removed when replacing z in c1 by its active representation,
4446 * because it is just 1 now. Therefore, we need to update locks when flattening the aggregation graph.
4447 * For this, the multi-aggregated variable knows its locks in addition to adding them to the active
4448 * representation, which corresponds to the locks from constraints where the variable was not replaced yet.
4449 * By removing the locks here, based on the old representation and adding them again after flattening,
4450 * we ensure that the locks are correct afterwards if coefficients were merged.
4451 */
4452 for( i = 0; i < NLOCKTYPES; ++i )
4453 {
4454 nlocksup[i] = var->nlocksup[i];
4455 nlocksdown[i] = var->nlocksdown[i];
4456
4457 SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, -nlocksdown[i], -nlocksup[i]) );
4458 }
4459
4463
4465
4467 {
4473 }
4474 /**@note After the flattening the multi aggregation might resolve to be in fact an aggregation (or even a fixing?).
4475 * This issue is not resolved right now, since var->data.multaggr.nvars < 2 should not cause troubles. However, one
4476 * may loose performance hereby, since aggregated variables are easier to handle.
4477 *
4478 * Note, that there are two cases where SCIPvarFlattenAggregationGraph() is called: The easier one is that it is
4479 * called while installing the multi-aggregation. in principle, the described issue could be handled straightforward
4480 * in this case by aggregating or fixing the variable instead. The more complicated case is the one, when the
4481 * multi-aggregation is used, e.g., in linear presolving (and the variable is already declared to be multi-aggregated).
4482 *
4483 * By now, it is not allowed to fix or aggregate multi-aggregated variables which would be necessary in this case.
4484 *
4485 * The same issue appears in the SCIPvarGetProbvar...() methods.
4486 */
4487
4491
4492 for( i = 0; i < NLOCKTYPES; ++i )
4493 {
4494 SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
4495 }
4496
4497 return SCIP_OKAY;
4498}
4499
4500/** merge two variable histories together; a typical use case is that \p othervar is an image of the target variable
4501 * in a SCIP copy. Method should be applied with care, especially because no internal checks are performed whether
4502 * the history merge is reasonable
4503 *
4504 * @note Do not use this method if the two variables originate from two SCIP's with different objective functions, since
4505 * this corrupts the variable pseudo costs
4506 * @note Apply with care; no internal checks are performed if the two variables should be merged
4507 */
4509 SCIP_VAR* targetvar, /**< the variable that should contain both histories afterwards */
4510 SCIP_VAR* othervar, /**< the variable whose history is to be merged with that of the target variable */
4511 SCIP_STAT* stat /**< problem statistics */
4512 )
4513{
4514 /* merge only the history of the current run into the target history */
4515 SCIPhistoryUnite(targetvar->history, othervar->historycrun, FALSE);
4516
4517 /* apply the changes also to the global history */
4518 SCIPhistoryUnite(stat->glbhistory, othervar->historycrun, FALSE);
4519}
4520
4521/** sets the history of a variable; this method is typically used within reoptimization to keep and update the variable
4522 * history over several iterations
4523 */
4525 SCIP_VAR* var, /**< variable */
4526 SCIP_HISTORY* history, /**< the history which is to set */
4527 SCIP_STAT* stat /**< problem statistics */
4528 )
4529{
4530 /* merge only the history of the current run into the target history */
4531 SCIPhistoryUnite(var->history, history, FALSE);
4532
4533 /* apply the changes also to the global history */
4534 SCIPhistoryUnite(stat->glbhistory, history, FALSE);
4535}
4536
4537/** tightens the bounds of both variables in aggregation x = a*y + c */
4538static
4540 SCIP_VAR* var, /**< problem variable */
4541 BMS_BLKMEM* blkmem, /**< block memory */
4542 SCIP_SET* set, /**< global SCIP settings */
4543 SCIP_STAT* stat, /**< problem statistics */
4544 SCIP_PROB* transprob, /**< tranformed problem data */
4545 SCIP_PROB* origprob, /**< original problem data */
4546 SCIP_PRIMAL* primal, /**< primal data */
4547 SCIP_TREE* tree, /**< branch and bound tree */
4548 SCIP_REOPT* reopt, /**< reoptimization data structure */
4549 SCIP_LP* lp, /**< current LP data */
4550 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4551 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4552 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4553 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4554 SCIP_VAR* aggvar, /**< variable y in aggregation x = a*y + c */
4555 SCIP_Real scalar, /**< multiplier a in aggregation x = a*y + c */
4556 SCIP_Real constant, /**< constant shift c in aggregation x = a*y + c */
4557 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4558 SCIP_Bool* fixed /**< pointer to store whether the variables were fixed */
4559 )
4560{
4561 SCIP_Real varlb;
4562 SCIP_Real varub;
4563 SCIP_Real aggvarlb;
4564 SCIP_Real aggvarub;
4565 SCIP_Bool aggvarbdschanged;
4566
4567 assert(var != NULL);
4568 assert(var->scip == set->scip);
4569 assert(aggvar != NULL);
4570 assert(!SCIPsetIsZero(set, scalar));
4571 assert(infeasible != NULL);
4572 assert(fixed != NULL);
4573
4574 *infeasible = FALSE;
4575 *fixed = FALSE;
4576
4577 SCIPsetDebugMsg(set, "updating bounds of variables in aggregation <%s> == %g*<%s> %+g\n", var->name, scalar, aggvar->name, constant);
4578 SCIPsetDebugMsg(set, " old bounds: <%s> [%g,%g] <%s> [%g,%g]\n",
4579 var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
4580
4581 /* loop as long additional changes may be found */
4582 do
4583 {
4585
4586 /* update the bounds of the aggregated variable x in x = a*y + c */
4587 if( scalar > 0.0 )
4588 {
4589 if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
4591 else
4592 varlb = aggvar->glbdom.lb * scalar + constant;
4593 if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
4595 else
4596 varub = aggvar->glbdom.ub * scalar + constant;
4597 }
4598 else
4599 {
4600 if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
4602 else
4603 varub = aggvar->glbdom.lb * scalar + constant;
4604 if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
4606 else
4607 varlb = aggvar->glbdom.ub * scalar + constant;
4608 }
4609 varlb = MAX(varlb, var->glbdom.lb);
4610 varub = MIN(varub, var->glbdom.ub);
4613
4614 /* check the new bounds */
4615 if( SCIPsetIsGT(set, varlb, varub) )
4616 {
4617 /* the aggregation is infeasible */
4618 *infeasible = TRUE;
4619 return SCIP_OKAY;
4620 }
4621 else if( SCIPsetIsEQ(set, varlb, varub) )
4622 {
4623 /* the aggregated variable is fixed -> fix both variables */
4624 SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4625 eventfilter, eventqueue, cliquetable, varlb, infeasible, fixed) );
4626 if( !(*infeasible) )
4627 {
4628 SCIP_Bool aggfixed;
4629
4630 SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4631 eventfilter, eventqueue, cliquetable, (varlb-constant)/scalar, infeasible, &aggfixed) );
4632 assert(*fixed == aggfixed);
4633 }
4634 return SCIP_OKAY;
4635 }
4636 else
4637 {
4638 if( SCIPsetIsGT(set, varlb, var->glbdom.lb) )
4639 {
4640 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, varlb) );
4641 }
4642 if( SCIPsetIsLT(set, varub, var->glbdom.ub) )
4643 {
4644 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, varub) );
4645 }
4646
4647 /* update the hole list of the aggregation variable */
4648 /**@todo update hole list of aggregation variable */
4649 }
4650
4651 /* update the bounds of the aggregation variable y in x = a*y + c -> y = (x-c)/a */
4652 if( scalar > 0.0 )
4653 {
4656 else
4657 aggvarlb = (var->glbdom.lb - constant) / scalar;
4660 else
4661 aggvarub = (var->glbdom.ub - constant) / scalar;
4662 }
4663 else
4664 {
4667 else
4668 aggvarub = (var->glbdom.lb - constant) / scalar;
4671 else
4672 aggvarlb = (var->glbdom.ub - constant) / scalar;
4673 }
4674 aggvarlb = MAX(aggvarlb, aggvar->glbdom.lb);
4675 aggvarub = MIN(aggvarub, aggvar->glbdom.ub);
4678
4679 /* check the new bounds */
4681 {
4682 /* the aggregation is infeasible */
4683 *infeasible = TRUE;
4684 return SCIP_OKAY;
4685 }
4686 else if( SCIPsetIsEQ(set, aggvarlb, aggvarub) )
4687 {
4688 /* the aggregation variable is fixed -> fix both variables */
4689 SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4690 eventfilter, eventqueue, cliquetable, aggvarlb, infeasible, fixed) );
4691 if( !(*infeasible) )
4692 {
4693 SCIP_Bool varfixed;
4694
4695 SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4696 eventfilter, eventqueue, cliquetable, aggvarlb * scalar + constant, infeasible, &varfixed) );
4697 assert(*fixed == varfixed);
4698 }
4699 return SCIP_OKAY;
4700 }
4701 else
4702 {
4703 SCIP_Real oldbd;
4704 if( SCIPsetIsGT(set, aggvarlb, aggvar->glbdom.lb) )
4705 {
4706 oldbd = aggvar->glbdom.lb;
4707 SCIP_CALL( SCIPvarChgLbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, aggvarlb) );
4708 aggvarbdschanged = !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.lb);
4709 }
4710 if( SCIPsetIsLT(set, aggvarub, aggvar->glbdom.ub) )
4711 {
4712 oldbd = aggvar->glbdom.ub;
4713 SCIP_CALL( SCIPvarChgUbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, aggvarub) );
4715 }
4716
4717 /* update the hole list of the aggregation variable */
4718 /**@todo update hole list of aggregation variable */
4719 }
4720 }
4721 while( aggvarbdschanged );
4722
4723 SCIPsetDebugMsg(set, " new bounds: <%s> [%g,%g] <%s> [%g,%g]\n",
4724 var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
4725
4726 return SCIP_OKAY;
4727}
4728
4729/** converts loose variable into aggregated variable */
4731 SCIP_VAR* var, /**< loose problem variable */
4732 BMS_BLKMEM* blkmem, /**< block memory */
4733 SCIP_SET* set, /**< global SCIP settings */
4734 SCIP_STAT* stat, /**< problem statistics */
4735 SCIP_PROB* transprob, /**< tranformed problem data */
4736 SCIP_PROB* origprob, /**< original problem data */
4737 SCIP_PRIMAL* primal, /**< primal data */
4738 SCIP_TREE* tree, /**< branch and bound tree */
4739 SCIP_REOPT* reopt, /**< reoptimization data structure */
4740 SCIP_LP* lp, /**< current LP data */
4741 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4742 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4743 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4744 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4745 SCIP_VAR* aggvar, /**< loose variable y in aggregation x = a*y + c */
4746 SCIP_Real scalar, /**< multiplier a in aggregation x = a*y + c */
4747 SCIP_Real constant, /**< constant shift c in aggregation x = a*y + c */
4748 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4749 SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
4750 )
4751{
4752 SCIP_VAR** vars;
4753 SCIP_Real* coefs;
4754 SCIP_Real* constants;
4755 SCIP_Real obj;
4756 SCIP_Real branchfactor;
4757 SCIP_Bool fixed;
4758 int branchpriority;
4759 int nlocksdown[NLOCKTYPES];
4760 int nlocksup[NLOCKTYPES];
4761 int nvbds;
4762 int i;
4763 int j;
4764
4765 assert(var != NULL);
4766 assert(aggvar != NULL);
4767 assert(var->scip == set->scip);
4768 assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
4769 assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
4771 assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
4772 assert(infeasible != NULL);
4774
4775 *infeasible = FALSE;
4776 *aggregated = FALSE;
4777
4778 /* get active problem variable of aggregation variable */
4779 SCIP_CALL( SCIPvarGetProbvarSum(&aggvar, set, &scalar, &constant) );
4780
4781 /* aggregation is a fixing, if the scalar is zero */
4782 if( SCIPsetIsZero(set, scalar) )
4783 {
4784 SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventfilter,
4785 eventqueue, cliquetable, constant, infeasible, aggregated) );
4786 goto TERMINATE;
4787 }
4788
4789 /* don't perform the aggregation if the aggregation variable is multi-aggregated itself */
4791 return SCIP_OKAY;
4792
4793 /**@todo currently we don't perform the aggregation if the aggregation variable has a non-empty hole list; this
4794 * should be changed in the future
4795 */
4797 return SCIP_OKAY;
4798
4799 /* if the variable is not allowed to be aggregated */
4800 if( SCIPvarDoNotAggr(var) )
4801 {
4802 SCIPsetDebugMsg(set, "variable is not allowed to be aggregated.\n");
4803 return SCIP_OKAY;
4804 }
4805
4806 assert(aggvar->glbdom.lb == aggvar->locdom.lb); /*lint !e777*/
4807 assert(aggvar->glbdom.ub == aggvar->locdom.ub); /*lint !e777*/
4809
4810 SCIPsetDebugMsg(set, "aggregate variable <%s>[%g,%g] == %g*<%s>[%g,%g] %+g\n", var->name, var->glbdom.lb, var->glbdom.ub,
4811 scalar, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub, constant);
4812
4813 /* if variable and aggregation variable are equal, the variable can be fixed: x == a*x + c => x == c/(1-a) */
4814 if( var == aggvar )
4815 {
4816 if( SCIPsetIsEQ(set, scalar, 1.0) )
4817 *infeasible = !SCIPsetIsZero(set, constant);
4818 else
4819 {
4820 SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4821 eventfilter, eventqueue, cliquetable, constant/(1.0-scalar), infeasible, aggregated) );
4822 }
4823 goto TERMINATE;
4824 }
4825
4826 /* tighten the bounds of aggregated and aggregation variable */
4827 SCIP_CALL( varUpdateAggregationBounds(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
4828 branchcand, eventfilter, eventqueue, cliquetable, aggvar, scalar, constant, infeasible, &fixed) );
4829 if( *infeasible || fixed )
4830 {
4831 *aggregated = fixed;
4832 goto TERMINATE;
4833 }
4834
4835 /* delete implications and variable bounds of the aggregated variable from other variables, but keep them in the
4836 * aggregated variable
4837 */
4838 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, FALSE) );
4839
4840 /* set the aggregated variable's objective value to 0.0 */
4841 obj = var->obj;
4842 SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
4843
4844 /* unlock all locks */
4845 for( i = 0; i < NLOCKTYPES; i++ )
4846 {
4847 nlocksdown[i] = var->nlocksdown[i];
4848 nlocksup[i] = var->nlocksup[i];
4849
4850 var->nlocksdown[i] = 0;
4851 var->nlocksup[i] = 0;
4852 }
4853
4854 /* check, if variable should be used as NEGATED variable of the aggregation variable */
4856 && var->negatedvar == NULL && aggvar->negatedvar == NULL
4857 && SCIPsetIsEQ(set, scalar, -1.0) && SCIPsetIsEQ(set, constant, 1.0) )
4858 {
4859 /* link both variables as negation pair */
4860 var->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
4861 var->data.negate.constant = 1.0;
4863 aggvar->negatedvar = var;
4864
4865 /* copy donot(mult)aggr status */
4866 aggvar->donotaggr |= var->donotaggr;
4867 aggvar->donotmultaggr |= var->donotmultaggr;
4868
4869 /* mark both variables to be non-deletable */
4872 }
4873 else
4874 {
4875 /* convert variable into aggregated variable */
4876 var->varstatus = SCIP_VARSTATUS_AGGREGATED; /*lint !e641*/
4878 var->data.aggregate.scalar = scalar;
4879 var->data.aggregate.constant = constant;
4880
4881 /* copy donot(mult)aggr status */
4882 aggvar->donotaggr |= var->donotaggr;
4883 aggvar->donotmultaggr |= var->donotmultaggr;
4884
4885 /* mark both variables to be non-deletable */
4888 }
4889
4890 /* make aggregated variable a parent of the aggregation variable */
4891 SCIP_CALL( varAddParent(aggvar, blkmem, set, var) );
4892
4893 /* relock the variable, thus increasing the locks of the aggregation variable */
4894 for( i = 0; i < NLOCKTYPES; i++ )
4895 {
4896 SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
4897 }
4898
4899 /* move the variable bounds to the aggregation variable:
4900 * - add all variable bounds again to the variable, thus adding it to the aggregation variable
4901 * - free the variable bounds data structures
4902 */
4903 if( var->vlbs != NULL )
4904 {
4907 coefs = SCIPvboundsGetCoefs(var->vlbs);
4908 constants = SCIPvboundsGetConstants(var->vlbs);
4909 for( i = 0; i < nvbds && !(*infeasible); ++i )
4910 {
4911 SCIP_CALL( SCIPvarAddVlb(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
4912 eventqueue, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
4913 }
4914 }
4915 if( var->vubs != NULL )
4916 {
4919 coefs = SCIPvboundsGetCoefs(var->vubs);
4920 constants = SCIPvboundsGetConstants(var->vubs);
4921 for( i = 0; i < nvbds && !(*infeasible); ++i )
4922 {
4923 SCIP_CALL( SCIPvarAddVub(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
4924 eventqueue, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
4925 }
4926 }
4927 SCIPvboundsFree(&var->vlbs, blkmem);
4928 SCIPvboundsFree(&var->vubs, blkmem);
4929
4930 /* move the implications to the aggregation variable:
4931 * - add all implications again to the variable, thus adding it to the aggregation variable
4932 * - free the implications data structures
4933 */
4935 {
4937 for( i = 0; i < 2; ++i )
4938 {
4941 SCIP_Real* implbounds;
4942 int nimpls;
4943
4944 nimpls = SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i);
4945 implvars = SCIPimplicsGetVars(var->implics, (SCIP_Bool)i);
4946 impltypes = SCIPimplicsGetTypes(var->implics, (SCIP_Bool)i);
4948
4949 for( j = 0; j < nimpls && !(*infeasible); ++j )
4950 {
4951 /* @todo can't we omit transitive closure, because it should already have been done when adding the
4952 * implication to the aggregated variable?
4953 */
4954 SCIP_CALL( SCIPvarAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
4955 branchcand, eventqueue, (SCIP_Bool)i, implvars[j], impltypes[j], implbounds[j], FALSE, infeasible,
4956 NULL) );
4957 assert(nimpls == SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i));
4958 }
4959 }
4960 }
4961 SCIPimplicsFree(&var->implics, blkmem);
4962
4963 /* add the history entries to the aggregation variable and clear the history of the aggregated variable */
4964 SCIPhistoryUnite(aggvar->history, var->history, scalar < 0.0);
4965 SCIPhistoryUnite(aggvar->historycrun, var->historycrun, scalar < 0.0);
4968
4969 /* update flags of aggregation variable */
4970 aggvar->removable &= var->removable;
4971
4972 /* update branching factors and priorities of both variables to be the maximum of both variables */
4973 branchfactor = MAX(aggvar->branchfactor, var->branchfactor);
4974 branchpriority = MAX(aggvar->branchpriority, var->branchpriority);
4975 SCIP_CALL( SCIPvarChgBranchFactor(aggvar, set, branchfactor) );
4976 SCIP_CALL( SCIPvarChgBranchPriority(aggvar, branchpriority) );
4977 SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
4978 SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
4979
4980 /* update branching direction of both variables to agree to a single direction */
4981 if( scalar >= 0.0 )
4982 {
4984 {
4986 }
4987 else if( (SCIP_BRANCHDIR)aggvar->branchdirection == SCIP_BRANCHDIR_AUTO )
4988 {
4990 }
4991 else if( var->branchdirection != aggvar->branchdirection )
4992 {
4994 }
4995 }
4996 else
4997 {
4999 {
5001 }
5002 else if( (SCIP_BRANCHDIR)aggvar->branchdirection == SCIP_BRANCHDIR_AUTO )
5003 {
5005 }
5006 else if( var->branchdirection != aggvar->branchdirection )
5007 {
5009 }
5010 }
5011
5012 if( var->probindex != -1 )
5013 {
5014 /* inform problem about the variable's status change */
5015 SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
5016 }
5017
5018 /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
5019 * variable and the problem's objective offset
5020 */
5021 SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventfilter, eventqueue, obj) );
5022
5023 /* issue VARFIXED event */
5024 SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 1) );
5025
5026 *aggregated = TRUE;
5027
5028TERMINATE:
5029 /* check aggregation on debugging solution */
5030 if( *infeasible || *aggregated )
5031 SCIP_CALL( SCIPdebugCheckAggregation(set, var, &aggvar, &scalar, constant, 1) ); /*lint !e506 !e774*/
5032
5033 return SCIP_OKAY;
5034}
5035
5036/** Tries to aggregate an equality a*x + b*y == c consisting of two (implicit) integral active problem variables x and
5037 * y. An integer aggregation (i.e. integral coefficients a' and b', such that a'*x + b'*y == c') is searched.
5038 *
5039 * This can lead to the detection of infeasibility (e.g. if c' is fractional), or to a rejection of the aggregation
5040 * (denoted by aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
5041 */
5042static
5044 SCIP_SET* set, /**< global SCIP settings */
5045 BMS_BLKMEM* blkmem, /**< block memory */
5046 SCIP_STAT* stat, /**< problem statistics */
5047 SCIP_PROB* transprob, /**< tranformed problem data */
5048 SCIP_PROB* origprob, /**< original problem data */
5049 SCIP_PRIMAL* primal, /**< primal data */
5050 SCIP_TREE* tree, /**< branch and bound tree */
5051 SCIP_REOPT* reopt, /**< reoptimization data structure */
5052 SCIP_LP* lp, /**< current LP data */
5053 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5054 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5055 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
5056 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5057 SCIP_VAR* varx, /**< integral variable x in equality a*x + b*y == c */
5058 SCIP_VAR* vary, /**< integral variable y in equality a*x + b*y == c */
5059 SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
5060 SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
5061 SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
5062 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
5063 SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
5064 )
5065{
5068 SCIP_Longint scalarxn = 0;
5069 SCIP_Longint scalarxd = 0;
5070 SCIP_Longint scalaryn = 0;
5071 SCIP_Longint scalaryd = 0;
5072 SCIP_Longint a;
5073 SCIP_Longint b;
5074 SCIP_Longint c;
5075 SCIP_Longint scm;
5076 SCIP_Longint gcd;
5077 SCIP_Longint currentclass;
5078 SCIP_Longint classstep;
5079 SCIP_Longint xsol;
5080 SCIP_Longint ysol;
5081 SCIP_Bool success;
5082 SCIP_VARTYPE vartype;
5083
5084#define MAXDNOM 1000000LL
5085
5086 assert(set != NULL);
5087 assert(blkmem != NULL);
5088 assert(stat != NULL);
5089 assert(transprob != NULL);
5090 assert(origprob != NULL);
5091 assert(tree != NULL);
5092 assert(lp != NULL);
5093 assert(cliquetable != NULL);
5094 assert(branchcand != NULL);
5095 assert(eventqueue != NULL);
5096 assert(varx != NULL);
5097 assert(vary != NULL);
5098 assert(varx != vary);
5099 assert(infeasible != NULL);
5108
5109 *infeasible = FALSE;
5110 *aggregated = FALSE;
5111
5112 /* if the variable is not allowed to be aggregated */
5113 if( SCIPvarDoNotAggr(varx) )
5114 {
5115 SCIPsetDebugMsg(set, "variable is not allowed to be aggregated.\n");
5116 return SCIP_OKAY;
5117 }
5118
5119 /* get rational representation of coefficients */
5121 if( success )
5123 if( !success )
5124 return SCIP_OKAY;
5125 assert(scalarxd >= 1);
5126 assert(scalaryd >= 1);
5127
5128 /* multiply equality with smallest common denominator */
5130 a = (scm/scalarxd)*scalarxn;
5131 b = (scm/scalaryd)*scalaryn;
5132 rhs *= scm;
5133
5134 /* divide equality by the greatest common divisor of a and b */
5136 a /= gcd;
5137 b /= gcd;
5138 rhs /= gcd;
5139 assert(a != 0);
5140 assert(b != 0);
5141
5142 /* check, if right hand side is integral */
5143 if( !SCIPsetIsFeasIntegral(set, rhs) )
5144 {
5145 *infeasible = TRUE;
5146 return SCIP_OKAY;
5147 }
5149
5150 /* check that the scalar and constant in the aggregation are not too large to avoid numerical problems */
5151 if( REALABS((SCIP_Real)(c/a)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) /*lint !e653*/
5152 || REALABS((SCIP_Real)(b)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) /*lint !e653*/
5153 || REALABS((SCIP_Real)(a)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
5154 {
5155 return SCIP_OKAY;
5156 }
5157
5158 /* check, if we are in an easy case with either |a| = 1 or |b| = 1 */
5159 if( (a == 1 || a == -1) && SCIPvarGetType(vary) == SCIP_VARTYPE_INTEGER )
5160 {
5161 /* aggregate x = - b/a*y + c/a */
5162 /*lint --e{653}*/
5163 SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5164 branchcand, eventfilter, eventqueue, vary, (SCIP_Real)(-b/a), (SCIP_Real)(c/a), infeasible, aggregated) );
5166 return SCIP_OKAY;
5167 }
5168 if( (b == 1 || b == -1) && SCIPvarGetType(varx) == SCIP_VARTYPE_INTEGER )
5169 {
5170 /* aggregate y = - a/b*x + c/b */
5171 /*lint --e{653}*/
5172 SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5173 branchcand, eventfilter, eventqueue, varx, (SCIP_Real)(-a/b), (SCIP_Real)(c/b), infeasible, aggregated) );
5175 return SCIP_OKAY;
5176 }
5177
5178 /* Both variables are integers, their coefficients are not multiples of each other, and they don't have any
5179 * common divisor. Let (x',y') be a solution of the equality
5180 * a*x + b*y == c -> a*x == c - b*y
5181 * Then x = -b*z + x', y = a*z + y' with z integral gives all solutions to the equality.
5182 */
5183
5184 /* find initial solution (x',y'):
5185 * - find y' such that c - b*y' is a multiple of a
5186 * - start in equivalence class c%a
5187 * - step through classes, where each step increases class number by (-b)%a, until class 0 is visited
5188 * - if equivalence class 0 is visited, we are done: y' equals the number of steps taken
5189 * - because a and b don't have a common divisor, each class is visited at most once, and at most a-1 steps are needed
5190 * - calculate x' with x' = (c - b*y')/a (which must be integral)
5191 *
5192 * Algorithm works for a > 0 only.
5193 */
5194 if( a < 0 )
5195 {
5196 a = -a;
5197 b = -b;
5198 c = -c;
5199 }
5200 assert(a > 0);
5201
5202 /* search upwards from ysol = 0 */
5203 ysol = 0;
5204 currentclass = c % a;
5205 if( currentclass < 0 )
5206 currentclass += a;
5207 assert(0 <= currentclass && currentclass < a);
5208
5209 classstep = (-b) % a;
5210
5211 if( classstep < 0 )
5212 classstep += a;
5213 assert(0 <= classstep && classstep < a);
5214
5215 while( currentclass != 0 )
5216 {
5217 assert(0 <= currentclass && currentclass < a);
5219 if( currentclass >= a )
5220 currentclass -= a;
5221 ysol++;
5222 }
5223 assert(ysol < a);
5224 assert(((c - b*ysol) % a) == 0);
5225
5226 xsol = (c - b*ysol)/a;
5227
5228 /* determine variable type for new artificial variable:
5229 *
5230 * if both variables are implicit integer the new variable can be implicit too, because the integer implication on
5231 * these both variables should be enforced by some other variables, otherwise the new variable needs to be of
5232 * integral type
5233 */
5236
5237 /* feasible solutions are (x,y) = (x',y') + z*(-b,a)
5238 * - create new integer variable z with infinite bounds
5239 * - aggregate variable x = -b*z + x'
5240 * - aggregate variable y = a*z + y'
5241 * - the bounds of z are calculated automatically during aggregation
5242 */
5247 NULL, NULL, NULL, NULL, NULL) );
5248
5249 SCIP_CALL( SCIPprobAddVar(transprob, blkmem, set, lp, branchcand, eventfilter, eventqueue, aggvar) );
5250
5251 SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5252 branchcand, eventfilter, eventqueue, aggvar, (SCIP_Real)(-b), (SCIP_Real)xsol, infeasible, aggregated) );
5253 assert(*aggregated || *infeasible);
5254
5255 if( !(*infeasible) )
5256 {
5257 SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5258 branchcand, eventfilter, eventqueue, aggvar, (SCIP_Real)a, (SCIP_Real)ysol, infeasible, aggregated) );
5259 assert(*aggregated || *infeasible);
5260 }
5261
5262 /* release z */
5263 SCIP_CALL( SCIPvarRelease(&aggvar, blkmem, set, eventqueue, lp) );
5264
5265 return SCIP_OKAY; /*lint !e438*/
5266}
5267
5268/** performs second step of SCIPaggregateVars():
5269 * the variable to be aggregated is chosen among active problem variables x' and y', preferring a less strict variable
5270 * type as aggregation variable (i.e. continuous variables are preferred over implicit integers, implicit integers
5271 * or integers over binaries). If none of the variables is continuous, it is tried to find an integer
5272 * aggregation (i.e. integral coefficients a'' and b'', such that a''*x' + b''*y' == c''). This can lead to
5273 * the detection of infeasibility (e.g. if c'' is fractional), or to a rejection of the aggregation (denoted by
5274 * aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
5275 *
5276 * @todo check for fixings, infeasibility, bound changes, or domain holes:
5277 * a) if there is no easy aggregation and we have one binary variable and another integer/implicit/binary variable
5278 * b) for implicit integer variables with fractional aggregation scalar (we cannot (for technical reasons) and do
5279 * not want to aggregate implicit integer variables, since we loose the corresponding divisibility property)
5280 */
5282 SCIP_SET* set, /**< global SCIP settings */
5283 BMS_BLKMEM* blkmem, /**< block memory */
5284 SCIP_STAT* stat, /**< problem statistics */
5285 SCIP_PROB* transprob, /**< tranformed problem data */
5286 SCIP_PROB* origprob, /**< original problem data */
5287 SCIP_PRIMAL* primal, /**< primal data */
5288 SCIP_TREE* tree, /**< branch and bound tree */
5289 SCIP_REOPT* reopt, /**< reoptimization data structure */
5290 SCIP_LP* lp, /**< current LP data */
5291 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5292 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5293 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
5294 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5295 SCIP_VAR* varx, /**< variable x in equality a*x + b*y == c */
5296 SCIP_VAR* vary, /**< variable y in equality a*x + b*y == c */
5297 SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
5298 SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
5299 SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
5300 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
5301 SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
5302 )
5303{
5304 SCIP_Bool easyaggr;
5305
5306 assert(set != NULL);
5307 assert(blkmem != NULL);
5308 assert(stat != NULL);
5309 assert(transprob != NULL);
5310 assert(origprob != NULL);
5311 assert(tree != NULL);
5312 assert(lp != NULL);
5313 assert(cliquetable != NULL);
5314 assert(branchcand != NULL);
5315 assert(eventqueue != NULL);
5316 assert(varx != NULL);
5317 assert(vary != NULL);
5318 assert(varx != vary);
5319 assert(infeasible != NULL);
5326
5327 *infeasible = FALSE;
5328 *aggregated = FALSE;
5329
5331 return SCIP_OKAY;
5332
5333 /* prefer aggregating the variable of more general type (preferred aggregation variable is varx) */
5336 {
5337 SCIP_VAR* var;
5338 SCIP_Real scalar;
5339
5340 /* switch the variables, such that varx is the variable of more general type (cont > implint > int > bin) */
5341 var = vary;
5342 vary = varx;
5343 varx = var;
5344 scalar = scalary;
5345 scalary = scalarx;
5346 scalarx = scalar;
5347 }
5348
5349 /* don't aggregate if the aggregation would lead to a binary variable aggregated to a non-binary variable */
5351 return SCIP_OKAY;
5352
5354
5355 /* figure out, which variable should be aggregated */
5356 easyaggr = FALSE;
5357
5358 /* check if it is an easy aggregation */
5360 {
5361 easyaggr = TRUE;
5362 }
5364 {
5365 easyaggr = TRUE;
5366 }
5368 {
5369 /* we have an easy aggregation if we flip the variables x and y */
5370 SCIP_VAR* var;
5371 SCIP_Real scalar;
5372
5373 /* switch the variables, such that varx is the aggregated variable */
5374 var = vary;
5375 vary = varx;
5376 varx = var;
5377 scalar = scalary;
5378 scalary = scalarx;
5379 scalarx = scalar;
5380 easyaggr = TRUE;
5381 }
5383 {
5384 /* the aggregation is still easy if both variables are continuous */
5385 assert(SCIPvarGetType(vary) == SCIP_VARTYPE_CONTINUOUS); /* otherwise we are in the first case */
5386 easyaggr = TRUE;
5387 }
5388
5389 /* did we find an "easy" aggregation? */
5390 if( easyaggr )
5391 {
5392 SCIP_Real scalar;
5393 SCIP_Real constant;
5394
5396
5397 /* calculate aggregation scalar and constant: a*x + b*y == c => x == -b/a * y + c/a */
5398 scalar = -scalary/scalarx;
5399 constant = rhs/scalarx;
5400
5401 if( REALABS(constant) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
5402 return SCIP_OKAY;
5403
5404 /* check aggregation for integer feasibility */
5407 && SCIPsetIsFeasIntegral(set, scalar) && !SCIPsetIsFeasIntegral(set, constant) )
5408 {
5409 *infeasible = TRUE;
5410 return SCIP_OKAY;
5411 }
5412
5413 /* if the aggregation scalar is fractional, we cannot (for technical reasons) and do not want to aggregate implicit integer variables,
5414 * since then we would loose the corresponding divisibility property
5415 */
5417
5418 /* aggregate the variable */
5419 SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5420 branchcand, eventfilter, eventqueue, vary, scalar, constant, infeasible, aggregated) );
5421 assert(*aggregated || *infeasible || SCIPvarDoNotAggr(varx));
5422 }
5425 {
5426 /* the variables are both integral: we have to try to find an integer aggregation */
5427 SCIP_CALL( tryAggregateIntVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5428 branchcand, eventfilter, eventqueue, varx, vary, scalarx, scalary, rhs, infeasible, aggregated) );
5429 }
5430
5431 return SCIP_OKAY;
5432}
5433
5434/** converts variable into multi-aggregated variable */
5436 SCIP_VAR* var, /**< problem variable */
5437 BMS_BLKMEM* blkmem, /**< block memory */
5438 SCIP_SET* set, /**< global SCIP settings */
5439 SCIP_STAT* stat, /**< problem statistics */
5440 SCIP_PROB* transprob, /**< tranformed problem data */
5441 SCIP_PROB* origprob, /**< original problem data */
5442 SCIP_PRIMAL* primal, /**< primal data */
5443 SCIP_TREE* tree, /**< branch and bound tree */
5444 SCIP_REOPT* reopt, /**< reoptimization data structure */
5445 SCIP_LP* lp, /**< current LP data */
5446 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5447 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5448 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
5449 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5450 int naggvars, /**< number n of variables in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5451 SCIP_VAR** aggvars, /**< variables y_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5452 SCIP_Real* scalars, /**< multipliers a_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5453 SCIP_Real constant, /**< constant shift c in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5454 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
5455 SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
5456 )
5457{
5458 SCIP_VAR** tmpvars;
5459 SCIP_Real* tmpscalars;
5460 SCIP_Real obj;
5461 SCIP_Real branchfactor;
5462 int branchpriority;
5463 SCIP_BRANCHDIR branchdirection;
5464 int nlocksdown[NLOCKTYPES];
5465 int nlocksup[NLOCKTYPES];
5466 int v;
5467 SCIP_Real tmpconstant;
5468 SCIP_Real tmpscalar;
5469 int ntmpvars;
5470 int tmpvarssize;
5471 int tmprequiredsize;
5472 int i;
5473
5474 assert(var != NULL);
5475 assert(var->scip == set->scip);
5476 assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
5477 assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
5478 assert(naggvars == 0 || aggvars != NULL);
5479 assert(naggvars == 0 || scalars != NULL);
5480 assert(infeasible != NULL);
5482
5483 SCIPsetDebugMsg(set, "trying multi-aggregating variable <%s> == ...%d vars... %+g\n", var->name, naggvars, constant);
5484
5485 *infeasible = FALSE;
5486 *aggregated = FALSE;
5487
5488 switch( SCIPvarGetStatus(var) )
5489 {
5491 if( var->data.original.transvar == NULL )
5492 {
5493 SCIPerrorMessage("cannot multi-aggregate an untransformed original variable\n");
5494 return SCIP_INVALIDDATA;
5495 }
5496 SCIP_CALL( SCIPvarMultiaggregate(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
5497 reopt, lp, cliquetable, branchcand, eventfilter, eventqueue, naggvars, aggvars, scalars, constant, infeasible, aggregated) );
5498 break;
5499
5501 assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
5502
5503 /* check if we would create a self-reference */
5506 tmpconstant = constant;
5509
5510 /* get all active variables for multi-aggregation */
5513 {
5519 }
5520
5521 tmpscalar = 0.0;
5522
5523 /* iterate over all active variables of the multi-aggregation and filter all variables which are equal to the
5524 * possible multi-aggregated variable
5525 */
5526 for( v = ntmpvars - 1; v >= 0; --v )
5527 {
5528 assert(tmpvars[v] != NULL);
5530
5531 if( tmpvars[v]->index == var->index )
5532 {
5533 tmpscalar += tmpscalars[v];
5534 tmpvars[v] = tmpvars[ntmpvars - 1];
5535 tmpscalars[v] = tmpscalars[ntmpvars - 1];
5536 --ntmpvars;
5537 }
5538 }
5539
5540 /* this means that x = x + a_1*y_1 + ... + a_n*y_n + c */
5541 if( SCIPsetIsEQ(set, tmpscalar, 1.0) )
5542 {
5543 if( ntmpvars == 0 )
5544 {
5545 if( SCIPsetIsZero(set, tmpconstant) ) /* x = x */
5546 {
5547 SCIPsetDebugMsg(set, "Possible multi-aggregation was completely resolved and detected to be redundant.\n");
5548 goto TERMINATE;
5549 }
5550 else /* 0 = c and c != 0 */
5551 {
5552 SCIPsetDebugMsg(set, "Multi-aggregation was completely resolved and led to infeasibility.\n");
5553 *infeasible = TRUE;
5554 goto TERMINATE;
5555 }
5556 }
5557 else if( ntmpvars == 1 ) /* 0 = a*y + c => y = -c/a */
5558 {
5559 assert(tmpscalars[0] != 0.0);
5560 assert(tmpvars[0] != NULL);
5561
5562 SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(tmpvars[0]), -constant/tmpscalars[0]);
5563 SCIP_CALL( SCIPvarFix(tmpvars[0], blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5564 branchcand, eventfilter, eventqueue, cliquetable, -constant/tmpscalars[0], infeasible, aggregated) );
5565 goto TERMINATE;
5566 }
5567 else if( ntmpvars == 2 ) /* 0 = a_1*y_1 + a_2*y_2 + c => y_1 = -a_2/a_1 * y_2 - c/a_1 */
5568 {
5569 /* both variables are different active problem variables, and both scalars are non-zero: try to aggregate them */
5570 SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
5571 SCIPvarGetName(tmpvars[0]), SCIPvarGetName(tmpvars[1]), tmpscalars[0], tmpscalars[1], -tmpconstant);
5572
5573 SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
5574 cliquetable, branchcand, eventfilter, eventqueue, tmpvars[0], tmpvars[1], tmpscalars[0],
5575 tmpscalars[1], -tmpconstant, infeasible, aggregated) );
5576
5577 goto TERMINATE;
5578 }
5579 else
5580 /* @todo: it is possible to multi-aggregate another variable, does it make sense?,
5581 * rest looks like 0 = a_1*y_1 + ... + a_n*y_n + c and has at least three variables
5582 */
5583 goto TERMINATE;
5584 }
5585 /* this means that x = b*x + a_1*y_1 + ... + a_n*y_n + c */
5586 else if( !SCIPsetIsZero(set, tmpscalar) )
5587 {
5588 tmpscalar = 1 - tmpscalar;
5590 for( v = ntmpvars - 1; v >= 0; --v )
5591 tmpscalars[v] /= tmpscalar;
5592 }
5593
5594 /* check, if we are in one of the simple cases */
5595 if( ntmpvars == 0 )
5596 {
5597 SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(var), tmpconstant);
5598 SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
5599 eventfilter, eventqueue, cliquetable, tmpconstant, infeasible, aggregated) );
5600 goto TERMINATE;
5601 }
5602
5603 /* if only one aggregation variable is left, we perform a normal aggregation instead of a multi-aggregation */
5604 if( ntmpvars == 1 )
5605 {
5606 SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
5607 SCIPvarGetName(var), SCIPvarGetName(tmpvars[0]), 1.0, -tmpscalars[0], tmpconstant);
5608
5609 SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
5610 cliquetable, branchcand, eventfilter, eventqueue, var, tmpvars[0], 1.0, -tmpscalars[0], tmpconstant,
5611 infeasible, aggregated) );
5612
5613 goto TERMINATE;
5614 }
5615
5616 /**@todo currently we don't perform the multi aggregation if the multi aggregation variable has a non
5617 * empty hole list; this should be changed in the future */
5619 goto TERMINATE;
5620
5621 /* if the variable is not allowed to be multi-aggregated */
5623 {
5624 SCIPsetDebugMsg(set, "variable is not allowed to be multi-aggregated.\n");
5625 goto TERMINATE;
5626 }
5627
5628 /* if the variable to be multi-aggregated has implications or variable bounds (i.e. is the implied variable or
5629 * variable bound variable of another variable), we have to remove it from the other variables implications or
5630 * variable bounds
5631 */
5632 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
5633 assert(var->vlbs == NULL);
5634 assert(var->vubs == NULL);
5635 assert(var->implics == NULL);
5636
5637 /* set the aggregated variable's objective value to 0.0 */
5638 obj = var->obj;
5639 SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
5640
5641 /* since we change the variable type form loose to multi aggregated, we have to adjust the number of loose
5642 * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
5643 * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
5644 * objective of this variable is set to zero
5645 */
5647
5648 /* unlock all rounding locks */
5649 for( i = 0; i < NLOCKTYPES; i++ )
5650 {
5651 nlocksdown[i] = var->nlocksdown[i];
5652 nlocksup[i] = var->nlocksup[i];
5653
5654 var->nlocksdown[i] = 0;
5655 var->nlocksup[i] = 0;
5656 }
5657
5658 /* convert variable into multi-aggregated variable */
5659 var->varstatus = SCIP_VARSTATUS_MULTAGGR; /*lint !e641*/
5665
5666 /* mark variable to be non-deletable */
5668
5669 /* relock the variable, thus increasing the locks of the aggregation variables */
5670 for( i = 0; i < NLOCKTYPES; i++ )
5671 {
5672 SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
5673 }
5674
5675 /* update flags and branching factors and priorities of aggregation variables;
5676 * update preferred branching direction of all aggregation variables that don't have a preferred direction yet
5677 */
5678 branchfactor = var->branchfactor;
5679 branchpriority = var->branchpriority;
5680 branchdirection = (SCIP_BRANCHDIR)var->branchdirection;
5681
5682 for( v = 0; v < ntmpvars; ++v )
5683 {
5684 assert(tmpvars[v] != NULL);
5685 tmpvars[v]->removable &= var->removable;
5686 branchfactor = MAX(tmpvars[v]->branchfactor, branchfactor);
5687 branchpriority = MAX(tmpvars[v]->branchpriority, branchpriority);
5688
5689 /* mark variable to be non-deletable */
5690 SCIPvarMarkNotDeletable(tmpvars[v]);
5691 }
5692 for( v = 0; v < ntmpvars; ++v )
5693 {
5694 SCIP_CALL( SCIPvarChgBranchFactor(tmpvars[v], set, branchfactor) );
5695 SCIP_CALL( SCIPvarChgBranchPriority(tmpvars[v], branchpriority) );
5696 if( (SCIP_BRANCHDIR)tmpvars[v]->branchdirection == SCIP_BRANCHDIR_AUTO )
5697 {
5698 if( tmpscalars[v] >= 0.0 )
5699 {
5700 SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], branchdirection) );
5701 }
5702 else
5703 {
5704 SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], SCIPbranchdirOpposite(branchdirection)) );
5705 }
5706 }
5707 }
5708 SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
5709 SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
5710
5711 if( var->probindex != -1 )
5712 {
5713 /* inform problem about the variable's status change */
5714 SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
5715 }
5716
5717 /* issue VARFIXED event */
5718 SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 2) );
5719
5720 /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
5721 * variables and the problem's objective offset
5722 */
5723 SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventfilter, eventqueue, obj) );
5724
5725 *aggregated = TRUE;
5726
5727 TERMINATE:
5729 BMSfreeBlockMemoryArray(blkmem, &tmpvars, tmpvarssize);
5730
5731 break;
5732
5734 SCIPerrorMessage("cannot multi-aggregate a column variable\n");
5735 return SCIP_INVALIDDATA;
5736
5738 SCIPerrorMessage("cannot multi-aggregate a fixed variable\n");
5739 return SCIP_INVALIDDATA;
5740
5742 SCIPerrorMessage("cannot multi-aggregate an aggregated variable\n");
5743 return SCIP_INVALIDDATA;
5744
5746 SCIPerrorMessage("cannot multi-aggregate a multiple aggregated variable again\n");
5747 return SCIP_INVALIDDATA;
5748
5750 /* aggregate negation variable x in x' = offset - x, instead of aggregating x' directly:
5751 * x' = a_1*y_1 + ... + a_n*y_n + c -> x = offset - x' = offset - a_1*y_1 - ... - a_n*y_n - c
5752 */
5757
5758 /* switch the signs of the aggregation scalars */
5759 for( v = 0; v < naggvars; ++v )
5760 scalars[v] *= -1.0;
5761
5762 /* perform the multi aggregation on the negation variable */
5763 SCIP_CALL( SCIPvarMultiaggregate(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5764 cliquetable, branchcand, eventfilter, eventqueue, naggvars, aggvars, scalars,
5765 var->data.negate.constant - constant, infeasible, aggregated) );
5766
5767 /* switch the signs of the aggregation scalars again, to reset them to their original values */
5768 for( v = 0; v < naggvars; ++v )
5769 scalars[v] *= -1.0;
5770 break;
5771
5772 default:
5773 SCIPerrorMessage("unknown variable status\n");
5774 return SCIP_INVALIDDATA;
5775 }
5776
5777 /* check multi-aggregation on debugging solution */
5778 if( *infeasible || *aggregated )
5779 SCIP_CALL( SCIPdebugCheckAggregation(set, var, aggvars, scalars, constant, naggvars) ); /*lint !e506 !e774*/
5780
5781 return SCIP_OKAY;
5782}
5783
5784/** transformed variables are resolved to their active, fixed, or multi-aggregated problem variable of a variable,
5785 * or for original variables the same variable is returned
5786 */
5787static
5789 SCIP_VAR* var /**< problem variable */
5790 )
5791{
5793
5794 assert(var != NULL);
5795
5796 retvar = var;
5797
5798 SCIPdebugMessage("get active variable of <%s>\n", var->name);
5799
5800 while( TRUE ) /*lint !e716 */
5801 {
5802 assert(retvar != NULL);
5803
5804 switch( SCIPvarGetStatus(retvar) )
5805 {
5810 return retvar;
5811
5813 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
5814 if ( retvar->data.multaggr.nvars == 1 )
5815 retvar = retvar->data.multaggr.vars[0];
5816 else
5817 return retvar;
5818 break;
5819
5821 retvar = retvar->data.aggregate.var;
5822 break;
5823
5825 retvar = retvar->negatedvar;
5826 break;
5827
5828 default:
5829 SCIPerrorMessage("unknown variable status\n");
5830 SCIPABORT();
5831 return NULL; /*lint !e527*/
5832 }
5833 }
5834}
5835
5836/** returns whether variable is not allowed to be aggregated */
5838 SCIP_VAR* var /**< problem variable */
5839 )
5840{
5842
5843 assert(var != NULL);
5844
5846 assert(retvar != NULL);
5847
5848 switch( SCIPvarGetStatus(retvar) )
5849 {
5854 return retvar->donotaggr;
5855
5857 return FALSE;
5858
5861 default:
5862 /* aggregated and negated variables should be resolved by varGetActiveVar() */
5863 SCIPerrorMessage("wrong variable status\n");
5864 SCIPABORT();
5865 return FALSE; /*lint !e527 */
5866 }
5867}
5868
5869/** returns whether variable is not allowed to be multi-aggregated */
5871 SCIP_VAR* var /**< problem variable */
5872 )
5873{
5875
5876 assert(var != NULL);
5877
5879 assert(retvar != NULL);
5880
5881 switch( SCIPvarGetStatus(retvar) )
5882 {
5887 return retvar->donotmultaggr;
5888
5890 return FALSE;
5891
5894 default:
5895 /* aggregated and negated variables should be resolved by varGetActiveVar() */
5896 SCIPerrorMessage("wrong variable status\n");
5897 SCIPABORT();
5898 return FALSE; /*lint !e527 */
5899 }
5900}
5901
5902/** gets negated variable x' = offset - x of problem variable x; the negated variable is created if not yet existing;
5903 * the negation offset of binary variables is always 1, the offset of other variables is fixed to lb + ub when the
5904 * negated variable is created
5905 */
5907 SCIP_VAR* var, /**< problem variable to negate */
5908 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
5909 SCIP_SET* set, /**< global SCIP settings */
5910 SCIP_STAT* stat, /**< problem statistics */
5911 SCIP_VAR** negvar /**< pointer to store the negated variable */
5912 )
5913{
5914 assert(var != NULL);
5915 assert(var->scip == set->scip);
5916 assert(negvar != NULL);
5917
5918 /* check, if we already created the negated variable */
5919 if( var->negatedvar == NULL )
5920 {
5922
5924
5925 SCIPsetDebugMsg(set, "creating negated variable of <%s>\n", var->name);
5926
5927 /* negation is only possible for bounded variables */
5929 {
5930 SCIPerrorMessage("cannot negate unbounded variable\n");
5931 return SCIP_INVALIDDATA;
5932 }
5933
5935
5936 /* create negated variable */
5937 SCIP_CALL( varCreate(negvar, blkmem, set, stat, negvarname, var->glbdom.lb, var->glbdom.ub, 0.0,
5939 (*negvar)->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
5940 if( SCIPvarIsBinary(var) )
5941 (*negvar)->data.negate.constant = 1.0;
5942 else
5943 (*negvar)->data.negate.constant = var->glbdom.lb + var->glbdom.ub;
5944
5945 /* create event filter for transformed variable */
5947 {
5948 SCIP_CALL( SCIPeventfilterCreate(&(*negvar)->eventfilter, blkmem) );
5949 }
5950
5951 /* set the bounds corresponding to the negation variable */
5952 (*negvar)->glbdom.lb = (*negvar)->data.negate.constant - var->glbdom.ub;
5953 (*negvar)->glbdom.ub = (*negvar)->data.negate.constant - var->glbdom.lb;
5954 (*negvar)->locdom.lb = (*negvar)->data.negate.constant - var->locdom.ub;
5955 (*negvar)->locdom.ub = (*negvar)->data.negate.constant - var->locdom.lb;
5956 /**@todo create holes in the negated variable corresponding to the holes of the negation variable */
5957
5958 /* link the variables together */
5959 var->negatedvar = *negvar;
5960 (*negvar)->negatedvar = var;
5961
5962 /* mark both variables to be non-deletable */
5965
5966 /* copy the branch factor and priority, and use the negative preferred branching direction */
5967 (*negvar)->branchfactor = var->branchfactor;
5968 (*negvar)->branchpriority = var->branchpriority;
5969 (*negvar)->branchdirection = SCIPbranchdirOpposite((SCIP_BRANCHDIR)var->branchdirection); /*lint !e641*/
5970
5971 /* copy donot(mult)aggr status */
5972 (*negvar)->donotaggr = var->donotaggr;
5973 (*negvar)->donotmultaggr = var->donotmultaggr;
5974
5975 /* copy lazy bounds (they have to be flipped) */
5976 (*negvar)->lazylb = (*negvar)->data.negate.constant - var->lazyub;
5977 (*negvar)->lazyub = (*negvar)->data.negate.constant - var->lazylb;
5978
5979 /* make negated variable a parent of the negation variable (negated variable is captured as a parent) */
5980 SCIP_CALL( varAddParent(var, blkmem, set, *negvar) );
5981 assert((*negvar)->nuses == 1);
5982 }
5984
5985 /* return the negated variable */
5986 *negvar = var->negatedvar;
5987
5988 /* exactly one variable of the negation pair has to be marked as negated variable */
5990
5991 return SCIP_OKAY;
5992}
5993
5994/** informs variable that its position in problem's vars array changed */
5995static
5997 SCIP_VAR* var, /**< problem variable */
5998 int probindex /**< new problem index of variable (-1 for removal) */
5999 )
6000{
6001 assert(var != NULL);
6002 assert(probindex >= 0 || var->vlbs == NULL);
6003 assert(probindex >= 0 || var->vubs == NULL);
6004 assert(probindex >= 0 || var->implics == NULL);
6005
6006 var->probindex = probindex;
6008 {
6009 assert(var->data.col != NULL);
6010 var->data.col->var_probindex = probindex;
6011 }
6012}
6013
6014/** informs variable that its position in problem's vars array changed */
6016 SCIP_VAR* var, /**< problem variable */
6017 int probindex /**< new problem index of variable */
6018 )
6019{
6020 assert(var != NULL);
6021 assert(probindex >= 0);
6022
6023 varSetProbindex(var, probindex);
6024}
6025
6026/** gives the variable a new name
6027 *
6028 * @note the old pointer is overwritten, which might result in a memory leakage
6029 */
6031 SCIP_VAR* var, /**< problem variable */
6032 const char* name /**< new name of variable */
6033 )
6034{
6035 assert(var != NULL);
6036 assert(name != NULL);
6037
6038 var->name = (char*)name;
6039}
6040
6041/** informs variable that it will be removed from the problem; adjusts probindex and removes variable from the
6042 * implication graph;
6043 * If 'final' is TRUE, the thorough implication graph removal is not performed. Instead, only the
6044 * variable bounds and implication data structures of the variable are freed. Since in the final removal
6045 * of all variables from the transformed problem, this deletes the implication graph completely and is faster
6046 * than removing the variables one by one, each time updating all lists of the other variables.
6047 */
6049 SCIP_VAR* var, /**< problem variable */
6050 BMS_BLKMEM* blkmem, /**< block memory buffer */
6051 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6052 SCIP_SET* set, /**< global SCIP settings */
6053 SCIP_Bool final /**< is this the final removal of all problem variables? */
6054 )
6055{
6057 assert(var->scip == set->scip);
6058
6059 /* if the variable is active in the transformed problem, remove it from the implication graph */
6062 {
6063 if( final )
6064 {
6065 /* just destroy the data structures */
6066 SCIPvboundsFree(&var->vlbs, blkmem);
6067 SCIPvboundsFree(&var->vubs, blkmem);
6068 SCIPimplicsFree(&var->implics, blkmem);
6069 }
6070 else
6071 {
6072 /* unlink the variable from all other variables' lists and free the data structures */
6073 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
6074 }
6075 }
6076
6077 /* mark the variable to be no longer a member of the problem */
6078 varSetProbindex(var, -1);
6079
6080 return SCIP_OKAY;
6081}
6082
6083/** marks the variable to be deleted from the problem */
6085 SCIP_VAR* var /**< problem variable */
6086 )
6087{
6088 assert(var != NULL);
6089 assert(var->probindex != -1);
6090
6091 var->deleted = TRUE;
6092}
6093
6094/** marks the variable to not to be aggregated */
6096 SCIP_VAR* var /**< problem variable */
6097 )
6098{
6100
6101 assert(var != NULL);
6102
6104 assert(retvar != NULL);
6105
6106 switch( SCIPvarGetStatus(retvar) )
6107 {
6112 retvar->donotaggr = TRUE;
6113 break;
6114
6116 SCIPerrorMessage("cannot mark a multi-aggregated variable to not be aggregated.\n");
6117 return SCIP_INVALIDDATA;
6118
6121 default:
6122 /* aggregated and negated variables should be resolved by varGetActiveVar() */
6123 SCIPerrorMessage("wrong variable status\n");
6124 return SCIP_INVALIDDATA;
6125 }
6126
6127 return SCIP_OKAY;
6128}
6129
6130/** marks the variable to not to be multi-aggregated */
6132 SCIP_VAR* var /**< problem variable */
6133 )
6134{
6136
6137 assert(var != NULL);
6138
6140 assert(retvar != NULL);
6141
6142 switch( SCIPvarGetStatus(retvar) )
6143 {
6148 retvar->donotmultaggr = TRUE;
6149 break;
6150
6152 SCIPerrorMessage("cannot mark a multi-aggregated variable to not be multi-aggregated.\n");
6153 return SCIP_INVALIDDATA;
6154
6157 default:
6158 /* aggregated and negated variables should be resolved by varGetActiveVar() */
6159 SCIPerrorMessage("wrong variable status\n");
6160 return SCIP_INVALIDDATA;
6161 }
6162
6163 return SCIP_OKAY;
6164}
6165
6166/** changes type of variable; cannot be called, if var belongs to a problem */
6168 SCIP_VAR* var, /**< problem variable to change */
6169 BMS_BLKMEM* blkmem, /**< block memory */
6170 SCIP_SET* set, /**< global SCIP settings */
6171 SCIP_PRIMAL* primal, /**< primal data */
6172 SCIP_LP* lp, /**< current LP data */
6173 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6174 SCIP_VARTYPE vartype /**< new type of variable */
6175 )
6176{
6178 SCIP_VARTYPE oldtype;
6179
6180 assert(var != NULL);
6181
6182 SCIPdebugMessage("change type of <%s> from %d to %d\n", var->name, SCIPvarGetType(var), vartype);
6183
6184 if( var->probindex >= 0 )
6185 {
6186 SCIPerrorMessage("cannot change type of variable already in the problem\n");
6187 return SCIP_INVALIDDATA;
6188 }
6189
6190 oldtype = (SCIP_VARTYPE)var->vartype;
6191 var->vartype = vartype; /*lint !e641*/
6192
6194 {
6195 SCIP_CALL( SCIPeventCreateTypeChanged(&event, blkmem, var, oldtype, vartype) );
6196 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
6197 }
6198
6199 if( var->negatedvar != NULL )
6200 {
6203
6204 var->negatedvar->vartype = vartype; /*lint !e641*/
6205
6207 {
6208 SCIP_CALL( SCIPeventCreateTypeChanged(&event, blkmem, var->negatedvar, oldtype, vartype) );
6209 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
6210 }
6211 }
6212
6213 return SCIP_OKAY;
6214}
6215
6216/** appends OBJCHANGED event to the event queue */
6217static
6219 SCIP_VAR* var, /**< problem variable to change */
6220 BMS_BLKMEM* blkmem, /**< block memory */
6221 SCIP_SET* set, /**< global SCIP settings */
6222 SCIP_PRIMAL* primal, /**< primal data */
6223 SCIP_LP* lp, /**< current LP data */
6224 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6225 SCIP_Real oldobj, /**< old objective value for variable */
6226 SCIP_Real newobj /**< new objective value for variable */
6227 )
6228{
6230
6231 assert(var != NULL);
6232 assert(var->scip == set->scip);
6236
6237 /* In the case where the objcetive value of a variable is very close to epsilon, and it is aggregated
6238 * into a variable with a big objective value, round-off errors might make the assert oldobj != newobj fail.
6239 * Hence, we relax it by letting it pass if the variables are percieved the same and we use very large values
6240 * that make comparison with values close to epsilon inaccurate.
6241 */
6244 );
6245
6247 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
6248
6249 return SCIP_OKAY;
6250}
6251
6252/** changes objective value of variable */
6254 SCIP_VAR* var, /**< variable to change */
6255 BMS_BLKMEM* blkmem, /**< block memory */
6256 SCIP_SET* set, /**< global SCIP settings */
6257 SCIP_PROB* prob, /**< problem data */
6258 SCIP_PRIMAL* primal, /**< primal data */
6259 SCIP_LP* lp, /**< current LP data */
6260 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6261 SCIP_Real newobj /**< new objective value for variable */
6262 )
6263{
6264 SCIP_Real oldobj;
6265
6266 assert(var != NULL);
6267 assert(set != NULL);
6268 assert(var->scip == set->scip);
6269
6270 SCIPsetDebugMsg(set, "changing objective value of <%s> from %g to %g\n", var->name, var->obj, newobj);
6271
6272 if( !SCIPsetIsEQ(set, var->obj, newobj) )
6273 {
6274 switch( SCIPvarGetStatus(var) )
6275 {
6277 if( var->data.original.transvar != NULL )
6278 {
6280
6281 SCIP_CALL( SCIPvarChgObj(var->data.original.transvar, blkmem, set, prob, primal, lp, eventqueue,
6282 (SCIP_Real) prob->objsense * newobj/prob->objscale) );
6283 }
6284 else
6285 assert(set->stage == SCIP_STAGE_PROBLEM);
6286
6287 var->obj = newobj;
6289
6290 break;
6291
6294 oldobj = var->obj;
6295 var->obj = newobj;
6296
6297 /* update unchanged objective value of variable */
6298 if( !lp->divingobjchg )
6300
6301 /* update the number of variables with non-zero objective coefficient;
6302 * we only want to do the update, if the variable is added to the problem;
6303 * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
6304 */
6305 if( SCIPvarIsActive(var) )
6307
6308 SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
6309 break;
6310
6315 SCIPerrorMessage("cannot change objective value of a fixed, aggregated, multi-aggregated, or negated variable\n");
6316 return SCIP_INVALIDDATA;
6317
6318 default:
6319 SCIPerrorMessage("unknown variable status\n");
6320 return SCIP_INVALIDDATA;
6321 }
6322 }
6323
6324 return SCIP_OKAY;
6325}
6326
6327/** adds value to objective value of variable */
6329 SCIP_VAR* var, /**< variable to change */
6330 BMS_BLKMEM* blkmem, /**< block memory */
6331 SCIP_SET* set, /**< global SCIP settings */
6332 SCIP_STAT* stat, /**< problem statistics */
6333 SCIP_PROB* transprob, /**< transformed problem data */
6334 SCIP_PROB* origprob, /**< original problem data */
6335 SCIP_PRIMAL* primal, /**< primal data */
6336 SCIP_TREE* tree, /**< branch and bound tree */
6337 SCIP_REOPT* reopt, /**< reoptimization data structure */
6338 SCIP_LP* lp, /**< current LP data */
6339 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
6340 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6341 SCIP_Real addobj /**< additional objective value for variable */
6342 )
6343{
6344 assert(var != NULL);
6345 assert(set != NULL);
6346 assert(var->scip == set->scip);
6348
6349 SCIPsetDebugMsg(set, "adding %g to objective value %g of <%s>\n", addobj, var->obj, var->name);
6350
6351 if( !SCIPsetIsZero(set, addobj) )
6352 {
6353 SCIP_Real oldobj;
6354 int i;
6355
6356 switch( SCIPvarGetStatus(var) )
6357 {
6359 if( var->data.original.transvar != NULL )
6360 {
6361 SCIP_CALL( SCIPvarAddObj(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
6362 reopt, lp, eventfilter, eventqueue, (SCIP_Real) transprob->objsense * addobj/transprob->objscale) );
6363 }
6364 else
6365 assert(set->stage == SCIP_STAGE_PROBLEM);
6366
6367 var->obj += addobj;
6370
6371 break;
6372
6375 oldobj = var->obj;
6376 var->obj += addobj;
6377
6378 /* update unchanged objective value of variable */
6379 if( !lp->divingobjchg )
6380 {
6383 }
6384
6385 /* update the number of variables with non-zero objective coefficient;
6386 * we only want to do the update, if the variable is added to the problem;
6387 * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
6388 */
6389 if( SCIPvarIsActive(var) )
6390 SCIPprobUpdateNObjVars(transprob, set, oldobj, var->obj);
6391
6392 SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
6393 break;
6394
6397 SCIPprobAddObjoffset(transprob, var->locdom.lb * addobj);
6398 SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6399 break;
6400
6402 assert(!var->donotaggr);
6403 /* x = a*y + c -> add a*addobj to obj. val. of y, and c*addobj to obj. offset of problem */
6405 SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6406 SCIP_CALL( SCIPvarAddObj(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
6407 lp, eventfilter, eventqueue, var->data.aggregate.scalar * addobj) );
6408 break;
6409
6412 /* x = a_1*y_1 + ... + a_n*y_n + c -> add a_i*addobj to obj. val. of y_i, and c*addobj to obj. offset */
6414 SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6415 for( i = 0; i < var->data.multaggr.nvars; ++i )
6416 {
6417 SCIP_CALL( SCIPvarAddObj(var->data.multaggr.vars[i], blkmem, set, stat, transprob, origprob, primal, tree,
6418 reopt, lp, eventfilter, eventqueue, var->data.multaggr.scalars[i] * addobj) );
6419 }
6420 break;
6421
6423 /* x' = offset - x -> add -addobj to obj. val. of x and offset*addobj to obj. offset of problem */
6428 SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6429 SCIP_CALL( SCIPvarAddObj(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
6430 eventfilter, eventqueue, -addobj) );
6431 break;
6432
6433 default:
6434 SCIPerrorMessage("unknown variable status\n");
6435 return SCIP_INVALIDDATA;
6436 }
6437 }
6438
6439 return SCIP_OKAY;
6440}
6441
6442/** changes objective value of variable in current dive */
6444 SCIP_VAR* var, /**< problem variable to change */
6445 SCIP_SET* set, /**< global SCIP settings */
6446 SCIP_LP* lp, /**< current LP data */
6447 SCIP_Real newobj /**< new objective value for variable */
6448 )
6449{
6450 assert(var != NULL);
6451 assert(set != NULL);
6452 assert(var->scip == set->scip);
6453 assert(lp != NULL);
6454
6455 SCIPsetDebugMsg(set, "changing objective of <%s> to %g in current dive\n", var->name, newobj);
6456
6457 if( SCIPsetIsZero(set, newobj) )
6458 newobj = 0.0;
6459
6460 /* change objective value of attached variables */
6461 switch( SCIPvarGetStatus(var) )
6462 {
6466 break;
6467
6469 assert(var->data.col != NULL);
6471 break;
6472
6475 /* nothing to do here: only the constant shift in objective function would change */
6476 break;
6477
6478 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6482 /* the constant can be ignored, because it would only affect the objective shift */
6483 break;
6484
6486 SCIPerrorMessage("cannot change diving objective value of a multi-aggregated variable\n");
6487 return SCIP_INVALIDDATA;
6488
6489 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6494 /* the offset can be ignored, because it would only affect the objective shift */
6495 break;
6496
6497 default:
6498 SCIPerrorMessage("unknown variable status\n");
6499 return SCIP_INVALIDDATA;
6500 }
6501
6502 return SCIP_OKAY;
6503}
6504
6505/** adjust lower bound to integral value, if variable is integral */
6507 SCIP_VAR* var, /**< problem variable */
6508 SCIP_SET* set, /**< global SCIP settings */
6509 SCIP_Real* lb /**< pointer to lower bound to adjust */
6510 )
6511{
6512 assert(var != NULL);
6513 assert(set != NULL);
6514 assert(var->scip == set->scip);
6515 assert(lb != NULL);
6516
6517 SCIPsetDebugMsg(set, "adjust lower bound %g of <%s>\n", *lb, var->name);
6518
6519 *lb = adjustedLb(set, SCIPvarGetType(var), *lb);
6520}
6521
6522/** adjust upper bound to integral value, if variable is integral */
6524 SCIP_VAR* var, /**< problem variable */
6525 SCIP_SET* set, /**< global SCIP settings */
6526 SCIP_Real* ub /**< pointer to upper bound to adjust */
6527 )
6528{
6529 assert(var != NULL);
6530 assert(set != NULL);
6531 assert(var->scip == set->scip);
6532 assert(ub != NULL);
6533
6534 SCIPsetDebugMsg(set, "adjust upper bound %g of <%s>\n", *ub, var->name);
6535
6536 *ub = adjustedUb(set, SCIPvarGetType(var), *ub);
6537}
6538
6539/** adjust lower or upper bound to integral value, if variable is integral */
6541 SCIP_VAR* var, /**< problem variable */
6542 SCIP_SET* set, /**< global SCIP settings */
6543 SCIP_BOUNDTYPE boundtype, /**< type of bound to adjust */
6544 SCIP_Real* bd /**< pointer to bound to adjust */
6545 )
6546{
6547 assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
6548
6549 if( boundtype == SCIP_BOUNDTYPE_LOWER )
6551 else
6553}
6554
6555/** changes lower bound of original variable in original problem */
6557 SCIP_VAR* var, /**< problem variable to change */
6558 SCIP_SET* set, /**< global SCIP settings */
6559 SCIP_Real newbound /**< new bound for variable */
6560 )
6561{
6562 int i;
6563
6564 assert(var != NULL);
6567 assert(set != NULL);
6568 assert(var->scip == set->scip);
6569 assert(set->stage == SCIP_STAGE_PROBLEM);
6570
6571 /* check that the bound is feasible */
6573 /* adjust bound to integral value if variable is of integral type */
6574 newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6575
6576 if( SCIPsetIsZero(set, newbound) )
6577 newbound = 0.0;
6578
6579 /* original domains are only stored for ORIGINAL variables, not for NEGATED */
6581 {
6582 SCIPsetDebugMsg(set, "changing original lower bound of <%s> from %g to %g\n",
6583 var->name, var->data.original.origdom.lb, newbound);
6584
6585 if( SCIPsetIsEQ(set, var->data.original.origdom.lb, newbound) )
6586 return SCIP_OKAY;
6587
6588 /* change the bound */
6589 var->data.original.origdom.lb = newbound;
6590 }
6592 {
6593 assert( var->negatedvar != NULL );
6595 }
6596
6597 /* process parent variables */
6598 for( i = 0; i < var->nparentvars; ++i )
6599 {
6601
6603 assert(parentvar != NULL);
6605 assert(parentvar->negatedvar == var);
6607
6608 SCIP_CALL( SCIPvarChgUbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
6609 }
6610
6611 return SCIP_OKAY;
6612}
6613
6614/** changes upper bound of original variable in original problem */
6616 SCIP_VAR* var, /**< problem variable to change */
6617 SCIP_SET* set, /**< global SCIP settings */
6618 SCIP_Real newbound /**< new bound for variable */
6619 )
6620{
6621 int i;
6622
6623 assert(var != NULL);
6626 assert(set != NULL);
6627 assert(var->scip == set->scip);
6628 assert(set->stage == SCIP_STAGE_PROBLEM);
6629
6630 /* check that the bound is feasible */
6632 /* adjust bound to integral value if variable is of integral type */
6633 newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
6634
6635 if( SCIPsetIsZero(set, newbound) )
6636 newbound = 0.0;
6637
6638 /* original domains are only stored for ORIGINAL variables, not for NEGATED */
6640 {
6641 SCIPsetDebugMsg(set, "changing original upper bound of <%s> from %g to %g\n",
6642 var->name, var->data.original.origdom.ub, newbound);
6643
6644 if( SCIPsetIsEQ(set, var->data.original.origdom.ub, newbound) )
6645 return SCIP_OKAY;
6646
6647 /* change the bound */
6648 var->data.original.origdom.ub = newbound;
6649 }
6651 {
6652 assert( var->negatedvar != NULL );
6654 }
6655
6656 /* process parent variables */
6657 for( i = 0; i < var->nparentvars; ++i )
6658 {
6660
6662 assert(parentvar != NULL);
6664 assert(parentvar->negatedvar == var);
6666
6667 SCIP_CALL( SCIPvarChgLbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
6668 }
6669
6670 return SCIP_OKAY;
6671}
6672
6673/** appends GLBCHANGED event to the event queue */
6674static
6676 SCIP_VAR* var, /**< problem variable to change */
6677 BMS_BLKMEM* blkmem, /**< block memory */
6678 SCIP_SET* set, /**< global SCIP settings */
6679 SCIP_LP* lp, /**< current LP data */
6680 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6681 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6682 SCIP_Real oldbound, /**< old lower bound for variable */
6683 SCIP_Real newbound /**< new lower bound for variable */
6684 )
6685{
6686 assert(var != NULL);
6689 assert(!SCIPsetIsEQ(set, oldbound, newbound) || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
6690 assert(set != NULL);
6691 assert(var->scip == set->scip);
6692
6693 /* check, if the variable is being tracked for bound changes
6694 * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
6695 */
6699 {
6701
6702 SCIPsetDebugMsg(set, "issue GLBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
6703
6704 SCIP_CALL( SCIPeventCreateGlbChanged(&event, blkmem, var, oldbound, newbound) );
6705 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
6706 }
6707
6708 return SCIP_OKAY;
6709}
6710
6711/** appends GUBCHANGED event to the event queue */
6712static
6714 SCIP_VAR* var, /**< problem variable to change */
6715 BMS_BLKMEM* blkmem, /**< block memory */
6716 SCIP_SET* set, /**< global SCIP settings */
6717 SCIP_LP* lp, /**< current LP data */
6718 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6719 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6720 SCIP_Real oldbound, /**< old lower bound for variable */
6721 SCIP_Real newbound /**< new lower bound for variable */
6722 )
6723{
6724 assert(var != NULL);
6727 assert(!SCIPsetIsEQ(set, oldbound, newbound) || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
6728 assert(set != NULL);
6729 assert(var->scip == set->scip);
6730
6731 /* check, if the variable is being tracked for bound changes
6732 * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
6733 */
6737 {
6739
6740 SCIPsetDebugMsg(set, "issue GUBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
6741
6742 SCIP_CALL( SCIPeventCreateGubChanged(&event, blkmem, var, oldbound, newbound) );
6743 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
6744 }
6745
6746 return SCIP_OKAY;
6747}
6748
6749/** appends GHOLEADDED event to the event queue */
6750static
6752 SCIP_VAR* var, /**< problem variable to change */
6753 BMS_BLKMEM* blkmem, /**< block memory */
6754 SCIP_SET* set, /**< global SCIP settings */
6755 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6756 SCIP_Real left, /**< left bound of open interval in new hole */
6757 SCIP_Real right /**< right bound of open interval in new hole */
6758 )
6759{
6760 assert(var != NULL);
6763 assert(set != NULL);
6764 assert(var->scip == set->scip);
6765 assert(SCIPsetIsLT(set, left, right));
6766
6767 /* check, if the variable is being tracked for bound changes */
6769 {
6771
6772 SCIPsetDebugMsg(set, "issue GHOLEADDED event for variable <%s>: (%.15g,%.15g)\n", var->name, left, right);
6773
6774 SCIP_CALL( SCIPeventCreateGholeAdded(&event, blkmem, var, left, right) );
6775 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
6776 }
6777
6778 return SCIP_OKAY;
6779}
6780
6781/** increases root bound change statistics after a global bound change */
6782static
6784 SCIP_VAR* var, /**< problem variable to change */
6785 SCIP_SET* set, /**< global SCIP settings */
6786 SCIP_STAT* stat /**< problem statistics */
6787 )
6788{
6789 assert(var != NULL);
6790 assert(set != NULL);
6791 assert(var->scip == set->scip);
6792 assert(stat != NULL);
6793
6795 {
6796 stat->nrootboundchgs++;
6797 stat->nrootboundchgsrun++;
6799 {
6800 stat->nrootintfixings++;
6801 stat->nrootintfixingsrun++;
6802 }
6803 }
6804}
6805
6806/* forward declaration, because both methods call each other recursively */
6807
6808/* performs the current change in upper bound, changes all parents accordingly */
6809static
6811 SCIP_VAR* var, /**< problem variable to change */
6812 BMS_BLKMEM* blkmem, /**< block memory */
6813 SCIP_SET* set, /**< global SCIP settings */
6814 SCIP_STAT* stat, /**< problem statistics */
6815 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6816 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6817 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6818 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6819 SCIP_Real newbound /**< new bound for variable */
6820 );
6821
6822/** performs the current change in lower bound, changes all parents accordingly */
6823static
6825 SCIP_VAR* var, /**< problem variable to change */
6826 BMS_BLKMEM* blkmem, /**< block memory */
6827 SCIP_SET* set, /**< global SCIP settings */
6828 SCIP_STAT* stat, /**< problem statistics */
6829 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6830 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6831 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6832 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6833 SCIP_Real newbound /**< new bound for variable */
6834 )
6835{
6837 SCIP_Real oldbound;
6838 int i;
6839
6840 assert(var != NULL);
6841 /* local domains can violate global bounds but not more than feasibility epsilon */
6844 assert(blkmem != NULL);
6845 assert(set != NULL);
6846 assert(var->scip == set->scip);
6847 assert(stat != NULL);
6848
6849 /* adjust bound to integral value if variable is of integral type */
6850 newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6851
6852 /* check that the bound is feasible */
6853 if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound > var->glbdom.ub )
6854 {
6855 /* due to numerics we only want to be feasible in feasibility tolerance */
6856 assert(SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
6857 newbound = var->glbdom.ub;
6858 }
6860
6861 assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
6862
6863 SCIPsetDebugMsg(set, "process changing global lower bound of <%s> from %f to %f\n", var->name, var->glbdom.lb, newbound);
6864
6865 if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) && !(newbound != var->glbdom.lb && newbound * var->glbdom.lb <= 0.0) ) /*lint !e777*/
6866 return SCIP_OKAY;
6867
6868 /* check bound on debugging solution */
6869 SCIP_CALL( SCIPdebugCheckLbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
6870
6871 /* change the bound */
6872 oldbound = var->glbdom.lb;
6874 var->glbdom.lb = newbound;
6877
6879 {
6880 /* merges overlapping holes into single holes, moves bounds respectively */
6881 domMerge(&var->glbdom, blkmem, set, &newbound, NULL);
6882 }
6883
6884 /* update the root bound changes counters */
6885 varIncRootboundchgs(var, set, stat);
6886
6887 /* update the lbchginfos array by replacing worse local bounds with the new global bound and changing the
6888 * redundant bound changes to be branching decisions
6889 */
6890 for( i = 0; i < var->nlbchginfos; ++i )
6891 {
6892 assert(var->lbchginfos[i].var == var);
6893
6894 if( var->lbchginfos[i].oldbound < var->glbdom.lb )
6895 {
6896 SCIPsetDebugMsg(set, " -> adjust lower bound change <%s>: %g -> %g due to new global lower bound %g\n",
6900 {
6901 /* this bound change is redundant due to the new global bound */
6905 }
6906 else
6907 break; /* from now on, the remaining local bound changes are not redundant */
6908 }
6909 else
6910 break; /* from now on, the remaining local bound changes are not redundant */
6911 }
6912
6913 /* remove redundant implications and variable bounds */
6915 && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
6916 {
6917 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
6918 }
6919
6920 /* issue bound change event */
6922 if( var->eventfilter != NULL )
6923 {
6924 SCIP_CALL( varEventGlbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
6925 }
6926
6927 /* process parent variables */
6928 for( i = 0; i < var->nparentvars; ++i )
6929 {
6931 assert(parentvar != NULL);
6932
6933 switch( SCIPvarGetStatus(parentvar) )
6934 {
6936 SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6937 break;
6938
6943 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
6944 return SCIP_INVALIDDATA;
6945
6946 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6947 assert(parentvar->data.aggregate.var == var);
6948 if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
6949 {
6950 SCIP_Real parentnewbound;
6951
6952 /* a > 0 -> change lower bound of y */
6953 assert(SCIPsetIsInfinity(set, -parentvar->glbdom.lb) || SCIPsetIsInfinity(set, -oldbound)
6954 || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
6955 || (SCIPsetIsZero(set, parentvar->glbdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
6956
6957 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6958 parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6959 else
6960 parentnewbound = newbound;
6961 SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6962 }
6963 else
6964 {
6965 SCIP_Real parentnewbound;
6966
6967 /* a < 0 -> change upper bound of y */
6968 assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
6969 assert(SCIPsetIsInfinity(set, parentvar->glbdom.ub) || SCIPsetIsInfinity(set, -oldbound)
6970 || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
6971 || (SCIPsetIsZero(set, parentvar->glbdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
6972
6973 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6974 parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6975 else
6976 parentnewbound = -newbound;
6977 SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6978 }
6979 break;
6980
6981 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6982 assert(parentvar->negatedvar != NULL);
6984 assert(parentvar->negatedvar->negatedvar == parentvar);
6985 SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6986 parentvar->data.negate.constant - newbound) );
6987 break;
6988
6989 default:
6990 SCIPerrorMessage("unknown variable status\n");
6991 return SCIP_INVALIDDATA;
6992 }
6993 }
6994
6995 return SCIP_OKAY;
6996}
6997
6998/** performs the current change in upper bound, changes all parents accordingly */
6999static
7001 SCIP_VAR* var, /**< problem variable to change */
7002 BMS_BLKMEM* blkmem, /**< block memory */
7003 SCIP_SET* set, /**< global SCIP settings */
7004 SCIP_STAT* stat, /**< problem statistics */
7005 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7006 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7007 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7008 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7009 SCIP_Real newbound /**< new bound for variable */
7010 )
7011{
7013 SCIP_Real oldbound;
7014 int i;
7015
7016 assert(var != NULL);
7017 /* local domains can violate global bounds but not more than feasibility epsilon */
7020 assert(blkmem != NULL);
7021 assert(set != NULL);
7022 assert(var->scip == set->scip);
7023 assert(stat != NULL);
7024
7025 /* adjust bound to integral value if variable is of integral type */
7026 newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7027
7028 /* check that the bound is feasible */
7030 {
7031 /* due to numerics we only want to be feasible in feasibility tolerance */
7032 assert(SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
7033 newbound = var->glbdom.lb;
7034 }
7036
7037 assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
7038
7039 SCIPsetDebugMsg(set, "process changing global upper bound of <%s> from %f to %f\n", var->name, var->glbdom.ub, newbound);
7040
7041 if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) && !(newbound != var->glbdom.ub && newbound * var->glbdom.ub <= 0.0) ) /*lint !e777*/
7042 return SCIP_OKAY;
7043
7044 /* check bound on debugging solution */
7045 SCIP_CALL( SCIPdebugCheckUbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
7046
7047 /* change the bound */
7048 oldbound = var->glbdom.ub;
7050 var->glbdom.ub = newbound;
7053
7055 {
7056 /* merges overlapping holes into single holes, moves bounds respectively */
7057 domMerge(&var->glbdom, blkmem, set, NULL, &newbound);
7058 }
7059
7060 /* update the root bound changes counters */
7061 varIncRootboundchgs(var, set, stat);
7062
7063 /* update the ubchginfos array by replacing worse local bounds with the new global bound and changing the
7064 * redundant bound changes to be branching decisions
7065 */
7066 for( i = 0; i < var->nubchginfos; ++i )
7067 {
7068 assert(var->ubchginfos[i].var == var);
7069 if( var->ubchginfos[i].oldbound > var->glbdom.ub )
7070 {
7071 SCIPsetDebugMsg(set, " -> adjust upper bound change <%s>: %g -> %g due to new global upper bound %g\n",
7075 {
7076 /* this bound change is redundant due to the new global bound */
7080 }
7081 else
7082 break; /* from now on, the remaining local bound changes are not redundant */
7083 }
7084 else
7085 break; /* from now on, the remaining local bound changes are not redundant */
7086 }
7087
7088 /* remove redundant implications and variable bounds */
7090 && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
7091 {
7092 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
7093 }
7094
7095 /* issue bound change event */
7097 if( var->eventfilter != NULL )
7098 {
7099 SCIP_CALL( varEventGubChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7100 }
7101
7102 /* process parent variables */
7103 for( i = 0; i < var->nparentvars; ++i )
7104 {
7106 assert(parentvar != NULL);
7107
7108 switch( SCIPvarGetStatus(parentvar) )
7109 {
7111 SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7112 break;
7113
7118 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7119 return SCIP_INVALIDDATA;
7120
7121 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7122 assert(parentvar->data.aggregate.var == var);
7123 if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7124 {
7125 SCIP_Real parentnewbound;
7126
7127 /* a > 0 -> change upper bound of y */
7128 assert(SCIPsetIsInfinity(set, parentvar->glbdom.ub) || SCIPsetIsInfinity(set, oldbound)
7129 || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub,
7130 oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7131 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7132 parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7133 else
7134 parentnewbound = newbound;
7135 SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
7136 }
7137 else
7138 {
7139 SCIP_Real parentnewbound;
7140
7141 /* a < 0 -> change lower bound of y */
7142 assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7143 assert(SCIPsetIsInfinity(set, -parentvar->glbdom.lb) || SCIPsetIsInfinity(set, oldbound)
7144 || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb,
7145 oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7146 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7147 parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7148 else
7149 parentnewbound = -newbound;
7150 SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
7151 }
7152 break;
7153
7154 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7155 assert(parentvar->negatedvar != NULL);
7157 assert(parentvar->negatedvar->negatedvar == parentvar);
7158 SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7159 parentvar->data.negate.constant - newbound) );
7160 break;
7161
7162 default:
7163 SCIPerrorMessage("unknown variable status\n");
7164 return SCIP_INVALIDDATA;
7165 }
7166 }
7167
7168 return SCIP_OKAY;
7169}
7170
7171/** changes global lower bound of variable; if possible, adjusts bound to integral value;
7172 * updates local lower bound if the global bound is tighter
7173 */
7175 SCIP_VAR* var, /**< problem variable to change */
7176 BMS_BLKMEM* blkmem, /**< block memory */
7177 SCIP_SET* set, /**< global SCIP settings */
7178 SCIP_STAT* stat, /**< problem statistics */
7179 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7180 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7181 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7182 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7183 SCIP_Real newbound /**< new bound for variable */
7184 )
7185{
7186 assert(var != NULL);
7187 assert(blkmem != NULL);
7188 assert(set != NULL);
7189 assert(var->scip == set->scip);
7190
7191 /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7192 * of the domain within feastol
7193 */
7195
7196 /* adjust bound to integral value if variable is of integral type */
7197 newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7198
7199 /* check that the adjusted bound is feasible
7200 * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
7201 * here because we reset bounds to their original value!
7202 */
7204
7206 {
7207 /* we do not want to exceed the upperbound, which could have happened due to numerics */
7208 newbound = MIN(newbound, var->glbdom.ub);
7209 }
7211
7212 /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
7213 * SCIPvarFix() allows fixings that are outside of the domain within feastol
7214 */
7215 assert(lp == NULL || SCIPsetIsFeasLE(set, var->glbdom.lb, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
7216
7217 SCIPsetDebugMsg(set, "changing global lower bound of <%s> from %g to %g\n", var->name, var->glbdom.lb, newbound);
7218
7219 if( SCIPsetIsEQ(set, var->glbdom.lb, newbound) && !(newbound != var->glbdom.lb && newbound * var->glbdom.lb <= 0.0) ) /*lint !e777*/
7220 return SCIP_OKAY;
7221
7222 /* change bounds of attached variables */
7223 switch( SCIPvarGetStatus(var) )
7224 {
7226 if( var->data.original.transvar != NULL )
7227 {
7228 SCIP_CALL( SCIPvarChgLbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
7229 cliquetable, newbound) );
7230 }
7231 else
7232 {
7233 assert(set->stage == SCIP_STAGE_PROBLEM);
7234 if( newbound > SCIPvarGetLbLocal(var) )
7235 {
7236 SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7237 }
7238 SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7239 }
7240 break;
7241
7244 if( newbound > SCIPvarGetLbLocal(var) )
7245 {
7246 SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7247 }
7248 SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7249 break;
7250
7252 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7253 return SCIP_INVALIDDATA;
7254
7255 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7258 {
7259 SCIP_Real childnewbound;
7260
7261 /* a > 0 -> change lower bound of y */
7265 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7267 else
7268 childnewbound = newbound;
7269 SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7270 childnewbound) );
7271 }
7273 {
7274 SCIP_Real childnewbound;
7275
7276 /* a < 0 -> change upper bound of y */
7280 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7282 else
7283 childnewbound = -newbound;
7284 SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7285 childnewbound) );
7286 }
7287 else
7288 {
7289 SCIPerrorMessage("scalar is zero in aggregation\n");
7290 return SCIP_INVALIDDATA;
7291 }
7292 break;
7293
7295 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7296 return SCIP_INVALIDDATA;
7297
7298 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7302 SCIP_CALL( SCIPvarChgUbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7303 var->data.negate.constant - newbound) );
7304 break;
7305
7306 default:
7307 SCIPerrorMessage("unknown variable status\n");
7308 return SCIP_INVALIDDATA;
7309 }
7310
7311 return SCIP_OKAY;
7312}
7313
7314/** changes global upper bound of variable; if possible, adjusts bound to integral value;
7315 * updates local upper bound if the global bound is tighter
7316 */
7318 SCIP_VAR* var, /**< problem variable to change */
7319 BMS_BLKMEM* blkmem, /**< block memory */
7320 SCIP_SET* set, /**< global SCIP settings */
7321 SCIP_STAT* stat, /**< problem statistics */
7322 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7323 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7324 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7325 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7326 SCIP_Real newbound /**< new bound for variable */
7327 )
7328{
7329 assert(var != NULL);
7330 assert(blkmem != NULL);
7331 assert(set != NULL);
7332 assert(var->scip == set->scip);
7333
7334 /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7335 * of the domain within feastol
7336 */
7338
7339 /* adjust bound to integral value if variable is of integral type */
7340 newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7341
7342 /* check that the adjusted bound is feasible
7343 * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
7344 * here because we reset bounds to their original value!
7345 */
7347
7349 {
7350 /* we do not want to undercut the lowerbound, which could have happened due to numerics */
7351 newbound = MAX(newbound, var->glbdom.lb);
7352 }
7354
7355 /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
7356 * SCIPvarFix() allows fixings that are outside of the domain within feastol
7357 */
7358 assert(lp == NULL || SCIPsetIsFeasGE(set, var->glbdom.ub, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
7359
7360 SCIPsetDebugMsg(set, "changing global upper bound of <%s> from %g to %g\n", var->name, var->glbdom.ub, newbound);
7361
7362 if( SCIPsetIsEQ(set, var->glbdom.ub, newbound) && !(newbound != var->glbdom.ub && newbound * var->glbdom.ub <= 0.0) ) /*lint !e777*/
7363 return SCIP_OKAY;
7364
7365 /* change bounds of attached variables */
7366 switch( SCIPvarGetStatus(var) )
7367 {
7369 if( var->data.original.transvar != NULL )
7370 {
7371 SCIP_CALL( SCIPvarChgUbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7372 newbound) );
7373 }
7374 else
7375 {
7376 assert(set->stage == SCIP_STAGE_PROBLEM);
7377 if( newbound < SCIPvarGetUbLocal(var) )
7378 {
7379 SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7380 }
7381 SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7382 }
7383 break;
7384
7387 if( newbound < SCIPvarGetUbLocal(var) )
7388 {
7389 SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7390 }
7391 SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7392 break;
7393
7395 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7396 return SCIP_INVALIDDATA;
7397
7398 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7401 {
7402 SCIP_Real childnewbound;
7403
7404 /* a > 0 -> change lower bound of y */
7408 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7410 else
7411 childnewbound = newbound;
7412 SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7413 childnewbound) );
7414 }
7416 {
7417 SCIP_Real childnewbound;
7418
7419 /* a < 0 -> change upper bound of y */
7423 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7425 else
7426 childnewbound = -newbound;
7427 SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7428 childnewbound) );
7429 }
7430 else
7431 {
7432 SCIPerrorMessage("scalar is zero in aggregation\n");
7433 return SCIP_INVALIDDATA;
7434 }
7435 break;
7436
7438 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7439 return SCIP_INVALIDDATA;
7440
7441 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7445 SCIP_CALL( SCIPvarChgLbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7446 var->data.negate.constant - newbound) );
7447 break;
7448
7449 default:
7450 SCIPerrorMessage("unknown variable status\n");
7451 return SCIP_INVALIDDATA;
7452 }
7453
7454 return SCIP_OKAY;
7455}
7456
7457/** changes lazy lower bound of the variable, this is only possible if the variable is not in the LP yet */
7459 SCIP_VAR* var, /**< problem variable */
7460 SCIP_SET* set, /**< global SCIP settings */
7461 SCIP_Real lazylb /**< the lazy lower bound to be set */
7462 )
7463{
7464 assert(var != NULL);
7465 assert(var->probindex != -1);
7466 assert(SCIPsetIsFeasGE(set, var->glbdom.ub, lazylb));
7467 assert(SCIPsetIsFeasGE(set, var->lazyub, lazylb));
7468 assert(set != NULL);
7469 assert(var->scip == set->scip);
7470
7471 /* variable should not be in the LP */
7473 return SCIP_INVALIDCALL;
7474
7475 var->lazylb = lazylb;
7476
7477 return SCIP_OKAY;
7478}
7479
7480/** changes lazy upper bound of the variable, this is only possible if the variable is not in the LP yet */
7482 SCIP_VAR* var, /**< problem variable */
7483 SCIP_SET* set, /**< global SCIP settings */
7484 SCIP_Real lazyub /**< the lazy lower bound to be set */
7485 )
7486{
7487 assert(var != NULL);
7488 assert(var->probindex != -1);
7489 assert(SCIPsetIsFeasGE(set, lazyub, var->glbdom.lb));
7490 assert(SCIPsetIsFeasGE(set, lazyub, var->lazylb));
7491 assert(set != NULL);
7492 assert(var->scip == set->scip);
7493
7494 /* variable should not be in the LP */
7496 return SCIP_INVALIDCALL;
7497
7498 var->lazyub = lazyub;
7499
7500 return SCIP_OKAY;
7501}
7502
7503
7504/** changes global bound of variable; if possible, adjusts bound to integral value;
7505 * updates local bound if the global bound is tighter
7506 */
7508 SCIP_VAR* var, /**< problem variable to change */
7509 BMS_BLKMEM* blkmem, /**< block memory */
7510 SCIP_SET* set, /**< global SCIP settings */
7511 SCIP_STAT* stat, /**< problem statistics */
7512 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7513 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7514 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7515 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7516 SCIP_Real newbound, /**< new bound for variable */
7517 SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
7518 )
7519{
7520 /* apply bound change to the LP data */
7521 switch( boundtype )
7522 {
7524 return SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
7526 return SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
7527 default:
7528 SCIPerrorMessage("unknown bound type\n");
7529 return SCIP_INVALIDDATA;
7530 }
7531}
7532
7533/** appends LBTIGHTENED or LBRELAXED event to the event queue */
7534static
7536 SCIP_VAR* var, /**< problem variable to change */
7537 BMS_BLKMEM* blkmem, /**< block memory */
7538 SCIP_SET* set, /**< global SCIP settings */
7539 SCIP_LP* lp, /**< current LP data */
7540 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7541 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7542 SCIP_Real oldbound, /**< old lower bound for variable */
7543 SCIP_Real newbound /**< new lower bound for variable */
7544 )
7545{
7546 assert(var != NULL);
7549 assert(!SCIPsetIsEQ(set, oldbound, newbound) || newbound == var->glbdom.lb || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
7550 assert(set != NULL);
7551 assert(var->scip == set->scip);
7552
7553 /* check, if the variable is being tracked for bound changes
7554 * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
7555 */
7559 {
7561
7562 SCIPsetDebugMsg(set, "issue LBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
7563
7564 SCIP_CALL( SCIPeventCreateLbChanged(&event, blkmem, var, oldbound, newbound) );
7565 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
7566 }
7567
7568 return SCIP_OKAY;
7569}
7570
7571/** appends UBTIGHTENED or UBRELAXED event to the event queue */
7572static
7574 SCIP_VAR* var, /**< problem variable to change */
7575 BMS_BLKMEM* blkmem, /**< block memory */
7576 SCIP_SET* set, /**< global SCIP settings */
7577 SCIP_LP* lp, /**< current LP data */
7578 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7579 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7580 SCIP_Real oldbound, /**< old upper bound for variable */
7581 SCIP_Real newbound /**< new upper bound for variable */
7582 )
7583{
7584 assert(var != NULL);
7587 assert(!SCIPsetIsEQ(set, oldbound, newbound) || newbound == var->glbdom.ub || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
7588 assert(set != NULL);
7589 assert(var->scip == set->scip);
7590
7591 /* check, if the variable is being tracked for bound changes
7592 * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
7593 */
7597 {
7599
7600 SCIPsetDebugMsg(set, "issue UBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
7601
7602 SCIP_CALL( SCIPeventCreateUbChanged(&event, blkmem, var, oldbound, newbound) );
7603 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
7604 }
7605
7606 return SCIP_OKAY;
7607}
7608
7609/* forward declaration, because both methods call each other recursively */
7610
7611/* performs the current change in upper bound, changes all parents accordingly */
7612static
7614 SCIP_VAR* var, /**< problem variable to change */
7615 BMS_BLKMEM* blkmem, /**< block memory */
7616 SCIP_SET* set, /**< global SCIP settings */
7617 SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7618 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7619 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7620 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7621 SCIP_Real newbound /**< new bound for variable */
7622 );
7623
7624/** performs the current change in lower bound, changes all parents accordingly */
7625static
7627 SCIP_VAR* var, /**< problem variable to change */
7628 BMS_BLKMEM* blkmem, /**< block memory */
7629 SCIP_SET* set, /**< global SCIP settings */
7630 SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7631 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7632 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7633 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7634 SCIP_Real newbound /**< new bound for variable */
7635 )
7636{
7638 SCIP_Real oldbound;
7639 int i;
7640
7641 assert(var != NULL);
7642 assert(set != NULL);
7643 assert(var->scip == set->scip);
7644 assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)
7645 || SCIPsetIsEQ(set, newbound, var->locdom.ub)))
7647 || SCIPsetIsEQ(set, newbound, var->locdom.ub)))
7649
7650 /* check that the bound is feasible */
7652 /* adjust bound to integral value if variable is of integral type */
7653 newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7654
7656 {
7657 /* we do not want to exceed the upper bound, which could have happened due to numerics */
7658 newbound = MIN(newbound, var->locdom.ub);
7659
7660 /* we do not want to undercut the global lower bound, which could have happened due to numerics */
7661 newbound = MAX(newbound, var->glbdom.lb);
7662 }
7664
7665 SCIPsetDebugMsg(set, "process changing lower bound of <%s> from %g to %g\n", var->name, var->locdom.lb, newbound);
7666
7667 if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) && var->glbdom.lb != var->locdom.lb ) /*lint !e777*/
7668 newbound = var->glbdom.lb;
7669 else if( SCIPsetIsEQ(set, newbound, var->locdom.lb) && !(newbound != var->locdom.lb && newbound * var->locdom.lb <= 0.0) ) /*lint !e777*/
7670 return SCIP_OKAY;
7671
7672 /* change the bound */
7673 oldbound = var->locdom.lb;
7675 var->locdom.lb = newbound;
7676
7677 /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
7678 * once update the statistic
7679 */
7680 if( stat != NULL )
7681 SCIPstatIncrement(stat, set, domchgcount);
7682
7684 {
7685 /* merges overlapping holes into single holes, moves bounds respectively */
7686 domMerge(&var->locdom, blkmem, set, &newbound, NULL);
7687 }
7688
7689 /* issue bound change event */
7691 if( var->eventfilter != NULL )
7692 {
7693 SCIP_CALL( varEventLbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7694 }
7695
7696 /* process parent variables */
7697 for( i = 0; i < var->nparentvars; ++i )
7698 {
7700 assert(parentvar != NULL);
7701
7702 switch( SCIPvarGetStatus(parentvar) )
7703 {
7705 SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
7706 break;
7707
7712 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7713 return SCIP_INVALIDDATA;
7714
7715 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7716 assert(parentvar->data.aggregate.var == var);
7717 if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7718 {
7719 SCIP_Real parentnewbound;
7720
7721 /* a > 0 -> change lower bound of y */
7722 assert(SCIPsetIsInfinity(set, -parentvar->locdom.lb) || SCIPsetIsInfinity(set, -oldbound)
7723 || SCIPsetIsFeasEQ(set, parentvar->locdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
7724 || (SCIPsetIsZero(set, parentvar->locdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
7725
7726 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7727 {
7728 parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7729 /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
7730 * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
7731 * as a result, the parent's lower bound is set to it's upper bound, and not above
7732 */
7733 if( parentnewbound > parentvar->glbdom.ub )
7734 {
7735 /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7737 parentnewbound = parentvar->glbdom.ub;
7738 }
7739 }
7740 else
7741 parentnewbound = newbound;
7742 SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7743 }
7744 else
7745 {
7746 SCIP_Real parentnewbound;
7747
7748 /* a < 0 -> change upper bound of y */
7749 assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7750 assert(SCIPsetIsInfinity(set, parentvar->locdom.ub) || SCIPsetIsInfinity(set, -oldbound)
7751 || SCIPsetIsFeasEQ(set, parentvar->locdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
7752 || (SCIPsetIsZero(set, parentvar->locdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
7753
7754 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7755 {
7756 parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7757 /* if parent's new upper bound is below its lower bound, then this could be due to numerical difficulties, e.g., if numbers are large
7758 * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
7759 * as a result, the parent's upper bound is set to it's lower bound, and not below
7760 */
7761 if( parentnewbound < parentvar->glbdom.lb )
7762 {
7763 /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7765 parentnewbound = parentvar->glbdom.lb;
7766 }
7767 }
7768 else
7769 parentnewbound = -newbound;
7770 SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7771 }
7772 break;
7773
7774 case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
7775 assert(parentvar->negatedvar != NULL);
7777 assert(parentvar->negatedvar->negatedvar == parentvar);
7778 SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
7779 parentvar->data.negate.constant - newbound) );
7780 break;
7781
7782 default:
7783 SCIPerrorMessage("unknown variable status\n");
7784 return SCIP_INVALIDDATA;
7785 }
7786 }
7787
7788 return SCIP_OKAY;
7789}
7790
7791/** performs the current change in upper bound, changes all parents accordingly */
7792static
7794 SCIP_VAR* var, /**< problem variable to change */
7795 BMS_BLKMEM* blkmem, /**< block memory */
7796 SCIP_SET* set, /**< global SCIP settings */
7797 SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7798 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7799 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7800 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7801 SCIP_Real newbound /**< new bound for variable */
7802 )
7803{
7805 SCIP_Real oldbound;
7806 int i;
7807
7808 assert(var != NULL);
7809 assert(set != NULL);
7810 assert(var->scip == set->scip);
7811 assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)
7812 || SCIPsetIsEQ(set, newbound, var->locdom.lb)))
7814 || SCIPsetIsEQ(set, newbound, var->locdom.lb)))
7816
7817 /* check that the bound is feasible */
7819 /* adjust bound to integral value if variable is of integral type */
7820 newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7821
7823 {
7824 /* we do not want to undercut the lower bound, which could have happened due to numerics */
7825 newbound = MAX(newbound, var->locdom.lb);
7826
7827 /* we do not want to exceed the global upper bound, which could have happened due to numerics */
7828 newbound = MIN(newbound, var->glbdom.ub);
7829 }
7831
7832 SCIPsetDebugMsg(set, "process changing upper bound of <%s> from %g to %g\n", var->name, var->locdom.ub, newbound);
7833
7834 if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) && var->glbdom.ub != var->locdom.ub ) /*lint !e777*/
7835 newbound = var->glbdom.ub;
7836 else if( SCIPsetIsEQ(set, newbound, var->locdom.ub) && !(newbound != var->locdom.ub && newbound * var->locdom.ub <= 0.0) ) /*lint !e777*/
7837 return SCIP_OKAY;
7838
7839 /* change the bound */
7840 oldbound = var->locdom.ub;
7842 var->locdom.ub = newbound;
7843
7844 /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
7845 * once update the statistic
7846 */
7847 if( stat != NULL )
7848 SCIPstatIncrement(stat, set, domchgcount);
7849
7851 {
7852 /* merges overlapping holes into single holes, moves bounds respectively */
7853 domMerge(&var->locdom, blkmem, set, NULL, &newbound);
7854 }
7855
7856 /* issue bound change event */
7858 if( var->eventfilter != NULL )
7859 {
7860 SCIP_CALL( varEventUbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7861 }
7862
7863 /* process parent variables */
7864 for( i = 0; i < var->nparentvars; ++i )
7865 {
7867 assert(parentvar != NULL);
7868
7869 switch( SCIPvarGetStatus(parentvar) )
7870 {
7872 SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
7873 break;
7874
7879 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7880 return SCIP_INVALIDDATA;
7881
7882 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7883 assert(parentvar->data.aggregate.var == var);
7884 if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7885 {
7886 SCIP_Real parentnewbound;
7887
7888 /* a > 0 -> change upper bound of x */
7889 assert(SCIPsetIsInfinity(set, parentvar->locdom.ub) || SCIPsetIsInfinity(set, oldbound)
7890 || SCIPsetIsFeasEQ(set, parentvar->locdom.ub,
7891 oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7892 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7893 {
7894 parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7895 /* if parent's new upper bound is below its lower bound, then this could be due to numerical difficulties, e.g., if numbers are large
7896 * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
7897 * as a result, the parent's upper bound is set to it's lower bound, and not below
7898 */
7899 if( parentnewbound < parentvar->glbdom.lb )
7900 {
7901 /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7903 parentnewbound = parentvar->glbdom.lb;
7904 }
7905 }
7906 else
7907 parentnewbound = newbound;
7908 SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7909 }
7910 else
7911 {
7912 SCIP_Real parentnewbound;
7913
7914 /* a < 0 -> change lower bound of x */
7915 assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7916 assert(SCIPsetIsInfinity(set, -parentvar->locdom.lb) || SCIPsetIsInfinity(set, oldbound)
7917 || SCIPsetIsFeasEQ(set, parentvar->locdom.lb,
7918 oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7919 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7920 {
7921 parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7922 /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
7923 * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
7924 * as a result, the parent's lower bound is set to it's upper bound, and not above
7925 */
7926 if( parentnewbound > parentvar->glbdom.ub )
7927 {
7928 /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7930 parentnewbound = parentvar->glbdom.ub;
7931 }
7932 }
7933 else
7934 parentnewbound = -newbound;
7935 SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7936 }
7937 break;
7938
7939 case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
7940 assert(parentvar->negatedvar != NULL);
7942 assert(parentvar->negatedvar->negatedvar == parentvar);
7943 SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
7944 parentvar->data.negate.constant - newbound) );
7945 break;
7946
7947 default:
7948 SCIPerrorMessage("unknown variable status\n");
7949 return SCIP_INVALIDDATA;
7950 }
7951 }
7952
7953 return SCIP_OKAY;
7954}
7955
7956/** changes current local lower bound of variable; if possible, adjusts bound to integral value; stores inference
7957 * information in variable
7958 */
7960 SCIP_VAR* var, /**< problem variable to change */
7961 BMS_BLKMEM* blkmem, /**< block memory */
7962 SCIP_SET* set, /**< global SCIP settings */
7963 SCIP_STAT* stat, /**< problem statistics */
7964 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7965 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7966 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7967 SCIP_Real newbound /**< new bound for variable */
7968 )
7969{
7970 assert(var != NULL);
7971 assert(blkmem != NULL);
7972 assert(set != NULL);
7973 assert(var->scip == set->scip);
7974
7975 /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7976 * of the domain within feastol
7977 */
7979
7980 /* adjust bound to integral value if variable is of integral type */
7981 newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7982
7983 /* check that the adjusted bound is feasible */
7985
7987 {
7988 /* we do not want to exceed the upperbound, which could have happened due to numerics */
7989 newbound = MIN(newbound, var->locdom.ub);
7990 }
7992
7993 SCIPsetDebugMsg(set, "changing lower bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
7994
7995 if( SCIPsetIsEQ(set, var->locdom.lb, newbound) && (!SCIPsetIsEQ(set, var->glbdom.lb, newbound) || var->locdom.lb == newbound) /*lint !e777*/
7996 && !(newbound != var->locdom.lb && newbound * var->locdom.lb <= 0.0) ) /*lint !e777*/
7997 return SCIP_OKAY;
7998
7999 /* change bounds of attached variables */
8000 switch( SCIPvarGetStatus(var) )
8001 {
8003 if( var->data.original.transvar != NULL )
8004 {
8005 SCIP_CALL( SCIPvarChgLbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
8006 newbound) );
8007 }
8008 else
8009 {
8010 assert(set->stage == SCIP_STAGE_PROBLEM);
8011 SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8012 }
8013 break;
8014
8017 SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8018 break;
8019
8021 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8022 return SCIP_INVALIDDATA;
8023
8024 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8027 {
8028 SCIP_Real childnewbound;
8029
8030 /* a > 0 -> change lower bound of y */
8034 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8036 else
8037 childnewbound = newbound;
8038 SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
8039 childnewbound) );
8040 }
8042 {
8043 SCIP_Real childnewbound;
8044
8045 /* a < 0 -> change upper bound of y */
8049 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8051 else
8052 childnewbound = -newbound;
8053 SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
8054 childnewbound) );
8055 }
8056 else
8057 {
8058 SCIPerrorMessage("scalar is zero in aggregation\n");
8059 return SCIP_INVALIDDATA;
8060 }
8061 break;
8062
8064 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8065 return SCIP_INVALIDDATA;
8066
8067 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8071 SCIP_CALL( SCIPvarChgUbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
8072 var->data.negate.constant - newbound) );
8073 break;
8074
8075 default:
8076 SCIPerrorMessage("unknown variable status\n");
8077 return SCIP_INVALIDDATA;
8078 }
8079
8080 return SCIP_OKAY;
8081}
8082
8083/** changes current local upper bound of variable; if possible, adjusts bound to integral value; stores inference
8084 * information in variable
8085 */
8087 SCIP_VAR* var, /**< problem variable to change */
8088 BMS_BLKMEM* blkmem, /**< block memory */
8089 SCIP_SET* set, /**< global SCIP settings */
8090 SCIP_STAT* stat, /**< problem statistics */
8091 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
8092 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
8093 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8094 SCIP_Real newbound /**< new bound for variable */
8095 )
8096{
8097 assert(var != NULL);
8098 assert(blkmem != NULL);
8099 assert(set != NULL);
8100 assert(var->scip == set->scip);
8101
8102 /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
8103 * of the domain within feastol
8104 */
8106
8107 /* adjust bound to integral value if variable is of integral type */
8108 newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
8109
8110 /* check that the adjusted bound is feasible */
8112
8114 {
8115 /* we do not want to undercut the lowerbound, which could have happened due to numerics */
8116 newbound = MAX(newbound, var->locdom.lb);
8117 }
8119
8120 SCIPsetDebugMsg(set, "changing upper bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
8121
8122 if( SCIPsetIsEQ(set, var->locdom.ub, newbound) && (!SCIPsetIsEQ(set, var->glbdom.ub, newbound) || var->locdom.ub == newbound) /*lint !e777*/
8123 && !(newbound != var->locdom.ub && newbound * var->locdom.ub <= 0.0) ) /*lint !e777*/
8124 return SCIP_OKAY;
8125
8126 /* change bounds of attached variables */
8127 switch( SCIPvarGetStatus(var) )
8128 {
8130 if( var->data.original.transvar != NULL )
8131 {
8132 SCIP_CALL( SCIPvarChgUbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8133 }
8134 else
8135 {
8136 assert(set->stage == SCIP_STAGE_PROBLEM);
8137 SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8138 }
8139 break;
8140
8143 SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8144 break;
8145
8147 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8148 return SCIP_INVALIDDATA;
8149
8150 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8153 {
8154 SCIP_Real childnewbound;
8155
8156 /* a > 0 -> change upper bound of y */
8160 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8162 else
8163 childnewbound = newbound;
8164 SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
8165 childnewbound) );
8166 }
8168 {
8169 SCIP_Real childnewbound;
8170
8171 /* a < 0 -> change lower bound of y */
8175 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8177 else
8178 childnewbound = -newbound;
8179 SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
8180 childnewbound) );
8181 }
8182 else
8183 {
8184 SCIPerrorMessage("scalar is zero in aggregation\n");
8185 return SCIP_INVALIDDATA;
8186 }
8187 break;
8188
8190 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8191 return SCIP_INVALIDDATA;
8192
8193 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8197 SCIP_CALL( SCIPvarChgLbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
8198 var->data.negate.constant - newbound) );
8199 break;
8200
8201 default:
8202 SCIPerrorMessage("unknown variable status\n");
8203 return SCIP_INVALIDDATA;
8204 }
8205
8206 return SCIP_OKAY;
8207}
8208
8209/** changes current local bound of variable; if possible, adjusts bound to integral value; stores inference
8210 * information in variable
8211 */
8213 SCIP_VAR* var, /**< problem variable to change */
8214 BMS_BLKMEM* blkmem, /**< block memory */
8215 SCIP_SET* set, /**< global SCIP settings */
8216 SCIP_STAT* stat, /**< problem statistics */
8217 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
8218 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
8219 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8220 SCIP_Real newbound, /**< new bound for variable */
8221 SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
8222 )
8223{
8224 /* apply bound change to the LP data */
8225 switch( boundtype )
8226 {
8228 return SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
8230 return SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
8231 default:
8232 SCIPerrorMessage("unknown bound type\n");
8233 return SCIP_INVALIDDATA;
8234 }
8235}
8236
8237/** changes lower bound of variable in current dive; if possible, adjusts bound to integral value */
8239 SCIP_VAR* var, /**< problem variable to change */
8240 SCIP_SET* set, /**< global SCIP settings */
8241 SCIP_LP* lp, /**< current LP data */
8242 SCIP_Real newbound /**< new bound for variable */
8243 )
8244{
8245 assert(var != NULL);
8246 assert(set != NULL);
8247 assert(var->scip == set->scip);
8248 assert(lp != NULL);
8249 assert(SCIPlpDiving(lp));
8250
8251 /* adjust bound for integral variables */
8252 SCIPvarAdjustLb(var, set, &newbound);
8253
8254 SCIPsetDebugMsg(set, "changing lower bound of <%s> to %g in current dive\n", var->name, newbound);
8255
8256 /* change bounds of attached variables */
8257 switch( SCIPvarGetStatus(var) )
8258 {
8262 break;
8263
8265 assert(var->data.col != NULL);
8266 SCIP_CALL( SCIPcolChgLb(var->data.col, set, lp, newbound) );
8267 break;
8268
8270 SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
8271 return SCIP_INVALIDDATA;
8272
8274 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8275 return SCIP_INVALIDDATA;
8276
8277 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8280 {
8281 SCIP_Real childnewbound;
8282
8283 /* a > 0 -> change lower bound of y */
8284 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8286 else
8287 childnewbound = newbound;
8289 }
8291 {
8292 SCIP_Real childnewbound;
8293
8294 /* a < 0 -> change upper bound of y */
8295 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8297 else
8298 childnewbound = -newbound;
8300 }
8301 else
8302 {
8303 SCIPerrorMessage("scalar is zero in aggregation\n");
8304 return SCIP_INVALIDDATA;
8305 }
8306 break;
8307
8309 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8310 return SCIP_INVALIDDATA;
8311
8312 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8317 break;
8318
8319 default:
8320 SCIPerrorMessage("unknown variable status\n");
8321 return SCIP_INVALIDDATA;
8322 }
8323
8324 return SCIP_OKAY;
8325}
8326
8327/** changes upper bound of variable in current dive; if possible, adjusts bound to integral value */
8329 SCIP_VAR* var, /**< problem variable to change */
8330 SCIP_SET* set, /**< global SCIP settings */
8331 SCIP_LP* lp, /**< current LP data */
8332 SCIP_Real newbound /**< new bound for variable */
8333 )
8334{
8335 assert(var != NULL);
8336 assert(set != NULL);
8337 assert(var->scip == set->scip);
8338 assert(lp != NULL);
8339 assert(SCIPlpDiving(lp));
8340
8341 /* adjust bound for integral variables */
8342 SCIPvarAdjustUb(var, set, &newbound);
8343
8344 SCIPsetDebugMsg(set, "changing upper bound of <%s> to %g in current dive\n", var->name, newbound);
8345
8346 /* change bounds of attached variables */
8347 switch( SCIPvarGetStatus(var) )
8348 {
8352 break;
8353
8355 assert(var->data.col != NULL);
8356 SCIP_CALL( SCIPcolChgUb(var->data.col, set, lp, newbound) );
8357 break;
8358
8360 SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
8361 return SCIP_INVALIDDATA;
8362
8364 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8365 return SCIP_INVALIDDATA;
8366
8367 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8370 {
8371 SCIP_Real childnewbound;
8372
8373 /* a > 0 -> change upper bound of y */
8374 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8376 else
8377 childnewbound = newbound;
8379 }
8381 {
8382 SCIP_Real childnewbound;
8383
8384 /* a < 0 -> change lower bound of y */
8385 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8387 else
8388 childnewbound = -newbound;
8390 }
8391 else
8392 {
8393 SCIPerrorMessage("scalar is zero in aggregation\n");
8394 return SCIP_INVALIDDATA;
8395 }
8396 break;
8397
8399 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8400 return SCIP_INVALIDDATA;
8401
8402 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8407 break;
8408
8409 default:
8410 SCIPerrorMessage("unknown variable status\n");
8411 return SCIP_INVALIDDATA;
8412 }
8413
8414 return SCIP_OKAY;
8415}
8416
8417/** for a multi-aggregated variable, gives the local lower bound computed by adding the local bounds from all
8418 * aggregation variables, this lower bound may be tighter than the one given by SCIPvarGetLbLocal, since the latter is
8419 * not updated if bounds of aggregation variables are changing
8420 *
8421 * calling this function for a non-multi-aggregated variable is not allowed
8422 */
8424 SCIP_VAR* var, /**< problem variable */
8425 SCIP_SET* set /**< global SCIP settings */
8426 )
8427{
8428 int i;
8429 SCIP_Real lb;
8430 SCIP_Real bnd;
8432 SCIP_Bool posinf;
8433 SCIP_Bool neginf;
8434
8435 assert(var != NULL);
8436 assert(set != NULL);
8437 assert(var->scip == set->scip);
8439
8440 posinf = FALSE;
8441 neginf = FALSE;
8442 lb = var->data.multaggr.constant;
8443 for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8444 {
8446 if( var->data.multaggr.scalars[i] > 0.0 )
8447 {
8449
8450 if( SCIPsetIsInfinity(set, bnd) )
8451 posinf = TRUE;
8452 else if( SCIPsetIsInfinity(set, -bnd) )
8453 neginf = TRUE;
8454 else
8455 lb += var->data.multaggr.scalars[i] * bnd;
8456 }
8457 else
8458 {
8460
8461 if( SCIPsetIsInfinity(set, -bnd) )
8462 posinf = TRUE;
8463 else if( SCIPsetIsInfinity(set, bnd) )
8464 neginf = TRUE;
8465 else
8466 lb += var->data.multaggr.scalars[i] * bnd;
8467 }
8468
8469 /* stop if two diffrent infinities (or a -infinity) were found and return local lower bound of multi aggregated
8470 * variable
8471 */
8472 if( neginf )
8473 return SCIPvarGetLbLocal(var);
8474 }
8475
8476 /* if positive infinity flag was set to true return infinity */
8477 if( posinf )
8478 return SCIPsetInfinity(set);
8479
8480 return (MAX(lb, SCIPvarGetLbLocal(var))); /*lint !e666*/
8481}
8482
8483/** for a multi-aggregated variable, gives the local upper bound computed by adding the local bounds from all
8484 * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbLocal, since the latter is
8485 * not updated if bounds of aggregation variables are changing
8486 *
8487 * calling this function for a non-multi-aggregated variable is not allowed
8488 */
8490 SCIP_VAR* var, /**< problem variable */
8491 SCIP_SET* set /**< global SCIP settings */
8492 )
8493{
8494 int i;
8495 SCIP_Real ub;
8496 SCIP_Real bnd;
8498 SCIP_Bool posinf;
8499 SCIP_Bool neginf;
8500
8501 assert(var != NULL);
8502 assert(set != NULL);
8503 assert(var->scip == set->scip);
8505
8506 posinf = FALSE;
8507 neginf = FALSE;
8508 ub = var->data.multaggr.constant;
8509 for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8510 {
8512 if( var->data.multaggr.scalars[i] > 0.0 )
8513 {
8515
8516 if( SCIPsetIsInfinity(set, bnd) )
8517 posinf = TRUE;
8518 else if( SCIPsetIsInfinity(set, -bnd) )
8519 neginf = TRUE;
8520 else
8521 ub += var->data.multaggr.scalars[i] * bnd;
8522 }
8523 else
8524 {
8526
8527 if( SCIPsetIsInfinity(set, -bnd) )
8528 posinf = TRUE;
8529 else if( SCIPsetIsInfinity(set, bnd) )
8530 neginf = TRUE;
8531 else
8532 ub += var->data.multaggr.scalars[i] * bnd;
8533 }
8534
8535 /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
8536 * variable
8537 */
8538 if( posinf )
8539 return SCIPvarGetUbLocal(var);
8540 }
8541
8542 /* if negative infinity flag was set to true return -infinity */
8543 if( neginf )
8544 return -SCIPsetInfinity(set);
8545
8546 return (MIN(ub, SCIPvarGetUbLocal(var))); /*lint !e666*/
8547}
8548
8549/** for a multi-aggregated variable, gives the global lower bound computed by adding the global bounds from all
8550 * aggregation variables, this global bound may be tighter than the one given by SCIPvarGetLbGlobal, since the latter is
8551 * not updated if bounds of aggregation variables are changing
8552 *
8553 * calling this function for a non-multi-aggregated variable is not allowed
8554 */
8556 SCIP_VAR* var, /**< problem variable */
8557 SCIP_SET* set /**< global SCIP settings */
8558 )
8559{
8560 int i;
8561 SCIP_Real lb;
8562 SCIP_Real bnd;
8564 SCIP_Bool posinf;
8565 SCIP_Bool neginf;
8566
8567 assert(var != NULL);
8568 assert(set != NULL);
8569 assert(var->scip == set->scip);
8571
8572 posinf = FALSE;
8573 neginf = FALSE;
8574 lb = var->data.multaggr.constant;
8575 for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8576 {
8578 if( var->data.multaggr.scalars[i] > 0.0 )
8579 {
8581
8582 if( SCIPsetIsInfinity(set, bnd) )
8583 posinf = TRUE;
8584 else if( SCIPsetIsInfinity(set, -bnd) )
8585 neginf = TRUE;
8586 else
8587 lb += var->data.multaggr.scalars[i] * bnd;
8588 }
8589 else
8590 {
8592
8593 if( SCIPsetIsInfinity(set, -bnd) )
8594 posinf = TRUE;
8595 else if( SCIPsetIsInfinity(set, bnd) )
8596 neginf = TRUE;
8597 else
8598 lb += var->data.multaggr.scalars[i] * bnd;
8599 }
8600
8601 /* stop if two diffrent infinities (or a -infinity) were found and return global lower bound of multi aggregated
8602 * variable
8603 */
8604 if( neginf )
8605 return SCIPvarGetLbGlobal(var);
8606 }
8607
8608 /* if positive infinity flag was set to true return infinity */
8609 if( posinf )
8610 return SCIPsetInfinity(set);
8611
8612 return (MAX(lb, SCIPvarGetLbGlobal(var))); /*lint !e666*/
8613}
8614
8615/** for a multi-aggregated variable, gives the global upper bound computed by adding the global bounds from all
8616 * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbGlobal, since the latter is
8617 * not updated if bounds of aggregation variables are changing
8618 *
8619 * calling this function for a non-multi-aggregated variable is not allowed
8620 */
8622 SCIP_VAR* var, /**< problem variable */
8623 SCIP_SET* set /**< global SCIP settings */
8624 )
8625{
8626 int i;
8627 SCIP_Real ub;
8628 SCIP_Real bnd;
8630 SCIP_Bool posinf;
8631 SCIP_Bool neginf;
8632
8633 assert(var != NULL);
8634 assert(set != NULL);
8635 assert(var->scip == set->scip);
8637
8638 posinf = FALSE;
8639 neginf = FALSE;
8640 ub = var->data.multaggr.constant;
8641 for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8642 {
8644 if( var->data.multaggr.scalars[i] > 0.0 )
8645 {
8647
8648 if( SCIPsetIsInfinity(set, bnd) )
8649 posinf = TRUE;
8650 else if( SCIPsetIsInfinity(set, -bnd) )
8651 neginf = TRUE;
8652 else
8653 ub += var->data.multaggr.scalars[i] * bnd;
8654 }
8655 else
8656 {
8658
8659 if( SCIPsetIsInfinity(set, -bnd) )
8660 posinf = TRUE;
8661 else if( SCIPsetIsInfinity(set, bnd) )
8662 neginf = TRUE;
8663 else
8664 ub += var->data.multaggr.scalars[i] * bnd;
8665 }
8666
8667 /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
8668 * variable
8669 */
8670 if( posinf )
8671 return SCIPvarGetUbGlobal(var);
8672 }
8673
8674 /* if negative infinity flag was set to true return -infinity */
8675 if( neginf )
8676 return -SCIPsetInfinity(set);
8677
8678 return (MIN(ub, SCIPvarGetUbGlobal(var))); /*lint !e666*/
8679}
8680
8681/** adds a hole to the original domain of the variable */
8683 SCIP_VAR* var, /**< problem variable */
8684 BMS_BLKMEM* blkmem, /**< block memory */
8685 SCIP_SET* set, /**< global SCIP settings */
8686 SCIP_Real left, /**< left bound of open interval in new hole */
8687 SCIP_Real right /**< right bound of open interval in new hole */
8688 )
8689{
8690 SCIP_Bool added;
8691
8692 assert(var != NULL);
8696 assert(set != NULL);
8697 assert(var->scip == set->scip);
8698 assert(set->stage == SCIP_STAGE_PROBLEM);
8699
8700 SCIPsetDebugMsg(set, "adding original hole (%g,%g) to <%s>\n", left, right, var->name);
8701
8702 if( SCIPsetIsEQ(set, left, right) )
8703 return SCIP_OKAY;
8704
8705 /* the interval should not be empty */
8706 assert(SCIPsetIsLT(set, left, right));
8707
8708 /* the the interval bound should already be adjusted */
8711
8712 /* the the interval should lay between the lower and upper bound */
8715
8716 /* add domain hole */
8717 SCIP_CALL( domAddHole(&var->data.original.origdom, blkmem, set, left, right, &added) );
8718
8719 /* merges overlapping holes into single holes, moves bounds respectively if hole was added */
8720 if( added )
8721 {
8722 domMerge(&var->data.original.origdom, blkmem, set, NULL, NULL);
8723 }
8724
8725 /**@todo add hole in parent and child variables (just like with bound changes);
8726 * warning! original vars' holes are in original blkmem, transformed vars' holes in transformed blkmem
8727 */
8728
8729 return SCIP_OKAY;
8730}
8731
8732/** performs the current add of domain, changes all parents accordingly */
8733static
8735 SCIP_VAR* var, /**< problem variable */
8736 BMS_BLKMEM* blkmem, /**< block memory */
8737 SCIP_SET* set, /**< global SCIP settings */
8738 SCIP_STAT* stat, /**< problem statistics */
8739 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8740 SCIP_Real left, /**< left bound of open interval in new hole */
8741 SCIP_Real right, /**< right bound of open interval in new hole */
8742 SCIP_Bool* added /**< pointer to store whether the hole was added */
8743 )
8744{
8746 SCIP_Real newlb;
8747 SCIP_Real newub;
8748 int i;
8749
8750 assert(var != NULL);
8751 assert(added != NULL);
8752 assert(blkmem != NULL);
8753
8754 /* the interval should not be empty */
8755 assert(SCIPsetIsLT(set, left, right));
8756
8757 /* the interval bound should already be adjusted */
8760
8761 /* the interval should lay between the lower and upper bound */
8764
8765 /* @todo add debugging mechanism for holes when using a debugging solution */
8766
8767 /* add hole to hole list */
8768 SCIP_CALL( domAddHole(&var->glbdom, blkmem, set, left, right, added) );
8769
8770 /* check if the hole is redundant */
8771 if( !(*added) )
8772 return SCIP_OKAY;
8773
8774 /* current bounds */
8775 newlb = var->glbdom.lb;
8776 newub = var->glbdom.ub;
8777
8778 /* merge domain holes */
8779 domMerge(&var->glbdom, blkmem, set, &newlb, &newub);
8780
8781 /* the bound should not be changed */
8784
8785 /* issue bound change event */
8787 if( var->eventfilter != NULL )
8788 {
8789 SCIP_CALL( varEventGholeAdded(var, blkmem, set, eventqueue, left, right) );
8790 }
8791
8792 /* process parent variables */
8793 for( i = 0; i < var->nparentvars; ++i )
8794 {
8795 SCIP_Real parentnewleft;
8796 SCIP_Real parentnewright;
8797 SCIP_Bool localadded;
8798
8800 assert(parentvar != NULL);
8801
8802 switch( SCIPvarGetStatus(parentvar) )
8803 {
8805 parentnewleft = left;
8806 parentnewright = right;
8807 break;
8808
8813 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
8814 return SCIP_INVALIDDATA;
8815
8816 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8817 assert(parentvar->data.aggregate.var == var);
8818
8819 if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
8820 {
8821 /* a > 0 -> change upper bound of x */
8822 parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8823 parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8824 }
8825 else
8826 {
8827 /* a < 0 -> change lower bound of x */
8828 assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
8829
8830 parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8831 parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8832 }
8833 break;
8834
8835 case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
8836 assert(parentvar->negatedvar != NULL);
8838 assert(parentvar->negatedvar->negatedvar == parentvar);
8839
8840 parentnewright = -left + parentvar->data.negate.constant;
8841 parentnewleft = -right + parentvar->data.negate.constant;
8842 break;
8843
8844 default:
8845 SCIPerrorMessage("unknown variable status\n");
8846 return SCIP_INVALIDDATA;
8847 }
8848
8849 SCIPsetDebugMsg(set, "add global hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
8850
8851 /* perform hole added for parent variable */
8852 assert(blkmem != NULL);
8854 SCIP_CALL( varProcessAddHoleGlobal(parentvar, blkmem, set, stat, eventqueue,
8857 }
8858
8859 return SCIP_OKAY;
8860}
8861
8862/** adds a hole to the variable's global and local domain */
8864 SCIP_VAR* var, /**< problem variable */
8865 BMS_BLKMEM* blkmem, /**< block memory */
8866 SCIP_SET* set, /**< global SCIP settings */
8867 SCIP_STAT* stat, /**< problem statistics */
8868 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8869 SCIP_Real left, /**< left bound of open interval in new hole */
8870 SCIP_Real right, /**< right bound of open interval in new hole */
8871 SCIP_Bool* added /**< pointer to store whether the hole was added */
8872 )
8873{
8874 SCIP_Real childnewleft;
8875 SCIP_Real childnewright;
8876
8877 assert(var != NULL);
8879 assert(blkmem != NULL);
8880 assert(added != NULL);
8881
8882 SCIPsetDebugMsg(set, "adding global hole (%g,%g) to <%s>\n", left, right, var->name);
8883
8884 /* the interval should not be empty */
8885 assert(SCIPsetIsLT(set, left, right));
8886
8887 /* the the interval bound should already be adjusted */
8890
8891 /* the the interval should lay between the lower and upper bound */
8894
8895 /* change bounds of attached variables */
8896 switch( SCIPvarGetStatus(var) )
8897 {
8899 if( var->data.original.transvar != NULL )
8900 {
8901 SCIP_CALL( SCIPvarAddHoleGlobal(var->data.original.transvar, blkmem, set, stat, eventqueue,
8902 left, right, added) );
8903 }
8904 else
8905 {
8906 assert(set->stage == SCIP_STAGE_PROBLEM);
8907
8908 SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
8909 if( *added )
8910 {
8911 SCIP_Bool localadded;
8912
8913 SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
8914 }
8915 }
8916 break;
8917
8920 SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
8921 if( *added )
8922 {
8923 SCIP_Bool localadded;
8924
8925 SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
8926 }
8927 break;
8928
8930 SCIPerrorMessage("cannot add hole of a fixed variable\n");
8931 return SCIP_INVALIDDATA;
8932
8933 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8935
8937 {
8938 /* a > 0 -> change lower bound of y */
8941 }
8943 {
8946 }
8947 else
8948 {
8949 SCIPerrorMessage("scalar is zero in aggregation\n");
8950 return SCIP_INVALIDDATA;
8951 }
8952 SCIP_CALL( SCIPvarAddHoleGlobal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
8954 break;
8955
8957 SCIPerrorMessage("cannot add a hole of a multi-aggregated variable.\n");
8958 return SCIP_INVALIDDATA;
8959
8960 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8964
8966 childnewleft = -right + var->data.negate.constant;
8967
8968 SCIP_CALL( SCIPvarAddHoleGlobal(var->negatedvar, blkmem, set, stat, eventqueue,
8970 break;
8971
8972 default:
8973 SCIPerrorMessage("unknown variable status\n");
8974 return SCIP_INVALIDDATA;
8975 }
8976
8977 return SCIP_OKAY;
8978}
8979
8980/** performs the current add of domain, changes all parents accordingly */
8981static
8983 SCIP_VAR* var, /**< problem variable */
8984 BMS_BLKMEM* blkmem, /**< block memory */
8985 SCIP_SET* set, /**< global SCIP settings */
8986 SCIP_STAT* stat, /**< problem statistics */
8987 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8988 SCIP_Real left, /**< left bound of open interval in new hole */
8989 SCIP_Real right, /**< right bound of open interval in new hole */
8990 SCIP_Bool* added /**< pointer to store whether the hole was added, or NULL */
8991 )
8992{
8994 SCIP_Real newlb;
8995 SCIP_Real newub;
8996 int i;
8997
8998 assert(var != NULL);
8999 assert(added != NULL);
9000 assert(blkmem != NULL);
9001
9002 /* the interval should not be empty */
9003 assert(SCIPsetIsLT(set, left, right));
9004
9005 /* the the interval bound should already be adjusted */
9008
9009 /* the the interval should lay between the lower and upper bound */
9012
9013 /* add hole to hole list */
9014 SCIP_CALL( domAddHole(&var->locdom, blkmem, set, left, right, added) );
9015
9016 /* check if the hole is redundant */
9017 if( !(*added) )
9018 return SCIP_OKAY;
9019
9020 /* current bounds */
9021 newlb = var->locdom.lb;
9022 newub = var->locdom.ub;
9023
9024 /* merge domain holes */
9025 domMerge(&var->locdom, blkmem, set, &newlb, &newub);
9026
9027 /* the bound should not be changed */
9030
9031#if 0
9032 /* issue bound change event */
9034 if( var->eventfilter != NULL )
9035 {
9036 SCIP_CALL( varEventLholeAdded(var, blkmem, set, lp, branchcand, eventqueue, left, right) );
9037 }
9038#endif
9039
9040 /* process parent variables */
9041 for( i = 0; i < var->nparentvars; ++i )
9042 {
9043 SCIP_Real parentnewleft;
9044 SCIP_Real parentnewright;
9045 SCIP_Bool localadded;
9046
9048 assert(parentvar != NULL);
9049
9050 switch( SCIPvarGetStatus(parentvar) )
9051 {
9053 parentnewleft = left;
9054 parentnewright = right;
9055 break;
9056
9061 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
9062 return SCIP_INVALIDDATA;
9063
9064 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
9065 assert(parentvar->data.aggregate.var == var);
9066
9067 if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
9068 {
9069 /* a > 0 -> change upper bound of x */
9070 parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
9071 parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
9072 }
9073 else
9074 {
9075 /* a < 0 -> change lower bound of x */
9076 assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
9077
9078 parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
9079 parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
9080 }
9081 break;
9082
9083 case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
9084 assert(parentvar->negatedvar != NULL);
9086 assert(parentvar->negatedvar->negatedvar == parentvar);
9087
9088 parentnewright = -left + parentvar->data.negate.constant;
9089 parentnewleft = -right + parentvar->data.negate.constant;
9090 break;
9091
9092 default:
9093 SCIPerrorMessage("unknown variable status\n");
9094 return SCIP_INVALIDDATA;
9095 }
9096
9097 SCIPsetDebugMsg(set, "add local hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
9098
9099 /* perform hole added for parent variable */
9100 assert(blkmem != NULL);
9102 SCIP_CALL( varProcessAddHoleLocal(parentvar, blkmem, set, stat, eventqueue,
9105 }
9106
9107 return SCIP_OKAY;
9108}
9109
9110/** adds a hole to the variable's current local domain */
9112 SCIP_VAR* var, /**< problem variable */
9113 BMS_BLKMEM* blkmem, /**< block memory */
9114 SCIP_SET* set, /**< global SCIP settings */
9115 SCIP_STAT* stat, /**< problem statistics */
9116 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
9117 SCIP_Real left, /**< left bound of open interval in new hole */
9118 SCIP_Real right, /**< right bound of open interval in new hole */
9119 SCIP_Bool* added /**< pointer to store whether the hole was added */
9120 )
9121{
9122 SCIP_Real childnewleft;
9123 SCIP_Real childnewright;
9124
9125 assert(var != NULL);
9126
9127 SCIPsetDebugMsg(set, "adding local hole (%g,%g) to <%s>\n", left, right, var->name);
9128
9129 assert(set != NULL);
9130 assert(var->scip == set->scip);
9132 assert(blkmem != NULL);
9133 assert(added != NULL);
9134
9135 /* the interval should not be empty */
9136 assert(SCIPsetIsLT(set, left, right));
9137
9138 /* the the interval bound should already be adjusted */
9141
9142 /* the the interval should lay between the lower and upper bound */
9145
9146 /* change bounds of attached variables */
9147 switch( SCIPvarGetStatus(var) )
9148 {
9150 if( var->data.original.transvar != NULL )
9151 {
9152 SCIP_CALL( SCIPvarAddHoleLocal(var->data.original.transvar, blkmem, set, stat, eventqueue,
9153 left, right, added) );
9154 }
9155 else
9156 {
9157 assert(set->stage == SCIP_STAGE_PROBLEM);
9158 SCIPstatIncrement(stat, set, domchgcount);
9159 SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
9160 }
9161 break;
9162
9165 SCIPstatIncrement(stat, set, domchgcount);
9166 SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
9167 break;
9168
9170 SCIPerrorMessage("cannot add domain hole to a fixed variable\n");
9171 return SCIP_INVALIDDATA;
9172
9173 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
9175
9177 {
9178 /* a > 0 -> change lower bound of y */
9181 }
9183 {
9186 }
9187 else
9188 {
9189 SCIPerrorMessage("scalar is zero in aggregation\n");
9190 return SCIP_INVALIDDATA;
9191 }
9192 SCIP_CALL( SCIPvarAddHoleLocal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
9194 break;
9195
9197 SCIPerrorMessage("cannot add domain hole to a multi-aggregated variable.\n");
9198 return SCIP_INVALIDDATA;
9199
9200 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
9204
9206 childnewleft = -right + var->data.negate.constant;
9207
9209 break;
9210
9211 default:
9212 SCIPerrorMessage("unknown variable status\n");
9213 return SCIP_INVALIDDATA;
9214 }
9215
9216 return SCIP_OKAY;
9217}
9218
9219/** resets the global and local bounds of original variable to their original values */
9221 SCIP_VAR* var, /**< problem variable */
9222 BMS_BLKMEM* blkmem, /**< block memory */
9223 SCIP_SET* set, /**< global SCIP settings */
9224 SCIP_STAT* stat /**< problem statistics */
9225 )
9226{
9227 assert(var != NULL);
9228 assert(set != NULL);
9229 assert(var->scip == set->scip);
9231 /* resetting of bounds on original variables which have a transformed counterpart easily fails if, e.g.,
9232 * the transformed variable has been fixed */
9234
9235 /* copy the original bounds back to the global and local bounds */
9240
9241 /* free the global and local holelists and duplicate the original ones */
9242 /**@todo this has also to be called recursively with methods similar to SCIPvarChgLbGlobal() */
9243 holelistFree(&var->glbdom.holelist, blkmem);
9244 holelistFree(&var->locdom.holelist, blkmem);
9247
9248 return SCIP_OKAY;
9249}
9250
9251/** issues a IMPLADDED event on the given variable */
9252static
9254 SCIP_VAR* var, /**< problem variable to change */
9255 BMS_BLKMEM* blkmem, /**< block memory */
9256 SCIP_SET* set, /**< global SCIP settings */
9257 SCIP_EVENTQUEUE* eventqueue /**< event queue */
9258 )
9259{
9261
9262 assert(var != NULL);
9263
9264 /* issue IMPLADDED event on variable */
9266 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
9267
9268 return SCIP_OKAY;
9269}
9270
9271/** actually performs the addition of a variable bound to the variable's vbound arrays */
9272static
9274 SCIP_VAR* var, /**< problem variable x in x <= b*z + d or x >= b*z + d */
9275 BMS_BLKMEM* blkmem, /**< block memory */
9276 SCIP_SET* set, /**< global SCIP settings */
9277 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9278 SCIP_BOUNDTYPE vbtype, /**< type of variable bound (LOWER or UPPER) */
9279 SCIP_VAR* vbvar, /**< variable z in x <= b*z + d or x >= b*z + d */
9280 SCIP_Real vbcoef, /**< coefficient b in x <= b*z + d or x >= b*z + d */
9281 SCIP_Real vbconstant /**< constant d in x <= b*z + d or x >= b*z + d */
9282 )
9283{
9284 SCIP_Bool added;
9285
9286 /* It can happen that the variable "var" and the variable "vbvar" are the same variable. For example if a variable
9287 * gets aggregated, the variable bounds (vbound) of that variable are copied to the other variable. A variable bound
9288 * variable of the aggregated variable might be the same as the one its gets aggregated too.
9289 *
9290 * If the variable "var" and the variable "vbvar" are the same, the variable bound which should be added here has to
9291 * be redundant. This is the case since an infeasibility should have be detected in the previous methods. As well as
9292 * the bounds of the variable which should be also already be tightened in the previous methods. Therefore, the
9293 * variable bound can be ignored.
9294 *
9295 * From the way the the variable bound system is implemented (detecting infeasibility, tighten bounds), the
9296 * equivalence of the variables should be checked here.
9297 */
9298 if( var == vbvar )
9299 {
9300 /* in this case the variable bound has to be redundant, this means for possible assignments to this variable; this
9301 * can be checked via the global bounds of the variable */
9302#ifndef NDEBUG
9303 SCIP_Real lb;
9304 SCIP_Real ub;
9305
9306 lb = SCIPvarGetLbGlobal(var);
9307 ub = SCIPvarGetUbGlobal(var);
9308
9310 {
9311 if( vbcoef > 0.0 )
9312 {
9313 assert(SCIPsetIsGE(set, lb, lb * vbcoef + vbconstant) );
9314 assert(SCIPsetIsGE(set, ub, ub * vbcoef + vbconstant) );
9315 }
9316 else
9317 {
9318 assert(SCIPsetIsGE(set, lb, ub * vbcoef + vbconstant) );
9319 assert(SCIPsetIsGE(set, ub, lb * vbcoef + vbconstant) );
9320 }
9321 }
9322 else
9323 {
9325 if( vbcoef > 0.0 )
9326 {
9327 assert(SCIPsetIsLE(set, lb, lb * vbcoef + vbconstant) );
9328 assert(SCIPsetIsLE(set, ub, ub * vbcoef + vbconstant) );
9329 }
9330 else
9331 {
9332 assert(SCIPsetIsLE(set, lb, ub * vbcoef + vbconstant) );
9333 assert(SCIPsetIsLE(set, ub, lb * vbcoef + vbconstant) );
9334 }
9335 }
9336#endif
9337 SCIPsetDebugMsg(set, "redundant variable bound: <%s> %s %g<%s> %+g\n",
9339
9340 return SCIP_OKAY;
9341 }
9342
9343 SCIPsetDebugMsg(set, "adding variable bound: <%s> %s %g<%s> %+g\n",
9345
9346 /* check variable bound on debugging solution */
9347 SCIP_CALL( SCIPdebugCheckVbound(set, var, vbtype, vbvar, vbcoef, vbconstant) ); /*lint !e506 !e774*/
9348
9349 /* perform the addition */
9351 {
9353 }
9354 else
9355 {
9357 }
9358 var->closestvblpcount = -1;
9359
9360 if( added )
9361 {
9362 /* issue IMPLADDED event */
9363 SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
9364 }
9365
9366 return SCIP_OKAY;
9367}
9368
9369/** checks whether the given implication is redundant or infeasible w.r.t. the implied variables global bounds */
9370static
9372 SCIP_SET* set, /**< global SCIP settings */
9373 SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9374 SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9375 SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9376 SCIP_Bool* redundant, /**< pointer to store whether the implication is redundant */
9377 SCIP_Bool* infeasible /**< pointer to store whether the implication is infeasible */
9378 )
9379{
9380 SCIP_Real impllb;
9381 SCIP_Real implub;
9382
9383 assert(redundant != NULL);
9384 assert(infeasible != NULL);
9385
9389 {
9390 *infeasible = SCIPsetIsFeasGT(set, implbound, implub);
9391 *redundant = SCIPsetIsFeasLE(set, implbound, impllb);
9392 }
9393 else
9394 {
9395 *infeasible = SCIPsetIsFeasLT(set, implbound, impllb);
9396 *redundant = SCIPsetIsFeasGE(set, implbound, implub);
9397 }
9398}
9399
9400/** applies the given implication, if it is not redundant */
9401static
9403 BMS_BLKMEM* blkmem, /**< block memory */
9404 SCIP_SET* set, /**< global SCIP settings */
9405 SCIP_STAT* stat, /**< problem statistics */
9406 SCIP_PROB* transprob, /**< transformed problem */
9407 SCIP_PROB* origprob, /**< original problem */
9408 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9409 SCIP_REOPT* reopt, /**< reoptimization data structure */
9410 SCIP_LP* lp, /**< current LP data */
9411 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9412 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9413 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9414 SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9415 SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9416 SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9417 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9418 int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9419 )
9420{
9421 SCIP_Real implub;
9422 SCIP_Real impllb;
9423
9424 assert(infeasible != NULL);
9425
9426 *infeasible = FALSE;
9427
9431 {
9433 {
9434 /* the implication produces a conflict: the problem is infeasible */
9435 *infeasible = TRUE;
9436 }
9437 else if( SCIPsetIsFeasGT(set, implbound, impllb) )
9438 {
9439 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9440 * with the local bound, in this case we need to store the bound change as pending bound change
9441 */
9443 {
9444 assert(tree != NULL);
9445 assert(transprob != NULL);
9446 assert(SCIPprobIsTransformed(transprob));
9447
9448 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9449 tree, reopt, lp, branchcand, eventqueue, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
9450 }
9451 else
9452 {
9453 SCIP_CALL( SCIPvarChgLbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
9454 }
9455
9456 if( nbdchgs != NULL )
9457 (*nbdchgs)++;
9458 }
9459 }
9460 else
9461 {
9463 {
9464 /* the implication produces a conflict: the problem is infeasible */
9465 *infeasible = TRUE;
9466 }
9467 else if( SCIPsetIsFeasLT(set, implbound, implub) )
9468 {
9469 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9470 * with the local bound, in this case we need to store the bound change as pending bound change
9471 */
9473 {
9474 assert(tree != NULL);
9475 assert(transprob != NULL);
9476 assert(SCIPprobIsTransformed(transprob));
9477
9478 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9479 tree, reopt, lp, branchcand, eventqueue, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
9480 }
9481 else
9482 {
9483 SCIP_CALL( SCIPvarChgUbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
9484 }
9485
9486 if( nbdchgs != NULL )
9487 (*nbdchgs)++;
9488 }
9489 }
9490
9491 return SCIP_OKAY;
9492}
9493
9494/** actually performs the addition of an implication to the variable's implication arrays,
9495 * and adds the corresponding implication or variable bound to the implied variable;
9496 * if the implication is conflicting, the variable is fixed to the opposite value;
9497 * if the variable is already fixed to the given value, the implication is performed immediately;
9498 * if the implication is redundant with respect to the variables' global bounds, it is ignored
9499 */
9500static
9502 SCIP_VAR* var, /**< problem variable */
9503 BMS_BLKMEM* blkmem, /**< block memory */
9504 SCIP_SET* set, /**< global SCIP settings */
9505 SCIP_STAT* stat, /**< problem statistics */
9506 SCIP_PROB* transprob, /**< transformed problem */
9507 SCIP_PROB* origprob, /**< original problem */
9508 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9509 SCIP_REOPT* reopt, /**< reoptimization data structure */
9510 SCIP_LP* lp, /**< current LP data */
9511 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9512 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9513 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9514 SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9515 SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9516 SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9517 SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9518 SCIP_Bool isshortcut, /**< is the implication a shortcut, i.e., added as part of the transitive closure of another implication? */
9519 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9520 int* nbdchgs, /**< pointer to count the number of performed bound changes, or NULL */
9521 SCIP_Bool* added /**< pointer to store whether an implication was added */
9522 )
9523{
9524 SCIP_Bool redundant;
9525 SCIP_Bool conflict;
9526
9527 assert(var != NULL);
9532 assert(infeasible != NULL);
9533 assert(added != NULL);
9534
9535 /* check implication on debugging solution */
9537
9538 *infeasible = FALSE;
9539 *added = FALSE;
9540
9541 /* check, if the implication is redundant or infeasible */
9542 checkImplic(set, implvar, impltype, implbound, &redundant, &conflict);
9543 assert(!redundant || !conflict);
9544 if( redundant )
9545 return SCIP_OKAY;
9546
9547 if( var == implvar )
9548 {
9549 /* special cases appear were a bound to a variable implies itself to be outside the bounds:
9550 * x == varfixing => x < 0 or x > 1
9551 */
9552 if( SCIPsetIsLT(set, implbound, 0.0) || SCIPsetIsGT(set, implbound, 1.0) )
9553 conflict = TRUE;
9554 else
9555 {
9556 /* variable implies itself: x == varfixing => x == (impltype == SCIP_BOUNDTYPE_LOWER) */
9560 conflict = conflict || ((varfixing == TRUE) == (impltype == SCIP_BOUNDTYPE_UPPER));
9561 if( !conflict )
9562 return SCIP_OKAY;
9563 }
9564 }
9565
9566 /* check, if the variable is already fixed */
9567 if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
9568 {
9569 /* if the variable is fixed to the given value, perform the implication; otherwise, ignore the implication */
9570 if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
9571 {
9572 SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
9573 cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
9574 }
9575 return SCIP_OKAY;
9576 }
9577
9580
9581 if( !conflict )
9582 {
9583 assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9584
9586 {
9587 SCIP_VAR* vars[2];
9588 SCIP_Bool vals[2];
9589
9592
9593 vars[0] = var;
9594 vars[1] = implvar;
9595 vals[0] = varfixing;
9596 vals[1] = (impltype == SCIP_BOUNDTYPE_UPPER);
9597
9598 /* add the clique to the clique table */
9599 SCIP_CALL( SCIPcliquetableAdd(cliquetable, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
9600 eventqueue, vars, vals, 2, FALSE, &conflict, nbdchgs) );
9601
9602 if( !conflict )
9603 return SCIP_OKAY;
9604 }
9605 else
9606 {
9607 /* add implication x == 0/1 -> y <= b / y >= b to the implications list of x */
9608 SCIPsetDebugMsg(set, "adding implication: <%s> == %u ==> <%s> %s %g\n",
9612 isshortcut, &conflict, added) );
9613 }
9614 }
9615 assert(!conflict || !(*added));
9616
9617 /* on conflict, fix the variable to the opposite value */
9618 if( conflict )
9619 {
9620 SCIPsetDebugMsg(set, " -> implication yields a conflict: fix <%s> == %d\n", SCIPvarGetName(var), !varfixing);
9621
9622 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9623 * with the local bound, in this case we need to store the bound change as pending bound change
9624 */
9626 {
9627 assert(tree != NULL);
9628 assert(transprob != NULL);
9629 assert(SCIPprobIsTransformed(transprob));
9630
9631 if( varfixing )
9632 {
9633 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9634 tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
9635 }
9636 else
9637 {
9638 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9639 tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
9640 }
9641 }
9642 else
9643 {
9644 if( varfixing )
9645 {
9646 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
9647 }
9648 else
9649 {
9650 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
9651 }
9652 }
9653 if( nbdchgs != NULL )
9654 (*nbdchgs)++;
9655
9656 return SCIP_OKAY;
9657 }
9658 else if( *added )
9659 {
9660 /* issue IMPLADDED event */
9661 SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
9662 }
9663 else
9664 {
9665 /* the implication was redundant: the inverse is also redundant */
9666 return SCIP_OKAY;
9667 }
9668
9669 assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9670
9671 /* check, whether implied variable is binary */
9672 if( !SCIPvarIsBinary(implvar) )
9673 {
9674 SCIP_Real lb;
9675 SCIP_Real ub;
9676
9677 /* add inverse variable bound to the variable bounds of y with global bounds y \in [lb,ub]:
9678 * x == 0 -> y <= b <-> y <= (ub - b)*x + b
9679 * x == 1 -> y <= b <-> y <= (b - ub)*x + ub
9680 * x == 0 -> y >= b <-> y >= (lb - b)*x + b
9681 * x == 1 -> y >= b <-> y >= (b - lb)*x + lb
9682 * for numerical reasons, ignore variable bounds with large absolute coefficient
9683 */
9687 {
9688 if( REALABS(implbound - ub) <= MAXABSVBCOEF )
9689 {
9690 SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, var,
9691 varfixing ? implbound - ub : ub - implbound, varfixing ? ub : implbound) );
9692 }
9693 }
9694 else
9695 {
9696 if( REALABS(implbound - lb) <= MAXABSVBCOEF )
9697 {
9698 SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, var,
9699 varfixing ? implbound - lb : lb - implbound, varfixing ? lb : implbound) );
9700 }
9701 }
9702 }
9703
9704 return SCIP_OKAY;
9705}
9706
9707/** adds transitive closure for binary implication x = a -> y = b */
9708static
9710 SCIP_VAR* var, /**< problem variable */
9711 BMS_BLKMEM* blkmem, /**< block memory */
9712 SCIP_SET* set, /**< global SCIP settings */
9713 SCIP_STAT* stat, /**< problem statistics */
9714 SCIP_PROB* transprob, /**< transformed problem */
9715 SCIP_PROB* origprob, /**< original problem */
9716 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9717 SCIP_REOPT* reopt, /**< reoptimization data structure */
9718 SCIP_LP* lp, /**< current LP data */
9719 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9720 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9721 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9722 SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9723 SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9724 SCIP_Bool implvarfixing, /**< fixing b in implication */
9725 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9726 int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9727 )
9728{
9731 SCIP_Real* implbounds;
9732 int nimpls;
9733 int i;
9734
9735 *infeasible = FALSE;
9736
9737 /* binary variable: implications of implvar */
9738 nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
9742
9743 /* if variable has too many implications, the implication graph may become too dense */
9744 i = MIN(nimpls, MAXIMPLSCLOSURE) - 1;
9745
9746 /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9747 * implvars[i] is fixed, s.t. the implication y == varfixing -> z <= b / z >= b is deleted; this affects the
9748 * array over which we currently iterate; the only thing that can happen, is that elements of the array are
9749 * deleted; in this case, the subsequent elements are moved to the front; if we iterate from back to front, the
9750 * only thing that can happen is that we add the same implication twice - this does no harm
9751 */
9752 while ( i >= 0 && !(*infeasible) )
9753 {
9754 SCIP_Bool added;
9755
9756 assert(implvars[i] != implvar);
9757
9758 /* we have x == varfixing -> y == implvarfixing -> z <= b / z >= b:
9759 * add implication x == varfixing -> z <= b / z >= b to the implications list of x
9760 */
9761 if( SCIPvarIsActive(implvars[i]) )
9762 {
9763 SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
9764 eventqueue, varfixing, implvars[i], impltypes[i], implbounds[i], TRUE, infeasible, nbdchgs, &added) );
9765 assert(SCIPimplicsGetNImpls(implvar->implics, implvarfixing) <= nimpls);
9766 nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
9767 i = MIN(i, nimpls); /* some elements from the array could have been removed */
9768 }
9769 --i;
9770 }
9771
9772 return SCIP_OKAY;
9773}
9774
9775/** adds given implication to the variable's implication list, and adds all implications directly implied by this
9776 * implication to the variable's implication list;
9777 * if the implication is conflicting, the variable is fixed to the opposite value;
9778 * if the variable is already fixed to the given value, the implication is performed immediately;
9779 * if the implication is redundant with respect to the variables' global bounds, it is ignored
9780 */
9781static
9783 SCIP_VAR* var, /**< problem variable */
9784 BMS_BLKMEM* blkmem, /**< block memory */
9785 SCIP_SET* set, /**< global SCIP settings */
9786 SCIP_STAT* stat, /**< problem statistics */
9787 SCIP_PROB* transprob, /**< transformed problem */
9788 SCIP_PROB* origprob, /**< original problem */
9789 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9790 SCIP_REOPT* reopt, /**< reoptimization data structure */
9791 SCIP_LP* lp, /**< current LP data */
9792 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9793 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9794 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9795 SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9796 SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9797 SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9798 SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9799 SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
9800 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9801 int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9802 )
9803{
9804 SCIP_Bool added;
9805
9806 assert(var != NULL);
9809 assert(implvar != NULL);
9811 assert(infeasible != NULL);
9812
9813 /* add implication x == varfixing -> y <= b / y >= b to the implications list of x */
9814 SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
9815 eventqueue, varfixing, implvar, impltype, implbound, FALSE, infeasible, nbdchgs, &added) );
9816
9817 if( *infeasible || var == implvar || !transitive || !added )
9818 return SCIP_OKAY;
9819
9820 assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9821
9822 /* add transitive closure */
9824 {
9825 SCIP_Bool implvarfixing;
9826
9828
9829 /* binary variable: implications of implvar */
9830 SCIP_CALL( varAddTransitiveBinaryClosureImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9831 cliquetable, branchcand, eventqueue, varfixing, implvar, implvarfixing, infeasible, nbdchgs) );
9832
9833 /* inverse implication */
9834 if( !(*infeasible) )
9835 {
9836 SCIP_CALL( varAddTransitiveBinaryClosureImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9837 cliquetable, branchcand, eventqueue, !implvarfixing, var, !varfixing, infeasible, nbdchgs) );
9838 }
9839 }
9840 else
9841 {
9842 /* non-binary variable: variable lower bounds of implvar */
9843 if( impltype == SCIP_BOUNDTYPE_UPPER && implvar->vlbs != NULL )
9844 {
9845 SCIP_VAR** vlbvars;
9846 SCIP_Real* vlbcoefs;
9847 SCIP_Real* vlbconstants;
9848 int nvlbvars;
9849 int i;
9850
9855
9856 /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9857 * vlbvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
9858 * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
9859 * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
9860 * is that we add the same implication twice - this does no harm
9861 */
9862 i = nvlbvars-1;
9863 while ( i >= 0 && !(*infeasible) )
9864 {
9865 assert(vlbvars[i] != implvar);
9867
9868 /* we have x == varfixing -> y <= b and y >= c*z + d:
9869 * c > 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
9870 * c < 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
9871 *
9872 * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
9873 * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
9874 * aggregation variable (the one which will stay active);
9875 *
9876 * W.l.o.g. we consider the variable upper bounds for now. Let "vubvar" be a variable upper bound of
9877 * the aggregated variable "aggvar"; During that copying of that variable upper bound variable
9878 * "vubvar" the variable lower and upper bounds of this variable "vubvar" are also considered; note
9879 * that the "aggvar" can be a variable lower bound variable of the variable "vubvar"; Due to that
9880 * situation it can happen that we reach that code place where "vlbvars[i] == aggvar". In particular
9881 * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
9882 * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
9883 * have to explicitly check that the active variable has not a variable status
9884 * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
9885 */
9887 {
9888 SCIP_Real vbimplbound;
9889
9891 if( vlbcoefs[i] >= 0.0 )
9892 {
9894 SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9895 branchcand, eventqueue, varfixing, vlbvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
9896 infeasible, nbdchgs, &added) );
9897 }
9898 else
9899 {
9901 SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9902 branchcand, eventqueue, varfixing, vlbvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
9903 infeasible, nbdchgs, &added) );
9904 }
9906 i = MIN(i, nvlbvars); /* some elements from the array could have been removed */
9907 }
9908 --i;
9909 }
9910 }
9911
9912 /* non-binary variable: variable upper bounds of implvar */
9913 if( impltype == SCIP_BOUNDTYPE_LOWER && implvar->vubs != NULL )
9914 {
9915 SCIP_VAR** vubvars;
9916 SCIP_Real* vubcoefs;
9917 SCIP_Real* vubconstants;
9918 int nvubvars;
9919 int i;
9920
9925
9926 /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9927 * vubvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
9928 * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
9929 * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
9930 * is that we add the same implication twice - this does no harm
9931 */
9932 i = nvubvars-1;
9933 while ( i >= 0 && !(*infeasible) )
9934 {
9935 assert(vubvars[i] != implvar);
9937
9938 /* we have x == varfixing -> y >= b and y <= c*z + d:
9939 * c > 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
9940 * c < 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
9941 *
9942 * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
9943 * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
9944 * aggregation variable (the one which will stay active);
9945 *
9946 * W.l.o.g. we consider the variable lower bounds for now. Let "vlbvar" be a variable lower bound of
9947 * the aggregated variable "aggvar"; During that copying of that variable lower bound variable
9948 * "vlbvar" the variable lower and upper bounds of this variable "vlbvar" are also considered; note
9949 * that the "aggvar" can be a variable upper bound variable of the variable "vlbvar"; Due to that
9950 * situation it can happen that we reach that code place where "vubvars[i] == aggvar". In particular
9951 * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
9952 * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
9953 * have to explicitly check that the active variable has not a variable status
9954 * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
9955 */
9957 {
9958 SCIP_Real vbimplbound;
9959
9961 if( vubcoefs[i] >= 0.0 )
9962 {
9964 SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9965 branchcand, eventqueue, varfixing, vubvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
9966 infeasible, nbdchgs, &added) );
9967 }
9968 else
9969 {
9971 SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9972 branchcand, eventqueue, varfixing, vubvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
9973 infeasible, nbdchgs, &added) );
9974 }
9976 i = MIN(i, nvubvars); /* some elements from the array could have been removed */
9977 }
9978 --i;
9979 }
9980 }
9981 }
9982
9983 return SCIP_OKAY;
9984}
9985
9986/** informs variable x about a globally valid variable lower bound x >= b*z + d with integer variable z;
9987 * if z is binary, the corresponding valid implication for z is also added;
9988 * improves the global bounds of the variable and the vlb variable if possible
9989 */
9991 SCIP_VAR* var, /**< problem variable */
9992 BMS_BLKMEM* blkmem, /**< block memory */
9993 SCIP_SET* set, /**< global SCIP settings */
9994 SCIP_STAT* stat, /**< problem statistics */
9995 SCIP_PROB* transprob, /**< transformed problem */
9996 SCIP_PROB* origprob, /**< original problem */
9997 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9998 SCIP_REOPT* reopt, /**< reoptimization data structure */
9999 SCIP_LP* lp, /**< current LP data */
10000 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10001 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10002 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10003 SCIP_VAR* vlbvar, /**< variable z in x >= b*z + d */
10004 SCIP_Real vlbcoef, /**< coefficient b in x >= b*z + d */
10005 SCIP_Real vlbconstant, /**< constant d in x >= b*z + d */
10006 SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
10007 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10008 int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
10009 )
10010{
10011 assert(var != NULL);
10012 assert(set != NULL);
10013 assert(var->scip == set->scip);
10015 assert(infeasible != NULL);
10016
10017 SCIPsetDebugMsg(set, "adding variable lower bound <%s> >= %g<%s> + %g\n", SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
10018
10019 *infeasible = FALSE;
10020 if( nbdchgs != NULL )
10021 *nbdchgs = 0;
10022
10023 switch( SCIPvarGetStatus(var) )
10024 {
10027 SCIP_CALL( SCIPvarAddVlb(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10028 cliquetable, branchcand, eventqueue, vlbvar, vlbcoef, vlbconstant, transitive, infeasible, nbdchgs) );
10029 break;
10030
10034 /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
10036 SCIPsetDebugMsg(set, " -> transformed to variable lower bound <%s> >= %g<%s> + %g\n", SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
10037
10038 /* if the vlb coefficient is zero, just update the lower bound of the variable */
10039 if( SCIPsetIsZero(set, vlbcoef) )
10040 {
10042 *infeasible = TRUE;
10044 {
10045 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10046 * with the local bound, in this case we need to store the bound change as pending bound change
10047 */
10049 {
10050 assert(tree != NULL);
10051 assert(transprob != NULL);
10052 assert(SCIPprobIsTransformed(transprob));
10053
10054 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10055 tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vlbconstant, SCIP_BOUNDTYPE_LOWER, FALSE) );
10056 }
10057 else
10058 {
10059 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vlbconstant) );
10060 }
10061
10062 if( nbdchgs != NULL )
10063 (*nbdchgs)++;
10064 }
10065 }
10066 else if( var == vlbvar )
10067 {
10068 /* the variables cancels out, the variable bound constraint is either redundant or proves global infeasibility */
10069 if( SCIPsetIsEQ(set, vlbcoef, 1.0) )
10070 {
10072 *infeasible = TRUE;
10073 return SCIP_OKAY;
10074 }
10075 else
10076 {
10077 SCIP_Real lb = SCIPvarGetLbGlobal(var);
10078 SCIP_Real ub = SCIPvarGetUbGlobal(var);
10079
10080 /* the variable bound constraint defines a new upper bound */
10081 if( SCIPsetIsGT(set, vlbcoef, 1.0) )
10082 {
10083 SCIP_Real newub = vlbconstant / (1.0 - vlbcoef);
10084
10085 if( SCIPsetIsFeasLT(set, newub, lb) )
10086 {
10087 *infeasible = TRUE;
10088 return SCIP_OKAY;
10089 }
10090 else if( SCIPsetIsFeasLT(set, newub, ub) )
10091 {
10092 /* bound might be adjusted due to integrality condition */
10094
10095 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10096 * with the local bound, in this case we need to store the bound change as pending bound change
10097 */
10099 {
10100 assert(tree != NULL);
10101 assert(transprob != NULL);
10102 assert(SCIPprobIsTransformed(transprob));
10103
10104 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10105 tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10106 }
10107 else
10108 {
10109 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newub) );
10110 }
10111
10112 if( nbdchgs != NULL )
10113 (*nbdchgs)++;
10114 }
10115 }
10116 /* the variable bound constraint defines a new lower bound */
10117 else
10118 {
10119 SCIP_Real newlb;
10120
10121 assert(SCIPsetIsLT(set, vlbcoef, 1.0));
10122
10123 newlb = vlbconstant / (1.0 - vlbcoef);
10124
10125 if( SCIPsetIsFeasGT(set, newlb, ub) )
10126 {
10127 *infeasible = TRUE;
10128 return SCIP_OKAY;
10129 }
10130 else if( SCIPsetIsFeasGT(set, newlb, lb) )
10131 {
10132 /* bound might be adjusted due to integrality condition */
10134
10135 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10136 * with the local bound, in this case we need to store the bound change as pending bound change
10137 */
10139 {
10140 assert(tree != NULL);
10141 assert(transprob != NULL);
10142 assert(SCIPprobIsTransformed(transprob));
10143
10144 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10145 tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10146 }
10147 else
10148 {
10149 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newlb) );
10150 }
10151
10152 if( nbdchgs != NULL )
10153 (*nbdchgs)++;
10154 }
10155 }
10156 }
10157 }
10158 else if( SCIPvarIsActive(vlbvar) )
10159 {
10160 SCIP_Real xlb;
10161 SCIP_Real xub;
10162 SCIP_Real zlb;
10163 SCIP_Real zub;
10164 SCIP_Real minvlb;
10165 SCIP_Real maxvlb;
10166
10168 assert(vlbcoef != 0.0);
10169
10172
10177
10178 /* improve global bounds of vlb variable, and calculate minimal and maximal value of variable bound */
10179 if( vlbcoef >= 0.0 )
10180 {
10181 SCIP_Real newzub;
10182
10183 if( !SCIPsetIsInfinity(set, xub) )
10184 {
10185 /* x >= b*z + d -> z <= (x-d)/b */
10187
10188 /* return if the new bound is less than -infinity */
10190 return SCIP_OKAY;
10191
10192 if( SCIPsetIsFeasLT(set, newzub, zlb) )
10193 {
10194 *infeasible = TRUE;
10195 return SCIP_OKAY;
10196 }
10197 if( SCIPsetIsFeasLT(set, newzub, zub) )
10198 {
10199 /* bound might be adjusted due to integrality condition */
10201
10202 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10203 * with the local bound, in this case we need to store the bound change as pending bound change
10204 */
10206 {
10207 assert(tree != NULL);
10208 assert(transprob != NULL);
10209 assert(SCIPprobIsTransformed(transprob));
10210
10211 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10212 tree, reopt, lp, branchcand, eventqueue, cliquetable, vlbvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10213 }
10214 else
10215 {
10216 SCIP_CALL( SCIPvarChgUbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
10217 }
10218 zub = newzub;
10219
10220 if( nbdchgs != NULL )
10221 (*nbdchgs)++;
10222 }
10224 if( !SCIPsetIsInfinity(set, -zlb) )
10226 }
10227 else
10228 {
10229 if( !SCIPsetIsInfinity(set, zub) )
10231 if( !SCIPsetIsInfinity(set, -zlb) )
10233 }
10234 }
10235 else
10236 {
10237 SCIP_Real newzlb;
10238
10239 if( !SCIPsetIsInfinity(set, xub) )
10240 {
10241 /* x >= b*z + d -> z >= (x-d)/b */
10243
10244 /* return if the new bound is larger than infinity */
10246 return SCIP_OKAY;
10247
10248 if( SCIPsetIsFeasGT(set, newzlb, zub) )
10249 {
10250 *infeasible = TRUE;
10251 return SCIP_OKAY;
10252 }
10253 if( SCIPsetIsFeasGT(set, newzlb, zlb) )
10254 {
10255 /* bound might be adjusted due to integrality condition */
10257
10258 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10259 * with the local bound, in this case we need to store the bound change as pending bound change
10260 */
10262 {
10263 assert(tree != NULL);
10264 assert(transprob != NULL);
10265 assert(SCIPprobIsTransformed(transprob));
10266
10267 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10268 tree, reopt, lp, branchcand, eventqueue, cliquetable, vlbvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10269 }
10270 else
10271 {
10272 SCIP_CALL( SCIPvarChgLbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
10273 }
10274 zlb = newzlb;
10275
10276 if( nbdchgs != NULL )
10277 (*nbdchgs)++;
10278 }
10280 if( !SCIPsetIsInfinity(set, zub) )
10282 }
10283 else
10284 {
10285 if( !SCIPsetIsInfinity(set, -zlb) )
10287 if( !SCIPsetIsInfinity(set, zub) )
10289 }
10290 }
10291 if( maxvlb < minvlb )
10292 maxvlb = minvlb;
10293
10294 /* adjust bounds due to integrality of variable */
10297
10298 /* check bounds for feasibility */
10300 {
10301 *infeasible = TRUE;
10302 return SCIP_OKAY;
10303 }
10304 /* improve global lower bound of variable */
10305 if( SCIPsetIsFeasGT(set, minvlb, xlb) )
10306 {
10307 /* bound might be adjusted due to integrality condition */
10309
10310 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10311 * with the local bound, in this case we need to store the bound change as pending bound change
10312 */
10314 {
10315 assert(tree != NULL);
10316 assert(transprob != NULL);
10317 assert(SCIPprobIsTransformed(transprob));
10318
10319 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10320 tree, reopt, lp, branchcand, eventqueue, cliquetable, var, minvlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10321 }
10322 else
10323 {
10324 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, minvlb) );
10325 }
10326 xlb = minvlb;
10327
10328 if( nbdchgs != NULL )
10329 (*nbdchgs)++;
10330 }
10331 minvlb = xlb;
10332
10333 /* improve variable bound for binary z by moving the variable's global bound to the vlb constant */
10335 {
10336 /* b > 0: x >= (maxvlb - minvlb) * z + minvlb
10337 * b < 0: x >= (minvlb - maxvlb) * z + maxvlb
10338 */
10339
10341
10342 if( vlbcoef >= 0.0 )
10343 {
10344 vlbcoef = maxvlb - minvlb;
10346 }
10347 else
10348 {
10349 vlbcoef = minvlb - maxvlb;
10351 }
10352 }
10353
10354 /* add variable bound to the variable bounds list */
10355 if( SCIPsetIsFeasGT(set, maxvlb, xlb) )
10356 {
10359
10360 /* if one of the variables is binary, add the corresponding implication to the variable's implication
10361 * list, thereby also adding the variable bound (or implication) to the other variable
10362 */
10364 {
10365 /* add corresponding implication:
10366 * b > 0, x >= b*z + d <-> z == 1 -> x >= b+d
10367 * b < 0, x >= b*z + d <-> z == 0 -> x >= d
10368 */
10369 SCIP_CALL( varAddTransitiveImplic(vlbvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10370 cliquetable, branchcand, eventqueue, (vlbcoef >= 0.0), var, SCIP_BOUNDTYPE_LOWER, maxvlb, transitive,
10371 infeasible, nbdchgs) );
10372 }
10374 {
10375 /* add corresponding implication:
10376 * b > 0, x >= b*z + d <-> x == 0 -> z <= -d/b
10377 * b < 0, x >= b*z + d <-> x == 0 -> z >= -d/b
10378 */
10379 SCIP_Real implbound;
10381
10382 /* tighten the implication bound if the variable is integer */
10384 {
10385 if( vlbcoef >= 0 )
10387 else
10389 }
10390 SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10391 cliquetable, branchcand, eventqueue, FALSE, vlbvar, (vlbcoef >= 0.0 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER),
10392 implbound, transitive, infeasible, nbdchgs) );
10393 }
10394 else
10395 {
10397 }
10398 }
10399 }
10400 break;
10401
10403 /* x = a*y + c: x >= b*z + d <=> a*y + c >= b*z + d <=> y >= b/a * z + (d-c)/a, if a > 0
10404 * y <= b/a * z + (d-c)/a, if a < 0
10405 */
10408 {
10409 /* a > 0 -> add variable lower bound */
10410 SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10411 cliquetable, branchcand, eventqueue, vlbvar, vlbcoef/var->data.aggregate.scalar,
10412 (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10413 }
10415 {
10416 /* a < 0 -> add variable upper bound */
10417 SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10418 cliquetable, branchcand, eventqueue, vlbvar, vlbcoef/var->data.aggregate.scalar,
10419 (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10420 }
10421 else
10422 {
10423 SCIPerrorMessage("scalar is zero in aggregation\n");
10424 return SCIP_INVALIDDATA;
10425 }
10426 break;
10427
10429 /* nothing to do here */
10430 break;
10431
10433 /* x = offset - x': x >= b*z + d <=> offset - x' >= b*z + d <=> x' <= -b*z + (offset-d) */
10437 SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10438 branchcand, eventqueue, vlbvar, -vlbcoef, var->data.negate.constant - vlbconstant, transitive, infeasible,
10439 nbdchgs) );
10440 break;
10441
10442 default:
10443 SCIPerrorMessage("unknown variable status\n");
10444 return SCIP_INVALIDDATA;
10445 }
10446
10447 return SCIP_OKAY;
10448}
10449
10450/** informs variable x about a globally valid variable upper bound x <= b*z + d with integer variable z;
10451 * if z is binary, the corresponding valid implication for z is also added;
10452 * updates the global bounds of the variable and the vub variable correspondingly
10453 */
10455 SCIP_VAR* var, /**< problem variable */
10456 BMS_BLKMEM* blkmem, /**< block memory */
10457 SCIP_SET* set, /**< global SCIP settings */
10458 SCIP_STAT* stat, /**< problem statistics */
10459 SCIP_PROB* transprob, /**< transformed problem */
10460 SCIP_PROB* origprob, /**< original problem */
10461 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10462 SCIP_REOPT* reopt, /**< reoptimization data structure */
10463 SCIP_LP* lp, /**< current LP data */
10464 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10465 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10466 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10467 SCIP_VAR* vubvar, /**< variable z in x <= b*z + d */
10468 SCIP_Real vubcoef, /**< coefficient b in x <= b*z + d */
10469 SCIP_Real vubconstant, /**< constant d in x <= b*z + d */
10470 SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
10471 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10472 int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
10473 )
10474{
10475 assert(var != NULL);
10476 assert(set != NULL);
10477 assert(var->scip == set->scip);
10479 assert(infeasible != NULL);
10480
10481 SCIPsetDebugMsg(set, "adding variable upper bound <%s> <= %g<%s> + %g\n", SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
10482
10483 *infeasible = FALSE;
10484 if( nbdchgs != NULL )
10485 *nbdchgs = 0;
10486
10487 switch( SCIPvarGetStatus(var) )
10488 {
10491 SCIP_CALL( SCIPvarAddVub(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10492 cliquetable, branchcand, eventqueue, vubvar, vubcoef, vubconstant, transitive, infeasible, nbdchgs) );
10493 break;
10494
10498 /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
10500 SCIPsetDebugMsg(set, " -> transformed to variable upper bound <%s> <= %g<%s> + %g\n",
10502
10503 /* if the vub coefficient is zero, just update the upper bound of the variable */
10504 if( SCIPsetIsZero(set, vubcoef) )
10505 {
10507 *infeasible = TRUE;
10509 {
10510 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10511 * with the local bound, in this case we need to store the bound change as pending bound change
10512 */
10514 {
10515 assert(tree != NULL);
10516 assert(transprob != NULL);
10517 assert(SCIPprobIsTransformed(transprob));
10518
10519 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10520 tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vubconstant, SCIP_BOUNDTYPE_UPPER, FALSE) );
10521 }
10522 else
10523 {
10524 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vubconstant) );
10525 }
10526
10527 if( nbdchgs != NULL )
10528 (*nbdchgs)++;
10529 }
10530 }
10531 else if( var == vubvar )
10532 {
10533 /* the variables cancels out, the variable bound constraint is either redundant or proves global infeasibility */
10534 if( SCIPsetIsEQ(set, vubcoef, 1.0) )
10535 {
10537 *infeasible = TRUE;
10538 return SCIP_OKAY;
10539 }
10540 else
10541 {
10542 SCIP_Real lb = SCIPvarGetLbGlobal(var);
10543 SCIP_Real ub = SCIPvarGetUbGlobal(var);
10544
10545 /* the variable bound constraint defines a new lower bound */
10546 if( SCIPsetIsGT(set, vubcoef, 1.0) )
10547 {
10548 SCIP_Real newlb = vubconstant / (1.0 - vubcoef);
10549
10550 if( SCIPsetIsFeasGT(set, newlb, ub) )
10551 {
10552 *infeasible = TRUE;
10553 return SCIP_OKAY;
10554 }
10555 else if( SCIPsetIsFeasGT(set, newlb, lb) )
10556 {
10557 /* bound might be adjusted due to integrality condition */
10559
10560 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10561 * with the local bound, in this case we need to store the bound change as pending bound change
10562 */
10564 {
10565 assert(tree != NULL);
10566 assert(transprob != NULL);
10567 assert(SCIPprobIsTransformed(transprob));
10568
10569 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10570 tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10571 }
10572 else
10573 {
10574 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newlb) );
10575 }
10576
10577 if( nbdchgs != NULL )
10578 (*nbdchgs)++;
10579 }
10580 }
10581 /* the variable bound constraint defines a new upper bound */
10582 else
10583 {
10584 SCIP_Real newub;
10585
10586 assert(SCIPsetIsLT(set, vubcoef, 1.0));
10587
10588 newub = vubconstant / (1.0 - vubcoef);
10589
10590 if( SCIPsetIsFeasLT(set, newub, lb) )
10591 {
10592 *infeasible = TRUE;
10593 return SCIP_OKAY;
10594 }
10595 else if( SCIPsetIsFeasLT(set, newub, ub) )
10596 {
10597 /* bound might be adjusted due to integrality condition */
10599
10600 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10601 * with the local bound, in this case we need to store the bound change as pending bound change
10602 */
10604 {
10605 assert(tree != NULL);
10606 assert(transprob != NULL);
10607 assert(SCIPprobIsTransformed(transprob));
10608
10609 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10610 tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10611 }
10612 else
10613 {
10614 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newub) );
10615 }
10616
10617 if( nbdchgs != NULL )
10618 (*nbdchgs)++;
10619 }
10620 }
10621 }
10622 }
10623 else if( SCIPvarIsActive(vubvar) )
10624 {
10625 SCIP_Real xlb;
10626 SCIP_Real xub;
10627 SCIP_Real zlb;
10628 SCIP_Real zub;
10629 SCIP_Real minvub;
10630 SCIP_Real maxvub;
10631
10633 assert(vubcoef != 0.0);
10634
10637
10642
10643 /* improve global bounds of vub variable, and calculate minimal and maximal value of variable bound */
10644 if( vubcoef >= 0.0 )
10645 {
10646 SCIP_Real newzlb;
10647
10648 if( !SCIPsetIsInfinity(set, -xlb) )
10649 {
10650 /* x <= b*z + d -> z >= (x-d)/b */
10652 if( SCIPsetIsFeasGT(set, newzlb, zub) )
10653 {
10654 *infeasible = TRUE;
10655 return SCIP_OKAY;
10656 }
10657 if( SCIPsetIsFeasGT(set, newzlb, zlb) )
10658 {
10659 /* bound might be adjusted due to integrality condition */
10661
10662 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10663 * with the local bound, in this case we need to store the bound change as pending bound change
10664 */
10666 {
10667 assert(tree != NULL);
10668 assert(transprob != NULL);
10669 assert(SCIPprobIsTransformed(transprob));
10670
10671 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10672 tree, reopt, lp, branchcand, eventqueue, cliquetable, vubvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10673 }
10674 else
10675 {
10676 SCIP_CALL( SCIPvarChgLbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
10677 }
10678 zlb = newzlb;
10679
10680 if( nbdchgs != NULL )
10681 (*nbdchgs)++;
10682 }
10684 if( !SCIPsetIsInfinity(set, zub) )
10686 }
10687 else
10688 {
10689 if( !SCIPsetIsInfinity(set, zub) )
10691 if( !SCIPsetIsInfinity(set, -zlb) )
10693 }
10694 }
10695 else
10696 {
10697 SCIP_Real newzub;
10698
10699 if( !SCIPsetIsInfinity(set, -xlb) )
10700 {
10701 /* x <= b*z + d -> z <= (x-d)/b */
10703 if( SCIPsetIsFeasLT(set, newzub, zlb) )
10704 {
10705 *infeasible = TRUE;
10706 return SCIP_OKAY;
10707 }
10708 if( SCIPsetIsFeasLT(set, newzub, zub) )
10709 {
10710 /* bound might be adjusted due to integrality condition */
10712
10713 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10714 * with the local bound, in this case we need to store the bound change as pending bound change
10715 */
10717 {
10718 assert(tree != NULL);
10719 assert(transprob != NULL);
10720 assert(SCIPprobIsTransformed(transprob));
10721
10722 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10723 tree, reopt, lp, branchcand, eventqueue, cliquetable, vubvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10724 }
10725 else
10726 {
10727 SCIP_CALL( SCIPvarChgUbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
10728 }
10729 zub = newzub;
10730
10731 if( nbdchgs != NULL )
10732 (*nbdchgs)++;
10733 }
10735 if( !SCIPsetIsInfinity(set, -zlb) )
10737 }
10738 else
10739 {
10740 if( !SCIPsetIsInfinity(set, zub) )
10742 if( !SCIPsetIsInfinity(set, -zlb) )
10744 }
10745 }
10746 if( minvub > maxvub )
10747 minvub = maxvub;
10748
10749 /* adjust bounds due to integrality of vub variable */
10752
10753 /* check bounds for feasibility */
10755 {
10756 *infeasible = TRUE;
10757 return SCIP_OKAY;
10758 }
10759
10760 /* improve global upper bound of variable */
10761 if( SCIPsetIsFeasLT(set, maxvub, xub) )
10762 {
10763 /* bound might be adjusted due to integrality condition */
10765
10766 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10767 * with the local bound, in this case we need to store the bound change as pending bound change
10768 */
10770 {
10771 assert(tree != NULL);
10772 assert(transprob != NULL);
10773 assert(SCIPprobIsTransformed(transprob));
10774
10775 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10776 tree, reopt, lp, branchcand, eventqueue, cliquetable, var, maxvub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10777 }
10778 else
10779 {
10780 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, maxvub) );
10781 }
10782 xub = maxvub;
10783
10784 if( nbdchgs != NULL )
10785 (*nbdchgs)++;
10786 }
10787 maxvub = xub;
10788
10789 /* improve variable bound for binary z by moving the variable's global bound to the vub constant */
10790 if( SCIPvarIsBinary(vubvar) )
10791 {
10792 /* b > 0: x <= (maxvub - minvub) * z + minvub
10793 * b < 0: x <= (minvub - maxvub) * z + maxvub
10794 */
10795
10797
10798 if( vubcoef >= 0.0 )
10799 {
10800 vubcoef = maxvub - minvub;
10802 }
10803 else
10804 {
10805 vubcoef = minvub - maxvub;
10807 }
10808 }
10809
10810 /* add variable bound to the variable bounds list */
10811 if( SCIPsetIsFeasLT(set, minvub, xub) )
10812 {
10815
10816 /* if one of the variables is binary, add the corresponding implication to the variable's implication
10817 * list, thereby also adding the variable bound (or implication) to the other variable
10818 */
10820 {
10821 /* add corresponding implication:
10822 * b > 0, x <= b*z + d <-> z == 0 -> x <= d
10823 * b < 0, x <= b*z + d <-> z == 1 -> x <= b+d
10824 */
10825 SCIP_CALL( varAddTransitiveImplic(vubvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10826 cliquetable, branchcand, eventqueue, (vubcoef < 0.0), var, SCIP_BOUNDTYPE_UPPER, minvub, transitive,
10827 infeasible, nbdchgs) );
10828 }
10830 {
10831 /* add corresponding implication:
10832 * b > 0, x <= b*z + d <-> x == 1 -> z >= (1-d)/b
10833 * b < 0, x <= b*z + d <-> x == 1 -> z <= (1-d)/b
10834 */
10835 SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10836 cliquetable, branchcand, eventqueue, TRUE, vubvar, (vubcoef >= 0.0 ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER),
10837 (1.0-vubconstant)/vubcoef, transitive, infeasible, nbdchgs) );
10838 }
10839 else
10840 {
10842 }
10843 }
10844 }
10845 break;
10846
10848 /* x = a*y + c: x <= b*z + d <=> a*y + c <= b*z + d <=> y <= b/a * z + (d-c)/a, if a > 0
10849 * y >= b/a * z + (d-c)/a, if a < 0
10850 */
10853 {
10854 /* a > 0 -> add variable upper bound */
10855 SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10856 cliquetable, branchcand, eventqueue, vubvar, vubcoef/var->data.aggregate.scalar,
10857 (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10858 }
10860 {
10861 /* a < 0 -> add variable lower bound */
10862 SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10863 cliquetable, branchcand, eventqueue, vubvar, vubcoef/var->data.aggregate.scalar,
10864 (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10865 }
10866 else
10867 {
10868 SCIPerrorMessage("scalar is zero in aggregation\n");
10869 return SCIP_INVALIDDATA;
10870 }
10871 break;
10872
10874 /* nothing to do here */
10875 break;
10876
10878 /* x = offset - x': x <= b*z + d <=> offset - x' <= b*z + d <=> x' >= -b*z + (offset-d) */
10882 SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10883 branchcand, eventqueue, vubvar, -vubcoef, var->data.negate.constant - vubconstant, transitive, infeasible,
10884 nbdchgs) );
10885 break;
10886
10887 default:
10888 SCIPerrorMessage("unknown variable status\n");
10889 return SCIP_INVALIDDATA;
10890 }
10891
10892 return SCIP_OKAY;
10893}
10894
10895/** informs binary variable x about a globally valid implication: x == 0 or x == 1 ==> y <= b or y >= b;
10896 * also adds the corresponding implication or variable bound to the implied variable;
10897 * if the implication is conflicting, the variable is fixed to the opposite value;
10898 * if the variable is already fixed to the given value, the implication is performed immediately;
10899 * if the implication is redundant with respect to the variables' global bounds, it is ignored
10900 */
10902 SCIP_VAR* var, /**< problem variable */
10903 BMS_BLKMEM* blkmem, /**< block memory */
10904 SCIP_SET* set, /**< global SCIP settings */
10905 SCIP_STAT* stat, /**< problem statistics */
10906 SCIP_PROB* transprob, /**< transformed problem */
10907 SCIP_PROB* origprob, /**< original problem */
10908 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10909 SCIP_REOPT* reopt, /**< reoptimization data structure */
10910 SCIP_LP* lp, /**< current LP data */
10911 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10912 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10913 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10914 SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
10915 SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
10916 SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
10917 SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
10918 SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
10919 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10920 int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
10921 )
10922{
10923 assert(var != NULL);
10924 assert(set != NULL);
10925 assert(var->scip == set->scip);
10927 assert(infeasible != NULL);
10928
10929 *infeasible = FALSE;
10930 if( nbdchgs != NULL )
10931 *nbdchgs = 0;
10932
10933 switch( SCIPvarGetStatus(var) )
10934 {
10937 SCIP_CALL( SCIPvarAddImplic(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10938 cliquetable, branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible,
10939 nbdchgs) );
10940 break;
10941
10944 /* if the variable is fixed (although it has no FIXED status), and varfixing corresponds to the fixed value of
10945 * the variable, the implication can be applied directly;
10946 * otherwise, add implication to the implications list (and add inverse of implication to the implied variable)
10947 */
10948 if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
10949 {
10950 if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
10951 {
10952 SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
10953 cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
10954 }
10955 }
10956 else
10957 {
10961 {
10962 SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10963 branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
10964 }
10965 }
10966 break;
10967
10969 /* if varfixing corresponds to the fixed value of the variable, the implication can be applied directly */
10970 if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
10971 {
10972 SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
10973 cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
10974 }
10975 break;
10976
10978 /* implication added for x == 1:
10979 * x == 1 && x = 1*z + 0 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10980 * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10981 * implication added for x == 0:
10982 * x == 0 && x = 1*z + 0 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10983 * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10984 *
10985 * use only binary variables z
10986 */
10989 {
10992
10993 if( var->data.aggregate.scalar > 0 )
10994 {
10995 SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10996 cliquetable, branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible,
10997 nbdchgs) );
10998 }
10999 else
11000 {
11001 SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11002 cliquetable, branchcand, eventqueue, !varfixing, implvar, impltype, implbound, transitive, infeasible,
11003 nbdchgs) );
11004 }
11005 }
11006 break;
11007
11009 /* nothing to do here */
11010 break;
11011
11013 /* implication added for x == 1:
11014 * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
11015 * implication added for x == 0:
11016 * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
11017 */
11022
11024 {
11025 SCIP_CALL( SCIPvarAddImplic(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11026 cliquetable, branchcand, eventqueue, !varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
11027 }
11028 /* in case one both variables are not of binary type we have to add the implication as variable bounds */
11029 else
11030 {
11031 /* if the implied variable is of binary type exchange the variables */
11033 {
11034 SCIP_CALL( SCIPvarAddImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
11035 branchcand, eventqueue, (impltype == SCIP_BOUNDTYPE_UPPER) ? TRUE : FALSE, var->negatedvar,
11037 infeasible, nbdchgs) );
11038 }
11039 else
11040 {
11041 /* both variables are not of binary type but are implicit binary; in that case we can only add this
11042 * implication as variable bounds
11043 */
11044
11045 /* add variable lower bound on the negation of var */
11046 if( varfixing )
11047 {
11048 /* (x = 1 => i) z = 0 ii) z = 1) <=> ( i) z = 1 ii) z = 0 => ~x = 1), this is done by adding ~x >= b*z + d
11049 * as variable lower bound
11050 */
11051 SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11052 cliquetable, branchcand, eventqueue, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : -1.0,
11053 (impltype == SCIP_BOUNDTYPE_UPPER) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
11054 }
11055 else
11056 {
11057 /* (x = 0 => i) z = 0 ii) z = 1) <=> ( i) z = 1 ii) z = 0 => ~x = 0), this is done by adding ~x <= b*z + d
11058 * as variable upper bound
11059 */
11060 SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11061 cliquetable, branchcand, eventqueue, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? -1.0 : 1.0,
11062 (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : 0.0, transitive, infeasible, nbdchgs) );
11063 }
11064
11065 /* add variable bound on implvar */
11067 {
11068 /* (z = 1 => i) x = 0 ii) x = 1) <=> ( i) ~x = 0 ii) ~x = 1 => z = 0), this is done by adding z <= b*~x + d
11069 * as variable upper bound
11070 */
11071 SCIP_CALL( SCIPvarAddVub(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
11072 branchcand, eventqueue, var->negatedvar, (varfixing) ? 1.0 : -1.0,
11073 (varfixing) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
11074 }
11075 else
11076 {
11077 /* (z = 0 => i) x = 0 ii) x = 1) <=> ( i) ~x = 0 ii) ~x = 1 => z = 1), this is done by adding z >= b*~x + d
11078 * as variable upper bound
11079 */
11080 SCIP_CALL( SCIPvarAddVlb(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
11081 branchcand, eventqueue, var->negatedvar, (varfixing) ? -1.0 : 1.0, (varfixing) ? 1.0 : 0.0,
11082 transitive, infeasible, nbdchgs) );
11083 }
11084 }
11085 }
11086 break;
11087
11088 default:
11089 SCIPerrorMessage("unknown variable status\n");
11090 return SCIP_INVALIDDATA;
11091 }
11092
11093 return SCIP_OKAY;
11094}
11095
11096/** returns whether there is an implication x == varfixing -> y <= b or y >= b in the implication graph;
11097 * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
11098 * both variables must be active, variable x must be binary
11099 */
11101 SCIP_VAR* var, /**< problem variable x */
11102 SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
11103 SCIP_VAR* implvar, /**< variable y to search for */
11104 SCIP_BOUNDTYPE impltype /**< type of implication y <=/>= b to search for */
11105 )
11106{
11107 assert(var != NULL);
11108 assert(implvar != NULL);
11112
11114}
11115
11116/** returns whether there is an implication x == varfixing -> y == implvarfixing in the implication graph;
11117 * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
11118 * both variables must be active binary variables
11119 */
11121 SCIP_VAR* var, /**< problem variable x */
11122 SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
11123 SCIP_VAR* implvar, /**< variable y to search for */
11124 SCIP_Bool implvarfixing /**< value of the implied variable to search for */
11125 )
11126{
11128
11130}
11131
11132/** gets the values of b in implications x == varfixing -> y <= b or y >= b in the implication graph;
11133 * the values are set to SCIP_INVALID if there is no implied bound
11134 */
11136 SCIP_VAR* var, /**< problem variable x */
11137 SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
11138 SCIP_VAR* implvar, /**< variable y to search for */
11139 SCIP_Real* lb, /**< buffer to store the value of the implied lower bound */
11140 SCIP_Real* ub /**< buffer to store the value of the implied upper bound */
11141 )
11142{
11143 int lowerpos;
11144 int upperpos;
11145 SCIP_Real* bounds;
11146
11147 assert(lb != NULL);
11148 assert(ub != NULL);
11149
11150 *lb = SCIP_INVALID;
11151 *ub = SCIP_INVALID;
11152
11153 if( var->implics == NULL )
11154 return;
11155
11158
11159 if( bounds == NULL )
11160 return;
11161
11162 if( lowerpos >= 0 )
11163 *lb = bounds[lowerpos];
11164
11165 if( upperpos >= 0 )
11166 *ub = bounds[upperpos];
11167}
11168
11169
11170/** fixes the bounds of a binary variable to the given value, counting bound changes and detecting infeasibility */
11172 SCIP_VAR* var, /**< problem variable */
11173 BMS_BLKMEM* blkmem, /**< block memory */
11174 SCIP_SET* set, /**< global SCIP settings */
11175 SCIP_STAT* stat, /**< problem statistics */
11176 SCIP_PROB* transprob, /**< transformed problem */
11177 SCIP_PROB* origprob, /**< original problem */
11178 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
11179 SCIP_REOPT* reopt, /**< reoptimization data structure */
11180 SCIP_LP* lp, /**< current LP data */
11181 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
11182 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
11183 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11184 SCIP_Bool value, /**< value to fix variable to */
11185 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
11186 int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
11187 )
11188{
11189 assert(var != NULL);
11190 assert(set != NULL);
11191 assert(var->scip == set->scip);
11192 assert(infeasible != NULL);
11193
11194 *infeasible = FALSE;
11195
11196 if( value == FALSE )
11197 {
11198 if( var->glbdom.lb > 0.5 )
11199 *infeasible = TRUE;
11200 else if( var->glbdom.ub > 0.5 )
11201 {
11202 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
11203 * with the local bound, in this case we need to store the bound change as pending bound change
11204 */
11206 {
11207 assert(tree != NULL);
11208 assert(transprob != NULL);
11209 assert(SCIPprobIsTransformed(transprob));
11210
11211 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
11212 tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
11213 }
11214 else
11215 {
11216 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
11217 }
11218
11219 if( nbdchgs != NULL )
11220 (*nbdchgs)++;
11221 }
11222 }
11223 else
11224 {
11225 if( var->glbdom.ub < 0.5 )
11226 *infeasible = TRUE;
11227 else if( var->glbdom.lb < 0.5 )
11228 {
11229 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
11230 * with the local bound, in this case we need to store the bound change as pending bound change
11231 */
11233 {
11234 assert(tree != NULL);
11235 assert(transprob != NULL);
11236 assert(SCIPprobIsTransformed(transprob));
11237
11238 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
11239 tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
11240 }
11241 else
11242 {
11243 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
11244 }
11245
11246 if( nbdchgs != NULL )
11247 (*nbdchgs)++;
11248 }
11249 }
11250
11251 return SCIP_OKAY;
11252}
11253
11254/** adds the variable to the given clique and updates the list of cliques the binary variable is member of;
11255 * if the variable now appears twice in the clique with the same value, it is fixed to the opposite value;
11256 * if the variable now appears twice in the clique with opposite values, all other variables are fixed to
11257 * the opposite of the value they take in the clique
11258 */
11260 SCIP_VAR* var, /**< problem variable */
11261 BMS_BLKMEM* blkmem, /**< block memory */
11262 SCIP_SET* set, /**< global SCIP settings */
11263 SCIP_STAT* stat, /**< problem statistics */
11264 SCIP_PROB* transprob, /**< transformed problem */
11265 SCIP_PROB* origprob, /**< original problem */
11266 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
11267 SCIP_REOPT* reopt, /**< reoptimization data structure */
11268 SCIP_LP* lp, /**< current LP data */
11269 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
11270 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
11271 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11272 SCIP_Bool value, /**< value of the variable in the clique */
11273 SCIP_CLIQUE* clique, /**< clique the variable should be added to */
11274 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
11275 int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
11276 )
11277{
11278 assert(var != NULL);
11279 assert(set != NULL);
11280 assert(var->scip == set->scip);
11282 assert(infeasible != NULL);
11283
11284 *infeasible = FALSE;
11285
11286 /* get corresponding active problem variable */
11293
11294 /* only column and loose variables may be member of a clique */
11296 {
11297 SCIP_Bool doubleentry;
11298 SCIP_Bool oppositeentry;
11299
11300 /* add variable to clique */
11301 SCIP_CALL( SCIPcliqueAddVar(clique, blkmem, set, var, value, &doubleentry, &oppositeentry) );
11302
11303 /* add clique to variable's clique list */
11304 SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
11305
11306 /* check consistency of cliquelist */
11308
11309 /* if the variable now appears twice with the same value in the clique, it can be fixed to the opposite value */
11310 if( doubleentry )
11311 {
11312 SCIP_CALL( SCIPvarFixBinary(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
11313 eventqueue, cliquetable, !value, infeasible, nbdchgs) );
11314 }
11315
11316 /* if the variable appears with both values in the clique, all other variables of the clique can be fixed
11317 * to the opposite of the value they take in the clique
11318 */
11319 if( oppositeentry )
11320 {
11321 SCIP_VAR** vars;
11322 SCIP_Bool* values;
11323 int nvars;
11324 int i;
11325
11326 nvars = SCIPcliqueGetNVars(clique);
11327 vars = SCIPcliqueGetVars(clique);
11328 values = SCIPcliqueGetValues(clique);
11329 for( i = 0; i < nvars && !(*infeasible); ++i )
11330 {
11331 if( vars[i] == var )
11332 continue;
11333
11334 SCIP_CALL( SCIPvarFixBinary(vars[i], blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
11335 eventqueue, cliquetable, !values[i], infeasible, nbdchgs) );
11336 }
11337 }
11338 }
11339
11340 return SCIP_OKAY;
11341}
11342
11343/** adds a filled clique to the cliquelists of all corresponding variables */
11345 SCIP_VAR** vars, /**< problem variables */
11346 SCIP_Bool* values, /**< values of the variables in the clique */
11347 int nvars, /**< number of problem variables */
11348 BMS_BLKMEM* blkmem, /**< block memory */
11349 SCIP_SET* set, /**< global SCIP settings */
11350 SCIP_CLIQUE* clique /**< clique that contains all given variables and values */
11351 )
11352{
11353 SCIP_VAR* var;
11354 int v;
11355
11356 assert(vars != NULL);
11357 assert(values != NULL);
11358 assert(nvars > 0);
11359 assert(set != NULL);
11360 assert(blkmem != NULL);
11361 assert(clique != NULL);
11362
11363 for( v = nvars - 1; v >= 0; --v )
11364 {
11365 var = vars[v];
11368
11369 /* add clique to variable's clique list */
11370 SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, values[v], clique) );
11371
11372 /* check consistency of cliquelist */
11374 }
11375
11376 return SCIP_OKAY;
11377}
11378
11379/** adds a clique to the list of cliques of the given binary variable, but does not change the clique
11380 * itself
11381 */
11383 SCIP_VAR* var, /**< problem variable */
11384 BMS_BLKMEM* blkmem, /**< block memory */
11385 SCIP_SET* set, /**< global SCIP settings */
11386 SCIP_Bool value, /**< value of the variable in the clique */
11387 SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
11388 )
11389{
11390 assert(var != NULL);
11393
11394 /* add clique to variable's clique list */
11395 SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
11396
11397 return SCIP_OKAY;
11398}
11399
11400
11401/** deletes a clique from the list of cliques the binary variable is member of, but does not change the clique
11402 * itself
11403 */
11405 SCIP_VAR* var, /**< problem variable */
11406 BMS_BLKMEM* blkmem, /**< block memory */
11407 SCIP_Bool value, /**< value of the variable in the clique */
11408 SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
11409 )
11410{
11411 assert(var != NULL);
11413
11414 /* delete clique from variable's clique list */
11415 SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
11416
11417 return SCIP_OKAY;
11418}
11419
11420/** deletes the variable from the given clique and updates the list of cliques the binary variable is member of */
11422 SCIP_VAR* var, /**< problem variable */
11423 BMS_BLKMEM* blkmem, /**< block memory */
11424 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11425 SCIP_Bool value, /**< value of the variable in the clique */
11426 SCIP_CLIQUE* clique /**< clique the variable should be removed from */
11427 )
11428{
11429 assert(var != NULL);
11431
11432 /* get corresponding active problem variable */
11439
11440 /* only column and loose variables may be member of a clique */
11442 {
11443 /* delete clique from variable's clique list */
11444 SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
11445
11446 /* delete variable from clique */
11447 SCIPcliqueDelVar(clique, cliquetable, var, value);
11448
11449 /* check consistency of cliquelist */
11451 }
11452
11453 return SCIP_OKAY;
11454}
11455
11456/** returns whether there is a clique that contains both given variable/value pairs;
11457 * the variables must be active binary variables;
11458 * if regardimplics is FALSE, only the cliques in the clique table are looked at;
11459 * if regardimplics is TRUE, both the cliques and the implications of the implication graph are regarded
11460 *
11461 * @note a variable with it's negated variable are NOT! in a clique
11462 * @note a variable with itself are in a clique
11463 */
11465 SCIP_VAR* var1, /**< first variable */
11466 SCIP_Bool value1, /**< value of first variable */
11467 SCIP_VAR* var2, /**< second variable */
11468 SCIP_Bool value2, /**< value of second variable */
11469 SCIP_Bool regardimplics /**< should the implication graph also be searched for a clique? */
11470 )
11471{
11472 assert(var1 != NULL);
11473 assert(var2 != NULL);
11478
11479 return (SCIPcliquelistsHaveCommonClique(var1->cliquelist, value1, var2->cliquelist, value2)
11481}
11482
11483/** actually changes the branch factor of the variable and of all parent variables */
11484static
11486 SCIP_VAR* var, /**< problem variable */
11487 SCIP_SET* set, /**< global SCIP settings */
11488 SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
11489 )
11490{
11492 SCIP_Real eps;
11493 int i;
11494
11495 assert(var != NULL);
11496 assert(set != NULL);
11497 assert(var->scip == set->scip);
11498
11499 /* only use positive values */
11501 branchfactor = MAX(branchfactor, eps);
11502
11503 SCIPsetDebugMsg(set, "process changing branch factor of <%s> from %f to %f\n", var->name, var->branchfactor, branchfactor);
11504
11505 if( SCIPsetIsEQ(set, branchfactor, var->branchfactor) )
11506 return SCIP_OKAY;
11507
11508 /* change the branch factor */
11509 var->branchfactor = branchfactor;
11510
11511 /* process parent variables */
11512 for( i = 0; i < var->nparentvars; ++i )
11513 {
11515 assert(parentvar != NULL);
11516
11517 switch( SCIPvarGetStatus(parentvar) )
11518 {
11520 /* do not change priorities across the border between transformed and original problem */
11521 break;
11522
11527 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11528 SCIPABORT();
11529 return SCIP_INVALIDDATA; /*lint !e527*/
11530
11534 break;
11535
11536 default:
11537 SCIPerrorMessage("unknown variable status\n");
11538 SCIPABORT();
11539 return SCIP_ERROR; /*lint !e527*/
11540 }
11541 }
11542
11543 return SCIP_OKAY;
11544}
11545
11546/** sets the branch factor of the variable; this value can be used in the branching methods to scale the score
11547 * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
11548 */
11550 SCIP_VAR* var, /**< problem variable */
11551 SCIP_SET* set, /**< global SCIP settings */
11552 SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
11553 )
11554{
11555 int v;
11556
11557 assert(var != NULL);
11558 assert(set != NULL);
11559 assert(var->scip == set->scip);
11560 assert(branchfactor >= 0.0);
11561
11562 SCIPdebugMessage("changing branch factor of <%s> from %g to %g\n", var->name, var->branchfactor, branchfactor);
11563
11564 if( SCIPsetIsEQ(set, var->branchfactor, branchfactor) )
11565 return SCIP_OKAY;
11566
11567 /* change priorities of attached variables */
11568 switch( SCIPvarGetStatus(var) )
11569 {
11571 if( var->data.original.transvar != NULL )
11572 {
11574 }
11575 else
11576 {
11577 assert(set->stage == SCIP_STAGE_PROBLEM);
11578 var->branchfactor = branchfactor;
11579 }
11580 break;
11581
11585 SCIP_CALL( varProcessChgBranchFactor(var, set, branchfactor) );
11586 break;
11587
11589 assert(!var->donotaggr);
11592 break;
11593
11596 for( v = 0; v < var->data.multaggr.nvars; ++v )
11597 {
11598 SCIP_CALL( SCIPvarChgBranchFactor(var->data.multaggr.vars[v], set, branchfactor) );
11599 }
11600 break;
11601
11607 break;
11608
11609 default:
11610 SCIPerrorMessage("unknown variable status\n");
11611 SCIPABORT();
11612 return SCIP_ERROR; /*lint !e527*/
11613 }
11614
11615 return SCIP_OKAY;
11616}
11617
11618/** actually changes the branch priority of the variable and of all parent variables */
11619static
11621 SCIP_VAR* var, /**< problem variable */
11622 int branchpriority /**< branching priority of the variable */
11623 )
11624{
11626 int i;
11627
11628 assert(var != NULL);
11629
11630 SCIPdebugMessage("process changing branch priority of <%s> from %d to %d\n",
11631 var->name, var->branchpriority, branchpriority);
11632
11633 if( branchpriority == var->branchpriority )
11634 return SCIP_OKAY;
11635
11636 /* change the branch priority */
11637 var->branchpriority = branchpriority;
11638
11639 /* process parent variables */
11640 for( i = 0; i < var->nparentvars; ++i )
11641 {
11643 assert(parentvar != NULL);
11644
11645 switch( SCIPvarGetStatus(parentvar) )
11646 {
11648 /* do not change priorities across the border between transformed and original problem */
11649 break;
11650
11655 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11656 SCIPABORT();
11657 return SCIP_INVALIDDATA; /*lint !e527*/
11658
11662 break;
11663
11664 default:
11665 SCIPerrorMessage("unknown variable status\n");
11666 return SCIP_ERROR;
11667 }
11668 }
11669
11670 return SCIP_OKAY;
11671}
11672
11673/** sets the branch priority of the variable; variables with higher branch priority are always preferred to variables
11674 * with lower priority in selection of branching variable
11675 */
11677 SCIP_VAR* var, /**< problem variable */
11678 int branchpriority /**< branching priority of the variable */
11679 )
11680{
11681 int v;
11682
11683 assert(var != NULL);
11684
11685 SCIPdebugMessage("changing branch priority of <%s> from %d to %d\n", var->name, var->branchpriority, branchpriority);
11686
11687 if( var->branchpriority == branchpriority )
11688 return SCIP_OKAY;
11689
11690 /* change priorities of attached variables */
11691 switch( SCIPvarGetStatus(var) )
11692 {
11694 if( var->data.original.transvar != NULL )
11695 {
11697 }
11698 else
11699 var->branchpriority = branchpriority;
11700 break;
11701
11705 SCIP_CALL( varProcessChgBranchPriority(var, branchpriority) );
11706 break;
11707
11709 assert(!var->donotaggr);
11712 break;
11713
11716 for( v = 0; v < var->data.multaggr.nvars; ++v )
11717 {
11718 SCIP_CALL( SCIPvarChgBranchPriority(var->data.multaggr.vars[v], branchpriority) );
11719 }
11720 break;
11721
11726 SCIP_CALL( SCIPvarChgBranchPriority(var->negatedvar, branchpriority) );
11727 break;
11728
11729 default:
11730 SCIPerrorMessage("unknown variable status\n");
11731 SCIPABORT();
11732 return SCIP_ERROR; /*lint !e527*/
11733 }
11734
11735 return SCIP_OKAY;
11736}
11737
11738/** actually changes the branch direction of the variable and of all parent variables */
11739static
11741 SCIP_VAR* var, /**< problem variable */
11742 SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
11743 )
11744{
11746 int i;
11747
11748 assert(var != NULL);
11749
11750 SCIPdebugMessage("process changing branch direction of <%s> from %u to %d\n",
11751 var->name, var->branchdirection, branchdirection);
11752
11753 if( branchdirection == (SCIP_BRANCHDIR)var->branchdirection )
11754 return SCIP_OKAY;
11755
11756 /* change the branch direction */
11757 var->branchdirection = branchdirection; /*lint !e641*/
11758
11759 /* process parent variables */
11760 for( i = 0; i < var->nparentvars; ++i )
11761 {
11763 assert(parentvar != NULL);
11764
11765 switch( SCIPvarGetStatus(parentvar) )
11766 {
11768 /* do not change directions across the border between transformed and original problem */
11769 break;
11770
11775 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11776 SCIPABORT();
11777 return SCIP_INVALIDDATA; /*lint !e527*/
11778
11780 if( parentvar->data.aggregate.scalar > 0.0 )
11781 {
11783 }
11784 else
11785 {
11787 }
11788 break;
11789
11792 break;
11793
11794 default:
11795 SCIPerrorMessage("unknown variable status\n");
11796 SCIPABORT();
11797 return SCIP_ERROR; /*lint !e527*/
11798 }
11799 }
11800
11801 return SCIP_OKAY;
11802}
11803
11804/** sets the branch direction of the variable; variables with higher branch direction are always preferred to variables
11805 * with lower direction in selection of branching variable
11806 */
11808 SCIP_VAR* var, /**< problem variable */
11809 SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
11810 )
11811{
11812 int v;
11813
11814 assert(var != NULL);
11815
11816 SCIPdebugMessage("changing branch direction of <%s> from %u to %d\n", var->name, var->branchdirection, branchdirection);
11817
11818 if( (SCIP_BRANCHDIR)var->branchdirection == branchdirection )
11819 return SCIP_OKAY;
11820
11821 /* change directions of attached variables */
11822 switch( SCIPvarGetStatus(var) )
11823 {
11825 if( var->data.original.transvar != NULL )
11826 {
11828 }
11829 else
11830 var->branchdirection = branchdirection; /*lint !e641*/
11831 break;
11832
11836 SCIP_CALL( varProcessChgBranchDirection(var, branchdirection) );
11837 break;
11838
11840 assert(!var->donotaggr);
11842 if( var->data.aggregate.scalar > 0.0 )
11843 {
11845 }
11846 else
11847 {
11849 }
11850 break;
11851
11854 for( v = 0; v < var->data.multaggr.nvars; ++v )
11855 {
11856 /* only update branching direction of aggregation variables, if they don't have a preferred direction yet */
11857 assert(var->data.multaggr.vars[v] != NULL);
11859 {
11860 if( var->data.multaggr.scalars[v] > 0.0 )
11861 {
11862 SCIP_CALL( SCIPvarChgBranchDirection(var->data.multaggr.vars[v], branchdirection) );
11863 }
11864 else
11865 {
11867 }
11868 }
11869 }
11870 break;
11871
11877 break;
11878
11879 default:
11880 SCIPerrorMessage("unknown variable status\n");
11881 SCIPABORT();
11882 return SCIP_ERROR; /*lint !e527*/
11883 }
11884
11885 return SCIP_OKAY;
11886}
11887
11888/** compares the index of two variables, only active, fixed or negated variables are allowed, if a variable
11889 * is negated then the index of the corresponding active variable is taken, returns -1 if first is
11890 * smaller than, and +1 if first is greater than second variable index; returns 0 if both indices
11891 * are equal, which means both variables are equal
11892 */
11894 SCIP_VAR* var1, /**< first problem variable */
11895 SCIP_VAR* var2 /**< second problem variable */
11896 )
11897{
11898 assert(var1 != NULL);
11899 assert(var2 != NULL);
11902
11907
11908 assert(var1 != NULL);
11909 assert(var2 != NULL);
11910
11912 return -1;
11914 return +1;
11915
11916 assert(var1 == var2);
11917 return 0;
11918}
11919
11920/** comparison method for sorting active and negated variables by non-decreasing index, active and negated
11921 * variables are handled as the same variables
11922 */
11927
11928/** compares the index of two variables, returns -1 if first is smaller than, and +1 if first is greater than second
11929 * variable index; returns 0 if both indices are equal, which means both variables are equal
11930 */
11932 SCIP_VAR* var1, /**< first problem variable */
11933 SCIP_VAR* var2 /**< second problem variable */
11934 )
11935{
11936 assert(var1 != NULL);
11937 assert(var2 != NULL);
11938
11939 if( var1->index < var2->index )
11940 return -1;
11941 else if( var1->index > var2->index )
11942 return +1;
11943 else
11944 {
11945 assert(var1 == var2);
11946 return 0;
11947 }
11948}
11949
11950/** comparison method for sorting variables by non-decreasing index */
11955
11956/** comparison method for sorting variables by non-decreasing objective coefficient */
11958{
11959 SCIP_Real obj1;
11960 SCIP_Real obj2;
11961
11964
11965 if( obj1 < obj2 )
11966 return -1;
11967 else if( obj1 > obj2 )
11968 return +1;
11969 else
11970 return 0;
11971}
11972
11973/** hash key retrieval function for variables */
11975{ /*lint --e{715}*/
11976 return elem;
11977}
11978
11979/** returns TRUE iff the indices of both variables are equal */
11981{ /*lint --e{715}*/
11982 if( key1 == key2 )
11983 return TRUE;
11984 return FALSE;
11985}
11986
11987/** returns the hash value of the key */
11989{ /*lint --e{715}*/
11990 assert( SCIPvarGetIndex((SCIP_VAR*) key) >= 0 );
11991 return (unsigned int) SCIPvarGetIndex((SCIP_VAR*) key);
11992}
11993
11994/** return for given variables all their active counterparts; all active variables will be pairwise different */
11996 SCIP_SET* set, /**< global SCIP settings */
11997 SCIP_VAR** vars, /**< variable array with given variables and as output all active
11998 * variables, if enough slots exist
11999 */
12000 int* nvars, /**< number of given variables, and as output number of active variables,
12001 * if enough slots exist
12002 */
12003 int varssize, /**< available slots in vars array */
12004 int* requiredsize /**< pointer to store the required array size for the active variables */
12005 )
12006{
12008 int nactivevars;
12009 int activevarssize;
12010
12011 SCIP_VAR* var;
12012 int v;
12013
12014 SCIP_VAR** tmpvars;
12016 int tmpvarssize;
12017 int ntmpvars;
12018 int noldtmpvars;
12019 int nmultvars;
12020
12021 assert(set != NULL);
12022 assert(nvars != NULL);
12023 assert(vars != NULL || *nvars == 0);
12024 assert(varssize >= *nvars);
12026
12027 *requiredsize = 0;
12028
12029 if( *nvars == 0 )
12030 return SCIP_OKAY;
12031
12032 nactivevars = 0;
12034 ntmpvars = *nvars;
12035 tmpvarssize = *nvars;
12036
12037 /* temporary memory */
12039 /* coverity[copy_paste_error] */
12041
12043
12044 /* sort all variables to combine equal variables easily */
12045 SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
12046 for( v = ntmpvars - 1; v > 0; --v )
12047 {
12048 /* combine same variables */
12049 if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
12050 {
12051 --ntmpvars;
12052 tmpvars[v] = tmpvars[ntmpvars];
12053 }
12054 }
12055 /* sort all variables again to combine equal variables later on */
12056 if( noldtmpvars > ntmpvars )
12057 SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
12058
12059 /* collect for each variable the representation in active variables */
12060 while( ntmpvars >= 1 )
12061 {
12062 --ntmpvars;
12063 var = tmpvars[ntmpvars];
12064 assert( var != NULL );
12065
12066 switch( SCIPvarGetStatus(var) )
12067 {
12069 if( var->data.original.transvar == NULL )
12070 {
12071 SCIPerrorMessage("original variable has no transformed variable attached\n");
12072 SCIPABORT();
12073 return SCIP_INVALIDDATA; /*lint !e527*/
12074 }
12075 tmpvars[ntmpvars] = var->data.original.transvar;
12076 ++ntmpvars;
12077 break;
12078
12080 tmpvars[ntmpvars] = var->data.aggregate.var;
12081 ++ntmpvars;
12082 break;
12083
12085 tmpvars[ntmpvars] = var->negatedvar;
12086 ++ntmpvars;
12087 break;
12088
12091 /* check for space in temporary memory */
12093 {
12094 activevarssize *= 2;
12097 }
12099 nactivevars++;
12100 break;
12101
12103 /* x = a_1*y_1 + ... + a_n*y_n + c */
12106
12107 /* check for space in temporary memory */
12109 {
12110 while( nmultvars + ntmpvars > tmpvarssize )
12111 tmpvarssize *= 2;
12114 }
12115
12116 /* copy all multi-aggregation variables into our working array */
12117 BMScopyMemoryArray(&tmpvars[ntmpvars], multvars, nmultvars); /*lint !e866*/
12118
12119 /* get active, fixed or multi-aggregated corresponding variables for all new ones */
12121
12124
12125 /* sort all variables to combine equal variables easily */
12126 SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
12127 for( v = ntmpvars - 1; v > 0; --v )
12128 {
12129 /* combine same variables */
12130 if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
12131 {
12132 --ntmpvars;
12133 tmpvars[v] = tmpvars[ntmpvars];
12134 }
12135 }
12136 /* sort all variables again to combine equal variables later on */
12137 if( noldtmpvars > ntmpvars )
12138 SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
12139
12140 break;
12141
12143 /* no need for memorizing fixed variables */
12144 break;
12145
12146 default:
12147 SCIPerrorMessage("unknown variable status\n");
12148 SCIPABORT();
12149 return SCIP_INVALIDDATA; /*lint !e527*/
12150 }
12151 }
12152
12153 /* sort variable array by variable index */
12155
12156 /* eliminate duplicates and count required size */
12157 v = nactivevars - 1;
12158 while( v > 0 )
12159 {
12160 /* combine both variable since they are the same */
12161 if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
12162 {
12163 --nactivevars;
12165 }
12166 --v;
12167 }
12169
12170 if( varssize >= *requiredsize )
12171 {
12172 assert(vars != NULL);
12173
12174 *nvars = *requiredsize;
12176 }
12177
12178 SCIPsetFreeBufferArray(set, &tmpvars);
12180
12181 return SCIP_OKAY;
12182}
12183
12184/** gets corresponding active, fixed, or multi-aggregated problem variables of given variables,
12185 * @note the content of the given array will/might change
12186 */
12188 SCIP_VAR** vars, /**< array of problem variables */
12189 int nvars /**< number of variables */
12190 )
12191{
12192 int v;
12193
12194 assert(vars != NULL || nvars == 0);
12195
12196 for( v = nvars - 1; v >= 0; --v )
12197 {
12198 assert(vars != NULL);
12199 assert(vars[v] != NULL);
12200
12201 vars[v] = SCIPvarGetProbvar(vars[v]);
12202 assert(vars[v] != NULL);
12203 }
12204}
12205
12206/** gets corresponding active, fixed, or multi-aggregated problem variable of a variable */
12208 SCIP_VAR* var /**< problem variable */
12209 )
12210{
12212
12213 assert(var != NULL);
12214
12215 retvar = var;
12216
12217 SCIPdebugMessage("get problem variable of <%s>\n", var->name);
12218
12219 while( TRUE ) /*lint !e716 */
12220 {
12221 assert(retvar != NULL);
12222
12223 switch( SCIPvarGetStatus(retvar) )
12224 {
12226 if( retvar->data.original.transvar == NULL )
12227 {
12228 SCIPerrorMessage("original variable has no transformed variable attached\n");
12229 SCIPABORT();
12230 return NULL; /*lint !e527 */
12231 }
12232 retvar = retvar->data.original.transvar;
12233 break;
12234
12238 return retvar;
12239
12241 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12242 if ( retvar->data.multaggr.nvars == 1 )
12243 retvar = retvar->data.multaggr.vars[0];
12244 else
12245 return retvar;
12246 break;
12247
12249 retvar = retvar->data.aggregate.var;
12250 break;
12251
12253 retvar = retvar->negatedvar;
12254 break;
12255
12256 default:
12257 SCIPerrorMessage("unknown variable status\n");
12258 SCIPABORT();
12259 return NULL; /*lint !e527*/
12260 }
12261 }
12262}
12263
12264/** gets corresponding active, fixed, or multi-aggregated problem variables of binary variables and updates the given
12265 * negation status of each variable
12266 */
12268 SCIP_VAR*** vars, /**< pointer to binary problem variables */
12269 SCIP_Bool** negatedarr, /**< pointer to corresponding array to update the negation status */
12270 int nvars /**< number of variables and values in vars and negated array */
12271 )
12272{
12273 SCIP_VAR** var;
12274 SCIP_Bool* negated;
12275 int v;
12276
12277 assert(vars != NULL);
12278 assert(*vars != NULL || nvars == 0);
12280 assert(*negatedarr != NULL || nvars == 0);
12281
12282 for( v = nvars - 1; v >= 0; --v )
12283 {
12284 var = &((*vars)[v]);
12285 negated = &((*negatedarr)[v]);
12286
12287 /* get problem variable */
12289 }
12290
12291 return SCIP_OKAY;
12292}
12293
12294
12295/** gets corresponding active, fixed, or multi-aggregated problem variable of a binary variable and updates the given
12296 * negation status (this means you have to assign a value to SCIP_Bool negated before calling this method, usually
12297 * FALSE is used)
12298 */
12300 SCIP_VAR** var, /**< pointer to binary problem variable */
12301 SCIP_Bool* negated /**< pointer to update the negation status */
12302 )
12303{
12304 SCIP_Bool active = FALSE;
12305#ifndef NDEBUG
12306 SCIP_Real constant = 0.0;
12307 SCIP_Bool orignegated;
12308#endif
12309
12310 assert(var != NULL);
12311 assert(*var != NULL);
12312 assert(negated != NULL);
12314
12315#ifndef NDEBUG
12317#endif
12318
12319 while( !active && *var != NULL )
12320 {
12321 switch( SCIPvarGetStatus(*var) )
12322 {
12324 if( (*var)->data.original.transvar == NULL )
12325 return SCIP_OKAY;
12326 *var = (*var)->data.original.transvar;
12327 break;
12328
12332 active = TRUE;
12333 break;
12334
12336 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12337 if ( (*var)->data.multaggr.nvars == 1 )
12338 {
12339 assert( (*var)->data.multaggr.vars != NULL );
12340 assert( (*var)->data.multaggr.scalars != NULL );
12341 assert( SCIPvarIsBinary((*var)->data.multaggr.vars[0]) );
12342 assert(!EPSZ((*var)->data.multaggr.scalars[0], 1e-06));
12343
12344 /* if not all variables were fully propagated, it might happen that a variable is multi-aggregated to
12345 * another variable which needs to be fixed
12346 *
12347 * e.g. x = y - 1 => (x = 0 && y = 1)
12348 * e.g. x = y + 1 => (x = 1 && y = 0)
12349 *
12350 * is this special case we need to return the muti-aggregation
12351 */
12352 if( EPSEQ((*var)->data.multaggr.constant, -1.0, 1e-06) || (EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06) && EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06)) )
12353 {
12354 assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06));
12355 }
12356 else
12357 {
12358 /* @note due to fixations, a multi-aggregation can have a constant of zero and a negative scalar or even
12359 * a scalar in absolute value unequal to one, in this case this aggregation variable needs to be
12360 * fixed to zero, but this should be done by another enforcement; so not depending on the scalar,
12361 * we will return the aggregated variable;
12362 */
12363 if( !EPSEQ(REALABS((*var)->data.multaggr.scalars[0]), 1.0, 1e-06) )
12364 {
12365 active = TRUE;
12366 break;
12367 }
12368
12369 /* @note it may also happen that the constant is larger than 1 or smaller than 0, in that case the
12370 * aggregation variable needs to be fixed to one, but this should be done by another enforcement;
12371 * so if this is the case, we will return the aggregated variable
12372 */
12373 assert(EPSZ((*var)->data.multaggr.constant, 1e-06) || EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06)
12374 || EPSZ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1e-06)
12375 || EPSEQ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1.0, 1e-06));
12376
12377 if( !EPSZ((*var)->data.multaggr.constant, 1e-06) && !EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06) )
12378 {
12379 active = TRUE;
12380 break;
12381 }
12382
12383 assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06) || EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
12384
12385 if( EPSZ((*var)->data.multaggr.constant, 1e-06) )
12386 {
12387 /* if the scalar is negative, either the aggregation variable is already fixed to zero or has at
12388 * least one uplock (that hopefully will enforce this fixation to zero); can it happen that this
12389 * variable itself is multi-aggregated again?
12390 */
12391 assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06) ?
12392 ((SCIPvarGetUbGlobal((*var)->data.multaggr.vars[0]) < 0.5) ||
12393 SCIPvarGetNLocksUpType((*var)->data.multaggr.vars[0], SCIP_LOCKTYPE_MODEL) > 0) : TRUE);
12394 }
12395 else
12396 {
12397 assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
12398#ifndef NDEBUG
12399 constant += (*negated) != orignegated ? -1.0 : 1.0;
12400#endif
12401
12402 *negated = !(*negated);
12403 }
12404 *var = (*var)->data.multaggr.vars[0];
12405 break;
12406 }
12407 }
12408 active = TRUE; /*lint !e838*/
12409 break;
12410
12411 case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
12412 assert((*var)->data.aggregate.var != NULL);
12413 assert(EPSEQ((*var)->data.aggregate.scalar, 1.0, 1e-06) || EPSEQ((*var)->data.aggregate.scalar, -1.0, 1e-06));
12414 assert(EPSLE((*var)->data.aggregate.var->glbdom.ub - (*var)->data.aggregate.var->glbdom.lb, 1.0, 1e-06));
12415#ifndef NDEBUG
12416 constant += (*negated) != orignegated ? -(*var)->data.aggregate.constant : (*var)->data.aggregate.constant;
12417#endif
12418
12419 *negated = ((*var)->data.aggregate.scalar > 0.0) ? *negated : !(*negated);
12420 *var = (*var)->data.aggregate.var;
12421 break;
12422
12423 case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
12424 assert((*var)->negatedvar != NULL);
12425#ifndef NDEBUG
12426 constant += (*negated) != orignegated ? -1.0 : 1.0;
12427#endif
12428
12429 *negated = !(*negated);
12430 *var = (*var)->negatedvar;
12431 break;
12432
12433 default:
12434 SCIPerrorMessage("unknown variable status\n");
12435 return SCIP_INVALIDDATA;
12436 }
12437 }
12438 assert(active == (*var != NULL));
12439
12440 if( active )
12441 {
12443 assert(EPSZ(constant, 1e-06) || EPSEQ(constant, 1.0, 1e-06));
12444 assert(EPSZ(constant, 1e-06) == ((*negated) == orignegated));
12445
12446 return SCIP_OKAY;
12447 }
12448 else
12449 {
12450 SCIPerrorMessage("active variable path leads to NULL pointer\n");
12451 return SCIP_INVALIDDATA;
12452 }
12453}
12454
12455/** transforms given variable, boundtype and bound to the corresponding active, fixed, or multi-aggregated variable
12456 * values
12457 */
12459 SCIP_VAR** var, /**< pointer to problem variable */
12460 SCIP_Real* bound, /**< pointer to bound value to transform */
12461 SCIP_BOUNDTYPE* boundtype /**< pointer to type of bound: lower or upper bound */
12462 )
12463{
12464 assert(var != NULL);
12465 assert(*var != NULL);
12466 assert(bound != NULL);
12467 assert(boundtype != NULL);
12468
12469 SCIPdebugMessage("get probvar bound %g of type %d of variable <%s>\n", *bound, *boundtype, (*var)->name);
12470
12471 switch( SCIPvarGetStatus(*var) )
12472 {
12474 if( (*var)->data.original.transvar == NULL )
12475 {
12476 SCIPerrorMessage("original variable has no transformed variable attached\n");
12477 return SCIP_INVALIDDATA;
12478 }
12479 *var = (*var)->data.original.transvar;
12480 SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12481 break;
12482
12486 break;
12487
12489 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12490 if ( (*var)->data.multaggr.nvars == 1 )
12491 {
12492 assert( (*var)->data.multaggr.vars != NULL );
12493 assert( (*var)->data.multaggr.scalars != NULL );
12494 assert( (*var)->data.multaggr.scalars[0] != 0.0 );
12495
12496 (*bound) /= (*var)->data.multaggr.scalars[0];
12497 (*bound) -= (*var)->data.multaggr.constant/(*var)->data.multaggr.scalars[0];
12498 if ( (*var)->data.multaggr.scalars[0] < 0.0 )
12499 {
12500 if ( *boundtype == SCIP_BOUNDTYPE_LOWER )
12501 *boundtype = SCIP_BOUNDTYPE_UPPER;
12502 else
12503 *boundtype = SCIP_BOUNDTYPE_LOWER;
12504 }
12505 *var = (*var)->data.multaggr.vars[0];
12506 SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12507 }
12508 break;
12509
12510 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
12511 assert((*var)->data.aggregate.var != NULL);
12512 assert((*var)->data.aggregate.scalar != 0.0);
12513
12514 (*bound) /= (*var)->data.aggregate.scalar;
12515 (*bound) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12516 if( (*var)->data.aggregate.scalar < 0.0 )
12517 {
12518 if( *boundtype == SCIP_BOUNDTYPE_LOWER )
12519 *boundtype = SCIP_BOUNDTYPE_UPPER;
12520 else
12521 *boundtype = SCIP_BOUNDTYPE_LOWER;
12522 }
12523 *var = (*var)->data.aggregate.var;
12524 SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12525 break;
12526
12527 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12528 assert((*var)->negatedvar != NULL);
12529 assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12530 assert((*var)->negatedvar->negatedvar == *var);
12531 (*bound) = (*var)->data.negate.constant - *bound;
12532 if( *boundtype == SCIP_BOUNDTYPE_LOWER )
12533 *boundtype = SCIP_BOUNDTYPE_UPPER;
12534 else
12535 *boundtype = SCIP_BOUNDTYPE_LOWER;
12536 *var = (*var)->negatedvar;
12537 SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12538 break;
12539
12540 default:
12541 SCIPerrorMessage("unknown variable status\n");
12542 return SCIP_INVALIDDATA;
12543 }
12544
12545 return SCIP_OKAY;
12546}
12547
12548/** transforms given variable and domain hole to the corresponding active, fixed, or multi-aggregated variable
12549 * values
12550 */
12552 SCIP_VAR** var, /**< pointer to problem variable */
12553 SCIP_Real* left, /**< pointer to left bound of open interval in hole to transform */
12554 SCIP_Real* right /**< pointer to right bound of open interval in hole to transform */
12555 )
12556{
12557 assert(var != NULL);
12558 assert(*var != NULL);
12559 assert(left != NULL);
12560 assert(right != NULL);
12561
12562 SCIPdebugMessage("get probvar hole (%g,%g) of variable <%s>\n", *left, *right, (*var)->name);
12563
12564 switch( SCIPvarGetStatus(*var) )
12565 {
12567 if( (*var)->data.original.transvar == NULL )
12568 {
12569 SCIPerrorMessage("original variable has no transformed variable attached\n");
12570 return SCIP_INVALIDDATA;
12571 }
12572 *var = (*var)->data.original.transvar;
12573 SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
12574 break;
12575
12580 break;
12581
12582 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
12583 assert((*var)->data.aggregate.var != NULL);
12584 assert((*var)->data.aggregate.scalar != 0.0);
12585
12586 /* scale back */
12587 (*left) /= (*var)->data.aggregate.scalar;
12588 (*right) /= (*var)->data.aggregate.scalar;
12589
12590 /* shift back */
12591 (*left) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12592 (*right) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12593
12594 *var = (*var)->data.aggregate.var;
12595
12596 /* check if the interval bounds have to swapped */
12597 if( (*var)->data.aggregate.scalar < 0.0 )
12598 {
12599 SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
12600 }
12601 else
12602 {
12603 SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
12604 }
12605 break;
12606
12607 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12608 assert((*var)->negatedvar != NULL);
12609 assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12610 assert((*var)->negatedvar->negatedvar == *var);
12611
12612 /* shift and scale back */
12613 (*left) = (*var)->data.negate.constant - (*left);
12614 (*right) = (*var)->data.negate.constant - (*right);
12615
12616 *var = (*var)->negatedvar;
12617
12618 /* through the negated variable the left and right interval bound have to swapped */
12619 SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
12620 break;
12621
12622 default:
12623 SCIPerrorMessage("unknown variable status\n");
12624 return SCIP_INVALIDDATA;
12625 }
12626
12627 return SCIP_OKAY;
12628}
12629
12630/** transforms given variable, scalar and constant to the corresponding active, fixed, or
12631 * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed variable,
12632 * "scalar" will be 0.0 and the value of the sum will be stored in "constant"; a multi-aggregation
12633 * with only one active variable (this can happen due to fixings after the multi-aggregation),
12634 * is treated like an aggregation; if the multi-aggregation constant is infinite, "scalar" will be 0.0
12635 */
12637 SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
12638 SCIP_SET* set, /**< global SCIP settings */
12639 SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
12640 SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
12641 )
12642{
12643 assert(var != NULL);
12644 assert(scalar != NULL);
12645 assert(constant != NULL);
12646
12647 while( *var != NULL )
12648 {
12649 switch( SCIPvarGetStatus(*var) )
12650 {
12652 if( (*var)->data.original.transvar == NULL )
12653 {
12654 SCIPerrorMessage("original variable has no transformed variable attached\n");
12655 return SCIP_INVALIDDATA;
12656 }
12657 *var = (*var)->data.original.transvar;
12658 break;
12659
12662 return SCIP_OKAY;
12663
12664 case SCIP_VARSTATUS_FIXED: /* x = c' => a*x + c == (a*c' + c) */
12665 if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12666 {
12667 if( SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)) )
12668 {
12669 assert(*scalar != 0.0);
12670 if( (*scalar) * (*var)->glbdom.lb > 0.0 )
12671 (*constant) = SCIPsetInfinity(set);
12672 else
12673 (*constant) = -SCIPsetInfinity(set);
12674 }
12675 else
12676 (*constant) += *scalar * (*var)->glbdom.lb;
12677 }
12678#ifndef NDEBUG
12679 else
12680 {
12681 assert(!SCIPsetIsInfinity(set, (*constant)) || !((*scalar) * (*var)->glbdom.lb < 0.0 &&
12682 (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
12683 assert(!SCIPsetIsInfinity(set, -(*constant)) || !((*scalar) * (*var)->glbdom.lb > 0.0 &&
12684 (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
12685 }
12686#endif
12687 *scalar = 0.0;
12688 return SCIP_OKAY;
12689
12691 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12692 if ( (*var)->data.multaggr.nvars == 1 )
12693 {
12694 assert((*var)->data.multaggr.vars != NULL);
12695 assert((*var)->data.multaggr.scalars != NULL);
12696 assert((*var)->data.multaggr.vars[0] != NULL);
12697 if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12698 {
12699 /* the multi-aggregation constant can be infinite, if one of the multi-aggregation variables
12700 * was fixed to +/-infinity; ensure that the constant is set to +/-infinity, too, and the scalar
12701 * is set to 0.0, because the multi-aggregated variable can be seen as fixed, too
12702 */
12703 if( SCIPsetIsInfinity(set, (*var)->data.multaggr.constant)
12704 || SCIPsetIsInfinity(set, -((*var)->data.multaggr.constant)) )
12705 {
12706 if( (*scalar) * (*var)->data.multaggr.constant > 0 )
12707 {
12708 assert(!SCIPsetIsInfinity(set, -(*constant)));
12709 (*constant) = SCIPsetInfinity(set);
12710 }
12711 else
12712 {
12713 assert(!SCIPsetIsInfinity(set, *constant));
12714 (*constant) = -SCIPsetInfinity(set);
12715 }
12716 (*scalar) = 0.0;
12717 }
12718 else
12719 (*constant) += *scalar * (*var)->data.multaggr.constant;
12720 }
12721 (*scalar) *= (*var)->data.multaggr.scalars[0];
12722 *var = (*var)->data.multaggr.vars[0];
12723 break;
12724 }
12725 return SCIP_OKAY;
12726
12727 case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
12728 assert((*var)->data.aggregate.var != NULL);
12729 assert(!SCIPsetIsInfinity(set, (*var)->data.aggregate.constant)
12730 && !SCIPsetIsInfinity(set, (*var)->data.aggregate.constant));
12731 if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12732 (*constant) += *scalar * (*var)->data.aggregate.constant;
12733 (*scalar) *= (*var)->data.aggregate.scalar;
12734 *var = (*var)->data.aggregate.var;
12735 break;
12736
12737 case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
12738 assert((*var)->negatedvar != NULL);
12739 assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12740 assert((*var)->negatedvar->negatedvar == *var);
12741 assert(!SCIPsetIsInfinity(set, (*var)->data.negate.constant)
12742 && !SCIPsetIsInfinity(set, (*var)->data.negate.constant));
12743 if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12744 (*constant) += *scalar * (*var)->data.negate.constant;
12745 (*scalar) *= -1.0;
12746 *var = (*var)->negatedvar;
12747 break;
12748
12749 default:
12750 SCIPerrorMessage("unknown variable status\n");
12751 SCIPABORT();
12752 return SCIP_INVALIDDATA; /*lint !e527*/
12753 }
12754 }
12755 *scalar = 0.0;
12756
12757 return SCIP_OKAY;
12758}
12759
12760/** retransforms given variable, scalar and constant to the corresponding original variable, scalar
12761 * and constant, if possible; if the retransformation is impossible, NULL is returned as variable
12762 */
12764 SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
12765 SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
12766 SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
12767 )
12768{
12770
12771 assert(var != NULL);
12772 assert(*var != NULL);
12773 assert(scalar != NULL);
12774 assert(constant != NULL);
12775
12776 while( !SCIPvarIsOriginal(*var) )
12777 {
12778 /* if the variable has no parent variables, it was generated during solving and has no corresponding original
12779 * var
12780 */
12781 if( (*var)->nparentvars == 0 )
12782 {
12783 /* negated variables do not need to have a parent variables, and negated variables can exist in original
12784 * space
12785 */
12787 ((*var)->negatedvar->nparentvars == 0 || (*var)->negatedvar->parentvars[0] != *var) )
12788 {
12789 *scalar *= -1.0;
12790 *constant -= (*var)->data.negate.constant * (*scalar);
12791 *var = (*var)->negatedvar;
12792
12793 continue;
12794 }
12795 /* if the variables does not have any parent the variables was created during solving and has no original
12796 * counterpart
12797 */
12798 else
12799 {
12800 *var = NULL;
12801
12802 return SCIP_OKAY;
12803 }
12804 }
12805
12806 /* follow the link to the first parent variable */
12807 parentvar = (*var)->parentvars[0];
12808 assert(parentvar != NULL);
12809
12810 switch( SCIPvarGetStatus(parentvar) )
12811 {
12813 break;
12814
12819 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
12820 return SCIP_INVALIDDATA;
12821
12822 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + b -> y = (x-b)/a, s*y + c = (s/a)*x + c-b*s/a */
12823 assert(parentvar->data.aggregate.var == *var);
12824 assert(parentvar->data.aggregate.scalar != 0.0);
12825 *scalar /= parentvar->data.aggregate.scalar;
12826 *constant -= parentvar->data.aggregate.constant * (*scalar);
12827 break;
12828
12829 case SCIP_VARSTATUS_NEGATED: /* x = b - y -> y = b - x, s*y + c = -s*x + c+b*s */
12830 assert(parentvar->negatedvar != NULL);
12832 assert(parentvar->negatedvar->negatedvar == parentvar);
12833 *scalar *= -1.0;
12834 *constant -= parentvar->data.negate.constant * (*scalar);
12835 break;
12836
12837 default:
12838 SCIPerrorMessage("unknown variable status\n");
12839 return SCIP_INVALIDDATA;
12840 }
12841
12842 assert( parentvar != NULL );
12843 *var = parentvar;
12844 }
12845
12846 return SCIP_OKAY;
12847}
12848
12849/** returns whether the given variable is the direct counterpart of an original problem variable */
12851 SCIP_VAR* var /**< problem variable */
12852 )
12853{
12855 assert(var != NULL);
12856
12857 if( !SCIPvarIsTransformed(var) || var->nparentvars < 1 )
12858 return FALSE;
12859
12861 parentvar = var->parentvars[0];
12862 assert(parentvar != NULL);
12863
12864 /* we follow the aggregation tree to the root unless an original variable has been found - the first entries in the parentlist are candidates */
12865 while( parentvar->nparentvars >= 1 && SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL )
12866 parentvar = parentvar->parentvars[0];
12867 assert( parentvar != NULL );
12868
12870}
12871
12872/** gets objective value of variable in current SCIP_LP; the value can be different from the objective value stored in
12873 * the variable's own data due to diving, that operate only on the LP without updating the variables
12874 */
12876 SCIP_VAR* var /**< problem variable */
12877 )
12878{
12879 assert(var != NULL);
12880
12881 /* get bounds of attached variables */
12882 switch( SCIPvarGetStatus(var) )
12883 {
12887
12889 assert(var->data.col != NULL);
12890 return SCIPcolGetObj(var->data.col);
12891
12894 return var->obj;
12895
12896 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12899
12901 SCIPerrorMessage("cannot get the objective value of a multiple aggregated variable\n");
12902 SCIPABORT();
12903 return 0.0; /*lint !e527*/
12904
12905 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12909 return -SCIPvarGetObjLP(var->negatedvar);
12910
12911 default:
12912 SCIPerrorMessage("unknown variable status\n");
12913 SCIPABORT();
12914 return 0.0; /*lint !e527*/
12915 }
12916}
12917
12918/** gets lower bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
12919 * data due to diving or conflict analysis, that operate only on the LP without updating the variables
12920 */
12922 SCIP_VAR* var, /**< problem variable */
12923 SCIP_SET* set /**< global SCIP settings */
12924 )
12925{
12926 assert(var != NULL);
12927 assert(set != NULL);
12928 assert(var->scip == set->scip);
12929
12930 /* get bounds of attached variables */
12931 switch( SCIPvarGetStatus(var) )
12932 {
12936
12938 assert(var->data.col != NULL);
12939 return SCIPcolGetLb(var->data.col);
12940
12943 return var->locdom.lb;
12944
12945 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12949 {
12950 return -SCIPsetInfinity(set);
12951 }
12952 else if( var->data.aggregate.scalar > 0.0 )
12953 {
12954 /* a > 0 -> get lower bound of y */
12956 }
12957 else if( var->data.aggregate.scalar < 0.0 )
12958 {
12959 /* a < 0 -> get upper bound of y */
12961 }
12962 else
12963 {
12964 SCIPerrorMessage("scalar is zero in aggregation\n");
12965 SCIPABORT();
12966 return SCIP_INVALID; /*lint !e527*/
12967 }
12968
12970 /**@todo get the sides of the corresponding linear constraint */
12971 SCIPerrorMessage("getting the bounds of a multiple aggregated variable is not implemented yet\n");
12972 SCIPABORT();
12973 return SCIP_INVALID; /*lint !e527*/
12974
12975 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12980
12981 default:
12982 SCIPerrorMessage("unknown variable status\n");
12983 SCIPABORT();
12984 return SCIP_INVALID; /*lint !e527*/
12985 }
12986}
12987
12988/** gets upper bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
12989 * data due to diving or conflict analysis, that operate only on the LP without updating the variables
12990 */
12992 SCIP_VAR* var, /**< problem variable */
12993 SCIP_SET* set /**< global SCIP settings */
12994 )
12995{
12996 assert(var != NULL);
12997 assert(set != NULL);
12998 assert(var->scip == set->scip);
12999
13000 /* get bounds of attached variables */
13001 switch( SCIPvarGetStatus(var) )
13002 {
13006
13008 assert(var->data.col != NULL);
13009 return SCIPcolGetUb(var->data.col);
13010
13013 return var->locdom.ub;
13014
13015 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
13019 {
13020 return SCIPsetInfinity(set);
13021 }
13022 if( var->data.aggregate.scalar > 0.0 )
13023 {
13024 /* a > 0 -> get upper bound of y */
13026 }
13027 else if( var->data.aggregate.scalar < 0.0 )
13028 {
13029 /* a < 0 -> get lower bound of y */
13031 }
13032 else
13033 {
13034 SCIPerrorMessage("scalar is zero in aggregation\n");
13035 SCIPABORT();
13036 return SCIP_INVALID; /*lint !e527*/
13037 }
13038
13040 SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
13041 SCIPABORT();
13042 return SCIP_INVALID; /*lint !e527*/
13043
13044 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13049
13050 default:
13051 SCIPerrorMessage("unknown variable status\n");
13052 SCIPABORT();
13053 return SCIP_INVALID; /*lint !e527*/
13054 }
13055}
13056
13057/** gets primal LP solution value of variable */
13059 SCIP_VAR* var /**< problem variable */
13060 )
13061{
13062 assert(var != NULL);
13063
13064 switch( SCIPvarGetStatus(var) )
13065 {
13067 if( var->data.original.transvar == NULL )
13068 return SCIP_INVALID;
13070
13073
13075 assert(var->data.col != NULL);
13076 return SCIPcolGetPrimsol(var->data.col);
13077
13079 assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13080 return var->locdom.lb;
13081
13083 {
13084 SCIP_Real lpsolval;
13085
13086 assert(!var->donotaggr);
13088 lpsolval = SCIPvarGetLPSol(var->data.aggregate.var);
13089
13090 /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13091 * corresponding infinity value instead of performing an arithmetical transformation (compare method
13092 * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13093 * (or is called by) a public interface method; instead, we only assert that values are finite
13094 * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13095 * positives and negatives if the parameter <numerics/infinity> is modified by the user
13096 */
13097 assert(lpsolval > -SCIP_DEFAULT_INFINITY);
13098 assert(lpsolval < +SCIP_DEFAULT_INFINITY);
13099 return var->data.aggregate.scalar * lpsolval + var->data.aggregate.constant;
13100 }
13102 {
13103 SCIP_Real primsol;
13104 int i;
13105
13109 /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13110 * assert(var->data.multaggr.nvars >= 2);
13111 */
13113 for( i = 0; i < var->data.multaggr.nvars; ++i )
13115 return primsol;
13116 }
13117 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13122
13123 default:
13124 SCIPerrorMessage("unknown variable status\n");
13125 SCIPABORT();
13126 return SCIP_INVALID; /*lint !e527*/
13127 }
13128}
13129
13130/** gets primal NLP solution value of variable */
13132 SCIP_VAR* var /**< problem variable */
13133 )
13134{
13135 SCIP_Real solval;
13136 int i;
13137
13138 assert(var != NULL);
13139
13140 /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
13141 switch( SCIPvarGetStatus(var) )
13142 {
13145
13148 return var->nlpsol;
13149
13151 assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
13152 assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
13153 assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
13154 return SCIPvarGetLbGlobal(var);
13155
13156 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13158 return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
13159
13161 solval = var->data.multaggr.constant;
13162 for( i = 0; i < var->data.multaggr.nvars; ++i )
13164 return solval;
13165
13167 solval = SCIPvarGetNLPSol(var->negatedvar);
13168 return var->data.negate.constant - solval;
13169
13170 default:
13171 SCIPerrorMessage("unknown variable status\n");
13172 SCIPABORT();
13173 return SCIP_INVALID; /*lint !e527*/
13174 }
13175}
13176
13177/** gets pseudo solution value of variable at current node */
13178static
13180 SCIP_VAR* var /**< problem variable */
13181 )
13182{
13183 SCIP_Real pseudosol;
13184 int i;
13185
13186 assert(var != NULL);
13187
13188 switch( SCIPvarGetStatus(var) )
13189 {
13191 if( var->data.original.transvar == NULL )
13192 return SCIP_INVALID;
13194
13198
13200 assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13201 return var->locdom.lb;
13202
13204 {
13205 SCIP_Real pseudosolval;
13206 assert(!var->donotaggr);
13208 /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13209 * corresponding infinity value instead of performing an arithmetical transformation (compare method
13210 * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13211 * (or is called by) a public interface method; instead, we only assert that values are finite
13212 * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13213 * positives and negatives if the parameter <numerics/infinity> is modified by the user
13214 */
13219 }
13224 /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13225 * assert(var->data.multaggr.nvars >= 2);
13226 */
13228 for( i = 0; i < var->data.multaggr.nvars; ++i )
13230 return pseudosol;
13231
13232 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13237
13238 default:
13239 SCIPerrorMessage("unknown variable status\n");
13240 SCIPABORT();
13241 return SCIP_INVALID; /*lint !e527*/
13242 }
13243}
13244
13245/** gets current LP or pseudo solution value of variable */
13247 SCIP_VAR* var, /**< problem variable */
13248 SCIP_Bool getlpval /**< should the LP solution value be returned? */
13249 )
13250{
13251 if( getlpval )
13252 return SCIPvarGetLPSol(var);
13253 else
13254 return SCIPvarGetPseudoSol(var);
13255}
13256
13257/** remembers the current solution as root solution in the problem variables */
13259 SCIP_VAR* var, /**< problem variable */
13260 SCIP_Bool roothaslp /**< is the root solution from LP? */
13261 )
13262{
13263 assert(var != NULL);
13264
13266}
13267
13268/** updates the current solution as best root solution of the given variable if it is better */
13270 SCIP_VAR* var, /**< problem variable */
13271 SCIP_SET* set, /**< global SCIP settings */
13272 SCIP_Real rootsol, /**< root solution value */
13273 SCIP_Real rootredcost, /**< root reduced cost */
13274 SCIP_Real rootlpobjval /**< objective value of the root LP */
13275 )
13276{
13277 assert(var != NULL);
13278 assert(set != NULL);
13279 assert(var->scip == set->scip);
13280
13281 /* if reduced cost are zero nothing to update */
13283 return;
13284
13285 /* check if we have already a best combination stored */
13287 {
13288 SCIP_Real currcutoffbound;
13289 SCIP_Real cutoffbound;
13290 SCIP_Real bound;
13291
13292 /* compute the cutoff bound which would improve the corresponding bound with the current stored root solution,
13293 * root reduced cost, and root LP objective value combination
13294 */
13295 if( var->bestrootredcost > 0.0 )
13297 else
13299
13301
13302 /* compute the cutoff bound which would improve the corresponding bound with new root solution, root reduced
13303 * cost, and root LP objective value combination
13304 */
13305 if( rootredcost > 0.0 )
13307 else
13309
13310 cutoffbound = (bound - rootsol) * rootredcost + rootlpobjval;
13311
13312 /* check if an improving root solution, root reduced cost, and root LP objective value is at hand */
13313 if( cutoffbound > currcutoffbound )
13314 {
13315 SCIPsetDebugMsg(set, "-> <%s> update potential cutoff bound <%g> -> <%g>\n",
13316 SCIPvarGetName(var), currcutoffbound, cutoffbound);
13317
13320 var->bestrootlpobjval = rootlpobjval;
13321 }
13322 }
13323 else
13324 {
13325 SCIPsetDebugMsg(set, "-> <%s> initialize best root reduced cost information\n", SCIPvarGetName(var));
13326 SCIPsetDebugMsg(set, " -> rootsol <%g>\n", rootsol);
13327 SCIPsetDebugMsg(set, " -> rootredcost <%g>\n", rootredcost);
13328 SCIPsetDebugMsg(set, " -> rootlpobjval <%g>\n", rootlpobjval);
13329
13332 var->bestrootlpobjval = rootlpobjval;
13333 }
13334}
13335
13336/** returns the solution of the variable in the last root node's relaxation, if the root relaxation is not yet
13337 * completely solved, zero is returned
13338 */
13340 SCIP_VAR* var /**< problem variable */
13341 )
13342{
13343 SCIP_Real rootsol;
13344 int i;
13345
13346 assert(var != NULL);
13347
13348 switch( SCIPvarGetStatus(var) )
13349 {
13351 if( var->data.original.transvar == NULL )
13352 return 0.0;
13354
13357 return var->rootsol;
13358
13360 assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13361 return var->locdom.lb;
13362
13364 assert(!var->donotaggr);
13366 /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13367 * corresponding infinity value instead of performing an arithmetical transformation (compare method
13368 * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13369 * (or is called by) a public interface method; instead, we only assert that values are finite
13370 * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13371 * positives and negatives if the parameter <numerics/infinity> is modified by the user
13372 */
13376
13381 /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13382 * assert(var->data.multaggr.nvars >= 2);
13383 */
13385 for( i = 0; i < var->data.multaggr.nvars; ++i )
13387 return rootsol;
13388
13389 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13394
13395 default:
13396 SCIPerrorMessage("unknown variable status\n");
13397 SCIPABORT();
13398 return SCIP_INVALID; /*lint !e527*/
13399 }
13400}
13401
13402/** returns for given variable the reduced cost */
13403static
13405 SCIP_VAR* var, /**< problem variable */
13406 SCIP_SET* set, /**< global SCIP settings */
13407 SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
13408 SCIP_STAT* stat, /**< problem statistics */
13409 SCIP_LP* lp /**< current LP data */
13410 )
13411{
13413 {
13414 SCIP_COL* col;
13415 SCIP_Real primsol;
13417 SCIP_Bool lpissolbasic;
13418
13419 col = SCIPvarGetCol(var);
13420 assert(col != NULL);
13421
13425
13428 {
13429 SCIP_Real redcost = SCIPcolGetRedcost(col, stat, lp);
13430
13437
13442 return redcost;
13443 else
13444 return 0.0;
13445 }
13446
13447 return 0.0;
13448 }
13449
13450 return 0.0;
13451}
13452
13453#define MAX_CLIQUELENGTH 50
13454/** returns for the given binary variable the reduced cost which are given by the variable itself and its implication if
13455 * the binary variable is fixed to the given value
13456 */
13458 SCIP_VAR* var, /**< problem variable */
13459 SCIP_SET* set, /**< global SCIP settings */
13460 SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
13461 SCIP_STAT* stat, /**< problem statistics */
13462 SCIP_PROB* prob, /**< transformed problem, or NULL */
13463 SCIP_LP* lp /**< current LP data */
13464 )
13465{
13466 SCIP_Real implredcost;
13467 int ncliques;
13468 int nvars;
13469
13472
13473 /* get reduced cost of given variable */
13475
13476#ifdef SCIP_MORE_DEBUG
13477 SCIPsetDebugMsg(set, "variable <%s> itself has reduced cost of %g\n", SCIPvarGetName(var), implredcost);
13478#endif
13479
13480 /* the following algorithm is expensive */
13481 ncliques = SCIPvarGetNCliques(var, varfixing);
13482
13483 if( ncliques > 0 )
13484 {
13485 SCIP_CLIQUE** cliques;
13486 SCIP_CLIQUE* clique;
13487 SCIP_VAR** clqvars;
13490 SCIP_Bool* clqvalues;
13491 int* entries;
13492 int* ids;
13493 SCIP_Real redcost;
13494 SCIP_Bool cleanedup;
13495 int nclqvars;
13496 int nentries;
13497 int nids;
13498 int id;
13499 int c;
13500 int v;
13501
13502 assert(prob != NULL);
13504
13505 nentries = SCIPprobGetNVars(prob) - SCIPprobGetNContVars(prob) + 1;
13506
13507 SCIP_CALL_ABORT( SCIPsetAllocBufferArray(set, &ids, nentries) );
13508 nids = 0;
13510
13511 cliques = SCIPvarGetCliques(var, varfixing);
13512 assert(cliques != NULL);
13513
13514 for( c = ncliques - 1; c >= 0; --c )
13515 {
13516 clique = cliques[c];
13517 assert(clique != NULL);
13518 nclqvars = SCIPcliqueGetNVars(clique);
13519 assert(nclqvars > 0);
13520
13522 continue;
13523
13524 clqvars = SCIPcliqueGetVars(clique);
13526 assert(clqvars != NULL);
13527 assert(clqvalues != NULL);
13528
13530
13531 for( v = nclqvars - 1; v >= 0; --v )
13532 {
13533 clqvar = clqvars[v];
13534 assert(clqvar != NULL);
13535
13536 /* ignore binary variable which are fixed */
13537 if( clqvar != var && (cleanedup || SCIPvarIsActive(clqvar)) &&
13539 {
13540 int probindex = SCIPvarGetProbindex(clqvar) + 1;
13541 assert(0 < probindex && probindex < nentries);
13542
13543#if 0
13544 /* check that the variable was not yet visited or does not appear with two contradicting implications, ->
13545 * can appear since there is no guarantee that all these infeasible bounds were found
13546 */
13547 assert(!entries[probindex] || entries[probindex] == (clqvalues[v] ? probindex : -probindex));
13548#endif
13549 if( entries[probindex] == 0 )
13550 {
13551 ids[nids] = probindex;
13552 ++nids;
13553
13554 /* mark variable as visited */
13555 entries[probindex] = (clqvalues[v] ? probindex : -probindex);
13556 }
13557 }
13558 }
13559 }
13560
13561 probvars = SCIPprobGetVars(prob);
13562 assert(probvars != NULL);
13563
13564 /* add all implied reduced cost */
13565 for( v = nids - 1; v >= 0; --v )
13566 {
13567 id = ids[v];
13568 assert(0 < id && id < nentries);
13569 assert(entries[id] != 0);
13570 assert(probvars[id - 1] != NULL);
13573 assert(SCIPvarGetLbLocal(probvars[id - 1]) < 0.5 && SCIPvarGetUbLocal(probvars[id - 1]) > 0.5);
13574
13575 if( (entries[id] > 0) != varfixing )
13576 redcost = getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
13577 else
13578 redcost = -getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
13579
13580 if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
13581 implredcost += redcost;
13582
13583 /* reset entries clear buffer array */
13584 entries[id] = 0;
13585 }
13586
13589 }
13590
13591#ifdef SCIP_MORE_DEBUG
13592 SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) has implied reduced cost of %g\n", SCIPvarGetName(var), ncliques,
13593 implredcost);
13594#endif
13595
13596 /* collect non-binary implication information */
13598
13599 if( nvars > 0 )
13600 {
13601 SCIP_VAR** vars;
13603 SCIP_COL* col;
13604 SCIP_Real* bounds;
13605 SCIP_BOUNDTYPE* boundtypes;
13606 SCIP_Real redcost;
13607 SCIP_Real lb;
13608 SCIP_Real ub;
13609 SCIP_Bool lpissolbasic;
13610 int v;
13611
13613 boundtypes = SCIPimplicsGetTypes(var->implics, varfixing);
13616
13617 for( v = nvars - 1; v >= 0; --v )
13618 {
13619 implvar = vars[v];
13620 assert(implvar != NULL);
13621
13624
13625 /* ignore binary variable which are fixed or not of column status */
13627 continue;
13628
13629 col = SCIPvarGetCol(implvar);
13630 assert(col != NULL);
13631 redcost = 0.0;
13632
13633 /* solved lp with basis information or not? */
13634 if( lpissolbasic )
13635 {
13637
13638 /* check if the implication is not not yet applied */
13639 if( basestat == SCIP_BASESTAT_LOWER && boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGT(set, bounds[v], lb) )
13640 {
13641 redcost = SCIPcolGetRedcost(col, stat, lp);
13643
13644 if( !varfixing )
13645 redcost *= (lb - bounds[v]);
13646 else
13647 redcost *= (bounds[v] - lb);
13648 }
13649 else if( basestat == SCIP_BASESTAT_UPPER && boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLT(set, bounds[v], ub) )
13650 {
13651 redcost = SCIPcolGetRedcost(col, stat, lp);
13653
13654 if( varfixing )
13655 redcost *= (bounds[v] - ub);
13656 else
13657 redcost *= (ub - bounds[v]);
13658 }
13659 }
13660 else
13661 {
13662 SCIP_Real primsol = SCIPcolGetPrimsol(col);
13663
13664 /* check if the implication is not not yet applied */
13665 if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasEQ(set, lb, primsol) && SCIPsetIsFeasGT(set, bounds[v], lb) )
13666 {
13667 redcost = SCIPcolGetRedcost(col, stat, lp);
13669
13670 if( varfixing )
13671 redcost *= (lb - bounds[v]);
13672 else
13673 redcost *= (bounds[v] - lb);
13674 }
13675 else if( boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasEQ(set, ub, primsol) && SCIPsetIsFeasLT(set, bounds[v], ub) )
13676 {
13677 redcost = SCIPcolGetRedcost(col, stat, lp);
13679
13680 if( varfixing )
13681 redcost *= (bounds[v] - ub);
13682 else
13683 redcost *= (ub - bounds[v]);
13684 }
13685 }
13686
13687 /* improve implied reduced cost */
13688 if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
13689 implredcost += redcost;
13690 }
13691 }
13692
13693#ifdef SCIP_MORE_DEBUG
13694 SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) and implications (%d) has implied reduced cost of %g\n",
13695 SCIPvarGetName(var), ncliques, nvars, implredcost);
13696#endif
13697
13698 return implredcost;
13699}
13700
13701/** returns the best solution (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation, if
13702 * the root relaxation is not yet completely solved, zero is returned
13703 */
13705 SCIP_VAR* var /**< problem variable */
13706 )
13707{
13708 SCIP_Real rootsol;
13709 int i;
13710
13711 assert(var != NULL);
13712
13713 switch( SCIPvarGetStatus(var) )
13714 {
13716 if( var->data.original.transvar == NULL )
13717 return 0.0;
13719
13722 return var->bestrootsol;
13723
13725 assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13726 return var->locdom.lb;
13727
13729 assert(!var->donotaggr);
13731 /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13732 * corresponding infinity value instead of performing an arithmetical transformation (compare method
13733 * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13734 * (or is called by) a public interface method; instead, we only assert that values are finite
13735 * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13736 * positives and negatives if the parameter <numerics/infinity> is modified by the user
13737 */
13741
13746 /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13747 * assert(var->data.multaggr.nvars >= 2);
13748 */
13750 for( i = 0; i < var->data.multaggr.nvars; ++i )
13752 return rootsol;
13753
13754 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13759
13760 default:
13761 SCIPerrorMessage("unknown variable status\n");
13762 SCIPABORT();
13763 return 0.0; /*lint !e527*/
13764 }
13765}
13766
13767/** returns the best reduced costs (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation,
13768 * if the root relaxation is not yet completely solved, or the variable was no column of the root LP, SCIP_INVALID is
13769 * returned
13770 */
13772 SCIP_VAR* var /**< problem variable */
13773 )
13774{
13775 assert(var != NULL);
13776
13777 switch( SCIPvarGetStatus(var) )
13778 {
13780 if( var->data.original.transvar == NULL )
13781 return SCIP_INVALID;
13783
13786 return var->bestrootredcost;
13787
13792 return 0.0;
13793
13794 default:
13795 SCIPerrorMessage("unknown variable status\n");
13796 SCIPABORT();
13797 return 0.0; /*lint !e527*/
13798 }
13799}
13800
13801/** returns the best objective value (w.r.t. root reduced cost propagation) of the root LP which belongs the root
13802 * reduced cost which is accessible via SCIPvarGetRootRedcost() or the variable was no column of the root LP,
13803 * SCIP_INVALID is returned
13804 */
13806 SCIP_VAR* var /**< problem variable */
13807 )
13808{
13809 assert(var != NULL);
13810
13811 switch( SCIPvarGetStatus(var) )
13812 {
13814 if( var->data.original.transvar == NULL )
13815 return SCIP_INVALID;
13817
13820 return var->bestrootlpobjval;
13821
13826 return SCIP_INVALID;
13827
13828 default:
13829 SCIPerrorMessage("unknown variable status\n");
13830 SCIPABORT();
13831 return SCIP_INVALID; /*lint !e527*/
13832 }
13833}
13834
13835/** set the given solution as the best root solution w.r.t. root reduced cost propagation in the variables */
13837 SCIP_VAR* var, /**< problem variable */
13838 SCIP_Real rootsol, /**< root solution value */
13839 SCIP_Real rootredcost, /**< root reduced cost */
13840 SCIP_Real rootlpobjval /**< objective value of the root LP */
13841 )
13842{
13843 assert(var != NULL);
13844
13847 var->bestrootlpobjval = rootlpobjval;
13848}
13849
13850/** stores the solution value as relaxation solution in the problem variable */
13852 SCIP_VAR* var, /**< problem variable */
13853 SCIP_SET* set, /**< global SCIP settings */
13854 SCIP_RELAXATION* relaxation, /**< global relaxation data */
13855 SCIP_Real solval, /**< solution value in the current relaxation solution */
13856 SCIP_Bool updateobj /**< should the objective value be updated? */
13857 )
13858{
13859 assert(var != NULL);
13860 assert(relaxation != NULL);
13861 assert(set != NULL);
13862 assert(var->scip == set->scip);
13863
13864 /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
13865 switch( SCIPvarGetStatus(var) )
13866 {
13869 break;
13870
13873 if( updateobj )
13874 SCIPrelaxationSolObjAdd(relaxation, var->obj * (solval - var->relaxsol));
13875 var->relaxsol = solval;
13876 break;
13877
13879 if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
13880 {
13881 SCIPerrorMessage("cannot set relaxation solution value for variable <%s> fixed to %.15g to different value %.15g\n",
13882 SCIPvarGetName(var), var->glbdom.lb, solval);
13883 return SCIP_INVALIDDATA;
13884 }
13885 break;
13886
13887 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13891 break;
13893 SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
13894 return SCIP_INVALIDDATA;
13895
13898 break;
13899
13900 default:
13901 SCIPerrorMessage("unknown variable status\n");
13902 return SCIP_INVALIDDATA;
13903 }
13904
13905 return SCIP_OKAY;
13906}
13907
13908/** returns the solution value of the problem variable in the relaxation solution
13909 *
13910 * @todo Inline this function - similar to SCIPvarGetLPSol_rec.
13911 */
13913 SCIP_VAR* var, /**< problem variable */
13914 SCIP_SET* set /**< global SCIP settings */
13915 )
13916{
13917 SCIP_Real solvalsum;
13918 SCIP_Real solval;
13919 int i;
13920
13921 assert(var != NULL);
13922 assert(set != NULL);
13923 assert(var->scip == set->scip);
13924
13925 /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
13926 switch( SCIPvarGetStatus(var) )
13927 {
13930
13933 return var->relaxsol;
13934
13936 assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
13937 assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
13938 assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
13939 return SCIPvarGetLbGlobal(var);
13940
13941 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13943 if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
13944 {
13945 if( var->data.aggregate.scalar * solval > 0.0 )
13946 return SCIPsetInfinity(set);
13947 if( var->data.aggregate.scalar * solval < 0.0 )
13948 return -SCIPsetInfinity(set);
13949 }
13950 return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
13951
13954 for( i = 0; i < var->data.multaggr.nvars; ++i )
13955 {
13957 if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
13958 {
13959 if( var->data.multaggr.scalars[i] * solval > 0.0 )
13960 return SCIPsetInfinity(set);
13961 if( var->data.multaggr.scalars[i] * solval < 0.0 )
13962 return -SCIPsetInfinity(set);
13963 }
13964 solvalsum += var->data.multaggr.scalars[i] * solval;
13965 }
13966 return solvalsum;
13967
13970 if( SCIPsetIsInfinity(set, solval) )
13971 return -SCIPsetInfinity(set);
13972 if( SCIPsetIsInfinity(set, -solval) )
13973 return SCIPsetInfinity(set);
13974 return var->data.negate.constant - solval;
13975
13976 default:
13977 SCIPerrorMessage("unknown variable status\n");
13978 SCIPABORT();
13979 return SCIP_INVALID; /*lint !e527*/
13980 }
13981}
13982
13983/** returns the solution value of the transformed problem variable in the relaxation solution */
13985 SCIP_VAR* var /**< problem variable */
13986 )
13987{
13988 assert(var != NULL);
13990
13991 return var->relaxsol;
13992}
13993
13994/** stores the solution value as NLP solution in the problem variable */
13996 SCIP_VAR* var, /**< problem variable */
13997 SCIP_SET* set, /**< global SCIP settings */
13998 SCIP_Real solval /**< solution value in the current NLP solution */
13999 )
14000{
14001 assert(var != NULL);
14002 assert(set != NULL);
14003 assert(var->scip == set->scip);
14004
14005 /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
14006 switch( SCIPvarGetStatus(var) )
14007 {
14010 break;
14011
14014 var->nlpsol = solval;
14015 break;
14016
14018 if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
14019 {
14020 SCIPerrorMessage("cannot set NLP solution value for variable <%s> fixed to %.15g to different value %.15g\n",
14021 SCIPvarGetName(var), var->glbdom.lb, solval);
14022 SCIPABORT();
14023 return SCIP_INVALIDCALL; /*lint !e527*/
14024 }
14025 break;
14026
14027 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
14030 break;
14031
14033 SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
14034 SCIPABORT();
14035 return SCIP_INVALIDCALL; /*lint !e527*/
14036
14039 break;
14040
14041 default:
14042 SCIPerrorMessage("unknown variable status\n");
14043 SCIPABORT();
14044 return SCIP_ERROR; /*lint !e527*/
14045 }
14046
14047 return SCIP_OKAY;
14048}
14049
14050/** returns a weighted average solution value of the variable in all feasible primal solutions found so far */
14052 SCIP_VAR* var /**< problem variable */
14053 )
14054{
14055 SCIP_Real avgsol;
14056 int i;
14057
14058 assert(var != NULL);
14059
14060 switch( SCIPvarGetStatus(var) )
14061 {
14063 if( var->data.original.transvar == NULL )
14064 return 0.0;
14066
14072 return avgsol;
14073
14075 assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
14076 return var->locdom.lb;
14077
14079 assert(!var->donotaggr);
14083
14088 /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
14089 * assert(var->data.multaggr.nvars >= 2);
14090 */
14092 for( i = 0; i < var->data.multaggr.nvars; ++i )
14094 return avgsol;
14095
14096 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
14101
14102 default:
14103 SCIPerrorMessage("unknown variable status\n");
14104 SCIPABORT();
14105 return 0.0; /*lint !e527*/
14106 }
14107}
14108
14109/** returns solution value and index of variable lower bound that is closest to the variable's value in the given primal solution
14110 * or current LP solution if no primal solution is given; returns an index of -1 if no variable lower bound is available
14111 */
14113 SCIP_VAR* var, /**< active problem variable */
14114 SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
14115 SCIP_SET* set, /**< global SCIP settings */
14116 SCIP_STAT* stat, /**< problem statistics */
14117 SCIP_Real* closestvlb, /**< pointer to store the value of the closest variable lower bound */
14118 int* closestvlbidx /**< pointer to store the index of the closest variable lower bound */
14119 )
14120{
14121 int nvlbs;
14122
14123 assert(var != NULL);
14124 assert(stat != NULL);
14125 assert(set != NULL);
14126 assert(var->scip == set->scip);
14128 assert(closestvlbidx != NULL);
14129
14130 *closestvlbidx = -1;
14132
14134 if( nvlbs > 0 )
14135 {
14136 SCIP_VAR** vlbvars;
14137 SCIP_Real* vlbcoefs;
14138 SCIP_Real* vlbconsts;
14139 int i;
14140
14144
14145 /* check for cached values */
14146 if( var->closestvblpcount == stat->lpcount && var->closestvlbidx != -1 && sol == NULL)
14147 {
14148 i = var->closestvlbidx;
14149 assert(0 <= i && i < nvlbs);
14151 *closestvlbidx = i;
14153 }
14154 else
14155 {
14156 /* search best VUB */
14157 for( i = 0; i < nvlbs; i++ )
14158 {
14159 if( SCIPvarIsActive(vlbvars[i]) )
14160 {
14161 SCIP_Real vlbsol;
14162
14164 if( vlbsol > *closestvlb )
14165 {
14166 *closestvlb = vlbsol;
14167 *closestvlbidx = i;
14168 }
14169 }
14170 }
14171
14172 if( sol == NULL )
14173 {
14174 /* update cached value */
14175 if( var->closestvblpcount != stat->lpcount )
14176 var->closestvubidx = -1;
14177 var->closestvlbidx = *closestvlbidx;
14178 var->closestvblpcount = stat->lpcount;
14179 }
14180 }
14181 }
14182}
14183
14184/** returns solution value and index of variable upper bound that is closest to the variable's value in the given primal solution;
14185 * or current LP solution if no primal solution is given; returns an index of -1 if no variable upper bound is available
14186 */
14188 SCIP_VAR* var, /**< active problem variable */
14189 SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
14190 SCIP_SET* set, /**< global SCIP settings */
14191 SCIP_STAT* stat, /**< problem statistics */
14192 SCIP_Real* closestvub, /**< pointer to store the value of the closest variable upper bound */
14193 int* closestvubidx /**< pointer to store the index of the closest variable upper bound */
14194 )
14195{
14196 int nvubs;
14197
14198 assert(var != NULL);
14199 assert(set != NULL);
14200 assert(var->scip == set->scip);
14202 assert(closestvubidx != NULL);
14203
14204 *closestvubidx = -1;
14206
14208 if( nvubs > 0 )
14209 {
14210 SCIP_VAR** vubvars;
14211 SCIP_Real* vubcoefs;
14212 SCIP_Real* vubconsts;
14213 int i;
14214
14218
14219 /* check for cached values */
14220 if( var->closestvblpcount == stat->lpcount && var->closestvubidx != -1 && sol == NULL)
14221 {
14222 i = var->closestvubidx;
14223 assert(0 <= i && i < nvubs);
14225 *closestvubidx = i;
14227 }
14228 else
14229 {
14230 /* search best VUB */
14231 for( i = 0; i < nvubs; i++ )
14232 {
14233 if( SCIPvarIsActive(vubvars[i]) )
14234 {
14235 SCIP_Real vubsol;
14236
14238 if( vubsol < *closestvub )
14239 {
14240 *closestvub = vubsol;
14241 *closestvubidx = i;
14242 }
14243 }
14244 }
14245
14246 if( sol == NULL )
14247 {
14248 /* update cached value */
14249 if( var->closestvblpcount != stat->lpcount )
14250 var->closestvlbidx = -1;
14251 var->closestvubidx = *closestvubidx;
14252 var->closestvblpcount = stat->lpcount;
14253 }
14254 }
14255 }
14256}
14257
14258/** resolves variable to columns and adds them with the coefficient to the row */
14260 SCIP_VAR* var, /**< problem variable */
14261 BMS_BLKMEM* blkmem, /**< block memory */
14262 SCIP_SET* set, /**< global SCIP settings */
14263 SCIP_STAT* stat, /**< problem statistics */
14264 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
14265 SCIP_PROB* prob, /**< problem data */
14266 SCIP_LP* lp, /**< current LP data */
14267 SCIP_ROW* row, /**< LP row */
14268 SCIP_Real val /**< value of coefficient */
14269 )
14270{
14271 int i;
14272
14273 assert(var != NULL);
14274 assert(set != NULL);
14275 assert(var->scip == set->scip);
14276 assert(row != NULL);
14278
14279 SCIPsetDebugMsg(set, "adding coefficient %g<%s> to row <%s>\n", val, var->name, row->name);
14280
14281 if ( SCIPsetIsZero(set, val) )
14282 return SCIP_OKAY;
14283
14284 switch( SCIPvarGetStatus(var) )
14285 {
14287 if( var->data.original.transvar == NULL )
14288 {
14289 SCIPerrorMessage("cannot add untransformed original variable <%s> to LP row <%s>\n", var->name, row->name);
14290 return SCIP_INVALIDDATA;
14291 }
14292 SCIP_CALL( SCIPvarAddToRow(var->data.original.transvar, blkmem, set, stat, eventqueue, prob, lp, row, val) );
14293 return SCIP_OKAY;
14294
14296 /* add globally fixed variables as constant */
14297 if( SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub) )
14298 {
14299 SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->glbdom.lb) );
14300 return SCIP_OKAY;
14301 }
14302 /* convert loose variable into column */
14303 SCIP_CALL( SCIPvarColumn(var, blkmem, set, stat, prob, lp) );
14305 /*lint -fallthrough*/
14306
14308 assert(var->data.col != NULL);
14309 assert(var->data.col->var == var);
14310 SCIP_CALL( SCIProwIncCoef(row, blkmem, set, eventqueue, lp, var->data.col, val) );
14311 return SCIP_OKAY;
14312
14314 assert(var->glbdom.lb == var->glbdom.ub); /*lint !e777*/
14315 assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
14316 assert(var->locdom.lb == var->glbdom.lb); /*lint !e777*/
14318 SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->locdom.lb) );
14319 return SCIP_OKAY;
14320
14322 assert(!var->donotaggr);
14324 SCIP_CALL( SCIPvarAddToRow(var->data.aggregate.var, blkmem, set, stat, eventqueue, prob, lp,
14325 row, var->data.aggregate.scalar * val) );
14326 SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.aggregate.constant * val) );
14327 return SCIP_OKAY;
14328
14333 /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
14334 * assert(var->data.multaggr.nvars >= 2);
14335 */
14336 for( i = 0; i < var->data.multaggr.nvars; ++i )
14337 {
14338 SCIP_CALL( SCIPvarAddToRow(var->data.multaggr.vars[i], blkmem, set, stat, eventqueue, prob, lp,
14339 row, var->data.multaggr.scalars[i] * val) );
14340 }
14341 SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.multaggr.constant * val) );
14342 return SCIP_OKAY;
14343
14344 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
14348 SCIP_CALL( SCIPvarAddToRow(var->negatedvar, blkmem, set, stat, eventqueue, prob, lp, row, -val) );
14349 SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.negate.constant * val) );
14350 return SCIP_OKAY;
14351
14352 default:
14353 SCIPerrorMessage("unknown variable status\n");
14354 return SCIP_INVALIDDATA;
14355 }
14356}
14357
14358/* optionally, define this compiler flag to write complete variable histories to a file */
14359#ifdef SCIP_HISTORYTOFILE
14360SCIP_Longint counter = 0l;
14361const char* historypath="."; /* allows for user-defined path; use '.' for calling directory of SCIP */
14362#include "scip/scip.h"
14363#endif
14364
14365/** updates the pseudo costs of the given variable and the global pseudo costs after a change of
14366 * "solvaldelta" in the variable's solution value and resulting change of "objdelta" in the in the LP's objective value
14367 */
14369 SCIP_VAR* var, /**< problem variable */
14370 SCIP_SET* set, /**< global SCIP settings */
14371 SCIP_STAT* stat, /**< problem statistics */
14372 SCIP_Real solvaldelta, /**< difference of variable's new LP value - old LP value */
14373 SCIP_Real objdelta, /**< difference of new LP's objective value - old LP's objective value */
14374 SCIP_Real weight /**< weight in (0,1] of this update in pseudo cost sum */
14375 )
14376{
14377 SCIP_Real oldrootpseudocosts;
14378 assert(var != NULL);
14379 assert(set != NULL);
14380 assert(var->scip == set->scip);
14381 assert(stat != NULL);
14382
14383 /* check if history statistics should be collected for a variable */
14384 if( !stat->collectvarhistory )
14385 return SCIP_OKAY;
14386
14387 switch( SCIPvarGetStatus(var) )
14388 {
14390 if( var->data.original.transvar == NULL )
14391 {
14392 SCIPerrorMessage("cannot update pseudo costs of original untransformed variable\n");
14393 return SCIP_INVALIDDATA;
14394 }
14396 return SCIP_OKAY;
14397
14400 /* store old pseudo-costs for root LP best-estimate update */
14402
14403 /* update history */
14408
14409 /* update root LP best-estimate */
14411
14412 /* append history to file */
14413#ifdef SCIP_HISTORYTOFILE
14414 {
14415 FILE* f;
14416 char filename[256];
14417 SCIP_NODE* currentnode;
14419 currentnode = SCIPgetFocusNode(set->scip);
14420 parentnode = SCIPnodeGetParent(currentnode);
14421
14422 sprintf(filename, "%s/%s.pse", historypath, SCIPgetProbName(set->scip));
14423 f = fopen(filename, "a");
14424 if( NULL != f )
14425 {
14426 fprintf(f, "%lld %s \t %lld \t %lld \t %lld \t %d \t %15.9f \t %.3f\n",
14427 ++counter,
14429 SCIPnodeGetNumber(currentnode),
14432 SCIPgetDepth(set->scip),
14433 objdelta,
14434 solvaldelta);
14435 fclose(f);
14436 }
14437 }
14438#endif
14439 return SCIP_OKAY;
14440
14442 SCIPerrorMessage("cannot update pseudo cost values of a fixed variable\n");
14443 return SCIP_INVALIDDATA;
14444
14449 return SCIP_OKAY;
14450
14452 SCIPerrorMessage("cannot update pseudo cost values of a multi-aggregated variable\n");
14453 return SCIP_INVALIDDATA;
14454
14457 return SCIP_OKAY;
14458
14459 default:
14460 SCIPerrorMessage("unknown variable status\n");
14461 return SCIP_INVALIDDATA;
14462 }
14463}
14464
14465/** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value */
14467 SCIP_VAR* var, /**< problem variable */
14468 SCIP_STAT* stat, /**< problem statistics */
14469 SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
14470 )
14471{
14473
14474 assert(var != NULL);
14475 assert(stat != NULL);
14476
14477 switch( SCIPvarGetStatus(var) )
14478 {
14480 if( var->data.original.transvar == NULL )
14482 else
14484
14488
14492
14494 return 0.0;
14495
14498
14500 return 0.0;
14501
14504
14505 default:
14506 SCIPerrorMessage("unknown variable status\n");
14507 SCIPABORT();
14508 return 0.0; /*lint !e527*/
14509 }
14510}
14511
14512/** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value,
14513 * only using the pseudo cost information of the current run
14514 */
14516 SCIP_VAR* var, /**< problem variable */
14517 SCIP_STAT* stat, /**< problem statistics */
14518 SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
14519 )
14520{
14522
14523 assert(var != NULL);
14524 assert(stat != NULL);
14525
14526 switch( SCIPvarGetStatus(var) )
14527 {
14529 if( var->data.original.transvar == NULL )
14531 else
14533
14537
14541
14543 return 0.0;
14544
14547
14549 return 0.0;
14550
14553
14554 default:
14555 SCIPerrorMessage("unknown variable status\n");
14556 SCIPABORT();
14557 return 0.0; /*lint !e527*/
14558 }
14559}
14560
14561/** gets the variable's (possible fractional) number of pseudo cost updates for the given direction */
14563 SCIP_VAR* var, /**< problem variable */
14564 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14565 )
14566{
14567 assert(var != NULL);
14569
14570 switch( SCIPvarGetStatus(var) )
14571 {
14573 if( var->data.original.transvar == NULL )
14574 return 0.0;
14575 else
14577
14581
14583 return 0.0;
14584
14586 if( var->data.aggregate.scalar > 0.0 )
14588 else
14590
14592 return 0.0;
14593
14596
14597 default:
14598 SCIPerrorMessage("unknown variable status\n");
14599 SCIPABORT();
14600 return 0.0; /*lint !e527*/
14601 }
14602}
14603
14604/** gets the variable's (possible fractional) number of pseudo cost updates for the given direction,
14605 * only using the pseudo cost information of the current run
14606 */
14608 SCIP_VAR* var, /**< problem variable */
14609 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14610 )
14611{
14612 assert(var != NULL);
14614
14615 switch( SCIPvarGetStatus(var) )
14616 {
14618 if( var->data.original.transvar == NULL )
14619 return 0.0;
14620 else
14622
14626
14628 return 0.0;
14629
14631 if( var->data.aggregate.scalar > 0.0 )
14633 else
14635
14637 return 0.0;
14638
14641
14642 default:
14643 SCIPerrorMessage("unknown variable status\n");
14644 SCIPABORT();
14645 return 0.0; /*lint !e527*/
14646 }
14647}
14648
14649/** compares both possible directions for rounding the given solution value and returns the minimum pseudo-costs of the variable */
14651 SCIP_VAR* var, /**< problem variable */
14652 SCIP_STAT* stat, /**< problem statistics */
14653 SCIP_SET* set, /**< global SCIP settings */
14654 SCIP_Real solval /**< solution value, e.g., LP solution value */
14655 )
14656{
14657 SCIP_Real upscore;
14658 SCIP_Real downscore;
14659 SCIP_Real solvaldeltaup;
14660 SCIP_Real solvaldeltadown;
14661
14662 /* LP root estimate only works for variables with fractional LP root solution */
14663 if( SCIPsetIsFeasIntegral(set, solval) )
14664 return 0.0;
14665
14666 /* no min pseudo-cost score is calculated as long as the variable was not initialized in a direction */
14668 return 0.0;
14669
14670 /* compute delta's to ceil and floor of root LP solution value */
14671 solvaldeltaup = SCIPsetCeil(set, solval) - solval;
14672 solvaldeltadown = SCIPsetFloor(set, solval) - solval;
14673
14676
14677 return MIN(upscore, downscore);
14678}
14679
14680/** gets the an estimate of the variable's pseudo cost variance in direction \p dir */
14682 SCIP_VAR* var, /**< problem variable */
14683 SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
14684 SCIP_Bool onlycurrentrun /**< return pseudo cost variance only for current branch and bound run */
14685 )
14686{
14687 assert(var != NULL);
14689
14690 switch( SCIPvarGetStatus(var) )
14691 {
14693 if( var->data.original.transvar == NULL )
14694 return 0.0;
14695 else
14697
14700 if( onlycurrentrun )
14702 else
14704
14706 return 0.0;
14707
14709 if( var->data.aggregate.scalar > 0.0 )
14711 else
14713
14715 return 0.0;
14716
14719
14720 default:
14721 SCIPerrorMessage("unknown variable status\n");
14722 SCIPABORT();
14723 return 0.0; /*lint !e527*/
14724 }
14725}
14726
14727/** calculates a confidence bound for this variable under the assumption of normally distributed pseudo costs
14728 *
14729 * The confidence bound \f$ \theta \geq 0\f$ denotes the interval borders \f$ [X - \theta, \ X + \theta]\f$, which contains
14730 * the true pseudo costs of the variable, i.e., the expected value of the normal distribution, with a probability
14731 * of 2 * clevel - 1.
14732 *
14733 * @return value of confidence bound for this variable
14734 */
14736 SCIP_VAR* var, /**< variable in question */
14737 SCIP_SET* set, /**< global SCIP settings */
14738 SCIP_BRANCHDIR dir, /**< the branching direction for the confidence bound */
14739 SCIP_Bool onlycurrentrun, /**< should only the current run be taken into account */
14740 SCIP_CONFIDENCELEVEL clevel /**< confidence level for the interval */
14741 )
14742{
14743 SCIP_Real confidencebound;
14744
14747 {
14748 SCIP_Real count;
14749
14750 if( onlycurrentrun )
14752 else
14754 /* assertion is valid because variance is positive */
14755 assert(count >= 1.9);
14756
14757 confidencebound /= count; /*lint !e414 division by zero can obviously not occur */
14759
14760 /* the actual, underlying distribution of the mean is a student-t-distribution with degrees of freedom equal to
14761 * the number of pseudo cost evaluations of this variable in the respective direction. */
14763 }
14764 else
14765 confidencebound = 0.0;
14766
14767 return confidencebound;
14768}
14769
14770/** check if the current pseudo cost relative error in a direction violates the given threshold. The Relative
14771 * Error is calculated at a specific confidence level
14772 */
14774 SCIP_VAR* var, /**< variable in question */
14775 SCIP_SET* set, /**< global SCIP settings */
14776 SCIP_STAT* stat, /**< problem statistics */
14777 SCIP_Real threshold, /**< threshold for relative errors to be considered reliable (enough) */
14778 SCIP_CONFIDENCELEVEL clevel /**< a given confidence level */
14779 )
14780{
14781 SCIP_Real downsize;
14782 SCIP_Real upsize;
14783 SCIP_Real size;
14784 SCIP_Real relerrorup;
14785 SCIP_Real relerrordown;
14786 SCIP_Real relerror;
14787
14788 /* check, if the pseudo cost score of the variable is reliable */
14791 size = MIN(downsize, upsize);
14792
14793 /* Pseudo costs relative error can only be reliable if both directions have been tried at least twice */
14794 if( size <= 1.9 )
14795 return FALSE;
14796
14797 /* use the relative error between the current mean pseudo cost value of the candidate and its upper
14798 * confidence interval bound at confidence level of 95% for individual variable reliability.
14799 * this is only possible if we have at least 2 measurements and therefore a valid variance estimate.
14800 */
14801 if( downsize >= 1.9 )
14802 {
14803 SCIP_Real normval;
14804
14807 normval = MAX(1.0, normval);
14808
14810 }
14811 else
14812 relerrordown = 0.0;
14813
14814 if( upsize >= 1.9 )
14815 {
14816 SCIP_Real normval;
14817
14820 normval = MAX(1.0, normval);
14822 }
14823 else
14824 relerrorup = 0.0;
14825
14826 /* consider the relative error threshold violated, if it is violated in at least one branching direction */
14828
14829 return (relerror <= threshold);
14830}
14831
14832/** check if variable pseudo-costs have a significant difference in location. The significance depends on
14833 * the choice of \p clevel and on the kind of tested hypothesis. The one-sided hypothesis, which
14834 * should be rejected, is that fracy * mu_y >= fracx * mu_x, where mu_y and mu_x denote the
14835 * unknown location means of the underlying pseudo-cost distributions of x and y.
14836 *
14837 * This method is applied best if variable x has a better pseudo-cost score than y. The method hypothesizes that y were actually
14838 * better than x (despite the current information), meaning that y can be expected to yield branching
14839 * decisions as least as good as x in the long run. If the method returns TRUE, the current history information is
14840 * sufficient to safely rely on the alternative hypothesis that x yields indeed a better branching score (on average)
14841 * than y.
14842 *
14843 * @note The order of x and y matters for the one-sided hypothesis
14844 *
14845 * @note set \p onesided to FALSE if you are not sure which variable is better. The hypothesis tested then reads
14846 * fracy * mu_y == fracx * mu_x vs the alternative hypothesis fracy * mu_y != fracx * mu_x.
14847 *
14848 * @return TRUE if the hypothesis can be safely rejected at the given confidence level
14849 */
14851 SCIP_SET* set, /**< global SCIP settings */
14852 SCIP_STAT* stat, /**< problem statistics */
14853 SCIP_VAR* varx, /**< variable x */
14854 SCIP_Real fracx, /**< the fractionality of variable x */
14855 SCIP_VAR* vary, /**< variable y */
14856 SCIP_Real fracy, /**< the fractionality of variable y */
14857 SCIP_BRANCHDIR dir, /**< branching direction */
14858 SCIP_CONFIDENCELEVEL clevel, /**< confidence level for rejecting hypothesis */
14859 SCIP_Bool onesided /**< should a one-sided hypothesis y >= x be tested? */
14860 )
14861{
14862 SCIP_Real meanx;
14863 SCIP_Real meany;
14864 SCIP_Real variancex;
14865 SCIP_Real variancey;
14866 SCIP_Real countx;
14867 SCIP_Real county;
14868 SCIP_Real tresult;
14869 SCIP_Real realdirection;
14870
14871 if( varx == vary )
14872 return FALSE;
14873
14876
14877 /* if not at least 2 measurements were taken, return FALSE */
14878 if( countx <= 1.9 || county <= 1.9 )
14879 return FALSE;
14880
14881 realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
14882
14883 meanx = fracx * SCIPvarGetPseudocost(varx, stat, realdirection);
14884 meany = fracy * SCIPvarGetPseudocost(vary, stat, realdirection);
14885
14888
14889 /* if there is no variance, the means are taken from a constant distribution */
14890 if( SCIPsetIsFeasEQ(set, variancex + variancey, 0.0) )
14891 return (onesided ? SCIPsetIsFeasGT(set, meanx, meany) : !SCIPsetIsFeasEQ(set, meanx, meany));
14892
14894
14895 /* for the two-sided hypothesis, just take the absolute of t */
14896 if( !onesided )
14898
14899 return (tresult >= SCIPstudentTGetCriticalValue(clevel, (int)(countx + county - 2)));
14900}
14901
14902/** tests at a given confidence level whether the variable pseudo-costs only have a small probability to
14903 * exceed a \p threshold. This is useful to determine if past observations provide enough evidence
14904 * to skip an expensive strong-branching step if there is already a candidate that has been proven to yield an improvement
14905 * of at least \p threshold.
14906 *
14907 * @note use \p clevel to adjust the level of confidence. For SCIP_CONFIDENCELEVEL_MIN, the method returns TRUE if
14908 * the estimated probability to exceed \p threshold is less than 25 %.
14909 *
14910 * @see SCIP_Confidencelevel for a list of available levels. The used probability limits refer to the one-sided levels
14911 * of confidence.
14912 *
14913 * @return TRUE if the variable pseudo-cost probabilistic model is likely to be smaller than \p threshold
14914 * at the given confidence level \p clevel.
14915 */
14917 SCIP_SET* set, /**< global SCIP settings */
14918 SCIP_STAT* stat, /**< problem statistics */
14919 SCIP_VAR* var, /**< variable x */
14920 SCIP_Real frac, /**< the fractionality of variable x */
14921 SCIP_Real threshold, /**< the threshold to test against */
14922 SCIP_BRANCHDIR dir, /**< branching direction */
14923 SCIP_CONFIDENCELEVEL clevel /**< confidence level for rejecting hypothesis */
14924 )
14925{
14926 SCIP_Real mean;
14927 SCIP_Real variance;
14928 SCIP_Real count;
14929 SCIP_Real realdirection;
14930 SCIP_Real probability;
14931 SCIP_Real problimit;
14932
14934
14935 /* if not at least 2 measurements were taken, return FALSE */
14936 if( count <= 1.9 )
14937 return FALSE;
14938
14939 realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
14940
14943
14944 /* if mean is at least threshold, it has at least a 50% probability to exceed threshold, we therefore return FALSE */
14946 return FALSE;
14947
14948 /* if there is no variance, the means are taken from a constant distribution */
14949 if( SCIPsetIsFeasEQ(set, variance, 0.0) )
14951
14952 /* obtain probability of a normally distributed random variable at given mean and variance to yield at most threshold */
14953 probability = SCIPnormalCDF(mean, variance, threshold);
14954
14955 /* determine a probability limit corresponding to the given confidence level */
14956 switch( clevel )
14957 {
14959 problimit = 0.75;
14960 break;
14962 problimit = 0.875;
14963 break;
14965 problimit = 0.9;
14966 break;
14968 problimit = 0.95;
14969 break;
14971 problimit = 0.975;
14972 break;
14973 default:
14974 problimit = -1;
14975 SCIPerrorMessage("Confidence level set to unknown value <%d>", (int)clevel);
14976 SCIPABORT();
14977 break;
14978 }
14979
14980 return (probability >= problimit);
14981}
14982
14983/** find the corresponding history entry if already existing, otherwise create new entry */
14984static
14986 SCIP_VAR* var, /**< problem variable */
14987 SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14988 BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14989 SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14990 SCIP_HISTORY** history /**< pointer to store the value based history, or NULL */
14991 )
14992{
14993 assert(var != NULL);
14994 assert(blkmem != NULL);
14995 assert(set != NULL);
14996 assert(history != NULL);
14997
14998 (*history) = NULL;
14999
15000 if( var->valuehistory == NULL )
15001 {
15003 }
15004
15005 SCIP_CALL( SCIPvaluehistoryFind(var->valuehistory, blkmem, set, value, history) );
15006
15007 return SCIP_OKAY;
15008}
15009
15010/** check if value based history should be used */
15011static
15013 SCIP_VAR* var, /**< problem variable */
15014 SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15015 SCIP_SET* set /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15016 )
15017{
15018 /* check if the domain value is unknown (not specific) */
15019 if( value == SCIP_UNKNOWN ) /*lint !e777*/
15020 return FALSE;
15021
15022 assert(set != NULL);
15023
15024 /* check if value based history should be collected */
15025 if( !set->history_valuebased )
15026 return FALSE;
15027
15028 /* value based history is not collected for binary variable since the standard history already contains all information */
15030 return FALSE;
15031
15032 /* value based history is not collected for continuous variables */
15034 return FALSE;
15035
15036 return TRUE;
15037}
15038
15039/** increases VSIDS of the variable by the given weight */
15041 SCIP_VAR* var, /**< problem variable */
15042 BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15043 SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15044 SCIP_STAT* stat, /**< problem statistics */
15045 SCIP_BRANCHDIR dir, /**< branching direction */
15046 SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15047 SCIP_Real weight /**< weight of this update in VSIDS */
15048 )
15049{
15050 assert(var != NULL);
15052
15053 /* check if history statistics should be collected for a variable */
15054 if( !stat->collectvarhistory )
15055 return SCIP_OKAY;
15056
15057 if( SCIPsetIsZero(set, weight) )
15058 return SCIP_OKAY;
15059
15060 switch( SCIPvarGetStatus(var) )
15061 {
15063 if( var->data.original.transvar == NULL )
15064 {
15065 SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
15066 return SCIP_INVALIDDATA;
15067 }
15068 SCIP_CALL( SCIPvarIncVSIDS(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
15069 return SCIP_OKAY;
15070
15073 {
15076
15077 if( useValuehistory(var, value, set) )
15078 {
15079 SCIP_HISTORY* history;
15080
15081 SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15082 assert(history != NULL);
15083
15084 SCIPhistoryIncVSIDS(history, dir, weight);
15085 SCIPsetDebugMsg(set, "variable (<%s> %s %g) + <%g> = <%g>\n", SCIPvarGetName(var), dir == SCIP_BRANCHDIR_UPWARDS ? ">=" : "<=",
15086 value, weight, SCIPhistoryGetVSIDS(history, dir));
15087 }
15088
15089 return SCIP_OKAY;
15090 }
15092 SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
15093 return SCIP_INVALIDDATA;
15094
15096 value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15097
15098 if( var->data.aggregate.scalar > 0.0 )
15099 {
15100 SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
15101 }
15102 else
15103 {
15104 assert(var->data.aggregate.scalar < 0.0);
15105 SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15106 }
15107 return SCIP_OKAY;
15108
15110 SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
15111 return SCIP_INVALIDDATA;
15112
15114 value = 1.0 - value;
15115
15116 SCIP_CALL( SCIPvarIncVSIDS(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15117 return SCIP_OKAY;
15118
15119 default:
15120 SCIPerrorMessage("unknown variable status\n");
15121 return SCIP_INVALIDDATA;
15122 }
15123}
15124
15125/** scales the VSIDS of the variable by the given scalar */
15127 SCIP_VAR* var, /**< problem variable */
15128 SCIP_Real scalar /**< scalar to multiply the VSIDSs with */
15129 )
15130{
15131 assert(var != NULL);
15132
15133 switch( SCIPvarGetStatus(var) )
15134 {
15136 if( var->data.original.transvar == NULL )
15137 {
15138 SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
15139 return SCIP_INVALIDDATA;
15140 }
15142 return SCIP_OKAY;
15143
15146 {
15150
15151 return SCIP_OKAY;
15152 }
15154 SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
15155 return SCIP_INVALIDDATA;
15156
15159 return SCIP_OKAY;
15160
15162 SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
15163 return SCIP_INVALIDDATA;
15164
15167 return SCIP_OKAY;
15168
15169 default:
15170 SCIPerrorMessage("unknown variable status\n");
15171 return SCIP_INVALIDDATA;
15172 }
15173}
15174
15175/** increases the number of active conflicts by one and the overall length of the variable by the given length */
15177 SCIP_VAR* var, /**< problem variable */
15178 BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15179 SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15180 SCIP_STAT* stat, /**< problem statistics */
15181 SCIP_BRANCHDIR dir, /**< branching direction */
15182 SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15183 SCIP_Real length /**< length of the conflict */
15184 )
15185{
15186 assert(var != NULL);
15188
15189 /* check if history statistics should be collected for a variable */
15190 if( !stat->collectvarhistory )
15191 return SCIP_OKAY;
15192
15193 switch( SCIPvarGetStatus(var) )
15194 {
15196 if( var->data.original.transvar == NULL )
15197 {
15198 SCIPerrorMessage("cannot update conflict score of original untransformed variable\n");
15199 return SCIP_INVALIDDATA;
15200 }
15201 SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.original.transvar, blkmem, set, stat, dir, value, length) );
15202 return SCIP_OKAY;
15203
15206 {
15209
15210 if( useValuehistory(var, value, set) )
15211 {
15212 SCIP_HISTORY* history;
15213
15214 SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15215 assert(history != NULL);
15216
15217 SCIPhistoryIncNActiveConflicts(history, dir, length);
15218 }
15219
15220 return SCIP_OKAY;
15221 }
15223 SCIPerrorMessage("cannot update conflict score of a fixed variable\n");
15224 return SCIP_INVALIDDATA;
15225
15227 value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15228
15229 if( var->data.aggregate.scalar > 0.0 )
15230 {
15231 SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, dir, value, length) );
15232 }
15233 else
15234 {
15235 assert(var->data.aggregate.scalar < 0.0);
15237 }
15238 return SCIP_OKAY;
15239
15241 SCIPerrorMessage("cannot update conflict score of a multi-aggregated variable\n");
15242 return SCIP_INVALIDDATA;
15243
15245 value = 1.0 - value;
15246
15247 SCIP_CALL( SCIPvarIncNActiveConflicts(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
15248 return SCIP_OKAY;
15249
15250 default:
15251 SCIPerrorMessage("unknown variable status\n");
15252 return SCIP_INVALIDDATA;
15253 }
15254}
15255
15256/** gets the number of active conflicts containing this variable in given direction */
15258 SCIP_VAR* var, /**< problem variable */
15259 SCIP_STAT* stat, /**< problem statistics */
15260 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15261 )
15262{
15263 assert(var != NULL);
15264 assert(stat != NULL);
15266
15267 switch( SCIPvarGetStatus(var) )
15268 {
15270 if( var->data.original.transvar == NULL )
15271 return 0;
15272 else
15274
15278
15280 return 0;
15281
15283 if( var->data.aggregate.scalar > 0.0 )
15285 else
15287
15289 return 0;
15290
15293
15294 default:
15295 SCIPerrorMessage("unknown variable status\n");
15296 SCIPABORT();
15297 return 0; /*lint !e527*/
15298 }
15299}
15300
15301/** gets the number of active conflicts containing this variable in given direction
15302 * in the current run
15303 */
15305 SCIP_VAR* var, /**< problem variable */
15306 SCIP_STAT* stat, /**< problem statistics */
15307 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15308 )
15309{
15310 assert(var != NULL);
15311 assert(stat != NULL);
15313
15314 switch( SCIPvarGetStatus(var) )
15315 {
15317 if( var->data.original.transvar == NULL )
15318 return 0;
15319 else
15321
15325
15327 return 0;
15328
15330 if( var->data.aggregate.scalar > 0.0 )
15332 else
15334
15336 return 0;
15337
15340
15341 default:
15342 SCIPerrorMessage("unknown variable status\n");
15343 SCIPABORT();
15344 return 0; /*lint !e527*/
15345 }
15346}
15347
15348/** gets the average conflict length in given direction due to branching on the variable */
15350 SCIP_VAR* var, /**< problem variable */
15351 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15352 )
15353{
15354 assert(var != NULL);
15356
15357 switch( SCIPvarGetStatus(var) )
15358 {
15360 if( var->data.original.transvar == NULL )
15361 return 0.0;
15362 else
15364
15369 return 0.0;
15370
15372 if( var->data.aggregate.scalar > 0.0 )
15374 else
15376
15378 return 0.0;
15379
15382
15383 default:
15384 SCIPerrorMessage("unknown variable status\n");
15385 SCIPABORT();
15386 return 0.0; /*lint !e527*/
15387 }
15388}
15389
15390/** gets the average conflict length in given direction due to branching on the variable
15391 * in the current run
15392 */
15394 SCIP_VAR* var, /**< problem variable */
15395 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15396 )
15397{
15398 assert(var != NULL);
15400
15401 switch( SCIPvarGetStatus(var) )
15402 {
15404 if( var->data.original.transvar == NULL )
15405 return 0.0;
15406 else
15408
15412
15414 return 0.0;
15415
15417 if( var->data.aggregate.scalar > 0.0 )
15419 else
15421
15423 return 0.0;
15424
15427
15428 default:
15429 SCIPerrorMessage("unknown variable status\n");
15430 SCIPABORT();
15431 return 0.0; /*lint !e527*/
15432 }
15433}
15434
15435/** increases the number of branchings counter of the variable */
15437 SCIP_VAR* var, /**< problem variable */
15438 BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15439 SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15440 SCIP_STAT* stat, /**< problem statistics */
15441 SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
15442 SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15443 int depth /**< depth at which the bound change took place */
15444 )
15445{
15446 assert(var != NULL);
15447 assert(stat != NULL);
15449
15450 /* check if history statistics should be collected for a variable */
15451 if( !stat->collectvarhistory )
15452 return SCIP_OKAY;
15453
15454 switch( SCIPvarGetStatus(var) )
15455 {
15457 if( var->data.original.transvar == NULL )
15458 {
15459 SCIPerrorMessage("cannot update branching counter of original untransformed variable\n");
15460 return SCIP_INVALIDDATA;
15461 }
15462 SCIP_CALL( SCIPvarIncNBranchings(var->data.original.transvar, blkmem, set, stat, dir, value, depth) );
15463 return SCIP_OKAY;
15464
15467 {
15472
15473 if( useValuehistory(var, value, set) )
15474 {
15475 SCIP_HISTORY* history;
15476
15477 SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15478 assert(history != NULL);
15479
15481 }
15482
15483 return SCIP_OKAY;
15484 }
15486 SCIPerrorMessage("cannot update branching counter of a fixed variable\n");
15487 return SCIP_INVALIDDATA;
15488
15490 value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15491
15492 if( var->data.aggregate.scalar > 0.0 )
15493 {
15494 SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, dir, value, depth) );
15495 }
15496 else
15497 {
15498 assert(var->data.aggregate.scalar < 0.0);
15500 }
15501 return SCIP_OKAY;
15502
15504 SCIPerrorMessage("cannot update branching counter of a multi-aggregated variable\n");
15505 return SCIP_INVALIDDATA;
15506
15508 value = 1.0 - value;
15509
15511 return SCIP_OKAY;
15512
15513 default:
15514 SCIPerrorMessage("unknown variable status\n");
15515 return SCIP_INVALIDDATA;
15516 }
15517}
15518
15519/** increases the inference sum of the variable by the given weight */
15521 SCIP_VAR* var, /**< problem variable */
15522 BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15523 SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15524 SCIP_STAT* stat, /**< problem statistics */
15525 SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
15526 SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15527 SCIP_Real weight /**< weight of this update in inference score */
15528 )
15529{
15530 assert(var != NULL);
15531 assert(stat != NULL);
15533
15534 /* check if history statistics should be collected for a variable */
15535 if( !stat->collectvarhistory )
15536 return SCIP_OKAY;
15537
15538 switch( SCIPvarGetStatus(var) )
15539 {
15541 if( var->data.original.transvar == NULL )
15542 {
15543 SCIPerrorMessage("cannot update inference counter of original untransformed variable\n");
15544 return SCIP_INVALIDDATA;
15545 }
15546 SCIP_CALL( SCIPvarIncInferenceSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
15547 return SCIP_OKAY;
15548
15551 {
15556
15557 if( useValuehistory(var, value, set) )
15558 {
15559 SCIP_HISTORY* history;
15560
15561 SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15562 assert(history != NULL);
15563
15564 SCIPhistoryIncInferenceSum(history, dir, weight);
15565 }
15566
15567 return SCIP_OKAY;
15568 }
15570 SCIPerrorMessage("cannot update inference counter of a fixed variable\n");
15571 return SCIP_INVALIDDATA;
15572
15574 value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15575
15576 if( var->data.aggregate.scalar > 0.0 )
15577 {
15578 SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
15579 }
15580 else
15581 {
15582 assert(var->data.aggregate.scalar < 0.0);
15583 SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15584 }
15585 return SCIP_OKAY;
15586
15588 SCIPerrorMessage("cannot update inference counter of a multi-aggregated variable\n");
15589 return SCIP_INVALIDDATA;
15590
15592 value = 1.0 - value;
15593
15594 SCIP_CALL( SCIPvarIncInferenceSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15595 return SCIP_OKAY;
15596
15597 default:
15598 SCIPerrorMessage("unknown variable status\n");
15599 return SCIP_INVALIDDATA;
15600 }
15601}
15602
15603/** increases the cutoff sum of the variable by the given weight */
15605 SCIP_VAR* var, /**< problem variable */
15606 BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15607 SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15608 SCIP_STAT* stat, /**< problem statistics */
15609 SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
15610 SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15611 SCIP_Real weight /**< weight of this update in cutoff score */
15612 )
15613{
15614 assert(var != NULL);
15615 assert(stat != NULL);
15617
15618 /* check if history statistics should be collected for a variable */
15619 if( !stat->collectvarhistory )
15620 return SCIP_OKAY;
15621
15622 switch( SCIPvarGetStatus(var) )
15623 {
15625 if( var->data.original.transvar == NULL )
15626 {
15627 SCIPerrorMessage("cannot update cutoff sum of original untransformed variable\n");
15628 return SCIP_INVALIDDATA;
15629 }
15630 SCIP_CALL( SCIPvarIncCutoffSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
15631 return SCIP_OKAY;
15632
15635 {
15638 SCIPhistoryIncCutoffSum(stat->glbhistory, dir, weight);
15640
15641 if( useValuehistory(var, value, set) )
15642 {
15643 SCIP_HISTORY* history;
15644
15645 SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15646 assert(history != NULL);
15647
15648 SCIPhistoryIncCutoffSum(history, dir, weight);
15649 }
15650
15651 return SCIP_OKAY;
15652 }
15654 SCIPerrorMessage("cannot update cutoff sum of a fixed variable\n");
15655 return SCIP_INVALIDDATA;
15656
15658 value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15659
15660 if( var->data.aggregate.scalar > 0.0 )
15661 {
15662 SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
15663 }
15664 else
15665 {
15666 assert(var->data.aggregate.scalar < 0.0);
15667 SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15668 }
15669 return SCIP_OKAY;
15670
15672 SCIPerrorMessage("cannot update cutoff sum of a multi-aggregated variable\n");
15673 return SCIP_INVALIDDATA;
15674
15676 value = 1.0 - value;
15677
15678 SCIP_CALL( SCIPvarIncCutoffSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15679 return SCIP_OKAY;
15680
15681 default:
15682 SCIPerrorMessage("unknown variable status\n");
15683 return SCIP_INVALIDDATA;
15684 }
15685}
15686
15687/** returns the number of times, a bound of the variable was changed in given direction due to branching */
15689 SCIP_VAR* var, /**< problem variable */
15690 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15691 )
15692{
15693 assert(var != NULL);
15695
15696 switch( SCIPvarGetStatus(var) )
15697 {
15699 if( var->data.original.transvar == NULL )
15700 return 0;
15701 else
15703
15707
15709 return 0;
15710
15712 if( var->data.aggregate.scalar > 0.0 )
15714 else
15716
15718 return 0;
15719
15722
15723 default:
15724 SCIPerrorMessage("unknown variable status\n");
15725 SCIPABORT();
15726 return 0; /*lint !e527*/
15727 }
15728}
15729
15730/** returns the number of times, a bound of the variable was changed in given direction due to branching
15731 * in the current run
15732 */
15734 SCIP_VAR* var, /**< problem variable */
15735 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15736 )
15737{
15738 assert(var != NULL);
15740
15741 switch( SCIPvarGetStatus(var) )
15742 {
15744 if( var->data.original.transvar == NULL )
15745 return 0;
15746 else
15748
15752
15754 return 0;
15755
15757 if( var->data.aggregate.scalar > 0.0 )
15759 else
15761
15763 return 0;
15764
15767
15768 default:
15769 SCIPerrorMessage("unknown variable status\n");
15770 SCIPABORT();
15771 return 0; /*lint !e527*/
15772 }
15773}
15774
15775/** returns the average depth of bound changes in given direction due to branching on the variable */
15777 SCIP_VAR* var, /**< problem variable */
15778 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15779 )
15780{
15781 assert(var != NULL);
15783
15784 switch( SCIPvarGetStatus(var) )
15785 {
15787 if( var->data.original.transvar == NULL )
15788 return 0.0;
15789 else
15791
15795
15797 return 0.0;
15798
15800 if( var->data.aggregate.scalar > 0.0 )
15802 else
15804
15806 return 0.0;
15807
15810
15811 default:
15812 SCIPerrorMessage("unknown variable status\n");
15813 SCIPABORT();
15814 return 0.0; /*lint !e527*/
15815 }
15816}
15817
15818/** returns the average depth of bound changes in given direction due to branching on the variable
15819 * in the current run
15820 */
15822 SCIP_VAR* var, /**< problem variable */
15823 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15824 )
15825{
15826 assert(var != NULL);
15828
15829 switch( SCIPvarGetStatus(var) )
15830 {
15832 if( var->data.original.transvar == NULL )
15833 return 0.0;
15834 else
15836
15840
15842 return 0.0;
15843
15845 if( var->data.aggregate.scalar > 0.0 )
15847 else
15850
15852 return 0.0;
15853
15857
15858 default:
15859 SCIPerrorMessage("unknown variable status\n");
15860 SCIPABORT();
15861 return 0.0; /*lint !e527*/
15862 }
15863}
15864
15865/** returns the variable's VSIDS score */
15867 SCIP_VAR* var, /**< problem variable */
15868 SCIP_STAT* stat, /**< problem statistics */
15869 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15870 )
15871{
15872 assert(var != NULL);
15873 assert(stat != NULL);
15875
15877 return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
15878
15879 switch( SCIPvarGetStatus(var) )
15880 {
15882 if( var->data.original.transvar == NULL )
15883 return 0.0;
15884 else
15885 return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
15886
15889 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE); /* column case already handled in if condition above */
15891
15893 return 0.0;
15894
15896 if( var->data.aggregate.scalar > 0.0 )
15897 return SCIPvarGetVSIDS(var->data.aggregate.var, stat, dir);
15898 else
15899 /* coverity[overrun-local] */
15901
15903 return 0.0;
15904
15906 /* coverity[overrun-local] */
15908
15909 default:
15910 SCIPerrorMessage("unknown variable status\n");
15911 SCIPABORT();
15912 return 0.0; /*lint !e527*/
15913 }
15914}
15915
15916/** returns the variable's VSIDS score only using conflicts of the current run */
15918 SCIP_VAR* var, /**< problem variable */
15919 SCIP_STAT* stat, /**< problem statistics */
15920 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15921 )
15922{
15923 assert(var != NULL);
15924 assert(stat != NULL);
15926
15928 {
15929 SCIPerrorMessage("invalid branching direction %d when asking for VSIDS value\n", dir);
15930 return SCIP_INVALID;
15931 }
15932
15933 switch( SCIPvarGetStatus(var) )
15934 {
15936 if( var->data.original.transvar == NULL )
15937 return 0.0;
15938 else
15940
15944
15946 return 0.0;
15947
15949 if( var->data.aggregate.scalar > 0.0 )
15951 else
15953
15955 return 0.0;
15956
15959
15960 default:
15961 SCIPerrorMessage("unknown variable status\n");
15962 SCIPABORT();
15963 return 0.0; /*lint !e527*/
15964 }
15965}
15966
15967/** returns the number of inferences branching on this variable in given direction triggered */
15969 SCIP_VAR* var, /**< problem variable */
15970 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15971 )
15972{
15973 assert(var != NULL);
15975
15976 switch( SCIPvarGetStatus(var) )
15977 {
15979 if( var->data.original.transvar == NULL )
15980 return 0.0;
15981 else
15983
15987
15989 return 0.0;
15990
15992 if( var->data.aggregate.scalar > 0.0 )
15994 else
15996
15998 return 0.0;
15999
16002
16003 default:
16004 SCIPerrorMessage("unknown variable status\n");
16005 SCIPABORT();
16006 return 0.0; /*lint !e527*/
16007 }
16008}
16009
16010/** returns the number of inferences branching on this variable in given direction triggered
16011 * in the current run
16012 */
16014 SCIP_VAR* var, /**< problem variable */
16015 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16016 )
16017{
16018 assert(var != NULL);
16020
16021 switch( SCIPvarGetStatus(var) )
16022 {
16024 if( var->data.original.transvar == NULL )
16025 return 0.0;
16026 else
16028
16032
16034 return 0.0;
16035
16037 if( var->data.aggregate.scalar > 0.0 )
16039 else
16041
16043 return 0.0;
16044
16047
16048 default:
16049 SCIPerrorMessage("unknown variable status\n");
16050 SCIPABORT();
16051 return 0.0; /*lint !e527*/
16052 }
16053}
16054
16055/** returns the average number of inferences found after branching on the variable in given direction */
16057 SCIP_VAR* var, /**< problem variable */
16058 SCIP_STAT* stat, /**< problem statistics */
16059 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16060 )
16061{
16062 assert(var != NULL);
16063 assert(stat != NULL);
16065
16066 switch( SCIPvarGetStatus(var) )
16067 {
16069 if( var->data.original.transvar == NULL )
16071 else
16073
16078 else
16079 {
16080 int nimpls;
16081 int ncliques;
16082
16085 return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistory, dir); /*lint !e790*/
16086 }
16087
16089 return 0.0;
16090
16092 if( var->data.aggregate.scalar > 0.0 )
16094 else
16096
16098 return 0.0;
16099
16102
16103 default:
16104 SCIPerrorMessage("unknown variable status\n");
16105 SCIPABORT();
16106 return 0.0; /*lint !e527*/
16107 }
16108}
16109
16110/** returns the average number of inferences found after branching on the variable in given direction
16111 * in the current run
16112 */
16114 SCIP_VAR* var, /**< problem variable */
16115 SCIP_STAT* stat, /**< problem statistics */
16116 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16117 )
16118{
16119 assert(var != NULL);
16120 assert(stat != NULL);
16122
16123 switch( SCIPvarGetStatus(var) )
16124 {
16126 if( var->data.original.transvar == NULL )
16128 else
16130
16135 else
16136 {
16137 int nimpls;
16138 int ncliques;
16139
16142 return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir); /*lint !e790*/
16143 }
16144
16146 return 0.0;
16147
16149 if( var->data.aggregate.scalar > 0.0 )
16151 else
16153
16155 return 0.0;
16156
16159
16160 default:
16161 SCIPerrorMessage("unknown variable status\n");
16162 SCIPABORT();
16163 return 0.0; /*lint !e527*/
16164 }
16165}
16166
16167/** returns the number of cutoffs branching on this variable in given direction produced */
16169 SCIP_VAR* var, /**< problem variable */
16170 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16171 )
16172{
16173 assert(var != NULL);
16175
16176 switch( SCIPvarGetStatus(var) )
16177 {
16179 if( var->data.original.transvar == NULL )
16180 return 0;
16181 else
16183
16187
16189 return 0;
16190
16192 if( var->data.aggregate.scalar > 0.0 )
16194 else
16196
16198 return 0;
16199
16202
16203 default:
16204 SCIPerrorMessage("unknown variable status\n");
16205 SCIPABORT();
16206 return 0; /*lint !e527*/
16207 }
16208}
16209
16210/** returns the number of cutoffs branching on this variable in given direction produced in the current run */
16212 SCIP_VAR* var, /**< problem variable */
16213 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16214 )
16215{
16216 assert(var != NULL);
16218
16219 switch( SCIPvarGetStatus(var) )
16220 {
16222 if( var->data.original.transvar == NULL )
16223 return 0;
16224 else
16226
16230
16232 return 0;
16233
16235 if( var->data.aggregate.scalar > 0.0 )
16237 else
16239
16241 return 0;
16242
16245
16246 default:
16247 SCIPerrorMessage("unknown variable status\n");
16248 SCIPABORT();
16249 return 0; /*lint !e527*/
16250 }
16251}
16252
16253/** returns the average number of cutoffs found after branching on the variable in given direction */
16255 SCIP_VAR* var, /**< problem variable */
16256 SCIP_STAT* stat, /**< problem statistics */
16257 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16258 )
16259{
16260 assert(var != NULL);
16261 assert(stat != NULL);
16263
16264 switch( SCIPvarGetStatus(var) )
16265 {
16267 if( var->data.original.transvar == NULL )
16269 else
16271
16277
16279 return 0.0;
16280
16282 if( var->data.aggregate.scalar > 0.0 )
16283 return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, dir);
16284 else
16286
16288 return 0.0;
16289
16292
16293 default:
16294 SCIPerrorMessage("unknown variable status\n");
16295 SCIPABORT();
16296 return 0.0; /*lint !e527*/
16297 }
16298}
16299
16300/** returns the average number of cutoffs found after branching on the variable in given direction in the current run */
16302 SCIP_VAR* var, /**< problem variable */
16303 SCIP_STAT* stat, /**< problem statistics */
16304 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16305 )
16306{
16307 assert(var != NULL);
16308 assert(stat != NULL);
16310
16311 switch( SCIPvarGetStatus(var) )
16312 {
16314 if( var->data.original.transvar == NULL )
16316 else
16318
16324
16326 return 0.0;
16327
16329 if( var->data.aggregate.scalar > 0.0 )
16331 else
16333
16335 return 0.0;
16336
16339
16340 default:
16341 SCIPerrorMessage("unknown variable status\n");
16342 SCIPABORT();
16343 return 0.0; /*lint !e527*/
16344 }
16345}
16346
16347
16348
16349
16350/*
16351 * information methods for bound changes
16352 */
16353
16354/** creates an artificial bound change information object with depth = INT_MAX and pos = -1 */
16356 SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
16357 BMS_BLKMEM* blkmem, /**< block memory */
16358 SCIP_VAR* var, /**< active variable that changed the bounds */
16359 SCIP_BOUNDTYPE boundtype, /**< type of bound for var: lower or upper bound */
16360 SCIP_Real oldbound, /**< old value for bound */
16361 SCIP_Real newbound /**< new value for bound */
16362 )
16363{
16364 assert(bdchginfo != NULL);
16365
16367 (*bdchginfo)->oldbound = oldbound;
16368 (*bdchginfo)->newbound = newbound;
16369 (*bdchginfo)->var = var;
16370 (*bdchginfo)->inferencedata.var = var;
16371 (*bdchginfo)->inferencedata.reason.prop = NULL;
16372 (*bdchginfo)->inferencedata.info = 0;
16373 (*bdchginfo)->bdchgidx.depth = INT_MAX;
16374 (*bdchginfo)->bdchgidx.pos = -1;
16375 (*bdchginfo)->pos = 0;
16376 (*bdchginfo)->boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
16377 (*bdchginfo)->boundtype = boundtype; /*lint !e641*/
16378 (*bdchginfo)->inferboundtype = boundtype; /*lint !e641*/
16379 (*bdchginfo)->redundant = FALSE;
16380
16381 return SCIP_OKAY;
16382}
16383
16384/** frees a bound change information object */
16386 SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
16387 BMS_BLKMEM* blkmem /**< block memory */
16388 )
16389{
16390 assert(bdchginfo != NULL);
16391
16393}
16394
16395/** returns the bound change information for the last lower bound change on given active problem variable before or
16396 * after the bound change with the given index was applied;
16397 * returns NULL, if no change to the lower bound was applied up to this point of time
16398 */
16400 SCIP_VAR* var, /**< active problem variable */
16401 SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16402 SCIP_Bool after /**< should the bound change with given index be included? */
16403 )
16404{
16405 int i;
16406
16407 assert(var != NULL);
16409
16410 /* search the correct bound change information for the given bound change index */
16411 if( after )
16412 {
16413 for( i = var->nlbchginfos-1; i >= 0; --i )
16414 {
16415 assert(var->lbchginfos[i].var == var);
16417 assert(var->lbchginfos[i].pos == i);
16418
16419 /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16420 if( var->lbchginfos[i].redundant )
16421 return NULL;
16423
16424 /* if we reached the bound change index, return the current bound change info */
16425 if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->lbchginfos[i].bdchgidx) )
16426 return &var->lbchginfos[i];
16427 }
16428 }
16429 else
16430 {
16431 for( i = var->nlbchginfos-1; i >= 0; --i )
16432 {
16433 assert(var->lbchginfos[i].var == var);
16435 assert(var->lbchginfos[i].pos == i);
16436
16437 /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16438 if( var->lbchginfos[i].redundant )
16439 return NULL;
16441
16442 /* if we reached the bound change index, return the current bound change info */
16443 if( SCIPbdchgidxIsEarlier(&var->lbchginfos[i].bdchgidx, bdchgidx) )
16444 return &var->lbchginfos[i];
16445 }
16446 }
16447
16448 return NULL;
16449}
16450
16451/** returns the bound change information for the last upper bound change on given active problem variable before or
16452 * after the bound change with the given index was applied;
16453 * returns NULL, if no change to the upper bound was applied up to this point of time
16454 */
16456 SCIP_VAR* var, /**< active problem variable */
16457 SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16458 SCIP_Bool after /**< should the bound change with given index be included? */
16459 )
16460{
16461 int i;
16462
16463 assert(var != NULL);
16465
16466 /* search the correct bound change information for the given bound change index */
16467 if( after )
16468 {
16469 for( i = var->nubchginfos-1; i >= 0; --i )
16470 {
16471 assert(var->ubchginfos[i].var == var);
16473 assert(var->ubchginfos[i].pos == i);
16474
16475 /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16476 if( var->ubchginfos[i].redundant )
16477 return NULL;
16479
16480 /* if we reached the bound change index, return the current bound change info */
16481 if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->ubchginfos[i].bdchgidx) )
16482 return &var->ubchginfos[i];
16483 }
16484 }
16485 else
16486 {
16487 for( i = var->nubchginfos-1; i >= 0; --i )
16488 {
16489 assert(var->ubchginfos[i].var == var);
16491 assert(var->ubchginfos[i].pos == i);
16492
16493 /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16494 if( var->ubchginfos[i].redundant )
16495 return NULL;
16497
16498 /* if we reached the bound change index, return the current bound change info */
16499 if( SCIPbdchgidxIsEarlier(&var->ubchginfos[i].bdchgidx, bdchgidx) )
16500 return &var->ubchginfos[i];
16501 }
16502 }
16503
16504 return NULL;
16505}
16506
16507/** returns the bound change information for the last lower or upper bound change on given active problem variable
16508 * before or after the bound change with the given index was applied;
16509 * returns NULL, if no change to the lower/upper bound was applied up to this point of time
16510 */
16512 SCIP_VAR* var, /**< active problem variable */
16513 SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
16514 SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16515 SCIP_Bool after /**< should the bound change with given index be included? */
16516 )
16517{
16518 if( boundtype == SCIP_BOUNDTYPE_LOWER )
16519 return SCIPvarGetLbchgInfo(var, bdchgidx, after);
16520 else
16521 {
16522 assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16523 return SCIPvarGetUbchgInfo(var, bdchgidx, after);
16524 }
16525}
16526
16527/** returns lower bound of variable directly before or after the bound change given by the bound change index
16528 * was applied
16529 *
16530 * @deprecated Please use SCIPgetVarLbAtIndex()
16531 */
16533 SCIP_VAR* var, /**< problem variable */
16534 SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16535 SCIP_Bool after /**< should the bound change with given index be included? */
16536 )
16537{
16538 SCIP_VARSTATUS varstatus;
16539 assert(var != NULL);
16540
16541 varstatus = SCIPvarGetStatus(var);
16542
16543 /* get bounds of attached variables */
16544 switch( varstatus )
16545 {
16548 return SCIPvarGetLbAtIndex(var->data.original.transvar, bdchgidx, after);
16549
16552 if( bdchgidx == NULL )
16553 return SCIPvarGetLbLocal(var);
16554 else
16555 {
16557
16558 bdchginfo = SCIPvarGetLbchgInfo(var, bdchgidx, after);
16559 if( bdchginfo != NULL )
16561 else
16562 return var->glbdom.lb;
16563 }
16565 return var->glbdom.lb;
16566
16567 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
16569 /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
16570 * corresponding infinity value instead of performing an arithmetical transformation (compare method
16571 * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
16572 * (or is called by) a public interface method; instead, we only assert that values are finite
16573 * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
16574 * positives and negatives if the parameter <numerics/infinity> is modified by the user
16575 */
16576 if( var->data.aggregate.scalar > 0.0 )
16577 {
16578 /* a > 0 -> get lower bound of y */
16583 }
16584 else if( var->data.aggregate.scalar < 0.0 )
16585 {
16586 /* a < 0 -> get upper bound of y */
16591 }
16592 else
16593 {
16594 SCIPerrorMessage("scalar is zero in aggregation\n");
16595 SCIPABORT();
16596 return SCIP_INVALID; /*lint !e527*/
16597 }
16598
16600 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
16601 if ( var->data.multaggr.nvars == 1 )
16602 {
16605 assert(var->data.multaggr.vars[0] != NULL);
16606
16607 if( var->data.multaggr.scalars[0] > 0.0 )
16608 {
16609 /* a > 0 -> get lower bound of y */
16612 return var->data.multaggr.scalars[0] * SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16614 }
16615 else if( var->data.multaggr.scalars[0] < 0.0 )
16616 {
16617 /* a < 0 -> get upper bound of y */
16620 return var->data.multaggr.scalars[0] * SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16622 }
16623 else
16624 {
16625 SCIPerrorMessage("scalar is zero in multi-aggregation\n");
16626 SCIPABORT();
16627 return SCIP_INVALID; /*lint !e527*/
16628 }
16629 }
16630 SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
16631 SCIPABORT();
16632 return SCIP_INVALID; /*lint !e527*/
16633
16634 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
16639 default:
16640 SCIPerrorMessage("unknown variable status\n");
16641 SCIPABORT();
16642 return SCIP_INVALID; /*lint !e527*/
16643 }
16644}
16645
16646/** returns upper bound of variable directly before or after the bound change given by the bound change index
16647 * was applied
16648 *
16649 * @deprecated Please use SCIPgetVarUbAtIndex()
16650 */
16652 SCIP_VAR* var, /**< problem variable */
16653 SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16654 SCIP_Bool after /**< should the bound change with given index be included? */
16655 )
16656{
16657 SCIP_VARSTATUS varstatus;
16658 assert(var != NULL);
16659
16660 varstatus = SCIPvarGetStatus(var);
16661
16662 /* get bounds of attached variables */
16663 switch( varstatus )
16664 {
16667 return SCIPvarGetUbAtIndex(var->data.original.transvar, bdchgidx, after);
16668
16671 if( bdchgidx == NULL )
16672 return SCIPvarGetUbLocal(var);
16673 else
16674 {
16676
16677 bdchginfo = SCIPvarGetUbchgInfo(var, bdchgidx, after);
16678 if( bdchginfo != NULL )
16680 else
16681 return var->glbdom.ub;
16682 }
16683
16685 return var->glbdom.ub;
16686
16687 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
16689 /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
16690 * corresponding infinity value instead of performing an arithmetical transformation (compare method
16691 * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
16692 * (or is called by) a public interface method; instead, we only assert that values are finite
16693 * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
16694 * positives and negatives if the parameter <numerics/infinity> is modified by the user
16695 */
16696 if( var->data.aggregate.scalar > 0.0 )
16697 {
16698 /* a > 0 -> get lower bound of y */
16703 }
16704 else if( var->data.aggregate.scalar < 0.0 )
16705 {
16706 /* a < 0 -> get upper bound of y */
16711 }
16712 else
16713 {
16714 SCIPerrorMessage("scalar is zero in aggregation\n");
16715 SCIPABORT();
16716 return SCIP_INVALID; /*lint !e527*/
16717 }
16718
16720 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
16721 if ( var->data.multaggr.nvars == 1 )
16722 {
16725 assert(var->data.multaggr.vars[0] != NULL);
16726
16727 if( var->data.multaggr.scalars[0] > 0.0 )
16728 {
16729 /* a > 0 -> get lower bound of y */
16732 return var->data.multaggr.scalars[0] * SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16734 }
16735 else if( var->data.multaggr.scalars[0] < 0.0 )
16736 {
16737 /* a < 0 -> get upper bound of y */
16740 return var->data.multaggr.scalars[0] * SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16742 }
16743 else
16744 {
16745 SCIPerrorMessage("scalar is zero in multi-aggregation\n");
16746 SCIPABORT();
16747 return SCIP_INVALID; /*lint !e527*/
16748 }
16749 }
16750 SCIPerrorMessage("cannot get the bounds of a multiple aggregated variable.\n");
16751 SCIPABORT();
16752 return SCIP_INVALID; /*lint !e527*/
16753
16754 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
16759
16760 default:
16761 SCIPerrorMessage("unknown variable status\n");
16762 SCIPABORT();
16763 return SCIP_INVALID; /*lint !e527*/
16764 }
16765}
16766
16767/** returns lower or upper bound of variable directly before or after the bound change given by the bound change index
16768 * was applied
16769 *
16770 * @deprecated Please use SCIPgetVarBdAtIndex()
16771 */
16773 SCIP_VAR* var, /**< problem variable */
16774 SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
16775 SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16776 SCIP_Bool after /**< should the bound change with given index be included? */
16777 )
16778{
16779 if( boundtype == SCIP_BOUNDTYPE_LOWER )
16780 return SCIPvarGetLbAtIndex(var, bdchgidx, after);
16781 else
16782 {
16783 assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16784 return SCIPvarGetUbAtIndex(var, bdchgidx, after);
16785 }
16786}
16787
16788/** returns whether the binary variable was fixed at the time given by the bound change index
16789 *
16790 * @deprecated Please use SCIPgetVarWasFixedAtIndex()
16791 */
16793 SCIP_VAR* var, /**< problem variable */
16794 SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16795 SCIP_Bool after /**< should the bound change with given index be included? */
16796 )
16797{
16798 assert(var != NULL);
16800
16801 /* check the current bounds first in order to decide at which bound change information we have to look
16802 * (which is expensive because we have to follow the aggregation tree to the active variable)
16803 */
16804 return ((SCIPvarGetLbLocal(var) > 0.5 && SCIPvarGetLbAtIndex(var, bdchgidx, after) > 0.5)
16805 || (SCIPvarGetUbLocal(var) < 0.5 && SCIPvarGetUbAtIndex(var, bdchgidx, after) < 0.5));
16806}
16807
16808/** bound change index representing the initial time before any bound changes took place */
16810
16811/** bound change index representing the presolving stage */
16813
16814/** returns the last bound change index, at which the bounds of the given variable were tightened */
16816 SCIP_VAR* var /**< problem variable */
16817 )
16818{
16821
16822 assert(var != NULL);
16823
16825
16826 /* check, if variable is original without transformed variable */
16827 if( var == NULL )
16828 return &initbdchgidx;
16829
16830 /* check, if variable was fixed in presolving */
16831 if( !SCIPvarIsActive(var) )
16832 return &presolvebdchgidx;
16833
16835
16836 /* get depths of last bound change information for the lower and upper bound */
16841
16843 return ubchgidx;
16844 else
16845 return lbchgidx;
16846}
16847
16848/** returns the last depth level, at which the bounds of the given variable were tightened;
16849 * returns -2, if the variable's bounds are still the global bounds
16850 * returns -1, if the variable was fixed in presolving
16851 */
16853 SCIP_VAR* var /**< problem variable */
16854 )
16855{
16856 SCIP_BDCHGIDX* bdchgidx;
16857
16858 bdchgidx = SCIPvarGetLastBdchgIndex(var);
16859 assert(bdchgidx != NULL);
16860
16861 return bdchgidx->depth;
16862}
16863
16864/** returns at which depth in the tree a bound change was applied to the variable that conflicts with the
16865 * given bound; returns -1 if the bound does not conflict with the current local bounds of the variable
16866 */
16868 SCIP_VAR* var, /**< problem variable */
16869 SCIP_SET* set, /**< global SCIP settings */
16870 SCIP_BOUNDTYPE boundtype, /**< bound type of the conflicting bound */
16871 SCIP_Real bound /**< conflicting bound */
16872 )
16873{
16874 int i;
16875
16876 assert(var != NULL);
16877 assert(set != NULL);
16878 assert(var->scip == set->scip);
16879
16880 if( boundtype == SCIP_BOUNDTYPE_LOWER )
16881 {
16882 /* check if the bound is in conflict with the current local bounds */
16883 if( SCIPsetIsLE(set, bound, var->locdom.ub) )
16884 return -1;
16885
16886 /* check if the bound is in conflict with the global bound */
16887 if( SCIPsetIsGT(set, bound, var->glbdom.ub) )
16888 return 0;
16889
16890 /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
16891 assert(var->nubchginfos > 0);
16893
16894 /* search for the first conflicting bound change */
16895 for( i = var->nubchginfos-1; i > 0 && SCIPsetIsGT(set, bound, var->ubchginfos[i-1].newbound); --i )
16896 {
16897 assert(var->ubchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
16899 }
16900 assert(SCIPsetIsGT(set, bound, var->ubchginfos[i].newbound)); /* bound change i is conflicting */
16901 assert(i == 0 || SCIPsetIsLE(set, bound, var->ubchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
16902
16903 /* return the depth at which the first conflicting bound change took place */
16904 return var->ubchginfos[i].bdchgidx.depth;
16905 }
16906 else
16907 {
16908 assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16909
16910 /* check if the bound is in conflict with the current local bounds */
16911 if( SCIPsetIsGE(set, bound, var->locdom.lb) )
16912 return -1;
16913
16914 /* check if the bound is in conflict with the global bound */
16915 if( SCIPsetIsLT(set, bound, var->glbdom.lb) )
16916 return 0;
16917
16918 /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
16919 assert(var->nlbchginfos > 0);
16921
16922 /* search for the first conflicting bound change */
16923 for( i = var->nlbchginfos-1; i > 0 && SCIPsetIsLT(set, bound, var->lbchginfos[i-1].newbound); --i )
16924 {
16925 assert(var->lbchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
16927 }
16928 assert(SCIPsetIsLT(set, bound, var->lbchginfos[i].newbound)); /* bound change i is conflicting */
16929 assert(i == 0 || SCIPsetIsGE(set, bound, var->lbchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
16930
16931 /* return the depth at which the first conflicting bound change took place */
16932 return var->lbchginfos[i].bdchgidx.depth;
16933 }
16934}
16935
16936/** returns whether the first binary variable was fixed earlier than the second one;
16937 * returns FALSE, if the first variable is not fixed, and returns TRUE, if the first variable is fixed, but the
16938 * second one is not fixed
16939 */
16941 SCIP_VAR* var1, /**< first binary variable */
16942 SCIP_VAR* var2 /**< second binary variable */
16943 )
16944{
16947
16948 assert(var1 != NULL);
16949 assert(var2 != NULL);
16952
16955 assert(var1 != NULL);
16956 assert(var2 != NULL);
16957
16958 /* check, if variables are globally fixed */
16959 if( !SCIPvarIsActive(var2) || var2->glbdom.lb > 0.5 || var2->glbdom.ub < 0.5 )
16960 return FALSE;
16961 if( !SCIPvarIsActive(var1) || var1->glbdom.lb > 0.5 || var1->glbdom.ub < 0.5 )
16962 return TRUE;
16963
16968 assert(var1->nlbchginfos + var1->nubchginfos <= 1);
16969 assert(var2->nlbchginfos + var2->nubchginfos <= 1);
16970 assert(var1->nlbchginfos == 0 || !var1->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
16971 assert(var1->nubchginfos == 0 || !var1->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
16972 assert(var2->nlbchginfos == 0 || !var2->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
16973 assert(var2->nubchginfos == 0 || !var2->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
16974
16975 if( var1->nlbchginfos == 1 )
16976 bdchgidx1 = &var1->lbchginfos[0].bdchgidx;
16977 else if( var1->nubchginfos == 1 )
16978 bdchgidx1 = &var1->ubchginfos[0].bdchgidx;
16979 else
16980 bdchgidx1 = NULL;
16981
16982 if( var2->nlbchginfos == 1 )
16983 bdchgidx2 = &var2->lbchginfos[0].bdchgidx;
16984 else if( var2->nubchginfos == 1 )
16985 bdchgidx2 = &var2->ubchginfos[0].bdchgidx;
16986 else
16987 bdchgidx2 = NULL;
16988
16990}
16991
16992
16993
16994/*
16995 * Hash functions
16996 */
16997
16998/** gets the key (i.e. the name) of the given variable */
17000{ /*lint --e{715}*/
17002
17003 assert(var != NULL);
17004 return var->name;
17005}
17006
17007
17008
17009
17010/*
17011 * simple functions implemented as defines
17012 */
17013
17014/* In debug mode, the following methods are implemented as function calls to ensure
17015 * type validity.
17016 * In optimized mode, the methods are implemented as defines to improve performance.
17017 * However, we want to have them in the library anyways, so we have to undef the defines.
17018 */
17019
17020#undef SCIPboundchgGetNewbound
17021#undef SCIPboundchgGetVar
17022#undef SCIPboundchgGetBoundchgtype
17023#undef SCIPboundchgGetBoundtype
17024#undef SCIPboundchgIsRedundant
17025#undef SCIPdomchgGetNBoundchgs
17026#undef SCIPdomchgGetBoundchg
17027#undef SCIPholelistGetLeft
17028#undef SCIPholelistGetRight
17029#undef SCIPholelistGetNext
17030#undef SCIPvarGetName
17031#undef SCIPvarGetNUses
17032#undef SCIPvarGetData
17033#undef SCIPvarSetData
17034#undef SCIPvarSetDelorigData
17035#undef SCIPvarSetTransData
17036#undef SCIPvarSetDeltransData
17037#undef SCIPvarGetStatus
17038#undef SCIPvarIsOriginal
17039#undef SCIPvarIsTransformed
17040#undef SCIPvarIsNegated
17041#undef SCIPvarGetType
17042#undef SCIPvarIsBinary
17043#undef SCIPvarIsIntegral
17044#undef SCIPvarIsInitial
17045#undef SCIPvarIsRemovable
17046#undef SCIPvarIsDeleted
17047#undef SCIPvarIsDeletable
17048#undef SCIPvarMarkDeletable
17049#undef SCIPvarMarkNotDeletable
17050#undef SCIPvarIsActive
17051#undef SCIPvarGetIndex
17052#undef SCIPvarGetProbindex
17053#undef SCIPvarGetTransVar
17054#undef SCIPvarGetCol
17055#undef SCIPvarIsInLP
17056#undef SCIPvarGetAggrVar
17057#undef SCIPvarGetAggrScalar
17058#undef SCIPvarGetAggrConstant
17059#undef SCIPvarGetMultaggrNVars
17060#undef SCIPvarGetMultaggrVars
17061#undef SCIPvarGetMultaggrScalars
17062#undef SCIPvarGetMultaggrConstant
17063#undef SCIPvarGetNegatedVar
17064#undef SCIPvarGetNegationVar
17065#undef SCIPvarGetNegationConstant
17066#undef SCIPvarGetObj
17067#undef SCIPvarGetLbOriginal
17068#undef SCIPvarGetUbOriginal
17069#undef SCIPvarGetHolelistOriginal
17070#undef SCIPvarGetLbGlobal
17071#undef SCIPvarGetUbGlobal
17072#undef SCIPvarGetHolelistGlobal
17073#undef SCIPvarGetBestBoundGlobal
17074#undef SCIPvarGetWorstBoundGlobal
17075#undef SCIPvarGetLbLocal
17076#undef SCIPvarGetUbLocal
17077#undef SCIPvarGetHolelistLocal
17078#undef SCIPvarGetBestBoundLocal
17079#undef SCIPvarGetWorstBoundLocal
17080#undef SCIPvarGetBestBoundType
17081#undef SCIPvarGetWorstBoundType
17082#undef SCIPvarGetLbLazy
17083#undef SCIPvarGetUbLazy
17084#undef SCIPvarGetBranchFactor
17085#undef SCIPvarGetBranchPriority
17086#undef SCIPvarGetBranchDirection
17087#undef SCIPvarGetNVlbs
17088#undef SCIPvarGetVlbVars
17089#undef SCIPvarGetVlbCoefs
17090#undef SCIPvarGetVlbConstants
17091#undef SCIPvarGetNVubs
17092#undef SCIPvarGetVubVars
17093#undef SCIPvarGetVubCoefs
17094#undef SCIPvarGetVubConstants
17095#undef SCIPvarGetNImpls
17096#undef SCIPvarGetImplVars
17097#undef SCIPvarGetImplTypes
17098#undef SCIPvarGetImplBounds
17099#undef SCIPvarGetImplIds
17100#undef SCIPvarGetNCliques
17101#undef SCIPvarGetCliques
17102#undef SCIPvarGetLPSol
17103#undef SCIPvarGetNLPSol
17104#undef SCIPvarGetBdchgInfoLb
17105#undef SCIPvarGetNBdchgInfosLb
17106#undef SCIPvarGetBdchgInfoUb
17107#undef SCIPvarGetNBdchgInfosUb
17108#undef SCIPvarGetValuehistory
17109#undef SCIPvarGetPseudoSol
17110#undef SCIPvarCatchEvent
17111#undef SCIPvarDropEvent
17112#undef SCIPvarGetVSIDS
17113#undef SCIPvarGetCliqueComponentIdx
17114#undef SCIPvarIsRelaxationOnly
17115#undef SCIPvarMarkRelaxationOnly
17116#undef SCIPbdchgidxGetPos
17117#undef SCIPbdchgidxIsEarlierNonNull
17118#undef SCIPbdchgidxIsEarlier
17119#undef SCIPbdchginfoGetOldbound
17120#undef SCIPbdchginfoGetNewbound
17121#undef SCIPbdchginfoGetVar
17122#undef SCIPbdchginfoGetChgtype
17123#undef SCIPbdchginfoGetBoundtype
17124#undef SCIPbdchginfoGetDepth
17125#undef SCIPbdchginfoGetPos
17126#undef SCIPbdchginfoGetIdx
17127#undef SCIPbdchginfoGetInferVar
17128#undef SCIPbdchginfoGetInferCons
17129#undef SCIPbdchginfoGetInferProp
17130#undef SCIPbdchginfoGetInferInfo
17131#undef SCIPbdchginfoGetInferBoundtype
17132#undef SCIPbdchginfoIsRedundant
17133#undef SCIPbdchginfoHasInferenceReason
17134#undef SCIPbdchginfoIsTighter
17135
17136
17137/** returns the new value of the bound in the bound change data */
17139 SCIP_BOUNDCHG* boundchg /**< bound change data */
17140 )
17141{
17142 assert(boundchg != NULL);
17143
17144 return boundchg->newbound;
17145}
17146
17147/** returns the variable of the bound change in the bound change data */
17149 SCIP_BOUNDCHG* boundchg /**< bound change data */
17150 )
17151{
17152 assert(boundchg != NULL);
17153
17154 return boundchg->var;
17155}
17156
17157/** returns the bound change type of the bound change in the bound change data */
17159 SCIP_BOUNDCHG* boundchg /**< bound change data */
17160 )
17161{
17162 assert(boundchg != NULL);
17163
17164 return (SCIP_BOUNDCHGTYPE)(boundchg->boundchgtype);
17165}
17166
17167/** returns the bound type of the bound change in the bound change data */
17169 SCIP_BOUNDCHG* boundchg /**< bound change data */
17170 )
17171{
17172 assert(boundchg != NULL);
17173
17174 return (SCIP_BOUNDTYPE)(boundchg->boundtype);
17175}
17176
17177/** returns whether the bound change is redundant due to a more global bound that is at least as strong */
17179 SCIP_BOUNDCHG* boundchg /**< bound change data */
17180 )
17181{
17182 assert(boundchg != NULL);
17183
17184 return boundchg->redundant;
17185}
17186
17187/** returns the number of bound changes in the domain change data */
17189 SCIP_DOMCHG* domchg /**< domain change data */
17190 )
17191{
17192 return domchg != NULL ? domchg->domchgbound.nboundchgs : 0;
17193}
17194
17195/** returns a particular bound change in the domain change data */
17197 SCIP_DOMCHG* domchg, /**< domain change data */
17198 int pos /**< position of the bound change in the domain change data */
17199 )
17200{
17201 assert(domchg != NULL);
17202 assert(0 <= pos && pos < (int)domchg->domchgbound.nboundchgs);
17203
17204 return &domchg->domchgbound.boundchgs[pos];
17205}
17206
17207/** returns left bound of open interval in hole */
17209 SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
17210 )
17211{
17212 assert(holelist != NULL);
17213
17214 return holelist->hole.left;
17215}
17216
17217/** returns right bound of open interval in hole */
17219 SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
17220 )
17221{
17222 assert(holelist != NULL);
17223
17224 return holelist->hole.right;
17225}
17226
17227/** returns next hole in list */
17229 SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
17230 )
17231{
17232 assert(holelist != NULL);
17233
17234 return holelist->next;
17235}
17236
17237/** returns the name of the variable
17238 *
17239 * @note to change the name of a variable, use SCIPchgVarName() from scip.h
17240 */
17241const char* SCIPvarGetName(
17242 SCIP_VAR* var /**< problem variable */
17243 )
17244{
17245 assert(var != NULL);
17246
17247 return var->name;
17248}
17249
17250/** gets number of times, the variable is currently captured */
17252 SCIP_VAR* var /**< problem variable */
17253 )
17254{
17255 assert(var != NULL);
17256
17257 return var->nuses;
17258}
17259
17260/** returns the user data of the variable */
17262 SCIP_VAR* var /**< problem variable */
17263 )
17264{
17265 assert(var != NULL);
17266
17267 return var->vardata;
17268}
17269
17270/** sets the user data for the variable */
17272 SCIP_VAR* var, /**< problem variable */
17273 SCIP_VARDATA* vardata /**< user variable data */
17274 )
17275{
17276 assert(var != NULL);
17277
17278 var->vardata = vardata;
17279}
17280
17281/** sets method to free user data for the original variable */
17283 SCIP_VAR* var, /**< problem variable */
17284 SCIP_DECL_VARDELORIG ((*vardelorig)) /**< frees user data of original variable */
17285 )
17286{
17287 assert(var != NULL);
17289
17290 var->vardelorig = vardelorig;
17291}
17292
17293/** sets method to transform user data of the variable */
17295 SCIP_VAR* var, /**< problem variable */
17296 SCIP_DECL_VARTRANS ((*vartrans)) /**< creates transformed user data by transforming original user data */
17297 )
17298{
17299 assert(var != NULL);
17301
17302 var->vartrans = vartrans;
17303}
17304
17305/** sets method to free transformed user data for the variable */
17307 SCIP_VAR* var, /**< problem variable */
17308 SCIP_DECL_VARDELTRANS ((*vardeltrans)) /**< frees user data of transformed variable */
17309 )
17310{
17311 assert(var != NULL);
17312
17313 var->vardeltrans = vardeltrans;
17314}
17315
17316/** sets method to copy this variable into sub-SCIPs */
17318 SCIP_VAR* var, /**< problem variable */
17319 SCIP_DECL_VARCOPY ((*varcopy)) /**< copy method of the variable */
17320 )
17321{
17322 assert(var != NULL);
17323
17324 var->varcopy = varcopy;
17325}
17326
17327/** sets the initial flag of a variable; only possible for original or loose variables */
17329 SCIP_VAR* var, /**< problem variable */
17330 SCIP_Bool initial /**< initial flag */
17331 )
17332{
17333 assert(var != NULL);
17334
17336 return SCIP_INVALIDCALL;
17337
17338 var->initial = initial;
17339
17340 return SCIP_OKAY;
17341}
17342
17343/** sets the removable flag of a variable; only possible for original or loose variables */
17345 SCIP_VAR* var, /**< problem variable */
17346 SCIP_Bool removable /**< removable flag */
17347 )
17348{
17349 assert(var != NULL);
17350
17352 return SCIP_INVALIDCALL;
17353
17354 var->removable = removable;
17355
17356 return SCIP_OKAY;
17357}
17358
17359/** gets status of variable */
17361 SCIP_VAR* var /**< problem variable */
17362 )
17363{
17364 assert(var != NULL);
17365
17366 return (SCIP_VARSTATUS)(var->varstatus);
17367}
17368
17369/** returns whether the variable belongs to the original problem */
17371 SCIP_VAR* var /**< problem variable */
17372 )
17373{
17374 assert(var != NULL);
17376
17380}
17381
17382/** returns whether the variable belongs to the transformed problem */
17384 SCIP_VAR* var /**< problem variable */
17385 )
17386{
17387 assert(var != NULL);
17389
17393}
17394
17395/** returns whether the variable was created by negation of a different variable */
17397 SCIP_VAR* var /**< problem variable */
17398 )
17399{
17400 assert(var != NULL);
17401
17403}
17404
17405/** gets type of variable */
17407 SCIP_VAR* var /**< problem variable */
17408 )
17409{
17410 assert(var != NULL);
17411
17412 return (SCIP_VARTYPE)(var->vartype);
17413}
17414
17415/** returns TRUE if the variable is of binary type; this is the case if:
17416 * (1) variable type is binary
17417 * (2) variable type is integer or implicit integer and
17418 * (i) the global lower bound is greater than or equal to zero
17419 * (ii) the global upper bound is less than or equal to one
17420 */
17422 SCIP_VAR* var /**< problem variable */
17423 )
17424{
17425 assert(var != NULL);
17426
17427 return (SCIPvarGetType(var) == SCIP_VARTYPE_BINARY ||
17428 (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && var->glbdom.lb >= 0.0 && var->glbdom.ub <= 1.0));
17429}
17430
17431/** returns whether variable is of integral type (binary, integer, or implicit integer) */
17433 SCIP_VAR* var /**< problem variable */
17434 )
17435{
17436 assert(var != NULL);
17437
17439}
17440
17441/** returns whether variable's column should be present in the initial root LP */
17443 SCIP_VAR* var /**< problem variable */
17444 )
17445{
17446 assert(var != NULL);
17447
17448 return var->initial;
17449}
17450
17451/** returns whether variable's column is removable from the LP (due to aging or cleanup) */
17453 SCIP_VAR* var /**< problem variable */
17454 )
17455{
17456 assert(var != NULL);
17457
17458 return var->removable;
17459}
17460
17461/** returns whether the variable was deleted from the problem */
17463 SCIP_VAR* var /**< problem variable */
17464 )
17465{
17466 assert(var != NULL);
17467
17468 return var->deleted;
17469}
17470
17471/** marks the variable to be deletable, i.e., it may be deleted completely from the problem;
17472 * method can only be called before the variable is added to the problem by SCIPaddVar() or SCIPaddPricedVar()
17473 */
17475 SCIP_VAR* var /**< problem variable */
17476 )
17477{
17478 assert(var != NULL);
17479 assert(var->probindex == -1);
17480
17481 var->deletable = TRUE;
17482}
17483
17484/** marks the variable to be not deletable from the problem */
17486 SCIP_VAR* var
17487 )
17488{
17489 assert(var != NULL);
17490
17491 var->deletable = FALSE;
17492}
17493
17494/** marks variable to be deleted from global structures (cliques etc.) when cleaning up
17495 *
17496 * @note: this is not equivalent to marking the variable itself for deletion, this is done by using SCIPvarMarkDeletable()
17497 */
17499 SCIP_VAR* var /**< problem variable */
17500 )
17501{
17502 assert(var != NULL);
17503
17505}
17506
17507/** returns whether the variable was flagged for deletion from global structures (cliques etc.) */
17509 SCIP_VAR* var /**< problem variable */
17510 )
17511{
17512 assert(var != NULL);
17513
17514 return var->delglobalstructs;
17515}
17516
17517/** returns whether a variable has been introduced to define a relaxation
17518 *
17519 * These variables are only valid for the current SCIP solve round,
17520 * they are not contained in any (checked) constraints, but may be used
17521 * in cutting planes, for example.
17522 * Relaxation-only variables are not copied by SCIPcopyVars and cuts
17523 * that contain these variables are not added as linear constraints when
17524 * restarting or transferring information from a copied SCIP to a SCIP.
17525 * Also conflicts with relaxation-only variables are not generated at
17526 * the moment.
17527 */
17529 SCIP_VAR* var /**< problem variable */
17530 )
17531{
17532 assert(var != NULL);
17533
17534 return var->relaxationonly;
17535}
17536
17537/** marks that this variable has only been introduced to define a relaxation
17538 *
17539 * The variable must not have a coefficient in the objective and must be deletable.
17540 * If it is not marked deletable, it will be marked as deletable, which is only possible
17541 * before the variable is added to a problem.
17542 *
17543 * @see SCIPvarIsRelaxationOnly
17544 * @see SCIPvarMarkDeletable
17545 */
17547 SCIP_VAR* var /**< problem variable */
17548 )
17549{
17550 assert(var != NULL);
17551 assert(SCIPvarGetObj(var) == 0.0);
17552
17553 if( !SCIPvarIsDeletable(var) )
17555
17557}
17558
17559/** returns whether variable is allowed to be deleted completely from the problem */
17561 SCIP_VAR* var
17562 )
17563{
17564 assert(var != NULL);
17565
17566 return var->deletable;
17567}
17568
17569/** returns whether variable is an active (neither fixed nor aggregated) variable */
17571 SCIP_VAR* var /**< problem variable */
17572 )
17573{
17574 assert(var != NULL);
17575
17576 return (var->probindex >= 0);
17577}
17578
17579/** gets unique index of variable */
17581 SCIP_VAR* var /**< problem variable */
17582 )
17583{
17584 assert(var != NULL);
17585
17586 return var->index;
17587}
17588
17589/** gets position of variable in problem, or -1 if variable is not active */
17591 SCIP_VAR* var /**< problem variable */
17592 )
17593{
17594 assert(var != NULL);
17595
17596 return var->probindex;
17597}
17598
17599/** gets transformed variable of ORIGINAL variable */
17601 SCIP_VAR* var /**< problem variable */
17602 )
17603{
17604 assert(var != NULL);
17606
17607 return var->data.original.transvar;
17608}
17609
17610/** gets column of COLUMN variable */
17612 SCIP_VAR* var /**< problem variable */
17613 )
17614{
17615 assert(var != NULL);
17617
17618 return var->data.col;
17619}
17620
17621/** returns whether the variable is a COLUMN variable that is member of the current LP */
17623 SCIP_VAR* var /**< problem variable */
17624 )
17625{
17626 assert(var != NULL);
17627
17629}
17630
17631/** gets aggregation variable y of an aggregated variable x = a*y + c */
17633 SCIP_VAR* var /**< problem variable */
17634 )
17635{
17636 assert(var != NULL);
17638 assert(!var->donotaggr);
17639
17640 return var->data.aggregate.var;
17641}
17642
17643/** gets aggregation scalar a of an aggregated variable x = a*y + c */
17645 SCIP_VAR* var /**< problem variable */
17646 )
17647{
17648 assert(var != NULL);
17650 assert(!var->donotaggr);
17651
17652 return var->data.aggregate.scalar;
17653}
17654
17655/** gets aggregation constant c of an aggregated variable x = a*y + c */
17657 SCIP_VAR* var /**< problem variable */
17658 )
17659{
17660 assert(var != NULL);
17662 assert(!var->donotaggr);
17663
17664 return var->data.aggregate.constant;
17665}
17666
17667/** gets number n of aggregation variables of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17669 SCIP_VAR* var /**< problem variable */
17670 )
17671{
17672 assert(var != NULL);
17675
17676 return var->data.multaggr.nvars;
17677}
17678
17679/** gets vector of aggregation variables y of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17681 SCIP_VAR* var /**< problem variable */
17682 )
17683{
17684 assert(var != NULL);
17687
17688 return var->data.multaggr.vars;
17689}
17690
17691/** gets vector of aggregation scalars a of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17693 SCIP_VAR* var /**< problem variable */
17694 )
17695{
17696 assert(var != NULL);
17699
17700 return var->data.multaggr.scalars;
17701}
17702
17703/** gets aggregation constant c of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17705 SCIP_VAR* var /**< problem variable */
17706 )
17707{
17708 assert(var != NULL);
17711
17712 return var->data.multaggr.constant;
17713}
17714
17715/** gets the negation of the given variable; may return NULL, if no negation is existing yet */
17717 SCIP_VAR* var /**< negated problem variable */
17718 )
17719{
17720 assert(var != NULL);
17721
17722 return var->negatedvar;
17723}
17724
17725/** gets the negation variable x of a negated variable x' = offset - x */
17727 SCIP_VAR* var /**< negated problem variable */
17728 )
17729{
17730 assert(var != NULL);
17732
17733 return var->negatedvar;
17734}
17735
17736/** gets the negation offset of a negated variable x' = offset - x */
17738 SCIP_VAR* var /**< negated problem variable */
17739 )
17740{
17741 assert(var != NULL);
17743
17744 return var->data.negate.constant;
17745}
17746
17747/** gets objective function value of variable */
17749 SCIP_VAR* var /**< problem variable */
17750 )
17751{
17752 assert(var != NULL);
17753
17754 return var->obj;
17755}
17756
17757/** gets the unchanged objective function value of a variable (ignoring temproray changes performed in probing mode) */
17759 SCIP_VAR* var /**< problem variable */
17760 )
17761{
17762 assert(var != NULL);
17763
17764 return var->unchangedobj;
17765}
17766
17767/** gets corresponding objective value of active, fixed, or multi-aggregated problem variable of given variable
17768 * e.g. obj(x) = 1 this method returns for ~x the value -1
17769 */
17771 SCIP_VAR* var, /**< problem variable */
17772 SCIP_Real* aggrobj /**< pointer to store the aggregated objective value */
17773 )
17774{
17775 SCIP_VAR* probvar = var;
17776 SCIP_Real mult = 1.0;
17777
17778 assert(probvar != NULL);
17779 assert(aggrobj != NULL);
17780
17781 while( probvar != NULL )
17782 {
17783 switch( SCIPvarGetStatus(probvar) )
17784 {
17788 (*aggrobj) = mult * SCIPvarGetObj(probvar);
17789 return SCIP_OKAY;
17790
17792 assert(SCIPvarGetObj(probvar) == 0.0);
17793 (*aggrobj) = 0.0;
17794 return SCIP_OKAY;
17795
17797 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
17798 if ( probvar->data.multaggr.nvars == 1 )
17799 {
17800 assert( probvar->data.multaggr.vars != NULL );
17801 assert( probvar->data.multaggr.scalars != NULL );
17802 assert( probvar->data.multaggr.vars[0] != NULL );
17803 mult *= probvar->data.multaggr.scalars[0];
17804 probvar = probvar->data.multaggr.vars[0];
17805 break;
17806 }
17807 else
17808 {
17809 SCIP_Real tmpobj;
17810 int v;
17811
17812 (*aggrobj) = 0.0;
17813
17814 for( v = probvar->data.multaggr.nvars - 1; v >= 0; --v )
17815 {
17816 SCIP_CALL( SCIPvarGetAggregatedObj(probvar->data.multaggr.vars[v], &tmpobj) );
17817 (*aggrobj) += probvar->data.multaggr.scalars[v] * tmpobj;
17818 }
17819 return SCIP_OKAY;
17820 }
17821
17822 case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
17823 assert(probvar->data.aggregate.var != NULL);
17824 mult *= probvar->data.aggregate.scalar;
17825 probvar = probvar->data.aggregate.var;
17826 break;
17827
17828 case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
17829 assert(probvar->negatedvar != NULL);
17831 assert(probvar->negatedvar->negatedvar == probvar);
17832 mult *= -1.0;
17833 probvar = probvar->negatedvar;
17834 break;
17835
17836 default:
17837 SCIPABORT();
17838 return SCIP_INVALIDDATA; /*lint !e527*/
17839 }
17840 }
17841
17842 return SCIP_INVALIDDATA;
17843}
17844
17845/** gets original lower bound of original problem variable (i.e. the bound set in problem creation) */
17847 SCIP_VAR* var /**< original problem variable */
17848 )
17849{
17850 assert(var != NULL);
17852
17854 return var->data.original.origdom.lb;
17855 else
17856 {
17860
17862 }
17863}
17864
17865/** gets original upper bound of original problem variable (i.e. the bound set in problem creation) */
17867 SCIP_VAR* var /**< original problem variable */
17868 )
17869{
17870 assert(var != NULL);
17872
17874 return var->data.original.origdom.ub;
17875 else
17876 {
17880
17882 }
17883}
17884
17885/** gets the original hole list of an original variable */
17887 SCIP_VAR* var /**< problem variable */
17888 )
17889{
17890 assert(var != NULL);
17892
17895
17896 return NULL;
17897}
17898
17899/** gets global lower bound of variable */
17901 SCIP_VAR* var /**< problem variable */
17902 )
17903{
17904 assert(var != NULL);
17905
17906 return var->glbdom.lb;
17907}
17908
17909/** gets global upper bound of variable */
17911 SCIP_VAR* var /**< problem variable */
17912 )
17913{
17914 assert(var != NULL);
17915
17916 return var->glbdom.ub;
17917}
17918
17919/** gets the global hole list of an active variable */
17921 SCIP_VAR* var /**< problem variable */
17922 )
17923{
17924 assert(var != NULL);
17925
17926 return var->glbdom.holelist;
17927}
17928
17929/** gets best global bound of variable with respect to the objective function */
17931 SCIP_VAR* var /**< problem variable */
17932 )
17933{
17934 assert(var != NULL);
17935
17936 if( var->obj >= 0.0 )
17937 return var->glbdom.lb;
17938 else
17939 return var->glbdom.ub;
17940}
17941
17942/** gets worst global bound of variable with respect to the objective function */
17944 SCIP_VAR* var /**< problem variable */
17945 )
17946{
17947 assert(var != NULL);
17948
17949 if( var->obj >= 0.0 )
17950 return var->glbdom.ub;
17951 else
17952 return var->glbdom.lb;
17953}
17954
17955/** gets current lower bound of variable */
17957 SCIP_VAR* var /**< problem variable */
17958 )
17959{
17960 assert(var != NULL);
17961
17962 return var->locdom.lb;
17963}
17964
17965/** gets current upper bound of variable */
17967 SCIP_VAR* var /**< problem variable */
17968 )
17969{
17970 assert(var != NULL);
17971
17972 return var->locdom.ub;
17973}
17974
17975/** gets the current hole list of an active variable */
17977 SCIP_VAR* var /**< problem variable */
17978 )
17979{
17980 assert(var != NULL);
17981
17982 return var->locdom.holelist;
17983}
17984
17985/** gets best local bound of variable with respect to the objective function */
17987 SCIP_VAR* var /**< problem variable */
17988 )
17989{
17990 assert(var != NULL);
17991
17992 if( var->obj >= 0.0 )
17993 return var->locdom.lb;
17994 else
17995 return var->locdom.ub;
17996}
17997
17998/** gets worst local bound of variable with respect to the objective function */
18000 SCIP_VAR* var /**< problem variable */
18001 )
18002{
18003 assert(var != NULL);
18004
18005 if( var->obj >= 0.0 )
18006 return var->locdom.ub;
18007 else
18008 return var->locdom.lb;
18009}
18010
18011/** gets type (lower or upper) of best bound of variable with respect to the objective function */
18013 SCIP_VAR* var /**< problem variable */
18014 )
18015{
18016 assert(var != NULL);
18017
18018 if( var->obj >= 0.0 )
18019 return SCIP_BOUNDTYPE_LOWER;
18020 else
18021 return SCIP_BOUNDTYPE_UPPER;
18022}
18023
18024/** gets type (lower or upper) of worst bound of variable with respect to the objective function */
18026 SCIP_VAR* var /**< problem variable */
18027 )
18028{
18029 assert(var != NULL);
18030
18031 if( var->obj >= 0.0 )
18032 return SCIP_BOUNDTYPE_UPPER;
18033 else
18034 return SCIP_BOUNDTYPE_LOWER;
18035}
18036
18037/** gets lazy lower bound of variable, returns -infinity if the variable has no lazy lower bound */
18039 SCIP_VAR* var /**< problem variable */
18040 )
18041{
18042 assert(var != NULL);
18043
18044 return var->lazylb;
18045}
18046
18047/** gets lazy upper bound of variable, returns infinity if the variable has no lazy upper bound */
18049 SCIP_VAR* var /**< problem variable */
18050 )
18051{
18052 assert(var != NULL);
18053
18054 return var->lazyub;
18055}
18056
18057/** gets the branch factor of the variable; this value can be used in the branching methods to scale the score
18058 * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
18059 */
18061 SCIP_VAR* var /**< problem variable */
18062 )
18063{
18064 assert(var != NULL);
18065
18066 return var->branchfactor;
18067}
18068
18069/** gets the branch priority of the variable; variables with higher priority should always be preferred to variables
18070 * with lower priority
18071 */
18073 SCIP_VAR* var /**< problem variable */
18074 )
18075{
18076 assert(var != NULL);
18077
18078 return var->branchpriority;
18079}
18080
18081/** gets the preferred branch direction of the variable (downwards, upwards, or auto) */
18083 SCIP_VAR* var /**< problem variable */
18084 )
18085{
18086 assert(var != NULL);
18087
18089}
18090
18091/** gets number of variable lower bounds x >= b_i*z_i + d_i of given variable x */
18093 SCIP_VAR* var /**< problem variable */
18094 )
18095{
18096 assert(var != NULL);
18097
18098 return SCIPvboundsGetNVbds(var->vlbs);
18099}
18100
18101/** gets array with bounding variables z_i in variable lower bounds x >= b_i*z_i + d_i of given variable x;
18102 * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
18103 */
18105 SCIP_VAR* var /**< problem variable */
18106 )
18107{
18108 assert(var != NULL);
18109
18110 return SCIPvboundsGetVars(var->vlbs);
18111}
18112
18113/** gets array with bounding coefficients b_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
18115 SCIP_VAR* var /**< problem variable */
18116 )
18117{
18118 assert(var != NULL);
18119
18120 return SCIPvboundsGetCoefs(var->vlbs);
18121}
18122
18123/** gets array with bounding constants d_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
18125 SCIP_VAR* var /**< problem variable */
18126 )
18127{
18128 assert(var != NULL);
18129
18131}
18132
18133/** gets number of variable upper bounds x <= b_i*z_i + d_i of given variable x */
18135 SCIP_VAR* var /**< problem variable */
18136 )
18137{
18138 assert(var != NULL);
18139
18140 return SCIPvboundsGetNVbds(var->vubs);
18141}
18142
18143/** gets array with bounding variables z_i in variable upper bounds x <= b_i*z_i + d_i of given variable x;
18144 * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
18145 */
18147 SCIP_VAR* var /**< problem variable */
18148 )
18149{
18150 assert(var != NULL);
18151
18152 return SCIPvboundsGetVars(var->vubs);
18153}
18154
18155/** gets array with bounding coefficients b_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
18157 SCIP_VAR* var /**< problem variable */
18158 )
18159{
18160 assert(var != NULL);
18161
18162 return SCIPvboundsGetCoefs(var->vubs);
18163}
18164
18165/** gets array with bounding constants d_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
18167 SCIP_VAR* var /**< problem variable */
18168 )
18169{
18170 assert(var != NULL);
18171
18173}
18174
18175/** gets number of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
18176 * there are no implications for nonbinary variable x
18177 */
18179 SCIP_VAR* var, /**< active problem variable */
18180 SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
18181 )
18182{
18183 assert(var != NULL);
18185
18187}
18188
18189/** gets array with implication variables y of implications y <= b or y >= b for x == 0 or x == 1 of given active
18190 * problem variable x, there are no implications for nonbinary variable x;
18191 * the implications are sorted such that implications with binary implied variables precede the ones with non-binary
18192 * implied variables, and as a second criteria, the implied variables are sorted by increasing variable index
18193 * (see SCIPvarGetIndex())
18194 */
18196 SCIP_VAR* var, /**< active problem variable */
18197 SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
18198 )
18199{
18200 assert(var != NULL);
18202
18204}
18205
18206/** gets array with implication types of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
18207 * variable x (SCIP_BOUNDTYPE_UPPER if y <= b, SCIP_BOUNDTYPE_LOWER if y >= b),
18208 * there are no implications for nonbinary variable x
18209 */
18211 SCIP_VAR* var, /**< active problem variable */
18212 SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
18213 )
18214{
18215 assert(var != NULL);
18217
18219}
18220
18221/** gets array with implication bounds b of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
18222 * variable x, there are no implications for nonbinary variable x
18223 */
18225 SCIP_VAR* var, /**< active problem variable */
18226 SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
18227 )
18228{
18229 assert(var != NULL);
18231
18233}
18234
18235/** Gets array with unique ids of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
18236 * there are no implications for nonbinary variable x.
18237 * If an implication is a shortcut, i.e., it was added as part of the transitive closure of another implication,
18238 * its id is negative, otherwise it is nonnegative.
18239 */
18241 SCIP_VAR* var, /**< active problem variable */
18242 SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
18243 )
18244{
18245 assert(var != NULL);
18247
18249}
18250
18251/** gets number of cliques, the active variable is contained in */
18253 SCIP_VAR* var, /**< active problem variable */
18254 SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
18255 )
18256{
18257 assert(var != NULL);
18258
18260}
18261
18262/** gets array of cliques, the active variable is contained in */
18264 SCIP_VAR* var, /**< active problem variable */
18265 SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
18266 )
18267{
18268 assert(var != NULL);
18269
18271}
18272
18273/** gets primal LP solution value of variable */
18275 SCIP_VAR* var /**< problem variable */
18276 )
18277{
18278 assert(var != NULL);
18279
18281 return SCIPcolGetPrimsol(var->data.col);
18282 else
18283 return SCIPvarGetLPSol_rec(var);
18284}
18285
18286/** gets primal NLP solution value of variable */
18288 SCIP_VAR* var /**< problem variable */
18289 )
18290{
18291 assert(var != NULL);
18292
18294 return var->nlpsol;
18295 else
18296 return SCIPvarGetNLPSol_rec(var);
18297}
18298
18299/** return lower bound change info at requested position */
18301 SCIP_VAR* var, /**< problem variable */
18302 int pos /**< requested position */
18303 )
18304{
18305 assert(pos >= 0);
18306 assert(pos < var->nlbchginfos);
18307
18308 return &var->lbchginfos[pos];
18309}
18310
18311/** gets the number of lower bound change info array */
18313 SCIP_VAR* var /**< problem variable */
18314 )
18315{
18316 return var->nlbchginfos;
18317}
18318
18319/** return upper bound change info at requested position */
18321 SCIP_VAR* var, /**< problem variable */
18322 int pos /**< requested position */
18323 )
18324{
18325 assert(pos >= 0);
18326 assert(pos < var->nubchginfos);
18327
18328 return &var->ubchginfos[pos];
18329}
18330
18331/** gets the number upper bound change info array */
18333 SCIP_VAR* var /**< problem variable */
18334 )
18335{
18336 assert(var != NULL);
18337
18338 return var->nubchginfos;
18339}
18340
18341/** returns the value based history for the variable */
18343 SCIP_VAR* var /**< problem variable */
18344 )
18345{
18346 assert(var != NULL);
18347
18348 return var->valuehistory;
18349}
18350
18351/** gets pseudo solution value of variable */
18353 SCIP_VAR* var /**< problem variable */
18354 )
18355{
18356 assert(var != NULL);
18357
18360 else
18362}
18363
18364/** returns the variable's VSIDS score */
18366 SCIP_VAR* var, /**< problem variable */
18367 SCIP_STAT* stat, /**< problem statistics */
18368 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
18369 )
18370{
18371 assert(var != NULL);
18372
18375 else
18376 return SCIPvarGetVSIDS_rec(var, stat, dir);
18377}
18378
18379/** includes event handler with given data in variable's event filter */
18381 SCIP_VAR* var, /**< problem variable */
18382 BMS_BLKMEM* blkmem, /**< block memory */
18383 SCIP_SET* set, /**< global SCIP settings */
18384 SCIP_EVENTTYPE eventtype, /**< event type to catch */
18385 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
18386 SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
18387 int* filterpos /**< pointer to store position of event filter entry, or NULL */
18388 )
18389{
18390 assert(var != NULL);
18391 assert(set != NULL);
18392 assert(var->scip == set->scip);
18394 assert((eventtype & ~SCIP_EVENTTYPE_VARCHANGED) == 0);
18395 assert((eventtype & SCIP_EVENTTYPE_VARCHANGED) != 0);
18397
18398 SCIPsetDebugMsg(set, "catch event of type 0x%" SCIP_EVENTTYPE_FORMAT " of variable <%s> with handler %p and data %p\n",
18399 eventtype, var->name, (void*)eventhdlr, (void*)eventdata);
18400
18401 SCIP_CALL( SCIPeventfilterAdd(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
18402
18403 return SCIP_OKAY;
18404}
18405
18406/** deletes event handler with given data from variable's event filter */
18408 SCIP_VAR* var, /**< problem variable */
18409 BMS_BLKMEM* blkmem, /**< block memory */
18410 SCIP_SET* set, /**< global SCIP settings */
18411 SCIP_EVENTTYPE eventtype, /**< event type mask of dropped event */
18412 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
18413 SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
18414 int filterpos /**< position of event filter entry returned by SCIPvarCatchEvent(), or -1 */
18415 )
18416{
18417 assert(var != NULL);
18418 assert(set != NULL);
18419 assert(var->scip == set->scip);
18422
18423 SCIPsetDebugMsg(set, "drop event of variable <%s> with handler %p and data %p\n", var->name, (void*)eventhdlr,
18424 (void*)eventdata);
18425
18426 SCIP_CALL( SCIPeventfilterDel(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
18427
18428 return SCIP_OKAY;
18429}
18430
18431/** returns the position of the bound change index */
18433 SCIP_BDCHGIDX* bdchgidx /**< bound change index */
18434 )
18435{
18436 assert(bdchgidx != NULL);
18437
18438 return bdchgidx->pos;
18439}
18440
18441/** returns whether first bound change index belongs to an earlier applied bound change than second one */
18443 SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index */
18444 SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index */
18445 )
18446{
18447 assert(bdchgidx1 != NULL);
18448 assert(bdchgidx1->depth >= -2);
18449 assert(bdchgidx1->pos >= 0);
18450 assert(bdchgidx2 != NULL);
18451 assert(bdchgidx2->depth >= -2);
18452 assert(bdchgidx2->pos >= 0);
18453
18454 return (bdchgidx1->depth < bdchgidx2->depth)
18455 || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
18456}
18457
18458/** returns whether first bound change index belongs to an earlier applied bound change than second one;
18459 * if a bound change index is NULL, the bound change index represents the current time, i.e. the time after the
18460 * last bound change was applied to the current node
18461 */
18463 SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index, or NULL */
18464 SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index, or NULL */
18465 )
18466{
18467 assert(bdchgidx1 == NULL || bdchgidx1->depth >= -2);
18468 assert(bdchgidx1 == NULL || bdchgidx1->pos >= 0);
18469 assert(bdchgidx2 == NULL || bdchgidx2->depth >= -2);
18470 assert(bdchgidx2 == NULL || bdchgidx2->pos >= 0);
18471
18472 if( bdchgidx1 == NULL )
18473 return FALSE;
18474 else if( bdchgidx2 == NULL )
18475 return TRUE;
18476 else
18477 return (bdchgidx1->depth < bdchgidx2->depth)
18478 || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
18479}
18480
18481/** returns old bound that was overwritten for given bound change information */
18483 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18484 )
18485{
18486 assert(bdchginfo != NULL);
18487
18488 return bdchginfo->oldbound;
18489}
18490
18491/** returns new bound installed for given bound change information */
18493 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18494 )
18495{
18496 assert(bdchginfo != NULL);
18497
18498 return bdchginfo->newbound;
18499}
18500
18501/** returns variable that belongs to the given bound change information */
18503 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18504 )
18505{
18506 assert(bdchginfo != NULL);
18507
18508 return bdchginfo->var;
18509}
18510
18511/** returns whether the bound change information belongs to a branching decision or a deduction */
18513 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18514 )
18515{
18516 assert(bdchginfo != NULL);
18517
18518 return (SCIP_BOUNDCHGTYPE)(bdchginfo->boundchgtype);
18519}
18520
18521/** returns whether the bound change information belongs to a lower or upper bound change */
18523 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18524 )
18525{
18526 assert(bdchginfo != NULL);
18527
18528 return (SCIP_BOUNDTYPE)(bdchginfo->boundtype);
18529}
18530
18531/** returns depth level of given bound change information */
18533 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18534 )
18535{
18536 assert(bdchginfo != NULL);
18537
18538 return bdchginfo->bdchgidx.depth;
18539}
18540
18541/** returns bound change position in its depth level of given bound change information */
18543 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18544 )
18545{
18546 assert(bdchginfo != NULL);
18547
18548 return bdchginfo->bdchgidx.pos;
18549}
18550
18551/** returns bound change index of given bound change information */
18553 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18554 )
18555{
18556 assert(bdchginfo != NULL);
18557
18558 return &bdchginfo->bdchgidx;
18559}
18560
18561/** returns inference variable of given bound change information */
18563 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18564 )
18565{
18566 assert(bdchginfo != NULL);
18569
18570 return bdchginfo->inferencedata.var;
18571}
18572
18573/** returns inference constraint of given bound change information */
18575 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18576 )
18577{
18578 assert(bdchginfo != NULL);
18580 assert(bdchginfo->inferencedata.reason.cons != NULL);
18581
18582 return bdchginfo->inferencedata.reason.cons;
18583}
18584
18585/** returns inference propagator of given bound change information, or NULL if no propagator was responsible */
18587 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18588 )
18589{
18590 assert(bdchginfo != NULL);
18592
18593 return bdchginfo->inferencedata.reason.prop;
18594}
18595
18596/** returns inference user information of given bound change information */
18598 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18599 )
18600{
18601 assert(bdchginfo != NULL);
18604
18605 return bdchginfo->inferencedata.info;
18606}
18607
18608/** returns inference bound of inference variable of given bound change information */
18610 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18611 )
18612{
18613 assert(bdchginfo != NULL);
18616
18617 return (SCIP_BOUNDTYPE)(bdchginfo->inferboundtype);
18618}
18619
18620/** returns the relaxed bound change type */
18622 SCIP_BDCHGINFO* bdchginfo /**< bound change to add to the conflict set */
18623 )
18624{
18625 return ((SCIP_BOUNDTYPE)(bdchginfo->boundtype) == SCIP_BOUNDTYPE_LOWER ? bdchginfo->var->conflictrelaxedlb : bdchginfo->var->conflictrelaxedub);
18626}
18627
18628
18629/** returns whether the bound change information belongs to a redundant bound change */
18631 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18632 )
18633{
18634 assert(bdchginfo != NULL);
18635 assert(bdchginfo->redundant == (bdchginfo->oldbound == bdchginfo->newbound)); /*lint !e777*/
18636
18637 return bdchginfo->redundant;
18638}
18639
18640/** returns whether the bound change has an inference reason (constraint or propagator), that can be resolved */
18642 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18643 )
18644{
18645 assert(bdchginfo != NULL);
18646
18649 && bdchginfo->inferencedata.reason.prop != NULL);
18650}
18651
18652/** for two bound change informations belonging to the same variable and bound, returns whether the first bound change
18653 * has a tighter new bound as the second bound change
18654 */
18656 SCIP_BDCHGINFO* bdchginfo1, /**< first bound change information */
18657 SCIP_BDCHGINFO* bdchginfo2 /**< second bound change information */
18658 )
18659{
18662 assert(bdchginfo1->var == bdchginfo2->var);
18663 assert(bdchginfo1->boundtype == bdchginfo2->boundtype);
18664
18666 ? bdchginfo1->newbound > bdchginfo2->newbound
18667 : bdchginfo1->newbound < bdchginfo2->newbound);
18668}
static long bound
static GRAPHNODE ** active
SCIP_VAR * a
SCIP_VAR ** b
void SCIPconsCapture(SCIP_CONS *cons)
Definition cons.c:6194
SCIP_RETCODE SCIPconsRelease(SCIP_CONS **cons, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition cons.c:6206
internal methods for constraints and constraint handlers
#define SCIPdebugCheckLbGlobal(scip, var, lb)
Definition debug.h:285
#define SCIPdebugCheckImplic(set, var, varfixing, implvar, impltype, implbound)
Definition debug.h:292
#define SCIPdebugCheckUbGlobal(scip, var, ub)
Definition debug.h:286
#define SCIPdebugCheckVbound(set, var, vbtype, vbvar, vbcoef, vbconstant)
Definition debug.h:291
#define SCIPdebugCheckAggregation(set, var, aggrvars, scalars, constant, naggrvars)
Definition debug.h:293
#define SCIP_DEFAULT_INFINITY
Definition def.h:191
#define SCIP_MAXSTRLEN
Definition def.h:302
#define SCIP_Longint
Definition def.h:171
#define EPSISINT(x, eps)
Definition def.h:223
#define SCIP_REAL_MAX
Definition def.h:187
#define SCIP_INVALID
Definition def.h:206
#define EPSLE(x, y, eps)
Definition def.h:213
#define SCIP_ALLOC(x)
Definition def.h:399
#define SCIP_Real
Definition def.h:186
#define SCIP_UNKNOWN
Definition def.h:207
#define EPSEQ(x, y, eps)
Definition def.h:211
#define TRUE
Definition def.h:95
#define FALSE
Definition def.h:96
#define SCIP_CALL_ABORT(x)
Definition def.h:367
#define SCIPABORT()
Definition def.h:360
#define SCIP_REAL_MIN
Definition def.h:188
#define REALABS(x)
Definition def.h:210
#define EPSZ(x, eps)
Definition def.h:216
#define SCIP_CALL(x)
Definition def.h:388
SCIP_RETCODE SCIPeventCreateLbChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition event.c:674
SCIP_RETCODE SCIPeventCreateVarFixed(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition event.c:562
SCIP_RETCODE SCIPeventCreateUbChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition event.c:700
SCIP_RETCODE SCIPeventCreateVarUnlocked(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition event.c:584
SCIP_RETCODE SCIPeventCreateObjChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldobj, SCIP_Real newobj)
Definition event.c:605
SCIP_RETCODE SCIPeventqueueAdd(SCIP_EVENTQUEUE *eventqueue, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENT **event)
Definition event.c:2240
SCIP_RETCODE SCIPeventfilterFree(SCIP_EVENTFILTER **eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition event.c:1846
SCIP_Bool SCIPeventqueueIsDelayed(SCIP_EVENTQUEUE *eventqueue)
Definition event.c:2568
SCIP_RETCODE SCIPeventCreateGholeAdded(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real left, SCIP_Real right)
Definition event.c:726
SCIP_RETCODE SCIPeventfilterDel(SCIP_EVENTFILTER *eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition event.c:1979
SCIP_RETCODE SCIPeventfilterCreate(SCIP_EVENTFILTER **eventfilter, BMS_BLKMEM *blkmem)
Definition event.c:1821
SCIP_RETCODE SCIPeventCreateImplAdded(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition event.c:814
SCIP_RETCODE SCIPeventfilterAdd(SCIP_EVENTFILTER *eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition event.c:1886
SCIP_RETCODE SCIPeventCreateGubChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition event.c:651
SCIP_RETCODE SCIPeventCreateGlbChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition event.c:628
SCIP_RETCODE SCIPeventCreateTypeChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_VARTYPE oldtype, SCIP_VARTYPE newtype)
Definition event.c:833
internal methods for managing events
const char * SCIPgetProbName(SCIP *scip)
Definition scip_prob.c:1067
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition misc.c:3106
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition misc.c:3373
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition misc.c:9032
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition misc.c:9284
SCIP_Bool SCIPrealToRational(SCIP_Real val, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Longint *nominator, SCIP_Longint *denominator)
Definition misc.c:9305
SCIP_Real SCIPcolGetObj(SCIP_COL *col)
Definition lp.c:16953
SCIP_Real SCIPcolGetLb(SCIP_COL *col)
Definition lp.c:16963
SCIP_Real SCIPcolGetPrimsol(SCIP_COL *col)
Definition lp.c:16996
SCIP_Real SCIPcolGetUb(SCIP_COL *col)
Definition lp.c:16973
SCIP_Bool SCIPcolIsInLP(SCIP_COL *col)
Definition lp.c:17115
SCIP_BASESTAT SCIPcolGetBasisStatus(SCIP_COL *col)
Definition lp.c:17031
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition cons.c:8088
SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
Definition tree.c:7444
SCIP_NODE * SCIPnodeGetParent(SCIP_NODE *node)
Definition tree.c:7724
const char * SCIPpropGetName(SCIP_PROP *prop)
Definition prop.c:941
SCIP_Longint SCIPgetNLPIterations(SCIP *scip)
SCIP_NODE * SCIPgetFocusNode(SCIP *scip)
Definition scip_tree.c:72
int SCIPgetDepth(SCIP *scip)
Definition scip_tree.c:670
SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition var.c:17442
SCIP_Real SCIPvarGetLPSol_rec(SCIP_VAR *var)
Definition var.c:13058
int SCIPvarCompareActiveAndNegated(SCIP_VAR *var1, SCIP_VAR *var2)
Definition var.c:11893
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition var.c:12763
SCIP_HOLELIST * SCIPvarGetHolelistLocal(SCIP_VAR *var)
Definition var.c:17976
int SCIPvarGetNVlbs(SCIP_VAR *var)
Definition var.c:18092
SCIP_RETCODE SCIPvarGetProbvarBound(SCIP_VAR **var, SCIP_Real *bound, SCIP_BOUNDTYPE *boundtype)
Definition var.c:12458
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition var.c:17462
SCIP_Real SCIPvarGetNegationConstant(SCIP_VAR *var)
Definition var.c:17737
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition var.c:17611
SCIP_Bool SCIPbdchginfoIsRedundant(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:18630
SCIP_Bool SCIPvarWasFixedAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition var.c:16792
SCIP_Real SCIPvarGetAvgBranchdepthCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:15821
SCIP_Bool SCIPvarMayRoundUp(SCIP_VAR *var)
Definition var.c:3451
SCIP_Real SCIPvarGetMultaggrConstant(SCIP_VAR *var)
Definition var.c:17704
SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
Definition var.c:18012
void SCIPvarSetTransData(SCIP_VAR *var,)
Definition var.c:17294
void SCIPvarsGetProbvar(SCIP_VAR **vars, int nvars)
Definition var.c:12187
SCIP_Real SCIPvarGetSol(SCIP_VAR *var, SCIP_Bool getlpval)
Definition var.c:13246
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition var.c:17716
SCIP_Real * SCIPvarGetVlbCoefs(SCIP_VAR *var)
Definition var.c:18114
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition var.c:17570
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition var.c:17421
SCIP_BOUNDTYPE SCIPboundchgGetBoundtype(SCIP_BOUNDCHG *boundchg)
Definition var.c:17168
SCIP_Real SCIPholelistGetRight(SCIP_HOLELIST *holelist)
Definition var.c:17218
void SCIPvarSetDelorigData(SCIP_VAR *var,)
Definition var.c:17282
SCIP_Real SCIPvarGetAvgBranchdepth(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:15776
SCIP_Real SCIPvarGetBestBoundGlobal(SCIP_VAR *var)
Definition var.c:17930
SCIP_Bool SCIPbdchgidxIsEarlier(SCIP_BDCHGIDX *bdchgidx1, SCIP_BDCHGIDX *bdchgidx2)
Definition var.c:18462
SCIP_Bool SCIPvarWasFixedEarlier(SCIP_VAR *var1, SCIP_VAR *var2)
Definition var.c:16940
SCIP_BDCHGIDX * SCIPbdchginfoGetIdx(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:18552
SCIP_VAR * SCIPboundchgGetVar(SCIP_BOUNDCHG *boundchg)
Definition var.c:17148
SCIP_Bool SCIPvarHasImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition var.c:11100
SCIP_BOUNDCHG * SCIPdomchgGetBoundchg(SCIP_DOMCHG *domchg, int pos)
Definition var.c:17196
int SCIPvarGetNImpls(SCIP_VAR *var, SCIP_Bool varfixing)
Definition var.c:18178
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition var.c:17360
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition var.c:3353
SCIP_BOUNDCHGTYPE SCIPboundchgGetBoundchgtype(SCIP_BOUNDCHG *boundchg)
Definition var.c:17158
SCIP_Real SCIPvarGetInferenceSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:15968
SCIP_Real SCIPvarGetAggrConstant(SCIP_VAR *var)
Definition var.c:17656
SCIP_RETCODE SCIPvarGetAggregatedObj(SCIP_VAR *var, SCIP_Real *aggrobj)
Definition var.c:17770
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition var.c:17966
int SCIPvarGetNLocksDown(SCIP_VAR *var)
Definition var.c:3416
SCIP_Real SCIPvarGetBestRootSol(SCIP_VAR *var)
Definition var.c:13704
SCIP_HOLELIST * SCIPholelistGetNext(SCIP_HOLELIST *holelist)
Definition var.c:17228
SCIP_Real SCIPvarGetLbOriginal(SCIP_VAR *var)
Definition var.c:17846
SCIP_BDCHGINFO * SCIPvarGetLbchgInfo(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition var.c:16399
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition var.c:17383
void SCIPvarMarkDeletable(SCIP_VAR *var)
Definition var.c:17474
void SCIPvarGetImplicVarBounds(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_Real *lb, SCIP_Real *ub)
Definition var.c:11135
SCIP_PROP * SCIPbdchginfoGetInferProp(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:18586
SCIP_Real SCIPboundchgGetNewbound(SCIP_BOUNDCHG *boundchg)
Definition var.c:17138
SCIP_Bool SCIPvarMayRoundDown(SCIP_VAR *var)
Definition var.c:3440
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition var.c:17748
SCIP_Real SCIPvarGetAggrScalar(SCIP_VAR *var)
Definition var.c:17644
SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
Definition var.c:12207
void SCIPvarMarkRelaxationOnly(SCIP_VAR *var)
Definition var.c:17546
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition var.c:17406
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition var.c:17910
SCIP_RETCODE SCIPvarSetInitial(SCIP_VAR *var, SCIP_Bool initial)
Definition var.c:17328
SCIP_VAR ** SCIPvarGetImplVars(SCIP_VAR *var, SCIP_Bool varfixing)
Definition var.c:18195
void SCIPvarSetBestRootSol(SCIP_VAR *var, SCIP_Real rootsol, SCIP_Real rootredcost, SCIP_Real rootlpobjval)
Definition var.c:13836
int SCIPbdchginfoGetDepth(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:18532
int SCIPbdchginfoGetInferInfo(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:18597
int SCIPvarGetIndex(SCIP_VAR *var)
Definition var.c:17580
SCIP_CONS * SCIPbdchginfoGetInferCons(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:18574
SCIP_Real SCIPvarGetNLPSol_rec(SCIP_VAR *var)
Definition var.c:13131
SCIP_BDCHGIDX * SCIPvarGetLastBdchgIndex(SCIP_VAR *var)
Definition var.c:16815
int SCIPbdchginfoGetPos(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:18542
SCIP_Real SCIPvarGetWorstBoundLocal(SCIP_VAR *var)
Definition var.c:17999
int SCIPvarGetNUses(SCIP_VAR *var)
Definition var.c:17251
int SCIPdomchgGetNBoundchgs(SCIP_DOMCHG *domchg)
Definition var.c:17188
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition var.c:17590
const char * SCIPvarGetName(SCIP_VAR *var)
Definition var.c:17241
SCIP_Real SCIPvarGetUbOriginal(SCIP_VAR *var)
Definition var.c:17866
SCIP_Real SCIPvarGetWorstBoundGlobal(SCIP_VAR *var)
Definition var.c:17943
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:18502
SCIP_Bool SCIPvarHasBinaryImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_Bool implvarfixing)
Definition var.c:11120
void SCIPvarMarkDeleteGlobalStructures(SCIP_VAR *var)
Definition var.c:17498
SCIP_Real * SCIPvarGetVlbConstants(SCIP_VAR *var)
Definition var.c:18124
SCIP_Real SCIPvarGetRootSol(SCIP_VAR *var)
Definition var.c:13339
int * SCIPvarGetImplIds(SCIP_VAR *var, SCIP_Bool varfixing)
Definition var.c:18240
SCIP_Real SCIPvarGetBestBoundLocal(SCIP_VAR *var)
Definition var.c:17986
int SCIPvarGetNVubs(SCIP_VAR *var)
Definition var.c:18134
SCIP_Real SCIPvarGetBranchFactor(SCIP_VAR *var)
Definition var.c:18060
SCIP_Real SCIPvarGetAvgSol(SCIP_VAR *var)
Definition var.c:14051
SCIP_Bool SCIPvarIsDeletable(SCIP_VAR *var)
Definition var.c:17560
SCIP_Real SCIPbdchginfoGetOldbound(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:18482
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition var.c:17432
SCIP_Bool SCIPvarIsTransformedOrigvar(SCIP_VAR *var)
Definition var.c:12850
SCIP_Real SCIPvarGetUbLazy(SCIP_VAR *var)
Definition var.c:18048
SCIP_Real SCIPvarGetPseudoSol(SCIP_VAR *var)
Definition var.c:18352
SCIP_BRANCHDIR SCIPvarGetBranchDirection(SCIP_VAR *var)
Definition var.c:18082
SCIP_BOUNDTYPE SCIPbdchginfoGetInferBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:18609
void SCIPvarSetData(SCIP_VAR *var, SCIP_VARDATA *vardata)
Definition var.c:17271
SCIP_Real * SCIPvarGetImplBounds(SCIP_VAR *var, SCIP_Bool varfixing)
Definition var.c:18224
void SCIPvarSetDeltransData(SCIP_VAR *var,)
Definition var.c:17306
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition var.c:18274
SCIP_BDCHGINFO * SCIPvarGetBdchgInfo(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition var.c:16511
SCIP_VARDATA * SCIPvarGetData(SCIP_VAR *var)
Definition var.c:17261
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition var.c:17680
SCIP_Bool SCIPbdchginfoIsTighter(SCIP_BDCHGINFO *bdchginfo1, SCIP_BDCHGINFO *bdchginfo2)
Definition var.c:18655
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition var.c:17668
SCIP_RETCODE SCIPvarSetRemovable(SCIP_VAR *var, SCIP_Bool removable)
Definition var.c:17344
SCIP_HOLELIST * SCIPvarGetHolelistOriginal(SCIP_VAR *var)
Definition var.c:17886
SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
Definition var.c:17452
int SCIPvarGetNCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition var.c:18252
SCIP_BOUNDCHGTYPE SCIPbdchginfoGetChgtype(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:18512
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition var.c:17956
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition var.c:17396
SCIP_VAR * SCIPbdchginfoGetInferVar(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:18562
SCIP_Bool SCIPbdchginfoHasInferenceReason(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:18641
SCIP_Bool SCIPboundchgIsRedundant(SCIP_BOUNDCHG *boundchg)
Definition var.c:17178
SCIP_Longint SCIPvarGetNBranchings(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:15688
SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
Definition var.c:17528
SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition var.c:17726
SCIP_RETCODE SCIPvarGetProbvarHole(SCIP_VAR **var, SCIP_Real *left, SCIP_Real *right)
Definition var.c:12551
SCIP_VAR ** SCIPvarGetVlbVars(SCIP_VAR *var)
Definition var.c:18104
SCIP_BDCHGINFO * SCIPvarGetUbchgInfo(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition var.c:16455
SCIP_Real SCIPholelistGetLeft(SCIP_HOLELIST *holelist)
Definition var.c:17208
int SCIPvarGetBranchPriority(SCIP_VAR *var)
Definition var.c:18072
SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
Definition var.c:17370
SCIP_CLIQUE ** SCIPvarGetCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition var.c:18263
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition var.c:17900
void SCIPvarMarkNotDeletable(SCIP_VAR *var)
Definition var.c:17485
SCIP_Real SCIPvarGetBestRootRedcost(SCIP_VAR *var)
Definition var.c:13771
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoLb(SCIP_VAR *var, int pos)
Definition var.c:18300
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition var.c:11931
SCIP_Real SCIPvarGetCutoffSumCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:16211
SCIP_Real SCIPvarGetBestRootLPObjval(SCIP_VAR *var)
Definition var.c:13805
SCIP_Real SCIPvarGetLbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition var.c:16532
SCIP_RETCODE SCIPvarGetProbvarBinary(SCIP_VAR **var, SCIP_Bool *negated)
Definition var.c:12299
SCIP_Longint SCIPvarGetNBranchingsCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:15733
SCIP_Real * SCIPvarGetVubConstants(SCIP_VAR *var)
Definition var.c:18166
int SCIPvarGetNLocksUp(SCIP_VAR *var)
Definition var.c:3429
SCIP_VAR * SCIPvarGetTransVar(SCIP_VAR *var)
Definition var.c:17600
SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
Definition var.c:18287
SCIP_VAR ** SCIPvarGetVubVars(SCIP_VAR *var)
Definition var.c:18146
int SCIPvarGetNBdchgInfosUb(SCIP_VAR *var)
Definition var.c:18332
SCIP_BOUNDTYPE SCIPbdchginfoGetBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:18522
SCIP_VALUEHISTORY * SCIPvarGetValuehistory(SCIP_VAR *var)
Definition var.c:18342
SCIP_BOUNDTYPE SCIPvarGetWorstBoundType(SCIP_VAR *var)
Definition var.c:18025
void SCIPvarSetCopyData(SCIP_VAR *var,)
Definition var.c:17317
SCIP_Real SCIPvarGetInferenceSumCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:16013
SCIP_Bool SCIPvarsHaveCommonClique(SCIP_VAR *var1, SCIP_Bool value1, SCIP_VAR *var2, SCIP_Bool value2, SCIP_Bool regardimplics)
Definition var.c:11464
SCIP_Bool SCIPbdchgidxIsEarlierNonNull(SCIP_BDCHGIDX *bdchgidx1, SCIP_BDCHGIDX *bdchgidx2)
Definition var.c:18442
SCIP_Real * SCIPvarGetVubCoefs(SCIP_VAR *var)
Definition var.c:18156
SCIP_HOLELIST * SCIPvarGetHolelistGlobal(SCIP_VAR *var)
Definition var.c:17920
SCIP_Real SCIPvarGetBdAtIndex(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition var.c:16772
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:18492
int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition var.c:3295
SCIP_Real SCIPvarGetUbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition var.c:16651
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoUb(SCIP_VAR *var, int pos)
Definition var.c:18320
int SCIPvarGetNBdchgInfosLb(SCIP_VAR *var)
Definition var.c:18312
SCIP_BOUNDTYPE * SCIPvarGetImplTypes(SCIP_VAR *var, SCIP_Bool varfixing)
Definition var.c:18210
int SCIPvarGetLastBdchgDepth(SCIP_VAR *var)
Definition var.c:16852
SCIP_RETCODE SCIPvarsGetProbvarBinary(SCIP_VAR ***vars, SCIP_Bool **negatedarr, int nvars)
Definition var.c:12267
SCIP_Real SCIPvarGetUnchangedObj(SCIP_VAR *var)
Definition var.c:17758
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition var.c:17692
SCIP_Real SCIPvarGetCutoffSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:16168
SCIP_Real SCIPvarGetLbLazy(SCIP_VAR *var)
Definition var.c:18038
SCIP_Bool SCIPvarIsInLP(SCIP_VAR *var)
Definition var.c:17622
SCIP_VAR * SCIPvarGetAggrVar(SCIP_VAR *var)
Definition var.c:17632
SCIP_Real SCIPnormalCDF(SCIP_Real mean, SCIP_Real variance, SCIP_Real value)
Definition misc.c:195
SCIP_Real SCIPcomputeTwoSampleTTestValue(SCIP_Real meanx, SCIP_Real meany, SCIP_Real variancex, SCIP_Real variancey, SCIP_Real countx, SCIP_Real county)
Definition misc.c:122
SCIP_Real SCIPstudentTGetCriticalValue(SCIP_CONFIDENCELEVEL clevel, int df)
Definition misc.c:105
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 SCIPsortPtrReal(void **ptrarray, SCIP_Real *realarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition misc.c:10788
SCIP_Bool SCIPstrToRealValue(const char *str, SCIP_Real *value, char **endptr)
Definition misc.c:10889
void SCIPstrCopySection(const char *str, char startchar, char endchar, char *token, int size, char **endptr)
Definition misc.c:10919
SCIP_RETCODE SCIPvaluehistoryCreate(SCIP_VALUEHISTORY **valuehistory, BMS_BLKMEM *blkmem)
Definition history.c:240
SCIP_RETCODE SCIPvaluehistoryFind(SCIP_VALUEHISTORY *valuehistory, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real value, SCIP_HISTORY **history)
Definition history.c:281
void SCIPvaluehistoryFree(SCIP_VALUEHISTORY **valuehistory, BMS_BLKMEM *blkmem)
Definition history.c:259
void SCIPvaluehistoryScaleVSIDS(SCIP_VALUEHISTORY *valuehistory, SCIP_Real scalar)
Definition history.c:326
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:439
SCIP_Real SCIPhistoryGetAvgInferences(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:658
SCIP_Longint SCIPhistoryGetNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:558
SCIP_Longint SCIPhistoryGetNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:632
SCIP_Real SCIPhistoryGetAvgConflictlength(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:571
SCIP_Real SCIPhistoryGetAvgCutoffs(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:684
SCIP_RETCODE SCIPhistoryCreate(SCIP_HISTORY **history, BMS_BLKMEM *blkmem)
Definition history.c:51
void SCIPhistoryIncInferenceSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition history.c:600
SCIP_Real SCIPhistoryGetCutoffSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:671
SCIP_Real SCIPhistoryGetPseudocostCount(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:477
SCIP_Real SCIPhistoryGetPseudocostVariance(SCIP_HISTORY *history, SCIP_BRANCHDIR direction)
Definition history.c:453
void SCIPhistoryIncNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real length)
Definition history.c:542
void SCIPhistoryScaleVSIDS(SCIP_HISTORY *history, SCIP_Real scalar)
Definition history.c:517
void SCIPhistoryIncCutoffSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition history.c:616
void SCIPhistoryIncNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, int depth)
Definition history.c:584
void SCIPhistoryUpdatePseudocost(SCIP_HISTORY *history, SCIP_SET *set, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition history.c:171
SCIP_Real SCIPhistoryGetVSIDS(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:529
SCIP_Real SCIPhistoryGetAvgBranchdepth(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:697
SCIP_Real SCIPhistoryGetInferenceSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:645
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:110
SCIP_BRANCHDIR SCIPbranchdirOpposite(SCIP_BRANCHDIR dir)
Definition history.c:430
void SCIPhistoryIncVSIDS(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition history.c:503
internal methods for branching and inference history
SCIP_VAR ** SCIPimplicsGetVars(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition implics.c:3331
void SCIPcliqueDelVar(SCIP_CLIQUE *clique, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Bool value)
Definition implics.c:1285
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:3306
void SCIPvboundsShrink(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem, int newnvbds)
Definition implics.c:333
SCIP_VAR ** SCIPcliqueGetVars(SCIP_CLIQUE *clique)
Definition implics.c:3380
SCIP_CLIQUE ** SCIPcliquelistGetCliques(SCIP_CLIQUELIST *cliquelist, SCIP_Bool value)
Definition implics.c:3455
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:3349
void SCIPcliquelistCheck(SCIP_CLIQUELIST *cliquelist, SCIP_VAR *var)
Definition implics.c:3464
SCIP_VAR ** SCIPvboundsGetVars(SCIP_VBOUNDS *vbounds)
Definition implics.c:3298
int SCIPcliqueGetNVars(SCIP_CLIQUE *clique)
Definition implics.c:3370
SCIP_Bool * SCIPcliqueGetValues(SCIP_CLIQUE *clique)
Definition implics.c:3392
SCIP_RETCODE SCIPvboundsDel(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem, SCIP_VAR *vbdvar, SCIP_Bool negativecoef)
Definition implics.c:288
SCIP_RETCODE SCIPcliquetableAdd(SCIP_CLIQUETABLE *cliquetable, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR **vars, SCIP_Bool *values, int nvars, SCIP_Bool isequation, SCIP_Bool *infeasible, int *nbdchgs)
Definition implics.c:2376
int * SCIPimplicsGetIds(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition implics.c:3361
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:3322
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:3340
int SCIPcliquelistGetNCliques(SCIP_CLIQUELIST *cliquelist, SCIP_Bool value)
Definition implics.c:3446
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:3426
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:3314
int SCIPvboundsGetNVbds(SCIP_VBOUNDS *vbounds)
Definition implics.c:3290
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:17837
SCIP_RETCODE SCIPcolChgUb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newub)
Definition lp.c:3802
SCIP_RETCODE SCIPcolFree(SCIP_COL **col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition lp.c:3377
SCIP_RETCODE SCIPcolChgLb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newlb)
Definition lp.c:3757
void SCIPlpDecNLoosevars(SCIP_LP *lp)
Definition lp.c:14330
SCIP_RETCODE SCIProwAddConstant(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_Real addval)
Definition lp.c:5640
SCIP_RETCODE SCIPcolChgObj(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newobj)
Definition lp.c:3698
SCIP_RETCODE SCIProwIncCoef(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_COL *col, SCIP_Real incval)
Definition lp.c:5528
SCIP_Bool SCIPlpDiving(SCIP_LP *lp)
Definition lp.c:17847
SCIP_Real SCIPcolGetRedcost(SCIP_COL *col, SCIP_STAT *stat, SCIP_LP *lp)
Definition lp.c:3952
SCIP_RETCODE SCIPcolCreate(SCIP_COL **col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var, int len, SCIP_ROW **rows, SCIP_Real *vals, SCIP_Bool removable)
Definition lp.c:3279
SCIP_RETCODE SCIPlpUpdateVarLoose(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition lp.c:14309
static const SCIP_Real scalars[]
Definition lp.c:5743
SCIP_RETCODE SCIPlpUpdateVarColumn(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition lp.c:14185
internal methods for LP management
#define NULL
Definition lpi_spx1.cpp:161
#define BMSreallocBlockMemorySize(mem, ptr, oldsize, newsize)
Definition memory.h:458
#define BMSduplicateBlockMemoryArray(mem, ptr, source, num)
Definition memory.h:464
#define BMSfreeBlockMemory(mem, ptr)
Definition memory.h:467
#define BMSallocBlockMemory(mem, ptr)
Definition memory.h:453
#define BMSfreeBlockMemoryArrayNull(mem, ptr, num)
Definition memory.h:470
#define BMSfreeBlockMemorySize(mem, ptr, size)
Definition memory.h:471
#define BMScopyMemoryArray(ptr, source, num)
Definition memory.h:136
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition memory.h:469
#define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
Definition memory.h:460
#define BMSallocBlockMemorySize(mem, ptr, size)
Definition memory.h:455
struct BMS_BlkMem BMS_BLKMEM
Definition memory.h:439
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 SCIPprimalUpdateObjoffset(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp)
Definition primal.c:488
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:1551
int SCIPprobGetNContVars(SCIP_PROB *prob)
Definition prob.c:2388
SCIP_RETCODE SCIPprobAddVar(SCIP_PROB *prob, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR *var)
Definition prob.c:937
SCIP_RETCODE SCIPprobVarChangedStatus(SCIP_PROB *prob, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_BRANCHCAND *branchcand, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var)
Definition prob.c:1191
const char * SCIPprobGetName(SCIP_PROB *prob)
Definition prob.c:2343
void SCIPprobAddObjoffset(SCIP_PROB *prob, SCIP_Real addval)
Definition prob.c:1440
int SCIPprobGetNVars(SCIP_PROB *prob)
Definition prob.c:2352
SCIP_VAR ** SCIPprobGetVars(SCIP_PROB *prob)
Definition prob.c:2397
SCIP_Bool SCIPprobIsTransformed(SCIP_PROB *prob)
Definition prob.c:2287
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:849
internal methods for relaxators
SCIP callable library.
SCIP_Bool SCIPsetIsDualfeasZero(SCIP_SET *set, SCIP_Real val)
Definition set.c:6852
SCIP_Real SCIPsetFloor(SCIP_SET *set, SCIP_Real val)
Definition set.c:6320
SCIP_Bool SCIPsetIsFeasPositive(SCIP_SET *set, SCIP_Real val)
Definition set.c:6652
SCIP_Bool SCIPsetIsGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:6227
SCIP_Real SCIPsetFeasCeil(SCIP_SET *set, SCIP_Real val)
Definition set.c:6709
SCIP_Bool SCIPsetIsFeasNegative(SCIP_SET *set, SCIP_Real val)
Definition set.c:6663
SCIP_Real SCIPsetFeastol(SCIP_SET *set)
Definition set.c:6040
SCIP_Real SCIPsetCeil(SCIP_SET *set, SCIP_Real val)
Definition set.c:6331
SCIP_Bool SCIPsetIsFeasGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:6597
SCIP_Bool SCIPsetIsFeasLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:6575
SCIP_Bool SCIPsetIsFeasEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:6531
SCIP_Bool SCIPsetIsPositive(SCIP_SET *set, SCIP_Real val)
Definition set.c:6256
SCIP_Bool SCIPsetIsLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:6191
SCIP_Real SCIPsetFeasFloor(SCIP_SET *set, SCIP_Real val)
Definition set.c:6698
SCIP_Bool SCIPsetIsDualfeasNegative(SCIP_SET *set, SCIP_Real val)
Definition set.c:6874
SCIP_Real SCIPsetEpsilon(SCIP_SET *set)
Definition set.c:6020
SCIP_Bool SCIPsetIsEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:6155
SCIP_Bool SCIPsetIsFeasZero(SCIP_SET *set, SCIP_Real val)
Definition set.c:6641
SCIP_STAGE SCIPsetGetStage(SCIP_SET *set)
Definition set.c:2915
SCIP_Bool SCIPsetIsFeasLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:6553
SCIP_Real SCIPsetInfinity(SCIP_SET *set)
Definition set.c:5998
SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:6173
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition set.c:6133
SCIP_Bool SCIPsetIsDualfeasPositive(SCIP_SET *set, SCIP_Real val)
Definition set.c:6863
SCIP_Bool SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:6209
SCIP_Bool SCIPsetIsIntegral(SCIP_SET *set, SCIP_Real val)
Definition set.c:6278
SCIP_Bool SCIPsetIsZero(SCIP_SET *set, SCIP_Real val)
Definition set.c:6245
SCIP_Bool SCIPsetIsFeasGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:6619
SCIP_Real SCIPsetGetHugeValue(SCIP_SET *set)
Definition set.c:6010
int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
Definition set.c:5712
SCIP_Bool SCIPsetIsFeasIntegral(SCIP_SET *set, SCIP_Real val)
Definition set.c:6674
SCIP_Bool SCIPsetIsNegative(SCIP_SET *set, SCIP_Real val)
Definition set.c:6267
internal methods for global SCIP settings
#define SCIPsetFreeBufferArray(set, ptr)
Definition set.h:1741
#define SCIPsetFreeCleanBufferArray(set, ptr)
Definition set.h:1748
#define SCIPsetAllocBufferArray(set, ptr, num)
Definition set.h:1734
#define SCIPsetAllocCleanBufferArray(set, ptr, num)
Definition set.h:1745
#define SCIPsetDuplicateBufferArray(set, ptr, source, num)
Definition set.h:1736
#define SCIPsetDebugMsg
Definition set.h:1770
#define SCIPsetReallocBufferArray(set, ptr, num)
Definition set.h:1738
SCIP_Real SCIPsolGetVal(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var)
Definition sol.c:1372
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:807
internal methods for problem statistics
#define SCIPstatIncrement(stat, set, field)
Definition stat.h:260
SCIP_VAR * var
Definition struct_var.h:187
SCIP_Real scalar
Definition struct_var.h:185
SCIP_Real constant
Definition struct_var.h:186
SCIP_BDCHGIDX bdchgidx
Definition struct_var.h:121
SCIP_Real newbound
Definition struct_var.h:118
SCIP_INFERENCEDATA inferencedata
Definition struct_var.h:120
unsigned int boundchgtype
Definition struct_var.h:123
unsigned int boundtype
Definition struct_var.h:124
SCIP_VAR * var
Definition struct_var.h:119
unsigned int redundant
Definition struct_var.h:126
unsigned int inferboundtype
Definition struct_var.h:125
SCIP_Real oldbound
Definition struct_var.h:117
unsigned int pos
Definition struct_var.h:122
unsigned int redundant
Definition struct_var.h:104
int lppos
Definition struct_lp.h:172
int lpipos
Definition struct_lp.h:173
SCIP_VAR * var
Definition struct_lp.h:160
int var_probindex
Definition struct_lp.h:178
SCIP_HOLECHG * holechgs
Definition struct_var.h:143
SCIP_BOUNDCHG * boundchgs
Definition struct_var.h:134
unsigned int nboundchgs
Definition struct_var.h:132
SCIP_BOUNDCHG * boundchgs
Definition struct_var.h:152
SCIP_HOLECHG * holechgs
Definition struct_var.h:153
unsigned int domchgtype
Definition struct_var.h:151
SCIP_Real lb
Definition struct_var.h:170
SCIP_Real ub
Definition struct_var.h:171
SCIP_HOLELIST * holelist
Definition struct_var.h:172
SCIP_EVENTTYPE eventmask
SCIP_HOLELIST ** ptr
Definition struct_var.h:67
SCIP_HOLELIST * oldlist
Definition struct_var.h:69
SCIP_HOLELIST * newlist
Definition struct_var.h:68
SCIP_Real right
Definition struct_var.h:54
SCIP_Real left
Definition struct_var.h:53
SCIP_HOLELIST * next
Definition struct_var.h:61
SCIP_HOLE hole
Definition struct_var.h:60
SCIP_Bool divingobjchg
Definition struct_lp.h:381
SCIP_VAR ** vars
Definition struct_var.h:195
SCIP_Real constant
Definition struct_var.h:193
SCIP_Real * scalars
Definition struct_var.h:194
SCIP_Real constant
Definition struct_var.h:203
SCIP_DOM origdom
Definition struct_var.h:178
SCIP_VAR * transvar
Definition struct_var.h:179
SCIP_OBJSENSE objsense
Definition struct_prob.h:86
SCIP_Real objscale
Definition struct_prob.h:51
char * name
Definition struct_lp.h:226
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_Real lazylb
Definition struct_var.h:223
SCIP_VARDATA * vardata
Definition struct_var.h:240
SCIP_EVENTFILTER * eventfilter
Definition struct_var.h:247
int nubchginfos
Definition struct_var.h:269
SCIP_Real lazyub
Definition struct_var.h:224
SCIP_ORIGINAL original
Definition struct_var.h:229
SCIP_VBOUNDS * vlbs
Definition struct_var.h:243
SCIP_AGGREGATE aggregate
Definition struct_var.h:231
SCIP_IMPLICS * implics
Definition struct_var.h:245
SCIP_VAR ** parentvars
Definition struct_var.h:241
SCIP_BDCHGINFO * lbchginfos
Definition struct_var.h:248
SCIP_Real rootsol
Definition struct_var.h:212
SCIP_VAR * negatedvar
Definition struct_var.h:242
SCIP * scip
Definition struct_var.h:288
unsigned int varstatus
Definition struct_var.h:281
int nlocksdown[NLOCKTYPES]
Definition struct_var.h:263
SCIP_Real bestrootsol
Definition struct_var.h:213
SCIP_HISTORY * historycrun
Definition struct_var.h:251
unsigned int relaxationonly
Definition struct_var.h:286
unsigned int donotmultaggr
Definition struct_var.h:279
int closestvubidx
Definition struct_var.h:273
SCIP_DOM glbdom
Definition struct_var.h:225
unsigned int vartype
Definition struct_var.h:280
SCIP_Real branchfactor
Definition struct_var.h:211
int conflictubcount
Definition struct_var.h:271
SCIP_Real unchangedobj
Definition struct_var.h:210
SCIP_BDCHGINFO * ubchginfos
Definition struct_var.h:249
SCIP_Real bestrootredcost
Definition struct_var.h:214
char * name
Definition struct_var.h:235
unsigned int deletable
Definition struct_var.h:276
unsigned int initial
Definition struct_var.h:274
SCIP_DOM locdom
Definition struct_var.h:226
unsigned int removable
Definition struct_var.h:275
SCIP_CLIQUELIST * cliquelist
Definition struct_var.h:246
SCIP_COL * col
Definition struct_var.h:230
unsigned int deleted
Definition struct_var.h:277
SCIP_MULTAGGR multaggr
Definition struct_var.h:232
SCIP_Real obj
Definition struct_var.h:209
int probindex
Definition struct_var.h:255
SCIP_Real nlpsol
Definition struct_var.h:217
int nlocksup[NLOCKTYPES]
Definition struct_var.h:264
int nlbchginfos
Definition struct_var.h:267
unsigned int branchdirection
Definition struct_var.h:283
unsigned int delglobalstructs
Definition struct_var.h:285
union SCIP_Var::@21 data
int lbchginfossize
Definition struct_var.h:266
SCIP_HISTORY * history
Definition struct_var.h:250
SCIP_VBOUNDS * vubs
Definition struct_var.h:244
int nparentvars
Definition struct_var.h:261
unsigned int donotaggr
Definition struct_var.h:278
int parentvarssize
Definition struct_var.h:260
int closestvlbidx
Definition struct_var.h:272
SCIP_NEGATE negate
Definition struct_var.h:233
SCIP_Real primsolavg
Definition struct_var.h:218
SCIP_Real relaxsol
Definition struct_var.h:216
SCIP_Longint closestvblpcount
Definition struct_var.h:253
SCIP_Real bestrootlpobjval
Definition struct_var.h:215
int ubchginfossize
Definition struct_var.h:268
SCIP_VALUEHISTORY * valuehistory
Definition struct_var.h:252
int branchpriority
Definition struct_var.h:265
int conflictlbcount
Definition struct_var.h:270
SCIP_PROB * origprob
Definition struct_scip.h:80
SCIP_PROB * transprob
Definition struct_scip.h:98
datastructures for managing events
data structures for 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
#define MAX(x, y)
Definition tclique_def.h:92
SCIP_NODE * SCIPtreeGetRootNode(SCIP_TREE *tree)
Definition tree.c:8454
SCIP_RETCODE SCIPnodeAddBoundchg(SCIP_NODE *node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype, SCIP_Bool probingchange)
Definition tree.c:2087
internal methods for branch and bound tree
#define SCIP_EVENTTYPE_GHOLEADDED
Definition type_event.h:81
#define SCIP_EVENTTYPE_GUBCHANGED
Definition type_event.h:76
struct SCIP_EventData SCIP_EVENTDATA
Definition type_event.h:173
#define SCIP_EVENTTYPE_FORMAT
Definition type_event.h:152
#define SCIP_EVENTTYPE_GLBCHANGED
Definition type_event.h:75
#define SCIP_EVENTTYPE_VARCHANGED
Definition type_event.h:130
#define SCIP_EVENTTYPE_LBCHANGED
Definition type_event.h:121
#define SCIP_EVENTTYPE_UBCHANGED
Definition type_event.h:122
uint64_t SCIP_EVENTTYPE
Definition type_event.h:151
@ SCIP_BRANCHDIR_DOWNWARDS
@ SCIP_BRANCHDIR_AUTO
@ SCIP_BRANCHDIR_UPWARDS
enum SCIP_BranchDir SCIP_BRANCHDIR
@ SCIP_BOUNDTYPE_UPPER
Definition type_lp.h:57
@ SCIP_BOUNDTYPE_LOWER
Definition type_lp.h:56
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition type_lp.h:59
@ 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
#define SCIP_DECL_SORTPTRCOMP(x)
Definition type_misc.h:188
#define SCIP_DECL_HASHKEYEQ(x)
Definition type_misc.h:194
#define SCIP_DECL_HASHGETKEY(x)
Definition type_misc.h:191
#define SCIP_DECL_HASHKEYVAL(x)
Definition type_misc.h:197
@ 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
enum SCIP_Objsense SCIP_OBJSENSE
Definition type_prob.h:50
@ 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
@ 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_VarData SCIP_VARDATA
Definition type_var.h:120
enum SCIP_BoundchgType SCIP_BOUNDCHGTYPE
Definition type_var.h:91
#define NLOCKTYPES
Definition type_var.h:94
#define SCIP_DECL_VARDELORIG(x)
Definition type_var.h:131
@ SCIP_DOMCHGTYPE_DYNAMIC
Definition type_var.h:78
@ SCIP_DOMCHGTYPE_BOUND
Definition type_var.h:80
@ SCIP_DOMCHGTYPE_BOTH
Definition type_var.h:79
#define SCIP_DECL_VARTRANS(x)
Definition type_var.h:151
@ SCIP_VARTYPE_INTEGER
Definition type_var.h:63
@ SCIP_VARTYPE_CONTINUOUS
Definition type_var.h:71
@ SCIP_VARTYPE_IMPLINT
Definition type_var.h:64
@ SCIP_VARTYPE_BINARY
Definition type_var.h:62
@ SCIP_BOUNDCHGTYPE_PROPINFER
Definition type_var.h:89
@ SCIP_BOUNDCHGTYPE_BRANCHING
Definition type_var.h:87
@ SCIP_BOUNDCHGTYPE_CONSINFER
Definition type_var.h:88
@ SCIP_VARSTATUS_ORIGINAL
Definition type_var.h:49
@ SCIP_VARSTATUS_FIXED
Definition type_var.h:52
@ SCIP_VARSTATUS_COLUMN
Definition type_var.h:51
@ SCIP_VARSTATUS_MULTAGGR
Definition type_var.h:54
@ SCIP_VARSTATUS_NEGATED
Definition type_var.h:55
@ SCIP_VARSTATUS_AGGREGATED
Definition type_var.h:53
@ SCIP_VARSTATUS_LOOSE
Definition type_var.h:50
#define SCIP_DECL_VARCOPY(x)
Definition type_var.h:194
#define SCIP_DECL_VARDELTRANS(x)
Definition type_var.h:164
enum SCIP_LockType SCIP_LOCKTYPE
Definition type_var.h:100
@ SCIP_LOCKTYPE_MODEL
Definition type_var.h:97
enum SCIP_Vartype SCIP_VARTYPE
Definition type_var.h:73
enum SCIP_Varstatus SCIP_VARSTATUS
Definition type_var.h:57
SCIP_DOMCHGBOUND domchgbound
Definition struct_var.h:162
SCIP_DOMCHGDYN domchgdyn
Definition struct_var.h:164
SCIP_DOMCHGBOTH domchgboth
Definition struct_var.h:163
SCIP_RETCODE SCIPvarRemove(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_CLIQUETABLE *cliquetable, SCIP_SET *set, SCIP_Bool final)
Definition var.c:6048
static SCIP_RETCODE varParse(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, const char *str, char *name, SCIP_Real *lb, SCIP_Real *ub, SCIP_Real *obj, SCIP_VARTYPE *vartype, SCIP_Real *lazylb, SCIP_Real *lazyub, SCIP_Bool local, char **endptr, SCIP_Bool *success)
Definition var.c:2349
SCIP_RETCODE SCIPvarAddObj(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_Real addobj)
Definition var.c:6328
SCIP_Real SCIPvarGetObjLP(SCIP_VAR *var)
Definition var.c:12875
SCIP_Real SCIPvarGetPseudocost(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition var.c:14466
SCIP_RETCODE SCIPvarsGetActiveVars(SCIP_SET *set, SCIP_VAR **vars, int *nvars, int varssize, int *requiredsize)
Definition var.c:11995
static SCIP_RETCODE tryAggregateIntVars(SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_Real scalarx, SCIP_Real scalary, SCIP_Real rhs, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition var.c:5043
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:15436
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:6675
static SCIP_RETCODE varEnsureUbchginfosSize(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition var.c:453
SCIP_RETCODE SCIPvarChgLbLazy(SCIP_VAR *var, SCIP_SET *set, SCIP_Real lazylb)
Definition var.c:7458
static SCIP_RETCODE domchgEnsureBoundchgsSize(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition var.c:1250
SCIP_RETCODE SCIPvarCreateTransformed(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
Definition var.c:2117
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:7793
SCIP_Real SCIPvarGetPseudocostCount(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:14562
SCIP_RETCODE SCIPvarResetBounds(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat)
Definition var.c:9220
void SCIPbdchginfoFree(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem)
Definition var.c:16385
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:224
SCIP_RETCODE SCIPvarGetTransformed(SCIP_VAR *origvar, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **transvar)
Definition var.c:3548
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:6253
static SCIP_RETCODE varProcessChgBranchPriority(SCIP_VAR *var, int branchpriority)
Definition var.c:11620
static SCIP_RETCODE parseValue(SCIP_SET *set, const char *str, SCIP_Real *value, char **endptr)
Definition var.c:2272
#define MAXDNOM
SCIP_Real SCIPvarGetPseudocostVariance(SCIP_VAR *var, SCIP_BRANCHDIR dir, SCIP_Bool onlycurrentrun)
Definition var.c:14681
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:910
SCIP_Real SCIPvarGetImplRedcost(SCIP_VAR *var, SCIP_SET *set, SCIP_Bool varfixing, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_LP *lp)
Definition var.c:13457
static SCIP_RETCODE varCreate(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARCOPY((*varcopy)), SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_VARDATA *vardata)
Definition var.c:1929
SCIP_RETCODE SCIPvarFix(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition var.c:3749
static SCIP_RETCODE varAddImplic(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool isshortcut, SCIP_Bool *infeasible, int *nbdchgs, SCIP_Bool *added)
Definition var.c:9501
void SCIPvarInitSolve(SCIP_VAR *var)
Definition var.c:2931
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:15520
static void printBounds(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, FILE *file, SCIP_Real lb, SCIP_Real ub, const char *name)
Definition var.c:2944
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:15040
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:7626
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:479
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:1348
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:8982
SCIP_Real SCIPvarGetAvgCutoffs(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition var.c:16254
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:628
SCIP_RETCODE SCIPdomchgMakeStatic(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition var.c:1161
static void checkImplic(SCIP_SET *set, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool *redundant, SCIP_Bool *infeasible)
Definition var.c:9371
static SCIP_VAR * varGetActiveVar(SCIP_VAR *var)
Definition var.c:5788
SCIP_RETCODE SCIPvarUpdatePseudocost(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition var.c:14368
SCIP_RETCODE SCIPvarTransform(SCIP_VAR *origvar, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_OBJSENSE objsense, SCIP_VAR **transvar)
Definition var.c:3461
SCIP_RETCODE SCIPvarAddHoleOriginal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real left, SCIP_Real right)
Definition var.c:8682
SCIP_RETCODE SCIPvarAddCliqueToList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition var.c:11382
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:6218
static SCIP_RETCODE varFree(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition var.c:2744
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:8863
SCIP_Real SCIPvarGetAvgInferencesCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition var.c:16113
static SCIP_RETCODE varEventImplAdded(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition var.c:9253
SCIP_RETCODE SCIPvarRelease(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition var.c:2872
void SCIPvarGetClosestVub(SCIP_VAR *var, SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *closestvub, int *closestvubidx)
Definition var.c:14187
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:15176
void SCIPvarAdjustLb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *lb)
Definition var.c:6506
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:18407
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:7174
SCIP_RETCODE SCIPvarSetNLPSol(SCIP_VAR *var, SCIP_SET *set, SCIP_Real solval)
Definition var.c:13995
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:2159
SCIP_Real SCIPvarCalcPscostConfidenceBound(SCIP_VAR *var, SCIP_SET *set, SCIP_BRANCHDIR dir, SCIP_Bool onlycurrentrun, SCIP_CONFIDENCELEVEL clevel)
Definition var.c:14735
static SCIP_BDCHGIDX presolvebdchgidx
Definition var.c:16812
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:7535
SCIP_Bool SCIPvarIsPscostRelerrorReliable(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real threshold, SCIP_CONFIDENCELEVEL clevel)
Definition var.c:14773
SCIP_RETCODE SCIPvarChgLbOriginal(SCIP_VAR *var, SCIP_SET *set, SCIP_Real newbound)
Definition var.c:6556
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:14259
SCIP_Real SCIPvarGetLbLP(SCIP_VAR *var, SCIP_SET *set)
Definition var.c:12921
void SCIPvarAdjustBd(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real *bd)
Definition var.c:6540
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:7573
SCIP_RETCODE SCIPvarChgObjDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newobj)
Definition var.c:6443
SCIP_RETCODE SCIPdomchgFree(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition var.c:1060
SCIP_Real SCIPvarGetRelaxSolTransVar(SCIP_VAR *var)
Definition var.c:13984
SCIP_RETCODE SCIPvarPrint(SCIP_VAR *var, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition var.c:3006
SCIP_Real SCIPvarGetVSIDS(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition var.c:18365
static SCIP_RETCODE varEventVarFixed(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, int fixeventtype)
Definition var.c:3654
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:15604
SCIP_Real SCIPvarGetMultaggrLbLocal(SCIP_VAR *var, SCIP_SET *set)
Definition var.c:8423
static SCIP_RETCODE varUpdateAggregationBounds(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *aggvar, SCIP_Real scalar, SCIP_Real constant, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition var.c:4539
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:14850
void SCIPvarCapture(SCIP_VAR *var)
Definition var.c:2847
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:6713
SCIP_RETCODE SCIPvarChgBranchDirection(SCIP_VAR *var, SCIP_BRANCHDIR branchdirection)
Definition var.c:11807
SCIP_Real SCIPvarGetPseudocostCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition var.c:14515
static SCIP_Real adjustedLb(SCIP_SET *set, SCIP_VARTYPE vartype, SCIP_Real lb)
Definition var.c:1568
SCIP_RETCODE SCIPdomchgAddHolechg(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HOLELIST **ptr, SCIP_HOLELIST *newlist, SCIP_HOLELIST *oldlist)
Definition var.c:1519
void SCIPvarStoreRootSol(SCIP_VAR *var, SCIP_Bool roothaslp)
Definition var.c:13258
static SCIP_RETCODE domchgEnsureHolechgsSize(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition var.c:1275
static SCIP_RETCODE varEnsureLbchginfosSize(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition var.c:427
SCIP_Bool SCIPvarDoNotAggr(SCIP_VAR *var)
Definition var.c:5837
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:6167
SCIP_RETCODE SCIPvarFlattenAggregationGraph(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition var.c:4413
SCIP_Longint SCIPvarGetNActiveConflicts(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition var.c:15257
void SCIPvarUpdateBestRootSol(SCIP_VAR *var, SCIP_SET *set, SCIP_Real rootsol, SCIP_Real rootredcost, SCIP_Real rootlpobjval)
Definition var.c:13269
SCIP_RETCODE SCIPvarCreateOriginal(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
Definition var.c:2074
SCIP_Real SCIPvarGetVSIDS_rec(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition var.c:15866
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:8212
SCIP_RETCODE SCIPvarFixBinary(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool value, SCIP_Bool *infeasible, int *nbdchgs)
Definition var.c:11171
SCIP_RETCODE SCIPvarScaleVSIDS(SCIP_VAR *var, SCIP_Real scalar)
Definition var.c:15126
static SCIP_RETCODE findValuehistoryEntry(SCIP_VAR *var, SCIP_Real value, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HISTORY **history)
Definition var.c:14985
SCIP_Real SCIPvarGetAvgConflictlength(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:15349
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:7000
SCIP_Real SCIPvarGetPseudocostCountCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:14607
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:7317
static SCIP_RETCODE varEnsureParentvarsSize(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition var.c:2619
SCIP_RETCODE SCIPvarGetActiveRepresentatives(SCIP_SET *set, SCIP_VAR **vars, SCIP_Real *scalars, int *nvars, int varssize, SCIP_Real *constant, int *requiredsize, SCIP_Bool mergemultiples)
Definition var.c:3918
#define MAX_CLIQUELENGTH
Definition var.c:13453
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:2560
SCIP_Real SCIPvarGetUbLP(SCIP_VAR *var, SCIP_SET *set)
Definition var.c:12991
SCIP_RETCODE SCIPvarColumn(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_LP *lp)
Definition var.c:3579
SCIP_RETCODE SCIPvarChgUbOriginal(SCIP_VAR *var, SCIP_SET *set, SCIP_Real newbound)
Definition var.c:6615
SCIP_RETCODE SCIPvarChgUbDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newbound)
Definition var.c:8328
static void domMerge(SCIP_DOM *dom, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real *newlb, SCIP_Real *newub)
Definition var.c:268
SCIP_Real SCIPvarGetAvgInferences(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition var.c:16056
int SCIPvarGetConflictingBdchgDepth(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real bound)
Definition var.c:16867
static SCIP_RETCODE varEventVarUnlocked(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition var.c:3146
SCIP_Real SCIPvarGetMultaggrUbGlobal(SCIP_VAR *var, SCIP_SET *set)
Definition var.c:8621
void SCIPvarGetClosestVlb(SCIP_VAR *var, SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *closestvlb, int *closestvlbidx)
Definition var.c:14112
SCIP_RETCODE SCIPvarChgUbLazy(SCIP_VAR *var, SCIP_SET *set, SCIP_Real lazyub)
Definition var.c:7481
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:9273
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:14916
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:1383
SCIP_RETCODE SCIPvarTryAggregateVars(SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_Real scalarx, SCIP_Real scalary, SCIP_Real rhs, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition var.c:5281
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:825
void SCIPvarMarkDeleted(SCIP_VAR *var)
Definition var.c:6084
#define MAXIMPLSCLOSURE
Definition var.c:77
static SCIP_RETCODE varSetName(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_STAT *stat, const char *name)
Definition var.c:1897
void SCIPvarMergeHistories(SCIP_VAR *targetvar, SCIP_VAR *othervar, SCIP_STAT *stat)
Definition var.c:4508
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:6751
static void printHolelist(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, SCIP_HOLELIST *holelist, const char *name)
Definition var.c:2972
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:554
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:18380
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:9111
SCIP_Bool SCIPvarIsMarkedDeleteGlobalStructures(SCIP_VAR *var)
Definition var.c:17508
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:1299
SCIP_RETCODE SCIPvarDelClique(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition var.c:11421
SCIP_RETCODE SCIPvarAggregate(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR *aggvar, SCIP_Real scalar, SCIP_Real constant, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition var.c:4730
SCIP_Real SCIPvarGetRelaxSol(SCIP_VAR *var, SCIP_SET *set)
Definition var.c:13912
SCIP_RETCODE SCIPvarDelCliqueFromList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition var.c:11404
int SCIPbdchgidxGetPos(SCIP_BDCHGIDX *bdchgidx)
Definition var.c:18432
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:7507
static SCIP_Bool useValuehistory(SCIP_VAR *var, SCIP_Real value, SCIP_SET *set)
Definition var.c:15012
static SCIP_Real adjustedUb(SCIP_SET *set, SCIP_VARTYPE vartype, SCIP_Real ub)
Definition var.c:1588
SCIP_RETCODE SCIPvarAddImplic(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool transitive, SCIP_Bool *infeasible, int *nbdchgs)
Definition var.c:10901
SCIP_RETCODE SCIPvarsAddClique(SCIP_VAR **vars, SCIP_Bool *values, int nvars, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_CLIQUE *clique)
Definition var.c:11344
SCIP_RETCODE SCIPvarMarkDoNotAggr(SCIP_VAR *var)
Definition var.c:6095
static SCIP_RETCODE varProcessChgBranchFactor(SCIP_VAR *var, SCIP_SET *set, SCIP_Real branchfactor)
Definition var.c:11485
SCIP_RETCODE SCIPdomchgAddBoundchg(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_VAR *var, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype, SCIP_BOUNDCHGTYPE boundchgtype, SCIP_Real lpsolval, SCIP_VAR *infervar, SCIP_CONS *infercons, SCIP_PROP *inferprop, int inferinfo, SCIP_BOUNDTYPE inferboundtype)
Definition var.c:1422
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:7959
SCIP_RETCODE SCIPvarLoose(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *prob, SCIP_LP *lp)
Definition var.c:3613
static SCIP_RETCODE varFreeParents(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition var.c:2671
static SCIP_BDCHGIDX initbdchgidx
Definition var.c:16809
SCIP_RETCODE SCIPvarChgBranchPriority(SCIP_VAR *var, int branchpriority)
Definition var.c:11676
static SCIP_RETCODE domchgCreate(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem)
Definition var.c:1039
SCIP_RETCODE SCIPvarMarkDoNotMultaggr(SCIP_VAR *var)
Definition var.c:6131
static SCIP_RETCODE holelistCreate(SCIP_HOLELIST **holelist, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real left, SCIP_Real right)
Definition var.c:152
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:3167
SCIP_RETCODE SCIPvarNegate(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **negvar)
Definition var.c:5906
SCIP_Real SCIPvarGetMultaggrUbLocal(SCIP_VAR *var, SCIP_SET *set)
Definition var.c:8489
SCIP_RETCODE SCIPbdchginfoCreate(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_Real oldbound, SCIP_Real newbound)
Definition var.c:16355
static SCIP_RETCODE varAddTransitiveImplic(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool transitive, SCIP_Bool *infeasible, int *nbdchgs)
Definition var.c:9782
SCIP_Real SCIPvarGetMinPseudocostScore(SCIP_VAR *var, SCIP_STAT *stat, SCIP_SET *set, SCIP_Real solval)
Definition var.c:14650
SCIP_RETCODE SCIPvarGetProbvarSum(SCIP_VAR **var, SCIP_SET *set, SCIP_Real *scalar, SCIP_Real *constant)
Definition var.c:12636
static void holelistFree(SCIP_HOLELIST **holelist, BMS_BLKMEM *blkmem)
Definition var.c:176
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:6824
static SCIP_RETCODE applyImplic(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool *infeasible, int *nbdchgs)
Definition var.c:9402
void SCIPvarAdjustUb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *ub)
Definition var.c:6523
SCIP_Real SCIPbdchginfoGetRelaxedBound(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:18621
static SCIP_Real getImplVarRedcost(SCIP_VAR *var, SCIP_SET *set, SCIP_Bool varfixing, SCIP_STAT *stat, SCIP_LP *lp)
Definition var.c:13404
SCIP_RETCODE SCIPvarChgLbDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newbound)
Definition var.c:8238
SCIP_RETCODE SCIPvarMultiaggregate(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, int naggvars, SCIP_VAR **aggvars, SCIP_Real *scalars, SCIP_Real constant, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition var.c:5435
static SCIP_Real SCIPvarGetPseudoSol_rec(SCIP_VAR *var)
Definition var.c:13179
#define MAXABSVBCOEF
Definition var.c:79
SCIP_Real SCIPvarGetAvgConflictlengthCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:15393
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:8086
static SCIP_RETCODE domchgMakeDynamic(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem)
Definition var.c:1109
SCIP_RETCODE SCIPvarAddVlb(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR *vlbvar, SCIP_Real vlbcoef, SCIP_Real vlbconstant, SCIP_Bool transitive, SCIP_Bool *infeasible, int *nbdchgs)
Definition var.c:9990
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:2496
static SCIP_RETCODE parseBounds(SCIP_SET *set, const char *str, char *type, SCIP_Real *lb, SCIP_Real *ub, char **endptr)
Definition var.c:2304
SCIP_Real SCIPvarGetVSIDSCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition var.c:15917
static void varIncRootboundchgs(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat)
Definition var.c:6783
void SCIPvarSetNamePointer(SCIP_VAR *var, const char *name)
Definition var.c:6030
static SCIP_RETCODE holelistDuplicate(SCIP_HOLELIST **target, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HOLELIST *source)
Definition var.c:202
SCIP_RETCODE SCIPvarChgName(SCIP_VAR *var, BMS_BLKMEM *blkmem, const char *name)
Definition var.c:2913
void SCIPvarSetHistory(SCIP_VAR *var, SCIP_HISTORY *history, SCIP_STAT *stat)
Definition var.c:4524
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:8734
void SCIPvarSetProbindex(SCIP_VAR *var, int probindex)
Definition var.c:6015
SCIP_RETCODE SCIPvarAddVub(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR *vubvar, SCIP_Real vubcoef, SCIP_Real vubconstant, SCIP_Bool transitive, SCIP_Bool *infeasible, int *nbdchgs)
Definition var.c:10454
static SCIP_RETCODE varAddParent(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_VAR *parentvar)
Definition var.c:2643
SCIP_Real SCIPvarGetMultaggrLbGlobal(SCIP_VAR *var, SCIP_SET *set)
Definition var.c:8555
SCIP_RETCODE SCIPvarSetRelaxSol(SCIP_VAR *var, SCIP_SET *set, SCIP_RELAXATION *relaxation, SCIP_Real solval, SCIP_Bool updateobj)
Definition var.c:13851
SCIP_RETCODE SCIPvarChgBranchFactor(SCIP_VAR *var, SCIP_SET *set, SCIP_Real branchfactor)
Definition var.c:11549
static SCIP_RETCODE boundchgReleaseData(SCIP_BOUNDCHG *boundchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition var.c:1002
SCIP_Longint SCIPvarGetNActiveConflictsCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition var.c:15304
SCIP_RETCODE SCIPvarAddClique(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool value, SCIP_CLIQUE *clique, SCIP_Bool *infeasible, int *nbdchgs)
Definition var.c:11259
static SCIP_RETCODE boundchgCaptureData(SCIP_BOUNDCHG *boundchg)
Definition var.c:970
static SCIP_RETCODE varProcessChgBranchDirection(SCIP_VAR *var, SCIP_BRANCHDIR branchdirection)
Definition var.c:11740
SCIP_Real SCIPvarGetAvgCutoffsCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition var.c:16301
SCIP_Bool SCIPvarDoNotMultaggr(SCIP_VAR *var)
Definition var.c:5870
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:1609
static void varSetProbindex(SCIP_VAR *var, int probindex)
Definition var.c:5996
static SCIP_RETCODE varAddTransitiveBinaryClosureImplic(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_Bool implvarfixing, SCIP_Bool *infeasible, int *nbdchgs)
Definition var.c:9709
internal methods for problem variables