Scippy

SCIP

Solving Constraint Integer Programs

var.c
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the program and library */
4/* SCIP --- Solving Constraint Integer Programs */
5/* */
6/* Copyright (c) 2002-2025 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);
110 strings = backtrace_symbols(array, size);
111 if( strings == NULL )
112 return;
113
114 /* skip first entry, which is the print_backtrace function */
115 for( i = 1; i < size; ++i )
116 {
117 /* if string is something like
118 * /path/to/scip/bin/../lib/shared/libscip-7.0.1.3.linux.x86_64.gnu.dbg.so(+0x2675dd3)
119 * (that is, no function name because it is a inlined function), then call
120 * addr2line -e <libname> <addr> to get func and code line
121 * dladdr() may be an alternative
122 */
123 char* openpar;
124 char* closepar = NULL;
125#ifndef DEBUGUSES_NOADDR2LINE
126 openpar = strchr(strings[i], '(');
127 if( openpar != NULL && openpar[1] == '+' )
128 closepar = strchr(openpar+2, ')');
129#endif
130 if( closepar != NULL )
131 {
132 char cmd[SCIP_MAXSTRLEN];
133 (void) SCIPsnprintf(cmd, SCIP_MAXSTRLEN, "addr2line -f -p -e \"%.*s\" %.*s", openpar - strings[i], strings[i], closepar-openpar-1, openpar+1);
134 printf(" ");
135 fflush(stdout);
136 system(cmd);
137 }
138 else
139 printf(" %s\n", strings[i]);
140 }
141
142 free(strings);
143}
144#endif
145
146/*
147 * hole, holelist, and domain methods
148 */
149
150/** creates a new holelist element */
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{
233 SCIP_HOLELIST** insertpos;
234 SCIP_HOLELIST* next;
235
236 assert(dom != NULL);
237 assert(added != NULL);
238
239 /* search for the position of the new hole */
240 insertpos = &dom->holelist;
241 while( *insertpos != NULL && (*insertpos)->hole.left < left )
242 insertpos = &(*insertpos)->next;
243
244 /* check if new hole already exists in the hole list or is a sub hole of an existing one */
245 if( *insertpos != NULL && (*insertpos)->hole.left == left && (*insertpos)->hole.right >= right ) /*lint !e777 */
246 {
247 SCIPsetDebugMsg(set, "new hole (%.15g,%.15g) is redundant through known hole (%.15g,%.15g)\n",
248 left, right, (*insertpos)->hole.left, (*insertpos)->hole.right);
249 *added = FALSE;
250 return SCIP_OKAY;
251 }
252
253 /* add hole */
254 *added = TRUE;
255
256 next = *insertpos;
257 SCIP_CALL( holelistCreate(insertpos, blkmem, set, left, right) );
258 (*insertpos)->next = next;
259
260 return SCIP_OKAY;
261}
262
263/** merges overlapping holes into single holes, computes and moves lower and upper bound, respectively */
264/**@todo the domMerge() method is currently called if a lower or an upper bound locally or globally changed; this could
265 * be more efficient if performed with the knowledge if it was a lower or an upper bound which triggered this
266 * merge */
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{
276 SCIP_HOLELIST** holelistptr;
277 SCIP_HOLELIST** lastnextptr;
278 SCIP_Real* lastrightptr;
279
280 assert(dom != NULL);
281 assert(SCIPsetIsLE(set, dom->lb, dom->ub));
282
283#ifndef NDEBUG
284 {
285 /* check if the holelist is sorted w.r.t. to the left interval bounds */
286 SCIP_Real lastleft;
287
288 holelistptr = &dom->holelist;
289
290 lastleft = -SCIPsetInfinity(set);
291
292 while( *holelistptr != NULL )
293 {
294 if( (*holelistptr)->next != NULL )
295 {
296 assert( SCIPsetIsLE(set, lastleft, (*holelistptr)->hole.left) );
297 lastleft = (*holelistptr)->hole.left;
298 }
299
300 holelistptr = &(*holelistptr)->next;
301 }
302 }
303#endif
304
305 SCIPsetDebugMsg(set, "merge hole list\n");
306
307 holelistptr = &dom->holelist;
308 lastrightptr = &dom->lb; /* lower bound is the right bound of the hole (-infinity,lb) */
309 lastnextptr = holelistptr;
310
311 while( *holelistptr != NULL )
312 {
313 SCIPsetDebugMsg(set, "check hole (%.15g,%.15g) last right interval was <%.15g>\n", (*holelistptr)->hole.left, (*holelistptr)->hole.right, *lastrightptr);
314
315 /* check that the hole is not empty */
316 assert(SCIPsetIsLT(set, (*holelistptr)->hole.left, (*holelistptr)->hole.right));
317
318 if( SCIPsetIsGE(set, (*holelistptr)->hole.left, dom->ub) )
319 {
320 /* the remaining holes start behind the upper bound: remove them */
321 SCIPsetDebugMsg(set, "remove remaining hole since upper bound <%.15g> is less then the left hand side of the current hole\n", dom->ub);
322 holelistFree(holelistptr, blkmem);
323 assert(*holelistptr == NULL);
324
325 /* unlink this hole from the previous hole */
326 *lastnextptr = NULL;
327 }
328 else if( SCIPsetIsGT(set, (*holelistptr)->hole.right, dom->ub) )
329 {
330 /* the hole overlaps the upper bound: decrease upper bound, remove this hole and all remaining holes */
331 SCIPsetDebugMsg(set, "upper bound <%.15g> lays in current hole; store new upper bound and remove this and all remaining holes\n", dom->ub);
332
333 assert(SCIPsetIsLT(set, (*holelistptr)->hole.left, dom->ub));
334
335 /* adjust upper bound */
336 dom->ub = (*holelistptr)->hole.left;
337
338 if(newub != NULL )
339 *newub = (*holelistptr)->hole.left;
340
341 /* remove remaining hole list */
342 holelistFree(holelistptr, blkmem);
343 assert(*holelistptr == NULL);
344
345 /* unlink this hole from the previous hole */
346 *lastnextptr = NULL;
347 }
348 else if( SCIPsetIsGT(set, *lastrightptr, (*holelistptr)->hole.left) )
349 {
350 /* the right bound of the last hole is greater than the left bound of this hole: increase the right bound of
351 * the last hole, delete this hole */
352 SCIP_HOLELIST* nextholelist;
353
354 if( SCIPsetIsEQ(set, *lastrightptr, dom->lb ) )
355 {
356 /* the reason for the overlap results from the lower bound hole (-infinity,lb); therefore, we can increase
357 * the lower bound */
358 SCIPsetDebugMsg(set, "lower bound <%.15g> lays in current hole; store new lower bound and remove hole\n", dom->lb);
359 *lastrightptr = MAX(*lastrightptr, (*holelistptr)->hole.right);
360
361 /* adjust lower bound */
362 dom->lb = *lastrightptr;
363
364 if(newlb != NULL )
365 *newlb = *lastrightptr;
366 }
367 else
368 {
369 SCIPsetDebugMsg(set, "current hole overlaps with the previous one (...,%.15g); merge to (...,%.15g)\n",
370 *lastrightptr, MAX(*lastrightptr, (*holelistptr)->hole.right) );
371 *lastrightptr = MAX(*lastrightptr, (*holelistptr)->hole.right);
372 }
373 nextholelist = (*holelistptr)->next;
374 (*holelistptr)->next = NULL;
375 holelistFree(holelistptr, blkmem);
376
377 /* connect the linked list after removing the hole */
378 *lastnextptr = nextholelist;
379
380 /* get next hole */
381 *holelistptr = nextholelist;
382 }
383 else
384 {
385 /* the holes do not overlap: update lastholelist and lastrightptr */
386 lastrightptr = &(*holelistptr)->hole.right;
387 lastnextptr = &(*holelistptr)->next;
388
389 /* get next hole */
390 holelistptr = &(*holelistptr)->next;
391 }
392 }
393
394#ifndef NDEBUG
395 {
396 /* check that holes are merged */
397 SCIP_Real lastright;
398
399 lastright = dom->lb; /* lower bound is the right bound of the hole (-infinity,lb) */
400 holelistptr = &dom->holelist;
401
402 while( *holelistptr != NULL )
403 {
404 /* check the the last right interval is smaller or equal to the current left interval (none overlapping) */
405 assert( SCIPsetIsLE(set, lastright, (*holelistptr)->hole.left) );
406
407 /* check the hole property (check that the hole is not empty) */
408 assert( SCIPsetIsLT(set, (*holelistptr)->hole.left, (*holelistptr)->hole.right) );
409 lastright = (*holelistptr)->hole.right;
410
411 /* get next hole */
412 holelistptr = &(*holelistptr)->next;
413 }
414
415 /* check the the last right interval is smaller or equal to the upper bound (none overlapping) */
416 assert( SCIPsetIsLE(set, lastright, dom->ub) );
417 }
418#endif
419}
420
421/*
422 * domain change methods
423 */
424
425/** ensures, that bound change info array for lower bound changes can store at least num entries */
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);
435 assert(var->nlbchginfos <= var->lbchginfossize);
436 assert(SCIPvarIsTransformed(var));
437
438 if( num > var->lbchginfossize )
439 {
440 int newsize;
441
442 newsize = SCIPsetCalcMemGrowSize(set, num);
443 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->lbchginfos, var->lbchginfossize, newsize) );
444 var->lbchginfossize = newsize;
445 }
446 assert(num <= var->lbchginfossize);
447
448 return SCIP_OKAY;
449}
450
451/** ensures, that bound change info array for upper bound changes can store at least num entries */
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);
461 assert(var->nubchginfos <= var->ubchginfossize);
462 assert(SCIPvarIsTransformed(var));
463
464 if( num > var->ubchginfossize )
465 {
466 int newsize;
467
468 newsize = SCIPsetCalcMemGrowSize(set, num);
469 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->ubchginfos, var->ubchginfossize, newsize) );
470 var->ubchginfossize = newsize;
471 }
472 assert(num <= var->ubchginfossize);
473
474 return SCIP_OKAY;
475}
476
477/** adds domain change info to the variable's lower bound change info array */
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
510 SCIP_CALL( varEnsureLbchginfosSize(var, blkmem, set, var->nlbchginfos+1) );
511 var->lbchginfos[var->nlbchginfos].oldbound = oldbound;
512 var->lbchginfos[var->nlbchginfos].newbound = newbound;
513 var->lbchginfos[var->nlbchginfos].var = var;
514 var->lbchginfos[var->nlbchginfos].bdchgidx.depth = depth;
515 var->lbchginfos[var->nlbchginfos].bdchgidx.pos = pos;
516 var->lbchginfos[var->nlbchginfos].pos = var->nlbchginfos; /*lint !e732*/
517 var->lbchginfos[var->nlbchginfos].boundchgtype = boundchgtype; /*lint !e641*/
518 var->lbchginfos[var->nlbchginfos].boundtype = SCIP_BOUNDTYPE_LOWER; /*lint !e641*/
520 var->lbchginfos[var->nlbchginfos].inferboundtype = inferboundtype; /*lint !e641*/
521 var->lbchginfos[var->nlbchginfos].inferencedata.var = infervar;
522 var->lbchginfos[var->nlbchginfos].inferencedata.info = inferinfo;
523
524 /**@note The "pos" data member of the bound change info has a size of 27 bits */
525 assert(var->nlbchginfos < 1 << 27);
526
527 switch( boundchgtype )
528 {
530 break;
532 assert(infercons != NULL);
533 var->lbchginfos[var->nlbchginfos].inferencedata.reason.cons = infercons;
534 break;
536 var->lbchginfos[var->nlbchginfos].inferencedata.reason.prop = inferprop;
537 break;
538 default:
539 SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
540 return SCIP_INVALIDDATA;
541 }
542
543 var->nlbchginfos++;
544
545 assert(var->nlbchginfos < 2
547 &var->lbchginfos[var->nlbchginfos-1].bdchgidx));
548
549 return SCIP_OKAY;
550}
551
552/** adds domain change info to the variable's upper bound change info array */
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
585 SCIP_CALL( varEnsureUbchginfosSize(var, blkmem, set, var->nubchginfos+1) );
586 var->ubchginfos[var->nubchginfos].oldbound = oldbound;
587 var->ubchginfos[var->nubchginfos].newbound = newbound;
588 var->ubchginfos[var->nubchginfos].var = var;
589 var->ubchginfos[var->nubchginfos].bdchgidx.depth = depth;
590 var->ubchginfos[var->nubchginfos].bdchgidx.pos = pos;
591 var->ubchginfos[var->nubchginfos].pos = var->nubchginfos; /*lint !e732*/
592 var->ubchginfos[var->nubchginfos].boundchgtype = boundchgtype; /*lint !e641*/
593 var->ubchginfos[var->nubchginfos].boundtype = SCIP_BOUNDTYPE_UPPER; /*lint !e641*/
595 var->ubchginfos[var->nubchginfos].inferboundtype = inferboundtype; /*lint !e641*/
596 var->ubchginfos[var->nubchginfos].inferencedata.var = infervar;
597 var->ubchginfos[var->nubchginfos].inferencedata.info = inferinfo;
598
599 /**@note The "pos" data member of the bound change info has a size of 27 bits */
600 assert(var->nubchginfos < 1 << 27);
601
602 switch( boundchgtype )
603 {
605 break;
607 assert(infercons != NULL);
608 var->ubchginfos[var->nubchginfos].inferencedata.reason.cons = infercons;
609 break;
611 var->ubchginfos[var->nubchginfos].inferencedata.reason.prop = inferprop;
612 break;
613 default:
614 SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
615 return SCIP_INVALIDDATA;
616 }
617
618 var->nubchginfos++;
619
620 assert(var->nubchginfos < 2
622 &var->ubchginfos[var->nubchginfos-1].bdchgidx));
623
624 return SCIP_OKAY;
625}
626
627/** applies single bound change */
629 SCIP_BOUNDCHG* boundchg, /**< bound change to apply */
630 BMS_BLKMEM* blkmem, /**< block memory */
631 SCIP_SET* set, /**< global SCIP settings */
632 SCIP_STAT* stat, /**< problem statistics */
633 SCIP_LP* lp, /**< current LP data */
634 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
635 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
636 int depth, /**< depth in the tree, where the bound change takes place */
637 int pos, /**< position of the bound change in its bound change array */
638 SCIP_Bool* cutoff /**< pointer to store whether an infeasible bound change was detected */
639 )
640{
641 SCIP_VAR* var;
642
643 assert(boundchg != NULL);
644 assert(stat != NULL);
645 assert(depth > 0);
646 assert(pos >= 0);
647 assert(cutoff != NULL);
648
649 *cutoff = FALSE;
650
651 /* ignore redundant bound changes */
652 if( boundchg->redundant )
653 return SCIP_OKAY;
654
655 var = boundchg->var;
656 assert(var != NULL);
658 assert(!SCIPvarIsIntegral(var) || SCIPsetIsFeasIntegral(set, boundchg->newbound));
659
660 /* apply bound change */
661 switch( boundchg->boundtype )
662 {
664 /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
665 if( SCIPsetIsGT(set, boundchg->newbound, var->locdom.lb) )
666 {
667 if( SCIPsetIsLE(set, boundchg->newbound, var->locdom.ub) )
668 {
669 /* add the bound change info to the variable's bound change info array */
670 switch( boundchg->boundchgtype )
671 {
673 SCIPsetDebugMsg(set, " -> branching: new lower bound of <%s>[%g,%g]: %g\n",
674 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
675 SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
677 stat->lastbranchvar = var;
679 stat->lastbranchvalue = boundchg->newbound;
680 break;
681
683 assert(boundchg->data.inferencedata.reason.cons != NULL);
684 SCIPsetDebugMsg(set, " -> constraint <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
685 SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
686 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
687 SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
688 boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
689 boundchg->data.inferencedata.info,
691 break;
692
694 SCIPsetDebugMsg(set, " -> propagator <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
695 boundchg->data.inferencedata.reason.prop != NULL
696 ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
697 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
698 SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
699 boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
700 boundchg->data.inferencedata.info,
702 break;
703
704 default:
705 SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
706 return SCIP_INVALIDDATA;
707 }
708
709 /* change local bound of variable */
710 SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, boundchg->newbound) );
711 }
712 else
713 {
714 SCIPsetDebugMsg(set, " -> cutoff: new lower bound of <%s>[%g,%g]: %g\n",
715 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
716 *cutoff = TRUE;
717 boundchg->redundant = TRUE; /* bound change has not entered the lbchginfos array of the variable! */
718 }
719 }
720 else
721 {
722 /* mark bound change to be inactive */
723 SCIPsetDebugMsg(set, " -> inactive %s: new lower bound of <%s>[%g,%g]: %g\n",
724 (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
725 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
726 boundchg->redundant = TRUE;
727 }
728 break;
729
731 /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
732 if( SCIPsetIsLT(set, boundchg->newbound, var->locdom.ub) )
733 {
734 if( SCIPsetIsGE(set, boundchg->newbound, var->locdom.lb) )
735 {
736 /* add the bound change info to the variable's bound change info array */
737 switch( boundchg->boundchgtype )
738 {
740 SCIPsetDebugMsg(set, " -> branching: new upper bound of <%s>[%g,%g]: %g\n",
741 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
742 SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
744 stat->lastbranchvar = var;
746 stat->lastbranchvalue = boundchg->newbound;
747 break;
748
750 assert(boundchg->data.inferencedata.reason.cons != NULL);
751 SCIPsetDebugMsg(set, " -> constraint <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
752 SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
753 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
754 SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
755 boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
756 boundchg->data.inferencedata.info,
758 break;
759
761 SCIPsetDebugMsg(set, " -> propagator <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
762 boundchg->data.inferencedata.reason.prop != NULL
763 ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
764 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
765 SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
766 boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
767 boundchg->data.inferencedata.info,
769 break;
770
771 default:
772 SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
773 return SCIP_INVALIDDATA;
774 }
775
776 /* change local bound of variable */
777 SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, boundchg->newbound) );
778 }
779 else
780 {
781 SCIPsetDebugMsg(set, " -> cutoff: new upper bound of <%s>[%g,%g]: %g\n",
782 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
783 *cutoff = TRUE;
784 boundchg->redundant = TRUE; /* bound change has not entered the ubchginfos array of the variable! */
785 }
786 }
787 else
788 {
789 /* mark bound change to be inactive */
790 SCIPsetDebugMsg(set, " -> inactive %s: new upper bound of <%s>[%g,%g]: %g\n",
791 (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
792 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
793 boundchg->redundant = TRUE;
794 }
795 break;
796
797 default:
798 SCIPerrorMessage("unknown bound type\n");
799 return SCIP_INVALIDDATA;
800 }
801
802 /* update the branching and inference history */
803 if( !boundchg->applied && !boundchg->redundant )
804 {
805 assert(var == boundchg->var);
806
808 {
809 SCIP_CALL( SCIPvarIncNBranchings(var, blkmem, set, stat,
812 }
813 else if( stat->lastbranchvar != NULL )
814 {
815 /**@todo if last branching variable is unknown, retrieve it from the nodes' boundchg arrays */
816 SCIP_CALL( SCIPvarIncInferenceSum(stat->lastbranchvar, blkmem, set, stat, stat->lastbranchdir, stat->lastbranchvalue, 1.0) );
817 }
818 boundchg->applied = TRUE;
819 }
820
821 return SCIP_OKAY;
822}
823
824/** undoes single bound change */
826 SCIP_BOUNDCHG* boundchg, /**< bound change to remove */
827 BMS_BLKMEM* blkmem, /**< block memory */
828 SCIP_SET* set, /**< global SCIP settings */
829 SCIP_STAT* stat, /**< problem statistics */
830 SCIP_LP* lp, /**< current LP data */
831 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
832 SCIP_EVENTQUEUE* eventqueue /**< event queue */
833 )
834{
835 SCIP_VAR* var;
836
837 assert(boundchg != NULL);
838 assert(stat != NULL);
839
840 /* ignore redundant bound changes */
841 if( boundchg->redundant )
842 return SCIP_OKAY;
843
844 var = boundchg->var;
845 assert(var != NULL);
847
848 /* undo bound change: apply the previous bound change of variable */
849 switch( boundchg->boundtype )
850 {
852 var->nlbchginfos--;
853 assert(var->nlbchginfos >= 0);
854 assert(var->lbchginfos != NULL);
855 assert( SCIPsetIsFeasEQ(set, var->lbchginfos[var->nlbchginfos].newbound, var->locdom.lb) ); /*lint !e777*/
856 assert( SCIPsetIsFeasLE(set, boundchg->newbound, var->locdom.lb) ); /* current lb might be larger to intermediate global bound change */
857
858 SCIPsetDebugMsg(set, "removed lower bound change info of var <%s>[%g,%g]: depth=%d, pos=%d, %g -> %g\n",
859 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub,
862
863 /* reinstall the previous local bound */
864 SCIP_CALL( SCIPvarChgLbLocal(boundchg->var, blkmem, set, stat, lp, branchcand, eventqueue,
865 var->lbchginfos[var->nlbchginfos].oldbound) );
866
867 /* in case all bound changes are removed the local bound should match the global bound */
868 assert(var->nlbchginfos > 0 || SCIPsetIsFeasEQ(set, var->locdom.lb, var->glbdom.lb));
869
870 break;
871
873 var->nubchginfos--;
874 assert(var->nubchginfos >= 0);
875 assert(var->ubchginfos != NULL);
876 assert( SCIPsetIsFeasEQ(set, var->ubchginfos[var->nubchginfos].newbound, var->locdom.ub) ); /*lint !e777*/
877 assert( SCIPsetIsFeasGE(set, boundchg->newbound, var->locdom.ub) ); /* current ub might be smaller to intermediate global bound change */
878
879 SCIPsetDebugMsg(set, "removed upper bound change info of var <%s>[%g,%g]: depth=%d, pos=%d, %g -> %g\n",
880 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub,
883
884 /* reinstall the previous local bound */
885 SCIP_CALL( SCIPvarChgUbLocal(boundchg->var, blkmem, set, stat, lp, branchcand, eventqueue,
886 var->ubchginfos[var->nubchginfos].oldbound) );
887
888 /* in case all bound changes are removed the local bound should match the global bound */
889 assert(var->nubchginfos > 0 || SCIPsetIsFeasEQ(set, var->locdom.ub, var->glbdom.ub));
890
891 break;
892
893 default:
894 SCIPerrorMessage("unknown bound type\n");
895 return SCIP_INVALIDDATA;
896 }
897
898 /* update last branching variable */
900 {
901 stat->lastbranchvar = NULL;
903 }
904
905 return SCIP_OKAY;
906}
907
908/** applies single bound change to the global problem by changing the global bound of the corresponding variable */
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
935 var = SCIPboundchgGetVar(boundchg);
936 newbound = SCIPboundchgGetNewbound(boundchg);
937 boundtype = SCIPboundchgGetBoundtype(boundchg);
938
939 /* check if the bound change is redundant which can happen due to a (better) global bound change which was performed
940 * after that bound change was applied
941 *
942 * @note a global bound change is not captured by the redundant member of the bound change data structure
943 */
944 if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasLE(set, newbound, SCIPvarGetLbGlobal(var)))
945 || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasGE(set, newbound, SCIPvarGetUbGlobal(var))) )
946 {
947 return SCIP_OKAY;
948 }
949
950 SCIPsetDebugMsg(set, "applying global bound change: <%s>[%g,%g] %s %g\n",
952 boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", newbound);
953
954 /* check for cutoff */
955 if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGT(set, newbound, SCIPvarGetUbGlobal(var)))
956 || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLT(set, newbound, SCIPvarGetLbGlobal(var))) )
957 {
958 *cutoff = TRUE;
959 return SCIP_OKAY;
960 }
961
962 /* apply bound change */
963 SCIP_CALL( SCIPvarChgBdGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound, boundtype) );
964
965 return SCIP_OKAY;
966}
967
968/** captures branching and inference data of bound change */
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);
978 SCIPvarCapture(boundchg->var);
979
980 switch( boundchg->boundchgtype )
981 {
984 break;
985
987 assert(boundchg->data.inferencedata.var != NULL);
988 assert(boundchg->data.inferencedata.reason.cons != NULL);
989 SCIPconsCapture(boundchg->data.inferencedata.reason.cons);
990 break;
991
992 default:
993 SCIPerrorMessage("invalid bound change type\n");
994 return SCIP_INVALIDDATA;
995 }
996
997 return SCIP_OKAY;
998}
999
1000/** releases branching and inference data of bound change */
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
1264 newsize = SCIPsetCalcMemGrowSize(set, num);
1265 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &domchg->domchgdyn.boundchgs, domchg->domchgdyn.boundchgssize, newsize) );
1266 domchg->domchgdyn.boundchgssize = newsize;
1267 }
1268 assert(num <= domchg->domchgdyn.boundchgssize);
1269
1270 return SCIP_OKAY;
1271}
1272
1273/** ensures, that holechgs array can store at least num additional entries */
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
1289 newsize = SCIPsetCalcMemGrowSize(set, num);
1290 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &domchg->domchgdyn.holechgs, domchg->domchgdyn.holechgssize, newsize) );
1291 domchg->domchgdyn.holechgssize = newsize;
1292 }
1293 assert(num <= domchg->domchgdyn.holechgssize);
1294
1295 return SCIP_OKAY;
1296}
1297
1298/** applies domain change */
1300 SCIP_DOMCHG* domchg, /**< domain change to apply */
1301 BMS_BLKMEM* blkmem, /**< block memory */
1302 SCIP_SET* set, /**< global SCIP settings */
1303 SCIP_STAT* stat, /**< problem statistics */
1304 SCIP_LP* lp, /**< current LP data */
1305 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1306 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1307 int depth, /**< depth in the tree, where the domain change takes place */
1308 SCIP_Bool* cutoff /**< pointer to store whether an infeasible domain change was detected */
1309 )
1310{
1311 int i;
1312
1313 assert(cutoff != NULL);
1314
1315 *cutoff = FALSE;
1316
1317 SCIPsetDebugMsg(set, "applying domain changes at %p in depth %d\n", (void*)domchg, depth);
1318
1319 if( domchg == NULL )
1320 return SCIP_OKAY;
1321
1322 /* apply bound changes */
1323 for( i = 0; i < (int)domchg->domchgbound.nboundchgs; ++i )
1324 {
1325 SCIP_CALL( SCIPboundchgApply(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp,
1326 branchcand, eventqueue, depth, i, cutoff) );
1327 if( *cutoff )
1328 break;
1329 }
1330 SCIPsetDebugMsg(set, " -> %u bound changes (cutoff %u)\n", domchg->domchgbound.nboundchgs, *cutoff);
1331
1332 /* mark all bound changes after a cutoff redundant */
1333 for( ; i < (int)domchg->domchgbound.nboundchgs; ++i )
1334 domchg->domchgbound.boundchgs[i].redundant = TRUE;
1335
1336 /* apply holelist changes */
1337 if( domchg->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_BOUND ) /*lint !e641*/
1338 {
1339 for( i = 0; i < domchg->domchgboth.nholechgs; ++i )
1340 *(domchg->domchgboth.holechgs[i].ptr) = domchg->domchgboth.holechgs[i].newlist;
1341 SCIPsetDebugMsg(set, " -> %d hole changes\n", domchg->domchgboth.nholechgs);
1342 }
1343
1344 return SCIP_OKAY;
1345}
1346
1347/** undoes domain change */
1349 SCIP_DOMCHG* domchg, /**< domain change to remove */
1350 BMS_BLKMEM* blkmem, /**< block memory */
1351 SCIP_SET* set, /**< global SCIP settings */
1352 SCIP_STAT* stat, /**< problem statistics */
1353 SCIP_LP* lp, /**< current LP data */
1354 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1355 SCIP_EVENTQUEUE* eventqueue /**< event queue */
1356 )
1357{
1358 int i;
1359
1360 SCIPsetDebugMsg(set, "undoing domain changes at %p\n", (void*)domchg);
1361 if( domchg == NULL )
1362 return SCIP_OKAY;
1363
1364 /* undo holelist changes */
1365 if( domchg->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_BOUND ) /*lint !e641*/
1366 {
1367 for( i = domchg->domchgboth.nholechgs-1; i >= 0; --i )
1368 *(domchg->domchgboth.holechgs[i].ptr) = domchg->domchgboth.holechgs[i].oldlist;
1369 SCIPsetDebugMsg(set, " -> %d hole changes\n", domchg->domchgboth.nholechgs);
1370 }
1371
1372 /* undo bound changes */
1373 for( i = domchg->domchgbound.nboundchgs-1; i >= 0; --i )
1374 {
1375 SCIP_CALL( SCIPboundchgUndo(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp, branchcand, eventqueue) );
1376 }
1377 SCIPsetDebugMsg(set, " -> %u bound changes\n", domchg->domchgbound.nboundchgs);
1378
1379 return SCIP_OKAY;
1380}
1381
1382/** applies domain change to the global problem */
1384 SCIP_DOMCHG* domchg, /**< domain change to apply */
1385 BMS_BLKMEM* blkmem, /**< block memory */
1386 SCIP_SET* set, /**< global SCIP settings */
1387 SCIP_STAT* stat, /**< problem statistics */
1388 SCIP_LP* lp, /**< current LP data */
1389 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1390 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1391 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1392 SCIP_Bool* cutoff /**< pointer to store whether an infeasible domain change was detected */
1393 )
1394{
1395 int i;
1396
1397 assert(cutoff != NULL);
1398
1399 *cutoff = FALSE;
1400
1401 if( domchg == NULL )
1402 return SCIP_OKAY;
1403
1404 SCIPsetDebugMsg(set, "applying domain changes at %p to the global problem\n", (void*)domchg);
1405
1406 /* apply bound changes */
1407 for( i = 0; i < (int)domchg->domchgbound.nboundchgs; ++i )
1408 {
1409 SCIP_CALL( boundchgApplyGlobal(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp,
1410 branchcand, eventqueue, cliquetable, cutoff) );
1411 if( *cutoff )
1412 break;
1413 }
1414 SCIPsetDebugMsg(set, " -> %u global bound changes\n", domchg->domchgbound.nboundchgs);
1415
1416 /**@todo globally apply holelist changes - how can this be done without confusing pointer updates? */
1417
1418 return SCIP_OKAY;
1419}
1420
1421/** adds bound change to domain changes */
1423 SCIP_DOMCHG** domchg, /**< pointer to domain change data structure */
1424 BMS_BLKMEM* blkmem, /**< block memory */
1425 SCIP_SET* set, /**< global SCIP settings */
1426 SCIP_VAR* var, /**< variable to change the bounds for */
1427 SCIP_Real newbound, /**< new value for bound */
1428 SCIP_BOUNDTYPE boundtype, /**< type of bound for var: lower or upper bound */
1429 SCIP_BOUNDCHGTYPE boundchgtype, /**< type of bound change: branching decision or inference */
1430 SCIP_Real lpsolval, /**< solval of variable in last LP on path to node, or SCIP_INVALID if unknown */
1431 SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself), or NULL */
1432 SCIP_CONS* infercons, /**< constraint that deduced the bound change, or NULL */
1433 SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
1434 int inferinfo, /**< user information for inference to help resolving the conflict */
1435 SCIP_BOUNDTYPE inferboundtype /**< type of bound for inference var: lower or upper bound */
1436 )
1437{
1438 SCIP_BOUNDCHG* boundchg;
1439
1440 assert(domchg != NULL);
1441 assert(var != NULL);
1444 assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, boundtype == SCIP_BOUNDTYPE_LOWER ? 1.0 : 0.0));
1445 assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
1446 assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
1447 assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
1448
1449 SCIPsetDebugMsg(set, "adding %s bound change <%s: %g> of variable <%s> to domain change at %p pointing to %p\n",
1450 boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
1451 newbound, var->name, (void*)domchg, (void*)*domchg);
1452
1453 /* if domain change data doesn't exist, create it;
1454 * if domain change is static, convert it into dynamic change
1455 */
1456 if( *domchg == NULL )
1457 {
1458 SCIP_CALL( domchgCreate(domchg, blkmem) );
1459 }
1460 else if( (*domchg)->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_DYNAMIC ) /*lint !e641*/
1461 {
1462 SCIP_CALL( domchgMakeDynamic(domchg, blkmem) );
1463 }
1464 assert(*domchg != NULL && (*domchg)->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1465
1466 /* get memory for additional bound change */
1467 SCIP_CALL( domchgEnsureBoundchgsSize(*domchg, blkmem, set, (*domchg)->domchgdyn.nboundchgs+1) );
1468
1469 /* fill in the bound change data */
1470 boundchg = &(*domchg)->domchgdyn.boundchgs[(*domchg)->domchgdyn.nboundchgs];
1471 boundchg->var = var;
1472 switch( boundchgtype )
1473 {
1475 boundchg->data.branchingdata.lpsolval = lpsolval;
1476 break;
1478 assert(infercons != NULL);
1479 boundchg->data.inferencedata.var = infervar;
1480 boundchg->data.inferencedata.reason.cons = infercons;
1481 boundchg->data.inferencedata.info = inferinfo;
1482 break;
1484 boundchg->data.inferencedata.var = infervar;
1485 boundchg->data.inferencedata.reason.prop = inferprop;
1486 boundchg->data.inferencedata.info = inferinfo;
1487 break;
1488 default:
1489 SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
1490 return SCIP_INVALIDDATA;
1491 }
1492
1493 boundchg->newbound = newbound;
1494 boundchg->boundchgtype = boundchgtype; /*lint !e641*/
1495 boundchg->boundtype = boundtype; /*lint !e641*/
1496 boundchg->inferboundtype = inferboundtype; /*lint !e641*/
1497 boundchg->applied = FALSE;
1498 boundchg->redundant = FALSE;
1499 (*domchg)->domchgdyn.nboundchgs++;
1500
1501 /* capture branching and inference data associated with the bound changes */
1502 SCIP_CALL( boundchgCaptureData(boundchg) );
1503
1504#ifdef SCIP_DISABLED_CODE /* expensive debug check */
1505#ifdef SCIP_MORE_DEBUG
1506 {
1507 int i;
1508 for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1509 assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1510 || SCIPsetIsFeasIntegral(set, (*domchg)->domchgbound.boundchgs[i].newbound));
1511 }
1512#endif
1513#endif
1514
1515 return SCIP_OKAY;
1516}
1517
1518/** adds hole change to domain changes */
1520 SCIP_DOMCHG** domchg, /**< pointer to domain change data structure */
1521 BMS_BLKMEM* blkmem, /**< block memory */
1522 SCIP_SET* set, /**< global SCIP settings */
1523 SCIP_HOLELIST** ptr, /**< changed list pointer */
1524 SCIP_HOLELIST* newlist, /**< new value of list pointer */
1525 SCIP_HOLELIST* oldlist /**< old value of list pointer */
1526 )
1527{
1528 SCIP_HOLECHG* holechg;
1529
1530 assert(domchg != NULL);
1531 assert(ptr != NULL);
1532
1533 /* if domain change data doesn't exist, create it;
1534 * if domain change is static, convert it into dynamic change
1535 */
1536 if( *domchg == NULL )
1537 {
1538 SCIP_CALL( domchgCreate(domchg, blkmem) );
1539 }
1540 else if( (*domchg)->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_DYNAMIC ) /*lint !e641*/
1541 {
1542 SCIP_CALL( domchgMakeDynamic(domchg, blkmem) );
1543 }
1544 assert(*domchg != NULL && (*domchg)->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1545
1546 /* get memory for additional hole change */
1547 SCIP_CALL( domchgEnsureHolechgsSize(*domchg, blkmem, set, (*domchg)->domchgdyn.nholechgs+1) );
1548
1549 /* fill in the hole change data */
1550 holechg = &(*domchg)->domchgdyn.holechgs[(*domchg)->domchgdyn.nholechgs];
1551 holechg->ptr = ptr;
1552 holechg->newlist = newlist;
1553 holechg->oldlist = oldlist;
1554 (*domchg)->domchgdyn.nholechgs++;
1555
1556 return SCIP_OKAY;
1557}
1558
1559
1560
1561
1562/*
1563 * methods for variables
1564 */
1565
1566/** returns adjusted lower bound value, which is rounded for integral variable types */
1567static
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
1589 SCIP_SET* set, /**< global SCIP settings */
1590 SCIP_VARTYPE vartype, /**< type of variable */
1591 SCIP_Real ub /**< upper bound to adjust */
1592 )
1593{
1594 if( ub > 0.0 && SCIPsetIsInfinity(set, ub) )
1595 return SCIPsetInfinity(set);
1596 else if( ub < 0.0 && SCIPsetIsInfinity(set, -ub) )
1597 return -SCIPsetInfinity(set);
1598 else if( vartype != SCIP_VARTYPE_CONTINUOUS )
1599 return SCIPsetFeasFloor(set, ub);
1600 else if( ub < 0.0 && ub > -SCIPsetEpsilon(set) )
1601 return 0.0;
1602 else
1603 return ub;
1604}
1605
1606/** removes (redundant) cliques, implications and variable bounds of variable from all other variables' implications and variable
1607 * bounds arrays, and optionally removes them also from the variable itself
1608 */
1610 SCIP_VAR* var, /**< problem variable */
1611 BMS_BLKMEM* blkmem, /**< block memory */
1612 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1613 SCIP_SET* set, /**< global SCIP settings */
1614 SCIP_Bool irrelevantvar, /**< has the variable become irrelevant? */
1615 SCIP_Bool onlyredundant, /**< should only the redundant implications and variable bounds be removed? */
1616 SCIP_Bool removefromvar /**< should the implications and variable bounds be removed from the var itself? */
1617 )
1618{
1619 SCIP_Real lb;
1620 SCIP_Real ub;
1621
1622 assert(var != NULL);
1624 assert(SCIPvarIsActive(var) || SCIPvarGetType(var) != SCIP_VARTYPE_BINARY);
1625
1626 lb = SCIPvarGetLbGlobal(var);
1627 ub = SCIPvarGetUbGlobal(var);
1628
1629 SCIPsetDebugMsg(set, "removing %s implications and vbounds of %s<%s>[%g,%g]\n",
1630 onlyredundant ? "redundant" : "all", irrelevantvar ? "irrelevant " : "", SCIPvarGetName(var), lb, ub);
1631
1632 /* remove implications of (fixed) binary variable */
1633 if( var->implics != NULL && (!onlyredundant || lb > 0.5 || ub < 0.5) )
1634 {
1635 SCIP_Bool varfixing;
1636
1637 assert(SCIPvarIsBinary(var));
1638
1639 varfixing = FALSE;
1640 do
1641 {
1642 SCIP_VAR** implvars;
1643 SCIP_BOUNDTYPE* impltypes;
1644 int nimpls;
1645 int i;
1646
1647 nimpls = SCIPimplicsGetNImpls(var->implics, varfixing);
1648 implvars = SCIPimplicsGetVars(var->implics, varfixing);
1649 impltypes = SCIPimplicsGetTypes(var->implics, varfixing);
1650
1651 for( i = 0; i < nimpls; i++ )
1652 {
1653 SCIP_VAR* implvar;
1654 SCIP_BOUNDTYPE impltype;
1655
1656 implvar = implvars[i];
1657 impltype = impltypes[i];
1658 assert(implvar != var);
1659
1660 /* remove for all implications z == 0 / 1 ==> x <= p / x >= p (x not binary)
1661 * the following variable bound from x's variable bounds
1662 * x <= b*z+d (z in vubs of x) , for z == 0 / 1 ==> x <= p
1663 * x >= b*z+d (z in vlbs of x) , for z == 0 / 1 ==> x >= p
1664 */
1665 if( impltype == SCIP_BOUNDTYPE_UPPER )
1666 {
1667 if( implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1668 {
1669 SCIPsetDebugMsg(set, "deleting variable bound: <%s> == %u ==> <%s> <= %g\n",
1670 SCIPvarGetName(var), varfixing, SCIPvarGetName(implvar),
1671 SCIPimplicsGetBounds(var->implics, varfixing)[i]);
1672 SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, varfixing) );
1673 implvar->closestvblpcount = -1;
1674 var->closestvblpcount = -1;
1675 }
1676 }
1677 else
1678 {
1679 if( implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1680 {
1681 SCIPsetDebugMsg(set, "deleting variable bound: <%s> == %u ==> <%s> >= %g\n",
1682 SCIPvarGetName(var), varfixing, SCIPvarGetName(implvar),
1683 SCIPimplicsGetBounds(var->implics, varfixing)[i]);
1684 SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, !varfixing) );
1685 implvar->closestvblpcount = -1;
1686 var->closestvblpcount = -1;
1687 }
1688 }
1689 }
1690 varfixing = !varfixing;
1691 }
1692 while( varfixing == TRUE );
1693
1694 if( removefromvar )
1695 {
1696 /* free the implications data structures */
1697 SCIPimplicsFree(&var->implics, blkmem);
1698 }
1699 }
1700
1701 /* remove the (redundant) variable lower bounds */
1702 if( var->vlbs != NULL )
1703 {
1704 SCIP_VAR** vars;
1705 SCIP_Real* coefs;
1706 SCIP_Real* constants;
1707 int nvbds;
1708 int newnvbds;
1709 int i;
1710
1711 nvbds = SCIPvboundsGetNVbds(var->vlbs);
1712 vars = SCIPvboundsGetVars(var->vlbs);
1713 coefs = SCIPvboundsGetCoefs(var->vlbs);
1714 constants = SCIPvboundsGetConstants(var->vlbs);
1715
1716 /* remove for all variable bounds x >= b*z+d the following implication from z's implications
1717 * z == ub ==> x >= b*ub + d , if b > 0
1718 * z == lb ==> x >= b*lb + d , if b < 0
1719 */
1720 newnvbds = 0;
1721 for( i = 0; i < nvbds; i++ )
1722 {
1723 SCIP_VAR* implvar;
1724 SCIP_Real coef;
1725
1726 assert(newnvbds <= i);
1727
1728 implvar = vars[i];
1729 assert(implvar != NULL);
1730
1731 coef = coefs[i];
1732 assert(!SCIPsetIsZero(set, coef));
1733
1734 /* check, if we want to remove the variable bound */
1735 if( onlyredundant )
1736 {
1737 SCIP_Real vbound;
1738
1739 vbound = MAX(coef * SCIPvarGetUbGlobal(implvar), coef * SCIPvarGetLbGlobal(implvar)) + constants[i]; /*lint !e666*/
1740 if( SCIPsetIsFeasGT(set, vbound, lb) )
1741 {
1742 /* the variable bound is not redundant: keep it */
1743 if( removefromvar )
1744 {
1745 if( newnvbds < i )
1746 {
1747 vars[newnvbds] = implvar;
1748 coefs[newnvbds] = coef;
1749 constants[newnvbds] = constants[i];
1750 }
1751 newnvbds++;
1752 }
1753 continue;
1754 }
1755 }
1756
1757 /* remove the corresponding implication */
1758 if( implvar->implics != NULL ) /* variable may have been aggregated in the mean time */
1759 {
1760 SCIPsetDebugMsg(set, "deleting implication: <%s> == %d ==> <%s> >= %g\n",
1761 SCIPvarGetName(implvar), (coef > 0.0), SCIPvarGetName(var), MAX(coef, 0.0) + constants[i]);
1762 SCIP_CALL( SCIPimplicsDel(&implvar->implics, blkmem, set, (coef > 0.0), var, SCIP_BOUNDTYPE_LOWER) );
1763 }
1764 if( coef > 0.0 && implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1765 {
1766 SCIPsetDebugMsg(set, "deleting variable upper bound from <%s> involving variable %s\n",
1767 SCIPvarGetName(implvar), SCIPvarGetName(var));
1768 SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, FALSE) );
1769 implvar->closestvblpcount = -1;
1770 var->closestvblpcount = -1;
1771 }
1772 else if( coef < 0.0 && implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1773 {
1774 SCIPsetDebugMsg(set, "deleting variable lower bound from <%s> involving variable %s\n",
1775 SCIPvarGetName(implvar), SCIPvarGetName(var));
1776 SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, TRUE) );
1777 implvar->closestvblpcount = -1;
1778 var->closestvblpcount = -1;
1779 }
1780 }
1781
1782 if( removefromvar )
1783 {
1784 /* update the number of variable bounds */
1785 SCIPvboundsShrink(&var->vlbs, blkmem, newnvbds);
1786 var->closestvblpcount = -1;
1787 }
1788 }
1789
1790 /**@todo in general, variable bounds like x >= b*z + d corresponding to an implication like z = ub ==> x >= b*ub + d
1791 * might be missing because we only add variable bounds with reasonably small value of b. thus, we currently
1792 * cannot remove such variables x from z's implications.
1793 */
1794
1795 /* remove the (redundant) variable upper bounds */
1796 if( var->vubs != NULL )
1797 {
1798 SCIP_VAR** vars;
1799 SCIP_Real* coefs;
1800 SCIP_Real* constants;
1801 int nvbds;
1802 int newnvbds;
1803 int i;
1804
1805 nvbds = SCIPvboundsGetNVbds(var->vubs);
1806 vars = SCIPvboundsGetVars(var->vubs);
1807 coefs = SCIPvboundsGetCoefs(var->vubs);
1808 constants = SCIPvboundsGetConstants(var->vubs);
1809
1810 /* remove for all variable bounds x <= b*z+d the following implication from z's implications
1811 * z == lb ==> x <= b*lb + d , if b > 0
1812 * z == ub ==> x <= b*ub + d , if b < 0
1813 */
1814 newnvbds = 0;
1815 for( i = 0; i < nvbds; i++ )
1816 {
1817 SCIP_VAR* implvar;
1818 SCIP_Real coef;
1819
1820 assert(newnvbds <= i);
1821
1822 implvar = vars[i];
1823 assert(implvar != NULL);
1824
1825 coef = coefs[i];
1826 assert(!SCIPsetIsZero(set, coef));
1827
1828 /* check, if we want to remove the variable bound */
1829 if( onlyredundant )
1830 {
1831 SCIP_Real vbound;
1832
1833 vbound = MIN(coef * SCIPvarGetUbGlobal(implvar), coef * SCIPvarGetLbGlobal(implvar)) + constants[i]; /*lint !e666*/
1834 if( SCIPsetIsFeasLT(set, vbound, ub) )
1835 {
1836 /* the variable bound is not redundant: keep it */
1837 if( removefromvar )
1838 {
1839 if( newnvbds < i )
1840 {
1841 vars[newnvbds] = implvar;
1842 coefs[newnvbds] = coefs[i];
1843 constants[newnvbds] = constants[i];
1844 }
1845 newnvbds++;
1846 }
1847 continue;
1848 }
1849 }
1850
1851 /* remove the corresponding implication */
1852 if( implvar->implics != NULL ) /* variable may have been aggregated in the mean time */
1853 {
1854 SCIPsetDebugMsg(set, "deleting implication: <%s> == %d ==> <%s> <= %g\n",
1855 SCIPvarGetName(implvar), (coef < 0.0), SCIPvarGetName(var), MIN(coef, 0.0) + constants[i]);
1856 SCIP_CALL( SCIPimplicsDel(&implvar->implics, blkmem, set, (coef < 0.0), var, SCIP_BOUNDTYPE_UPPER) );
1857 }
1858 if( coef < 0.0 && implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1859 {
1860 SCIPsetDebugMsg(set, "deleting variable upper bound from <%s> involving variable %s\n",
1861 SCIPvarGetName(implvar), SCIPvarGetName(var));
1862 SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, TRUE) );
1863 implvar->closestvblpcount = -1;
1864 var->closestvblpcount = -1;
1865 }
1866 else if( coef > 0.0 && implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1867 {
1868 SCIPsetDebugMsg(set, "deleting variable lower bound from <%s> involving variable %s\n",
1869 SCIPvarGetName(implvar), SCIPvarGetName(var));
1870 SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, FALSE) );
1871 implvar->closestvblpcount = -1;
1872 var->closestvblpcount = -1;
1873 }
1874 }
1875
1876 if( removefromvar )
1877 {
1878 /* update the number of variable bounds */
1879 SCIPvboundsShrink(&var->vubs, blkmem, newnvbds);
1880 var->closestvblpcount = -1;
1881 }
1882 }
1883
1884 /* remove the variable from all cliques */
1885 if( SCIPvarIsBinary(var) )
1886 SCIPcliquelistRemoveFromCliques(var->cliquelist, cliquetable, var, irrelevantvar);
1887
1888 /**@todo variable bounds like x <= b*z + d with z general integer are not removed from x's vbd arrays, because
1889 * z has no link (like in the binary case) to x
1890 */
1891
1892 return SCIP_OKAY;
1893}
1894
1895/** sets the variable name */
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
1977 SCIP_ALLOC( BMSallocBlockMemory(blkmem, var) );
1978
1979 /* set variable's name */
1980 SCIP_CALL( varSetName(*var, blkmem, stat, name) );
1981
1982#ifndef NDEBUG
1983 (*var)->scip = set->scip;
1984#endif
1985 (*var)->obj = obj;
1986 (*var)->unchangedobj = obj;
1987 (*var)->branchfactor = 1.0;
1988 (*var)->rootsol = 0.0;
1989 (*var)->bestrootsol = 0.0;
1990 (*var)->bestrootredcost = 0.0;
1991 (*var)->bestrootlpobjval = SCIP_INVALID;
1992 (*var)->relaxsol = 0.0;
1993 (*var)->nlpsol = 0.0;
1994 (*var)->primsolavg = 0.5 * (lb + ub);
1995 (*var)->conflictlb = SCIP_REAL_MIN;
1996 (*var)->conflictub = SCIP_REAL_MAX;
1997 (*var)->conflictrelaxedlb = (*var)->conflictlb;
1998 (*var)->conflictrelaxedub = (*var)->conflictub;
1999 (*var)->lazylb = -SCIPsetInfinity(set);
2000 (*var)->lazyub = SCIPsetInfinity(set);
2001 (*var)->glbdom.holelist = NULL;
2002 (*var)->glbdom.lb = lb;
2003 (*var)->glbdom.ub = ub;
2004 (*var)->locdom.holelist = NULL;
2005 (*var)->locdom.lb = lb;
2006 (*var)->locdom.ub = ub;
2007 (*var)->varcopy = varcopy;
2008 (*var)->vardelorig = vardelorig;
2009 (*var)->vartrans = vartrans;
2010 (*var)->vardeltrans = vardeltrans;
2011 (*var)->vardata = vardata;
2012 (*var)->parentvars = NULL;
2013 (*var)->negatedvar = NULL;
2014 (*var)->vlbs = NULL;
2015 (*var)->vubs = NULL;
2016 (*var)->implics = NULL;
2017 (*var)->cliquelist = NULL;
2018 (*var)->eventfilter = NULL;
2019 (*var)->lbchginfos = NULL;
2020 (*var)->ubchginfos = NULL;
2021 (*var)->index = stat->nvaridx;
2022 (*var)->probindex = -1;
2023 (*var)->pseudocandindex = -1;
2024 (*var)->eventqueueindexobj = -1;
2025 (*var)->eventqueueindexlb = -1;
2026 (*var)->eventqueueindexub = -1;
2027 (*var)->parentvarssize = 0;
2028 (*var)->nparentvars = 0;
2029 (*var)->nuses = 0;
2030 (*var)->branchpriority = 0;
2031 (*var)->branchdirection = SCIP_BRANCHDIR_AUTO; /*lint !e641*/
2032 (*var)->lbchginfossize = 0;
2033 (*var)->nlbchginfos = 0;
2034 (*var)->ubchginfossize = 0;
2035 (*var)->nubchginfos = 0;
2036 (*var)->conflictlbcount = 0;
2037 (*var)->conflictubcount = 0;
2038 (*var)->closestvlbidx = -1;
2039 (*var)->closestvubidx = -1;
2040 (*var)->closestvblpcount = -1;
2041 (*var)->initial = initial;
2042 (*var)->removable = removable;
2043 (*var)->deleted = FALSE;
2044 (*var)->donotaggr = FALSE;
2045 (*var)->donotmultaggr = FALSE;
2046 (*var)->vartype = vartype; /*lint !e641*/
2047 (*var)->pseudocostflag = FALSE;
2048 (*var)->eventqueueimpl = FALSE;
2049 (*var)->deletable = FALSE;
2050 (*var)->delglobalstructs = FALSE;
2051 (*var)->relaxationonly = FALSE;
2052
2053 for( i = 0; i < NLOCKTYPES; i++ )
2054 {
2055 (*var)->nlocksdown[i] = 0;
2056 (*var)->nlocksup[i] = 0;
2057 }
2058
2059 stat->nvaridx++;
2060
2061 /* create branching and inference history entries */
2062 SCIP_CALL( SCIPhistoryCreate(&(*var)->history, blkmem) );
2063 SCIP_CALL( SCIPhistoryCreate(&(*var)->historycrun, blkmem) );
2064
2065 /* the value based history is only created on demand */
2066 (*var)->valuehistory = NULL;
2067
2068 return SCIP_OKAY;
2069}
2070
2071/** creates and captures an original problem variable; an integer variable with bounds
2072 * zero and one is automatically converted into a binary variable
2073 */
2075 SCIP_VAR** var, /**< pointer to variable data */
2076 BMS_BLKMEM* blkmem, /**< block memory */
2077 SCIP_SET* set, /**< global SCIP settings */
2078 SCIP_STAT* stat, /**< problem statistics */
2079 const char* name, /**< name of variable, or NULL for automatic name creation */
2080 SCIP_Real lb, /**< lower bound of variable */
2081 SCIP_Real ub, /**< upper bound of variable */
2082 SCIP_Real obj, /**< objective function value */
2083 SCIP_VARTYPE vartype, /**< type of variable */
2084 SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2085 SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2086 SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2087 SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2088 SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2089 SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2090 SCIP_VARDATA* vardata /**< user data for this specific variable */
2091 )
2092{
2093 assert(var != NULL);
2094 assert(blkmem != NULL);
2095 assert(stat != NULL);
2096
2097 /* create variable */
2098 SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2099 varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2100
2101 /* set variable status and data */
2102 (*var)->varstatus = SCIP_VARSTATUS_ORIGINAL; /*lint !e641*/
2103 (*var)->data.original.origdom.holelist = NULL;
2104 (*var)->data.original.origdom.lb = lb;
2105 (*var)->data.original.origdom.ub = ub;
2106 (*var)->data.original.transvar = NULL;
2107
2108 /* capture variable */
2109 SCIPvarCapture(*var);
2110
2111 return SCIP_OKAY;
2112}
2113
2114/** creates and captures a loose variable belonging to the transformed problem; an integer variable with bounds
2115 * zero and one is automatically converted into a binary variable
2116 */
2118 SCIP_VAR** var, /**< pointer to variable data */
2119 BMS_BLKMEM* blkmem, /**< block memory */
2120 SCIP_SET* set, /**< global SCIP settings */
2121 SCIP_STAT* stat, /**< problem statistics */
2122 const char* name, /**< name of variable, or NULL for automatic name creation */
2123 SCIP_Real lb, /**< lower bound of variable */
2124 SCIP_Real ub, /**< upper bound of variable */
2125 SCIP_Real obj, /**< objective function value */
2126 SCIP_VARTYPE vartype, /**< type of variable */
2127 SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2128 SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2129 SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2130 SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2131 SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2132 SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2133 SCIP_VARDATA* vardata /**< user data for this specific variable */
2134 )
2135{
2136 assert(var != NULL);
2137 assert(blkmem != NULL);
2138
2139 /* create variable */
2140 SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2141 varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2142
2143 /* create event filter for transformed variable */
2144 SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
2145
2146 /* set variable status and data */
2147 (*var)->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
2148
2149 /* capture variable */
2150 SCIPvarCapture(*var);
2151
2152 return SCIP_OKAY;
2153}
2154
2155/** copies and captures a variable from source to target SCIP; an integer variable with bounds zero and one is
2156 * automatically converted into a binary variable; in case the variable data cannot be copied the variable is not
2157 * copied at all
2158 */
2160 SCIP_VAR** var, /**< pointer to store the target variable */
2161 BMS_BLKMEM* blkmem, /**< block memory */
2162 SCIP_SET* set, /**< global SCIP settings */
2163 SCIP_STAT* stat, /**< problem statistics */
2164 SCIP* sourcescip, /**< source SCIP data structure */
2165 SCIP_VAR* sourcevar, /**< source variable */
2166 SCIP_HASHMAP* varmap, /**< a hashmap to store the mapping of source variables corresponding
2167 * target variables */
2168 SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
2169 * target constraints */
2170 SCIP_Bool global /**< should global or local bounds be used? */
2171 )
2172{
2173 SCIP_VARDATA* targetdata;
2174 SCIP_RESULT result;
2175 SCIP_Real lb;
2176 SCIP_Real ub;
2177
2178 assert(set != NULL);
2179 assert(blkmem != NULL);
2180 assert(stat != NULL);
2181 assert(sourcescip != NULL);
2182 assert(sourcevar != NULL);
2183 assert(var != NULL);
2184 assert(set->stage == SCIP_STAGE_PROBLEM);
2185 assert(varmap != NULL);
2186 assert(consmap != NULL);
2187
2188 /** @todo copy hole lists */
2189 assert(global || SCIPvarGetHolelistLocal(sourcevar) == NULL);
2190 assert(!global || SCIPvarGetHolelistGlobal(sourcevar) == NULL);
2191
2192 result = SCIP_DIDNOTRUN;
2193 targetdata = NULL;
2194
2195 if( SCIPvarGetStatus(sourcevar) == SCIP_VARSTATUS_ORIGINAL )
2196 {
2197 lb = SCIPvarGetLbOriginal(sourcevar);
2198 ub = SCIPvarGetUbOriginal(sourcevar);
2199 }
2200 else
2201 {
2202 lb = global ? SCIPvarGetLbGlobal(sourcevar) : SCIPvarGetLbLocal(sourcevar);
2203 ub = global ? SCIPvarGetUbGlobal(sourcevar) : SCIPvarGetUbLocal(sourcevar);
2204 }
2205
2206 /* creates and captures the variable in the target SCIP and initialize callback methods and variable data to NULL */
2207 SCIP_CALL( SCIPvarCreateOriginal(var, blkmem, set, stat, SCIPvarGetName(sourcevar),
2208 lb, ub, SCIPvarGetObj(sourcevar), SCIPvarGetType(sourcevar),
2209 SCIPvarIsInitial(sourcevar), SCIPvarIsRemovable(sourcevar),
2210 NULL, NULL, NULL, NULL, NULL) );
2211 assert(*var != NULL);
2212
2213 /* directly copy donot(mult)aggr flag */
2214 (*var)->donotaggr = sourcevar->donotaggr;
2215 (*var)->donotmultaggr = sourcevar->donotmultaggr;
2216
2217 /* insert variable into mapping between source SCIP and the target SCIP */
2218 assert(!SCIPhashmapExists(varmap, sourcevar));
2219 SCIP_CALL( SCIPhashmapInsert(varmap, sourcevar, *var) );
2220
2221 /* in case there exists variable data and the variable data copy callback, try to copy variable data */
2222 if( sourcevar->vardata != NULL && sourcevar->varcopy != NULL )
2223 {
2224 SCIP_CALL( sourcevar->varcopy(set->scip, sourcescip, sourcevar, sourcevar->vardata,
2225 varmap, consmap, (*var), &targetdata, &result) );
2226
2227 /* evaluate result */
2228 if( result != SCIP_DIDNOTRUN && result != SCIP_SUCCESS )
2229 {
2230 SCIPerrorMessage("variable data copying method returned invalid result <%d>\n", result);
2231 return SCIP_INVALIDRESULT;
2232 }
2233
2234 assert(targetdata == NULL || result == SCIP_SUCCESS);
2235
2236 /* if copying was successful, add the created variable data to the variable as well as all callback methods */
2237 if( result == SCIP_SUCCESS )
2238 {
2239 (*var)->varcopy = sourcevar->varcopy;
2240 (*var)->vardelorig = sourcevar->vardelorig;
2241 (*var)->vartrans = sourcevar->vartrans;
2242 (*var)->vardeltrans = sourcevar->vardeltrans;
2243 (*var)->vardata = targetdata;
2244 }
2245 }
2246
2247 /* we initialize histories of the variables by copying the source variable-information */
2248 if( set->history_allowtransfer )
2249 {
2250 SCIPvarMergeHistories((*var), sourcevar, stat);
2251 }
2252
2253 /* in case the copying was successfully, add the created variable data to the variable as well as all callback
2254 * methods
2255 */
2256 if( result == SCIP_SUCCESS )
2257 {
2258 (*var)->varcopy = sourcevar->varcopy;
2259 (*var)->vardelorig = sourcevar->vardelorig;
2260 (*var)->vartrans = sourcevar->vartrans;
2261 (*var)->vardeltrans = sourcevar->vardeltrans;
2262 (*var)->vardata = targetdata;
2263 }
2264
2265 SCIPsetDebugMsg(set, "created copy <%s> of variable <%s>\n", SCIPvarGetName(*var), SCIPvarGetName(sourcevar));
2266
2267 return SCIP_OKAY;
2268}
2269
2270/** parse given string for a SCIP_Real bound */
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 */
2451 SCIP_CALL( parseBounds(set, strptr, token, &parsedlb, &parsedub, endptr) );
2452
2453 /* stop if parsing of bounds failed */
2454 if( *endptr == NULL )
2455 break;
2456
2457 if( strncmp(token, "local", 5) == 0 && local )
2458 {
2459 *lb = parsedlb;
2460 *ub = parsedub;
2461 }
2462 else if( strncmp(token, "lazy", 4) == 0 )
2463 {
2464 *lazylb = parsedlb;
2465 *lazyub = parsedub;
2466 }
2467 }
2468
2469 /* restore pointer */
2470 if ( *endptr == NULL )
2471 *endptr = strptr;
2472
2473 /* check bounds for binary variables */
2474 if ( (*vartype) == SCIP_VARTYPE_BINARY )
2475 {
2476 if ( SCIPsetIsLT(set, *lb, 0.0) || SCIPsetIsGT(set, *ub, 1.0) )
2477 {
2478 SCIPerrorMessage("Parsed invalid bounds for binary variable <%s>: [%f, %f].\n", name, *lb, *ub);
2479 return SCIP_READERROR;
2480 }
2481 if ( !SCIPsetIsInfinity(set, -(*lazylb)) && !SCIPsetIsInfinity(set, *lazyub) &&
2482 ( SCIPsetIsLT(set, *lazylb, 0.0) || SCIPsetIsGT(set, *lazyub, 1.0) ) )
2483 {
2484 SCIPerrorMessage("Parsed invalid lazy bounds for binary variable <%s>: [%f, %f].\n", name, *lazylb, *lazyub);
2485 return SCIP_READERROR;
2486 }
2487 }
2488
2489 return SCIP_OKAY;
2490}
2491
2492/** parses variable information (in cip format) out of a string; if the parsing process was successful an original
2493 * variable is created and captured; if variable is of integral type, fractional bounds are automatically rounded; an
2494 * integer variable with bounds zero and one is automatically converted into a binary variable
2495 */
2497 SCIP_VAR** var, /**< pointer to variable data */
2498 BMS_BLKMEM* blkmem, /**< block memory */
2499 SCIP_SET* set, /**< global SCIP settings */
2500 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2501 SCIP_STAT* stat, /**< problem statistics */
2502 const char* str, /**< string to parse */
2503 SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2504 SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2505 SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2506 SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable */
2507 SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data */
2508 SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable */
2509 SCIP_VARDATA* vardata, /**< user data for this specific variable */
2510 char** endptr, /**< pointer to store the final string position if successfully */
2511 SCIP_Bool* success /**< pointer store if the paring process was successful */
2512 )
2513{
2514 char name[SCIP_MAXSTRLEN];
2515 SCIP_Real lb;
2516 SCIP_Real ub;
2517 SCIP_Real obj;
2518 SCIP_VARTYPE vartype;
2519 SCIP_Real lazylb;
2520 SCIP_Real lazyub;
2521
2522 assert(var != NULL);
2523 assert(blkmem != NULL);
2524 assert(stat != NULL);
2525 assert(endptr != NULL);
2526 assert(success != NULL);
2527
2528 /* parse string in cip format for variable information */
2529 SCIP_CALL( varParse(set, messagehdlr, str, name, &lb, &ub, &obj, &vartype, &lazylb, &lazyub, FALSE, endptr, success) );
2530
2531 if( *success ) /*lint !e774*/
2532 {
2533 /* create variable */
2534 SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2535 varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2536
2537 /* set variable status and data */
2538 (*var)->varstatus = SCIP_VARSTATUS_ORIGINAL; /*lint !e641*/
2539 (*var)->data.original.origdom.holelist = NULL;
2540 (*var)->data.original.origdom.lb = lb;
2541 (*var)->data.original.origdom.ub = ub;
2542 (*var)->data.original.transvar = NULL;
2543
2544 /* set lazy status of variable bounds */
2545 (*var)->lazylb = lazylb;
2546 (*var)->lazyub = lazyub;
2547
2548 /* capture variable */
2549 SCIPvarCapture(*var);
2550 }
2551
2552 return SCIP_OKAY;
2553}
2554
2555/** parses variable information (in cip format) out of a string; if the parsing process was successful a loose variable
2556 * belonging to the transformed problem is created and captured; if variable is of integral type, fractional bounds are
2557 * automatically rounded; an integer variable with bounds zero and one is automatically converted into a binary
2558 * variable
2559 */
2561 SCIP_VAR** var, /**< pointer to variable data */
2562 BMS_BLKMEM* blkmem, /**< block memory */
2563 SCIP_SET* set, /**< global SCIP settings */
2564 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2565 SCIP_STAT* stat, /**< problem statistics */
2566 const char* str, /**< string to parse */
2567 SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2568 SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2569 SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2570 SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable */
2571 SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data */
2572 SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable */
2573 SCIP_VARDATA* vardata, /**< user data for this specific variable */
2574 char** endptr, /**< pointer to store the final string position if successfully */
2575 SCIP_Bool* success /**< pointer store if the paring process was successful */
2576 )
2577{
2578 char name[SCIP_MAXSTRLEN];
2579 SCIP_Real lb;
2580 SCIP_Real ub;
2581 SCIP_Real obj;
2582 SCIP_VARTYPE vartype;
2583 SCIP_Real lazylb;
2584 SCIP_Real lazyub;
2585
2586 assert(var != NULL);
2587 assert(blkmem != NULL);
2588 assert(endptr != NULL);
2589 assert(success != NULL);
2590
2591 /* parse string in cip format for variable information */
2592 SCIP_CALL( varParse(set, messagehdlr, str, name, &lb, &ub, &obj, &vartype, &lazylb, &lazyub, TRUE, endptr, success) );
2593
2594 if( *success ) /*lint !e774*/
2595 {
2596 /* create variable */
2597 SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2598 varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2599
2600 /* create event filter for transformed variable */
2601 SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
2602
2603 /* set variable status and data */
2604 (*var)->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
2605
2606 /* set lazy status of variable bounds */
2607 (*var)->lazylb = lazylb;
2608 (*var)->lazyub = lazyub;
2609
2610 /* capture variable */
2611 SCIPvarCapture(*var);
2612 }
2613
2614 return SCIP_OKAY;
2615}
2616
2617/** ensures, that parentvars array of var can store at least num entries */
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{
2626 assert(var->nparentvars <= var->parentvarssize);
2627
2628 if( num > var->parentvarssize )
2629 {
2630 int newsize;
2631
2632 newsize = SCIPsetCalcMemGrowSize(set, num);
2633 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->parentvars, var->parentvarssize, newsize) );
2634 var->parentvarssize = newsize;
2635 }
2636 assert(num <= var->parentvarssize);
2637
2638 return SCIP_OKAY;
2639}
2640
2641/** adds variable to parent list of a variable and captures parent variable */
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 */
2654 assert(var->nparentvars == 0 || SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL);
2655
2656 SCIPsetDebugMsg(set, "adding parent <%s>[%p] to variable <%s>[%p] in slot %d\n",
2657 parentvar->name, (void*)parentvar, var->name, (void*)var, var->nparentvars);
2658
2659 SCIP_CALL( varEnsureParentvarsSize(var, blkmem, set, var->nparentvars+1) );
2660
2661 var->parentvars[var->nparentvars] = parentvar;
2662 var->nparentvars++;
2663
2664 SCIPvarCapture(parentvar);
2665
2666 return SCIP_OKAY;
2667}
2668
2669/** deletes and releases all variables from the parent list of a variable, frees the memory of parents array */
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{
2679 SCIP_VAR* parentvar;
2680 int i;
2681
2682 SCIPsetDebugMsg(set, "free parents of <%s>\n", (*var)->name);
2683
2684 /* release the parent variables and remove the link from the parent variable to the child */
2685 for( i = 0; i < (*var)->nparentvars; ++i )
2686 {
2687 assert((*var)->parentvars != NULL);
2688 parentvar = (*var)->parentvars[i];
2689 assert(parentvar != NULL);
2690
2691 switch( SCIPvarGetStatus(parentvar) )
2692 {
2694 assert(parentvar->data.original.transvar == *var);
2695 assert(&parentvar->data.original.transvar != var);
2696 parentvar->data.original.transvar = NULL;
2697 break;
2698
2700 assert(parentvar->data.aggregate.var == *var);
2701 assert(&parentvar->data.aggregate.var != var);
2702 parentvar->data.aggregate.var = NULL;
2703 break;
2704
2705#ifdef SCIP_DISABLED_CODE
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
2859#ifdef DEBUGUSES_PROBNAME
2860 && ((var->scip->transprob != NULL && strcmp(SCIPprobGetName(var->scip->transprob), DEBUGUSES_PROBNAME) == 0) ||
2861 strcmp(SCIPprobGetName(var->scip->origprob), DEBUGUSES_PROBNAME) == 0)
2862#endif
2863 )
2864 {
2865 printf("Captured variable " DEBUGUSES_VARNAME " in SCIP %p, now %d uses; captured at\n", (void*)var->scip, var->nuses);
2866 print_backtrace();
2867 }
2868#endif
2869}
2870
2871/** decreases usage counter of variable, and frees memory if necessary */
2873 SCIP_VAR** var, /**< pointer to variable */
2874 BMS_BLKMEM* blkmem, /**< block memory */
2875 SCIP_SET* set, /**< global SCIP settings */
2876 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2877 SCIP_LP* lp /**< current LP data (or NULL, if it's an original variable) */
2878 )
2879{
2880 assert(var != NULL);
2881 assert(*var != NULL);
2882 assert((*var)->nuses >= 1);
2883 assert(blkmem != NULL);
2884 assert((*var)->scip == set->scip);
2885
2886 SCIPsetDebugMsg(set, "release variable <%s> with nuses=%d\n", (*var)->name, (*var)->nuses);
2887 (*var)->nuses--;
2888
2889#ifdef DEBUGUSES_VARNAME
2890 if( strcmp((*var)->name, DEBUGUSES_VARNAME) == 0
2891#ifdef DEBUGUSES_PROBNAME
2892 && (((*var)->scip->transprob != NULL && strcmp(SCIPprobGetName((*var)->scip->transprob), DEBUGUSES_PROBNAME) == 0) ||
2893 strcmp(SCIPprobGetName((*var)->scip->origprob), DEBUGUSES_PROBNAME) == 0)
2894#endif
2895 )
2896 {
2897 printf("Released variable " DEBUGUSES_VARNAME " in SCIP %p, now %d uses; released at\n", (void*)(*var)->scip, (*var)->nuses);
2898 print_backtrace();
2899 }
2900#endif
2901
2902 if( (*var)->nuses == 0 )
2903 {
2904 SCIP_CALL( varFree(var, blkmem, set, eventqueue, lp) );
2905 }
2906
2907 *var = NULL;
2908
2909 return SCIP_OKAY;
2910}
2911
2912/** change variable name */
2914 SCIP_VAR* var, /**< problem variable */
2915 BMS_BLKMEM* blkmem, /**< block memory */
2916 const char* name /**< name of variable */
2917 )
2918{
2919 assert(name != NULL);
2920
2921 /* remove old variable name */
2922 BMSfreeBlockMemoryArray(blkmem, &var->name, strlen(var->name)+1);
2923
2924 /* set new variable name */
2925 SCIP_CALL( varSetName(var, blkmem, NULL, name) );
2926
2927 return SCIP_OKAY;
2928}
2929
2930/** initializes variable data structure for solving */
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) */
3049 if( !SCIPvarIsTransformed(var) )
3050 {
3051 /* output original bound */
3052 lb = SCIPvarGetLbOriginal(var);
3053 ub = SCIPvarGetUbOriginal(var);
3054 printBounds(set, messagehdlr, file, lb, ub, "original bounds");
3055
3056 /* output lazy bound */
3057 lb = SCIPvarGetLbLazy(var);
3058 ub = SCIPvarGetUbLazy(var);
3059
3060 /* only display the lazy bounds if they are different from [-infinity,infinity] */
3061 if( !SCIPsetIsInfinity(set, -lb) || !SCIPsetIsInfinity(set, ub) )
3062 printBounds(set, messagehdlr, file, lb, ub, "lazy bounds");
3063
3064 holelist = SCIPvarGetHolelistOriginal(var);
3065 printHolelist(messagehdlr, file, holelist, "original holes");
3066 }
3067 else
3068 {
3069 /* output global bound */
3070 lb = SCIPvarGetLbGlobal(var);
3071 ub = SCIPvarGetUbGlobal(var);
3072 printBounds(set, messagehdlr, file, lb, ub, "global bounds");
3073
3074 /* output local bound */
3075 lb = SCIPvarGetLbLocal(var);
3076 ub = SCIPvarGetUbLocal(var);
3077 printBounds(set, messagehdlr, file, lb, ub, "local bounds");
3078
3079 /* output lazy bound */
3080 lb = SCIPvarGetLbLazy(var);
3081 ub = SCIPvarGetUbLazy(var);
3082
3083 /* only display the lazy bounds if they are different from [-infinity,infinity] */
3084 if( !SCIPsetIsInfinity(set, -lb) || !SCIPsetIsInfinity(set, ub) )
3085 printBounds(set, messagehdlr, file, lb, ub, "lazy bounds");
3086
3087 /* global hole list */
3088 holelist = SCIPvarGetHolelistGlobal(var);
3089 printHolelist(messagehdlr, file, holelist, "global holes");
3090
3091 /* local hole list */
3092 holelist = SCIPvarGetHolelistLocal(var);
3093 printHolelist(messagehdlr, file, holelist, "local holes");
3094 }
3095
3096 /* fixings and aggregations */
3097 switch( SCIPvarGetStatus(var) )
3098 {
3102 break;
3103
3105 SCIPmessageFPrintInfo(messagehdlr, file, ", fixed:");
3106 if( SCIPsetIsInfinity(set, var->glbdom.lb) )
3107 SCIPmessageFPrintInfo(messagehdlr, file, "+inf");
3108 else if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
3109 SCIPmessageFPrintInfo(messagehdlr, file, "-inf");
3110 else
3111 SCIPmessageFPrintInfo(messagehdlr, file, "%.15g", var->glbdom.lb);
3112 break;
3113
3115 SCIPmessageFPrintInfo(messagehdlr, file, ", aggregated:");
3117 SCIPmessageFPrintInfo(messagehdlr, file, " %.15g", var->data.aggregate.constant);
3118 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g<%s>", var->data.aggregate.scalar, SCIPvarGetName(var->data.aggregate.var));
3119 break;
3120
3122 SCIPmessageFPrintInfo(messagehdlr, file, ", aggregated:");
3123 if( var->data.multaggr.nvars == 0 || !SCIPsetIsZero(set, var->data.multaggr.constant) )
3124 SCIPmessageFPrintInfo(messagehdlr, file, " %.15g", var->data.multaggr.constant);
3125 for( i = 0; i < var->data.multaggr.nvars; ++i )
3126 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g<%s>", var->data.multaggr.scalars[i], SCIPvarGetName(var->data.multaggr.vars[i]));
3127 break;
3128
3130 SCIPmessageFPrintInfo(messagehdlr, file, ", negated: %.15g - <%s>", var->data.negate.constant, SCIPvarGetName(var->negatedvar));
3131 break;
3132
3133 default:
3134 SCIPerrorMessage("unknown variable status\n");
3135 SCIPABORT();
3136 return SCIP_ERROR; /*lint !e527*/
3137 }
3138
3139 SCIPmessageFPrintInfo(messagehdlr, file, "\n");
3140
3141 return SCIP_OKAY;
3142}
3143
3144/** issues a VARUNLOCKED event on the given variable */
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{
3153 SCIP_EVENT* event;
3154
3155 assert(var != NULL);
3156 assert(var->nlocksdown[SCIP_LOCKTYPE_MODEL] <= 1 && var->nlocksup[SCIP_LOCKTYPE_MODEL] <= 1);
3157 assert(var->scip == set->scip);
3158
3159 /* issue VARUNLOCKED event on variable */
3160 SCIP_CALL( SCIPeventCreateVarUnlocked(&event, blkmem, var) );
3161 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
3162
3163 return SCIP_OKAY;
3164}
3165
3166/** modifies lock numbers for rounding */
3168 SCIP_VAR* var, /**< problem variable */
3169 BMS_BLKMEM* blkmem, /**< block memory */
3170 SCIP_SET* set, /**< global SCIP settings */
3171 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3172 SCIP_LOCKTYPE locktype, /**< type of the variable locks */
3173 int addnlocksdown, /**< increase in number of rounding down locks */
3174 int addnlocksup /**< increase in number of rounding up locks */
3175 )
3176{
3177 SCIP_VAR* lockvar;
3178
3179 assert(var != NULL);
3180 assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
3181 assert(var->nlocksup[locktype] >= 0);
3182 assert(var->nlocksdown[locktype] >= 0);
3183 assert(var->scip == set->scip);
3184
3185 if( addnlocksdown == 0 && addnlocksup == 0 )
3186 return SCIP_OKAY;
3187
3188#ifdef SCIP_DEBUG
3189 SCIPsetDebugMsg(set, "add rounding locks %d/%d to variable <%s> (locks=%d/%d, type=%u)\n",
3190 addnlocksdown, addnlocksup, var->name, var->nlocksdown[locktype], var->nlocksup[locktype], locktype);
3191#endif
3192
3193 lockvar = var;
3194
3195 while( TRUE ) /*lint !e716 */
3196 {
3197 assert(lockvar != NULL);
3198
3199 switch( SCIPvarGetStatus(lockvar) )
3200 {
3202 if( lockvar->data.original.transvar != NULL )
3203 {
3204 lockvar = lockvar->data.original.transvar;
3205 break;
3206 }
3207 else
3208 {
3209 lockvar->nlocksdown[locktype] += addnlocksdown;
3210 lockvar->nlocksup[locktype] += addnlocksup;
3211
3212 assert(lockvar->nlocksdown[locktype] >= 0);
3213 assert(lockvar->nlocksup[locktype] >= 0);
3214
3215 return SCIP_OKAY;
3216 }
3220 lockvar->nlocksdown[locktype] += addnlocksdown;
3221 lockvar->nlocksup[locktype] += addnlocksup;
3222
3223 assert(lockvar->nlocksdown[locktype] >= 0);
3224 assert(lockvar->nlocksup[locktype] >= 0);
3225
3226 if( locktype == SCIP_LOCKTYPE_MODEL && lockvar->nlocksdown[locktype] <= 1
3227 && lockvar->nlocksup[locktype] <= 1 )
3228 {
3229 SCIP_CALL( varEventVarUnlocked(lockvar, blkmem, set, eventqueue) );
3230 }
3231
3232 return SCIP_OKAY;
3234 assert(!lockvar->donotaggr);
3235
3236 if( lockvar->data.aggregate.scalar < 0.0 )
3237 {
3238 int tmp = addnlocksup;
3239
3240 addnlocksup = addnlocksdown;
3241 addnlocksdown = tmp;
3242 }
3243
3244 lockvar = lockvar->data.aggregate.var;
3245 break;
3247 {
3248 int v;
3249
3250 assert(!lockvar->donotmultaggr);
3251
3252 lockvar->nlocksdown[locktype] += addnlocksdown;
3253 lockvar->nlocksup[locktype] += addnlocksup;
3254
3255 assert(lockvar->nlocksdown[locktype] >= 0);
3256 assert(lockvar->nlocksup[locktype] >= 0);
3257
3258 for( v = lockvar->data.multaggr.nvars - 1; v >= 0; --v )
3259 {
3260 if( lockvar->data.multaggr.scalars[v] > 0.0 )
3261 {
3262 SCIP_CALL( SCIPvarAddLocks(lockvar->data.multaggr.vars[v], blkmem, set, eventqueue, locktype, addnlocksdown,
3263 addnlocksup) );
3264 }
3265 else
3266 {
3267 SCIP_CALL( SCIPvarAddLocks(lockvar->data.multaggr.vars[v], blkmem, set, eventqueue, locktype, addnlocksup,
3268 addnlocksdown) );
3269 }
3270 }
3271 return SCIP_OKAY;
3272 }
3274 {
3275 int tmp = addnlocksup;
3276
3277 assert(lockvar->negatedvar != NULL);
3279 assert(lockvar->negatedvar->negatedvar == lockvar);
3280
3281 addnlocksup = addnlocksdown;
3282 addnlocksdown = tmp;
3283
3284 lockvar = lockvar->negatedvar;
3285 break;
3286 }
3287 default:
3288 SCIPerrorMessage("unknown variable status\n");
3289 return SCIP_INVALIDDATA;
3290 }
3291 }
3292}
3293
3294/** gets number of locks for rounding down of a special type */
3296 SCIP_VAR* var, /**< problem variable */
3297 SCIP_LOCKTYPE locktype /**< type of variable locks */
3298 )
3299{
3300 int nlocks;
3301 int i;
3302
3303 assert(var != NULL);
3304 assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
3305 assert(var->nlocksdown[locktype] >= 0);
3306
3307 switch( SCIPvarGetStatus(var) )
3308 {
3310 if( var->data.original.transvar != NULL )
3311 return SCIPvarGetNLocksDownType(var->data.original.transvar, locktype);
3312 else
3313 return var->nlocksdown[locktype];
3314
3318 return var->nlocksdown[locktype];
3319
3321 assert(!var->donotaggr);
3322 if( var->data.aggregate.scalar > 0.0 )
3323 return SCIPvarGetNLocksDownType(var->data.aggregate.var, locktype);
3324 else
3325 return SCIPvarGetNLocksUpType(var->data.aggregate.var, locktype);
3326
3328 assert(!var->donotmultaggr);
3329 nlocks = 0;
3330 for( i = 0; i < var->data.multaggr.nvars; ++i )
3331 {
3332 if( var->data.multaggr.scalars[i] > 0.0 )
3333 nlocks += SCIPvarGetNLocksDownType(var->data.multaggr.vars[i], locktype);
3334 else
3335 nlocks += SCIPvarGetNLocksUpType(var->data.multaggr.vars[i], locktype);
3336 }
3337 return nlocks;
3338
3340 assert(var->negatedvar != NULL);
3342 assert(var->negatedvar->negatedvar == var);
3343 return SCIPvarGetNLocksUpType(var->negatedvar, locktype);
3344
3345 default:
3346 SCIPerrorMessage("unknown variable status\n");
3347 SCIPABORT();
3348 return INT_MAX; /*lint !e527*/
3349 }
3350}
3351
3352/** gets number of locks for rounding up of a special type */
3354 SCIP_VAR* var, /**< problem variable */
3355 SCIP_LOCKTYPE locktype /**< type of variable locks */
3356 )
3357{
3358 int nlocks;
3359 int i;
3360
3361 assert(var != NULL);
3362 assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
3363 assert(var->nlocksup[locktype] >= 0);
3364
3365 switch( SCIPvarGetStatus(var) )
3366 {
3368 if( var->data.original.transvar != NULL )
3369 return SCIPvarGetNLocksUpType(var->data.original.transvar, locktype);
3370 else
3371 return var->nlocksup[locktype];
3372
3376 return var->nlocksup[locktype];
3377
3379 assert(!var->donotaggr);
3380 if( var->data.aggregate.scalar > 0.0 )
3381 return SCIPvarGetNLocksUpType(var->data.aggregate.var, locktype);
3382 else
3383 return SCIPvarGetNLocksDownType(var->data.aggregate.var, locktype);
3384
3386 assert(!var->donotmultaggr);
3387 nlocks = 0;
3388 for( i = 0; i < var->data.multaggr.nvars; ++i )
3389 {
3390 if( var->data.multaggr.scalars[i] > 0.0 )
3391 nlocks += SCIPvarGetNLocksUpType(var->data.multaggr.vars[i], locktype);
3392 else
3393 nlocks += SCIPvarGetNLocksDownType(var->data.multaggr.vars[i], locktype);
3394 }
3395 return nlocks;
3396
3398 assert(var->negatedvar != NULL);
3400 assert(var->negatedvar->negatedvar == var);
3401 return SCIPvarGetNLocksDownType(var->negatedvar, locktype);
3402
3403 default:
3404 SCIPerrorMessage("unknown variable status\n");
3405 SCIPABORT();
3406 return INT_MAX; /*lint !e527*/
3407 }
3408}
3409
3410/** gets number of locks for rounding down
3411 *
3412 * @note This method will always return variable locks of type model
3413 *
3414 * @note It is recommented to use SCIPvarGetNLocksDownType()
3415 */
3417 SCIP_VAR* var /**< problem variable */
3418 )
3419{
3421}
3422
3423/** gets number of locks for rounding up
3424 *
3425 * @note This method will always return variable locks of type model
3426 *
3427 * @note It is recommented to use SCIPvarGetNLocksUpType()
3428 */
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{
3455 return (SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 0);
3456}
3457
3458/** gets and captures transformed variable of a given variable; if the variable is not yet transformed,
3459 * a new transformed variable for this variable is created
3460 */
3462 SCIP_VAR* origvar, /**< original problem variable */
3463 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3464 SCIP_SET* set, /**< global SCIP settings */
3465 SCIP_STAT* stat, /**< problem statistics */
3466 SCIP_OBJSENSE objsense, /**< objective sense of original problem; transformed is always MINIMIZE */
3467 SCIP_VAR** transvar /**< pointer to store the transformed variable */
3468 )
3469{
3470 char name[SCIP_MAXSTRLEN];
3471
3472 assert(origvar != NULL);
3473 assert(origvar->scip == set->scip);
3474 assert(SCIPvarGetStatus(origvar) == SCIP_VARSTATUS_ORIGINAL);
3475 assert(SCIPsetIsEQ(set, origvar->glbdom.lb, origvar->locdom.lb));
3476 assert(SCIPsetIsEQ(set, origvar->glbdom.ub, origvar->locdom.ub));
3477 assert(origvar->vlbs == NULL);
3478 assert(origvar->vubs == NULL);
3479 assert(transvar != NULL);
3480
3481 /* check if variable is already transformed */
3482 if( origvar->data.original.transvar != NULL )
3483 {
3484 *transvar = origvar->data.original.transvar;
3485 SCIPvarCapture(*transvar);
3486 }
3487 else
3488 {
3489 int i;
3490
3491 /* create transformed variable */
3492 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "t_%s", origvar->name);
3493 SCIP_CALL( SCIPvarCreateTransformed(transvar, blkmem, set, stat, name,
3494 origvar->glbdom.lb, origvar->glbdom.ub, (SCIP_Real)objsense * origvar->obj,
3495 SCIPvarGetType(origvar), origvar->initial, origvar->removable,
3496 origvar->vardelorig, origvar->vartrans, origvar->vardeltrans, origvar->varcopy, NULL) );
3497
3498 /* copy the branch factor and priority */
3499 (*transvar)->branchfactor = origvar->branchfactor;
3500 (*transvar)->branchpriority = origvar->branchpriority;
3501 (*transvar)->branchdirection = origvar->branchdirection; /*lint !e732*/
3502
3503 /* duplicate hole lists */
3504 SCIP_CALL( holelistDuplicate(&(*transvar)->glbdom.holelist, blkmem, set, origvar->glbdom.holelist) );
3505 SCIP_CALL( holelistDuplicate(&(*transvar)->locdom.holelist, blkmem, set, origvar->locdom.holelist) );
3506
3507 /* link original and transformed variable */
3508 origvar->data.original.transvar = *transvar;
3509 SCIP_CALL( varAddParent(*transvar, blkmem, set, origvar) );
3510
3511 /* copy rounding locks */
3512 for( i = 0; i < NLOCKTYPES; i++ )
3513 {
3514 (*transvar)->nlocksdown[i] = origvar->nlocksdown[i];
3515 (*transvar)->nlocksup[i] = origvar->nlocksup[i];
3516 assert((*transvar)->nlocksdown[i] >= 0);
3517 assert((*transvar)->nlocksup[i] >= 0);
3518 }
3519
3520 /* copy donot(mult)aggr status */
3521 (*transvar)->donotaggr = origvar->donotaggr;
3522 (*transvar)->donotmultaggr = origvar->donotmultaggr;
3523
3524 /* copy lazy bounds */
3525 (*transvar)->lazylb = origvar->lazylb;
3526 (*transvar)->lazyub = origvar->lazyub;
3527
3528 /* transfer eventual variable statistics; do not update global statistics, because this has been done
3529 * when original variable was created
3530 */
3531 SCIPhistoryUnite((*transvar)->history, origvar->history, FALSE);
3532
3533 /* transform user data */
3534 if( origvar->vartrans != NULL )
3535 {
3536 SCIP_CALL( origvar->vartrans(set->scip, origvar, origvar->vardata, *transvar, &(*transvar)->vardata) );
3537 }
3538 else
3539 (*transvar)->vardata = origvar->vardata;
3540 }
3541
3542 SCIPsetDebugMsg(set, "transformed variable: <%s>[%p] -> <%s>[%p]\n", origvar->name, (void*)origvar, (*transvar)->name, (void*)*transvar);
3543
3544 return SCIP_OKAY;
3545}
3546
3547/** gets corresponding transformed variable of an original or negated original variable */
3549 SCIP_VAR* origvar, /**< original problem variable */
3550 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3551 SCIP_SET* set, /**< global SCIP settings */
3552 SCIP_STAT* stat, /**< problem statistics */
3553 SCIP_VAR** transvar /**< pointer to store the transformed variable, or NULL if not existing yet */
3554 )
3555{
3556 assert(origvar != NULL);
3558 assert(origvar->scip == set->scip);
3559
3561 {
3562 assert(origvar->negatedvar != NULL);
3564
3565 if( origvar->negatedvar->data.original.transvar == NULL )
3566 *transvar = NULL;
3567 else
3568 {
3569 SCIP_CALL( SCIPvarNegate(origvar->negatedvar->data.original.transvar, blkmem, set, stat, transvar) );
3570 }
3571 }
3572 else
3573 *transvar = origvar->data.original.transvar;
3574
3575 return SCIP_OKAY;
3576}
3577
3578/** converts loose transformed variable into column variable, creates LP column */
3580 SCIP_VAR* var, /**< problem variable */
3581 BMS_BLKMEM* blkmem, /**< block memory */
3582 SCIP_SET* set, /**< global SCIP settings */
3583 SCIP_STAT* stat, /**< problem statistics */
3584 SCIP_PROB* prob, /**< problem data */
3585 SCIP_LP* lp /**< current LP data */
3586 )
3587{
3588 assert(var != NULL);
3589 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
3590 assert(var->scip == set->scip);
3591
3592 SCIPsetDebugMsg(set, "creating column for variable <%s>\n", var->name);
3593
3594 /* switch variable status */
3595 var->varstatus = SCIP_VARSTATUS_COLUMN; /*lint !e641*/
3596
3597 /* create column of variable */
3598 SCIP_CALL( SCIPcolCreate(&var->data.col, blkmem, set, stat, var, 0, NULL, NULL, var->removable) );
3599
3600 if( var->probindex != -1 )
3601 {
3602 /* inform problem about the variable's status change */
3603 SCIP_CALL( SCIPprobVarChangedStatus(prob, blkmem, set, NULL, NULL, var) );
3604
3605 /* inform LP, that problem variable is now a column variable and no longer loose */
3606 SCIP_CALL( SCIPlpUpdateVarColumn(lp, set, var) );
3607 }
3608
3609 return SCIP_OKAY;
3610}
3611
3612/** converts column transformed variable back into loose variable, frees LP column */
3614 SCIP_VAR* var, /**< problem variable */
3615 BMS_BLKMEM* blkmem, /**< block memory */
3616 SCIP_SET* set, /**< global SCIP settings */
3617 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3618 SCIP_PROB* prob, /**< problem data */
3619 SCIP_LP* lp /**< current LP data */
3620 )
3621{
3622 assert(var != NULL);
3624 assert(var->scip == set->scip);
3625 assert(var->data.col != NULL);
3626 assert(var->data.col->lppos == -1);
3627 assert(var->data.col->lpipos == -1);
3628
3629 SCIPsetDebugMsg(set, "deleting column for variable <%s>\n", var->name);
3630
3631 /* free column of variable */
3632 SCIP_CALL( SCIPcolFree(&var->data.col, blkmem, set, eventqueue, lp) );
3633
3634 /* switch variable status */
3635 var->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
3636
3637 if( var->probindex != -1 )
3638 {
3639 /* inform problem about the variable's status change */
3640 SCIP_CALL( SCIPprobVarChangedStatus(prob, blkmem, set, NULL, NULL, var) );
3641
3642 /* inform LP, that problem variable is now a loose variable and no longer a column */
3643 SCIP_CALL( SCIPlpUpdateVarLoose(lp, set, var) );
3644 }
3645
3646 return SCIP_OKAY;
3647}
3648
3649/** issues a VARFIXED event on the given variable and all its parents (except ORIGINAL parents);
3650 * the event issuing on the parents is necessary, because unlike with bound changes, the parent variables
3651 * are not informed about a fixing of an active variable they are pointing to
3652 */
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{
3664 SCIP_EVENT* event;
3665 SCIP_VARSTATUS varstatus;
3666 int i;
3667
3668 assert(var != NULL);
3669 assert(var->scip == set->scip);
3670 assert(0 <= fixeventtype && fixeventtype <= 2);
3671
3672 /* issue VARFIXED event on variable */
3673 SCIP_CALL( SCIPeventCreateVarFixed(&event, blkmem, var) );
3674 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
3675
3676#ifndef NDEBUG
3677 for( i = var->nparentvars -1; i >= 0; --i )
3678 {
3680 }
3681#endif
3682
3683 switch( fixeventtype )
3684 {
3685 case 0:
3686 /* process all parents of a fixed variable */
3687 for( i = var->nparentvars - 1; i >= 0; --i )
3688 {
3689 varstatus = SCIPvarGetStatus(var->parentvars[i]);
3690
3691 assert(varstatus != SCIP_VARSTATUS_FIXED);
3692
3693 /* issue event on all not yet fixed parent variables, (that should already issued this event) except the original
3694 * one
3695 */
3696 if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3697 {
3698 SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3699 }
3700 }
3701 break;
3702 case 1:
3703 /* process all parents of a aggregated variable */
3704 for( i = var->nparentvars - 1; i >= 0; --i )
3705 {
3706 varstatus = SCIPvarGetStatus(var->parentvars[i]);
3707
3708 assert(varstatus != SCIP_VARSTATUS_FIXED);
3709
3710 /* issue event for not aggregated parent variable, because for these and its parents the var event was already
3711 * issued(, except the original one)
3712 *
3713 * @note that even before an aggregated parent variable, there might be variables, for which the vent was not
3714 * yet issued
3715 */
3716 if( varstatus == SCIP_VARSTATUS_AGGREGATED )
3717 continue;
3718
3719 if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3720 {
3721 SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3722 }
3723 }
3724 break;
3725 case 2:
3726 /* process all parents of a aggregated variable */
3727 for( i = var->nparentvars - 1; i >= 0; --i )
3728 {
3729 varstatus = SCIPvarGetStatus(var->parentvars[i]);
3730
3731 assert(varstatus != SCIP_VARSTATUS_FIXED);
3732
3733 /* issue event on all parent variables except the original one */
3734 if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3735 {
3736 SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3737 }
3738 }
3739 break;
3740 default:
3741 SCIPerrorMessage("unknown variable fixation event origin\n");
3742 return SCIP_INVALIDDATA;
3743 }
3744
3745 return SCIP_OKAY;
3746}
3747
3748/** converts variable into fixed variable */
3750 SCIP_VAR* var, /**< problem variable */
3751 BMS_BLKMEM* blkmem, /**< block memory */
3752 SCIP_SET* set, /**< global SCIP settings */
3753 SCIP_STAT* stat, /**< problem statistics */
3754 SCIP_PROB* transprob, /**< tranformed problem data */
3755 SCIP_PROB* origprob, /**< original problem data */
3756 SCIP_PRIMAL* primal, /**< primal data */
3757 SCIP_TREE* tree, /**< branch and bound tree */
3758 SCIP_REOPT* reopt, /**< reoptimization data structure */
3759 SCIP_LP* lp, /**< current LP data */
3760 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3761 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
3762 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3763 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
3764 SCIP_Real fixedval, /**< value to fix variable at */
3765 SCIP_Bool* infeasible, /**< pointer to store whether the fixing is infeasible */
3766 SCIP_Bool* fixed /**< pointer to store whether the fixing was performed (variable was unfixed) */
3767 )
3768{
3769 SCIP_Real obj;
3770 SCIP_Real childfixedval;
3771
3772 assert(var != NULL);
3773 assert(var->scip == set->scip);
3774 assert(SCIPsetIsEQ(set, var->glbdom.lb, var->locdom.lb));
3775 assert(SCIPsetIsEQ(set, var->glbdom.ub, var->locdom.ub));
3776 assert(infeasible != NULL);
3777 assert(fixed != NULL);
3778
3779 SCIPsetDebugMsg(set, "fix variable <%s>[%g,%g] to %g\n", var->name, var->glbdom.lb, var->glbdom.ub, fixedval);
3780
3781 *infeasible = FALSE;
3782 *fixed = FALSE;
3783
3785 {
3786 *infeasible = !SCIPsetIsFeasEQ(set, fixedval, var->locdom.lb);
3787 SCIPsetDebugMsg(set, " -> variable already fixed to %g (fixedval=%g): infeasible=%u\n", var->locdom.lb, fixedval, *infeasible);
3788 return SCIP_OKAY;
3789 }
3790 else if( ( SCIPvarIsIntegral(var) && !SCIPsetIsFeasIntegral(set, fixedval) )
3791 || SCIPsetIsFeasLT(set, fixedval, var->locdom.lb)
3792 || SCIPsetIsFeasGT(set, fixedval, var->locdom.ub) )
3793 {
3794 SCIPsetDebugMsg(set, " -> fixing infeasible: locdom=[%g,%g], fixedval=%g\n", var->locdom.lb, var->locdom.ub, fixedval);
3795 *infeasible = TRUE;
3796 return SCIP_OKAY;
3797 }
3798
3799 switch( SCIPvarGetStatus(var) )
3800 {
3802 if( var->data.original.transvar == NULL )
3803 {
3804 SCIPerrorMessage("cannot fix an untransformed original variable\n");
3805 return SCIP_INVALIDDATA;
3806 }
3807 SCIP_CALL( SCIPvarFix(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
3808 lp, branchcand, eventfilter, eventqueue, cliquetable, fixedval, infeasible, fixed) );
3809 break;
3810
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 /* free hole lists */
3826 holelistFree(&var->glbdom.holelist, blkmem);
3827 holelistFree(&var->locdom.holelist, blkmem);
3828
3829 /* adjust fixed value */
3830 if( SCIPvarIsIntegral(var) )
3831 fixedval = SCIPsetRound(set, fixedval);
3832
3833 /* change variable bounds to fixed value */
3834 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, fixedval) );
3835 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, fixedval) );
3836
3837 /* explicitly set variable's bounds if the fixed value was in epsilon range of the old bound (so above call didn't set bound) */
3838 var->glbdom.lb = fixedval;
3839 var->glbdom.ub = fixedval;
3840
3841 /* ensure local domain is fixed to same value as global domain */
3842 var->locdom.lb = fixedval;
3843 var->locdom.ub = fixedval;
3844
3845 /* delete implications and variable bounds information */
3846 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
3847 assert(var->vlbs == NULL);
3848 assert(var->vubs == NULL);
3849 assert(var->implics == NULL);
3850
3851 /* clear the history of the variable */
3854
3855 /* convert variable into fixed variable */
3856 var->varstatus = SCIP_VARSTATUS_FIXED; /*lint !e641*/
3857
3858 /* inform problem about the variable's status change */
3859 if( var->probindex != -1 )
3860 {
3861 SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
3862 }
3863
3864 /* reset the objective value of the fixed variable, thus adjusting the problem's objective offset */
3865 SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventfilter, eventqueue, obj) );
3866
3867 /* issue VARFIXED event */
3868 SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 0) );
3869
3870 *fixed = TRUE;
3871 break;
3872
3874 SCIPerrorMessage("cannot fix a column variable\n");
3875 return SCIP_INVALIDDATA;
3876
3878 SCIPerrorMessage("cannot fix a fixed variable again\n"); /*lint !e527*/
3879 SCIPABORT(); /* case is already handled in earlier if condition */
3880 return SCIP_INVALIDDATA; /*lint !e527*/
3881
3883 /* fix aggregation variable y in x = a*y + c, instead of fixing x directly */
3884 assert(SCIPsetIsZero(set, var->obj));
3885 assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
3886 if( SCIPsetIsInfinity(set, fixedval) || SCIPsetIsInfinity(set, -fixedval) )
3887 childfixedval = (var->data.aggregate.scalar < 0.0 ? -fixedval : fixedval);
3888 else
3889 childfixedval = (fixedval - var->data.aggregate.constant)/var->data.aggregate.scalar;
3890 SCIP_CALL( SCIPvarFix(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
3891 branchcand, eventfilter, eventqueue, cliquetable, childfixedval, infeasible, fixed) );
3892 break;
3893
3895 SCIPerrorMessage("cannot fix a multiple aggregated variable\n");
3896 SCIPABORT();
3897 return SCIP_INVALIDDATA; /*lint !e527*/
3898
3900 /* fix negation variable x in x' = offset - x, instead of fixing x' directly */
3901 assert(SCIPsetIsZero(set, var->obj));
3902 assert(var->negatedvar != NULL);
3904 assert(var->negatedvar->negatedvar == var);
3905 SCIP_CALL( SCIPvarFix(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
3906 branchcand, eventfilter, eventqueue, cliquetable, var->data.negate.constant - fixedval, infeasible, fixed) );
3907 break;
3908
3909 default:
3910 SCIPerrorMessage("unknown variable status\n");
3911 return SCIP_INVALIDDATA;
3912 }
3913
3914 return SCIP_OKAY;
3915}
3916
3917/** transforms given variables, scalars and constant to the corresponding active variables, scalars and constant
3918 *
3919 * If the number of needed active variables is greater than the available slots in the variable array, nothing happens except
3920 * that the required size is stored in the corresponding variable; hence, if afterwards the required size is greater than the
3921 * available slots (varssize), nothing happens; otherwise, the active variable representation is stored in the arrays.
3922 *
3923 * The reason for this approach is that we cannot reallocate memory, since we do not know how the
3924 * memory has been allocated (e.g., by a C++ 'new' or SCIP functions).
3925 */
3927 SCIP_SET* set, /**< global SCIP settings */
3928 SCIP_VAR** vars, /**< variable array to get active variables */
3929 SCIP_Real* scalars, /**< scalars a_1, ..., a_n in linear sum a_1*x_1 + ... + a_n*x_n + c */
3930 int* nvars, /**< pointer to number of variables and values in vars and scalars array */
3931 int varssize, /**< available slots in vars and scalars array */
3932 SCIP_Real* constant, /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c */
3933 int* requiredsize, /**< pointer to store the required array size for the active variables */
3934 SCIP_Bool mergemultiples /**< should multiple occurrences of a var be replaced by a single coeff? */
3935 )
3936{
3937 SCIP_VAR** activevars;
3938 SCIP_Real* activescalars;
3939 int nactivevars;
3940 SCIP_Real activeconstant;
3941 SCIP_Bool activeconstantinf;
3942 int activevarssize;
3943
3944 SCIP_VAR* var;
3945 SCIP_Real scalar;
3946 int v;
3947 int k;
3948
3949 SCIP_VAR** tmpvars;
3950 SCIP_VAR** multvars;
3951 SCIP_Real* tmpscalars;
3952 SCIP_Real* multscalars;
3953 int tmpvarssize;
3954 int ntmpvars;
3955 int nmultvars;
3956
3957 SCIP_VAR* multvar;
3958 SCIP_Real multscalar;
3959 SCIP_Real multconstant;
3960 int pos;
3961
3962 int noldtmpvars;
3963
3964 SCIP_VAR** tmpvars2;
3965 SCIP_Real* tmpscalars2;
3966 int tmpvarssize2;
3967 int ntmpvars2;
3968
3969 SCIP_Bool sortagain = FALSE;
3970
3971 assert(set != NULL);
3972 assert(nvars != NULL);
3973 assert(scalars != NULL || *nvars == 0);
3974 assert(constant != NULL);
3975 assert(requiredsize != NULL);
3976 assert(*nvars <= varssize);
3977
3978 *requiredsize = 0;
3979
3980 if( *nvars == 0 )
3981 return SCIP_OKAY;
3982
3983 assert(vars != NULL);
3984
3985 /* handle the "easy" case of just one variable and avoid memory allocation if the variable is already active */
3986 if( *nvars == 1 && (vars[0]->varstatus == ((int) SCIP_VARSTATUS_COLUMN) || vars[0]->varstatus == ((int) SCIP_VARSTATUS_LOOSE)) )
3987 {
3988 *requiredsize = 1;
3989
3990 return SCIP_OKAY;
3991 }
3992
3993 nactivevars = 0;
3994 activeconstant = 0.0;
3995 activeconstantinf = FALSE;
3996 activevarssize = (*nvars) * 2;
3997 ntmpvars = *nvars;
3998 tmpvarssize = *nvars;
3999
4000 tmpvarssize2 = 1;
4001
4002 /* allocate temporary memory */
4003 SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpvars2, tmpvarssize2) );
4004 SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpscalars2, tmpvarssize2) );
4005 SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
4006 SCIP_CALL( SCIPsetAllocBufferArray(set, &activescalars, activevarssize) );
4007 SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
4008 SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpscalars, scalars, ntmpvars) );
4009
4010 /* to avoid unnecessary expanding of variable arrays while disaggregating several variables multiple times combine same variables
4011 * first, first get all corresponding variables with status loose, column, multaggr or fixed
4012 */
4013 for( v = ntmpvars - 1; v >= 0; --v )
4014 {
4015 var = tmpvars[v];
4016 scalar = tmpscalars[v];
4017
4018 assert(var != NULL);
4019 /* transforms given variable, scalar and constant to the corresponding active, fixed, or
4020 * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed
4021 * variable, "scalar" will be 0.0 and the value of the sum will be stored in "constant".
4022 */
4023 SCIP_CALL( SCIPvarGetProbvarSum(&var, set, &scalar, &activeconstant) );
4024 assert(var != NULL);
4025
4026 assert(SCIPsetIsInfinity(set, activeconstant) == (activeconstant == SCIPsetInfinity(set))); /*lint !e777*/
4027 assert(SCIPsetIsInfinity(set, -activeconstant) == (activeconstant == -SCIPsetInfinity(set))); /*lint !e777*/
4028
4029 activeconstantinf = SCIPsetIsInfinity(set, activeconstant) || SCIPsetIsInfinity(set, -activeconstant);
4030
4035
4036 tmpvars[v] = var;
4037 tmpscalars[v] = scalar;
4038 }
4039 noldtmpvars = ntmpvars;
4040
4041 /* sort all variables to combine equal variables easily */
4042 SCIPsortPtrReal((void**)tmpvars, tmpscalars, SCIPvarComp, noldtmpvars);
4043 ntmpvars = 0;
4044 for( v = 1; v < noldtmpvars; ++v )
4045 {
4046 /* combine same variables */
4047 if( SCIPvarCompare(tmpvars[v], tmpvars[ntmpvars]) == 0 )
4048 {
4049 tmpscalars[ntmpvars] += tmpscalars[v];
4050 }
4051 else
4052 {
4053 ++ntmpvars;
4054 if( v > ntmpvars )
4055 {
4056 tmpscalars[ntmpvars] = tmpscalars[v];
4057 tmpvars[ntmpvars] = tmpvars[v];
4058 }
4059 }
4060 }
4061 ++ntmpvars;
4062
4063#ifdef SCIP_MORE_DEBUG
4064 for( v = 1; v < ntmpvars; ++v )
4065 assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
4066#endif
4067
4068 /* collect for each variable the representation in active variables */
4069 while( ntmpvars >= 1 )
4070 {
4071 --ntmpvars;
4072 ntmpvars2 = 0;
4073 var = tmpvars[ntmpvars];
4074 scalar = tmpscalars[ntmpvars];
4075
4076 assert(var != NULL);
4077
4078 /* TODO: maybe we should test here on SCIPsetIsZero() instead of 0.0 */
4079 if( scalar == 0.0 )
4080 continue;
4081
4086
4087 switch( SCIPvarGetStatus(var) )
4088 {
4091 /* x = a*y + c */
4092 if( nactivevars >= activevarssize )
4093 {
4094 activevarssize *= 2;
4095 SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
4096 SCIP_CALL( SCIPsetReallocBufferArray(set, &activescalars, activevarssize) );
4097 assert(nactivevars < activevarssize);
4098 }
4099 activevars[nactivevars] = var;
4100 activescalars[nactivevars] = scalar;
4101 nactivevars++;
4102 break;
4103
4105 /* x = a_1*y_1 + ... + a_n*y_n + c */
4106 nmultvars = var->data.multaggr.nvars;
4107 multvars = var->data.multaggr.vars;
4108 multscalars = var->data.multaggr.scalars;
4109 sortagain = TRUE;
4110
4111 if( nmultvars + ntmpvars > tmpvarssize )
4112 {
4113 while( nmultvars + ntmpvars > tmpvarssize )
4114 tmpvarssize *= 2;
4115 SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
4116 SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpscalars, tmpvarssize) );
4117 assert(nmultvars + ntmpvars <= tmpvarssize);
4118 }
4119
4120 if( nmultvars > tmpvarssize2 )
4121 {
4122 while( nmultvars > tmpvarssize2 )
4123 tmpvarssize2 *= 2;
4124 SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars2, tmpvarssize2) );
4125 SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpscalars2, tmpvarssize2) );
4126 assert(nmultvars <= tmpvarssize2);
4127 }
4128
4129 --nmultvars;
4130
4131 for( ; nmultvars >= 0; --nmultvars )
4132 {
4133 multvar = multvars[nmultvars];
4134 multscalar = multscalars[nmultvars];
4135 multconstant = 0;
4136
4137 assert(multvar != NULL);
4138 SCIP_CALL( SCIPvarGetProbvarSum(&multvar, set, &multscalar, &multconstant) );
4139 assert(multvar != NULL);
4140
4145
4146 if( !activeconstantinf )
4147 {
4148 assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
4149
4150 if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) )
4151 {
4152 assert(scalar != 0.0);
4153 if( scalar * multconstant > 0.0 )
4154 {
4155 activeconstant = SCIPsetInfinity(set);
4156 activeconstantinf = TRUE;
4157 }
4158 else
4159 {
4160 activeconstant = -SCIPsetInfinity(set);
4161 activeconstantinf = TRUE;
4162 }
4163 }
4164 else
4165 activeconstant += scalar * multconstant;
4166 }
4167#ifndef NDEBUG
4168 else
4169 {
4170 assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
4171 (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4172 assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
4173 (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4174 }
4175#endif
4176
4177 if( SCIPsortedvecFindPtr((void**)tmpvars, SCIPvarComp, multvar, ntmpvars, &pos) )
4178 {
4179 assert(SCIPvarCompare(tmpvars[pos], multvar) == 0);
4180 tmpscalars[pos] += scalar * multscalar;
4181 }
4182 else
4183 {
4184 tmpvars2[ntmpvars2] = multvar;
4185 tmpscalars2[ntmpvars2] = scalar * multscalar;
4186 ++(ntmpvars2);
4187 assert(ntmpvars2 <= tmpvarssize2);
4188 }
4189 }
4190
4191 if( ntmpvars2 > 0 )
4192 {
4193 /* sort all variables to combine equal variables easily */
4194 SCIPsortPtrReal((void**)tmpvars2, tmpscalars2, SCIPvarComp, ntmpvars2);
4195 pos = 0;
4196 for( v = 1; v < ntmpvars2; ++v )
4197 {
4198 /* combine same variables */
4199 if( SCIPvarCompare(tmpvars2[v], tmpvars2[pos]) == 0 )
4200 {
4201 tmpscalars2[pos] += tmpscalars2[v];
4202 }
4203 else
4204 {
4205 ++pos;
4206 if( v > pos )
4207 {
4208 tmpscalars2[pos] = tmpscalars2[v];
4209 tmpvars2[pos] = tmpvars2[v];
4210 }
4211 }
4212 }
4213 ntmpvars2 = pos + 1;
4214#ifdef SCIP_MORE_DEBUG
4215 for( v = 1; v < ntmpvars2; ++v )
4216 {
4217 assert(SCIPvarCompare(tmpvars2[v], tmpvars2[v-1]) > 0);
4218 }
4219 for( v = 1; v < ntmpvars; ++v )
4220 {
4221 assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
4222 }
4223#endif
4224 v = ntmpvars - 1;
4225 k = ntmpvars2 - 1;
4226 pos = ntmpvars + ntmpvars2 - 1;
4227 ntmpvars += ntmpvars2;
4228
4229 while( v >= 0 && k >= 0 )
4230 {
4231 assert(pos >= 0);
4232 assert(SCIPvarCompare(tmpvars[v], tmpvars2[k]) != 0);
4233 if( SCIPvarCompare(tmpvars[v], tmpvars2[k]) >= 0 )
4234 {
4235 tmpvars[pos] = tmpvars[v];
4236 tmpscalars[pos] = tmpscalars[v];
4237 --v;
4238 }
4239 else
4240 {
4241 tmpvars[pos] = tmpvars2[k];
4242 tmpscalars[pos] = tmpscalars2[k];
4243 --k;
4244 }
4245 --pos;
4246 assert(pos >= 0);
4247 }
4248 while( v >= 0 )
4249 {
4250 assert(pos >= 0);
4251 tmpvars[pos] = tmpvars[v];
4252 tmpscalars[pos] = tmpscalars[v];
4253 --v;
4254 --pos;
4255 }
4256 while( k >= 0 )
4257 {
4258 assert(pos >= 0);
4259 tmpvars[pos] = tmpvars2[k];
4260 tmpscalars[pos] = tmpscalars2[k];
4261 --k;
4262 --pos;
4263 }
4264 }
4265#ifdef SCIP_MORE_DEBUG
4266 for( v = 1; v < ntmpvars; ++v )
4267 {
4268 assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
4269 }
4270#endif
4271
4272 if( !activeconstantinf )
4273 {
4274 assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
4275
4276 multconstant = SCIPvarGetMultaggrConstant(var);
4277
4278 if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) )
4279 {
4280 assert(scalar != 0.0);
4281 if( scalar * multconstant > 0.0 )
4282 {
4283 activeconstant = SCIPsetInfinity(set);
4284 activeconstantinf = TRUE;
4285 }
4286 else
4287 {
4288 activeconstant = -SCIPsetInfinity(set);
4289 activeconstantinf = TRUE;
4290 }
4291 }
4292 else
4293 activeconstant += scalar * multconstant;
4294 }
4295#ifndef NDEBUG
4296 else
4297 {
4298 multconstant = SCIPvarGetMultaggrConstant(var);
4299 assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
4300 (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4301 assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
4302 (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4303 }
4304#endif
4305 break;
4306
4311 default:
4312 /* case x = c, but actually we should not be here, since SCIPvarGetProbvarSum() returns a scalar of 0.0 for
4313 * fixed variables and is handled already
4314 */
4315 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED);
4316 assert(SCIPsetIsZero(set, var->glbdom.lb) && SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub));
4317 }
4318 }
4319
4320 if( mergemultiples )
4321 {
4322 if( sortagain )
4323 {
4324 /* sort variable and scalar array by variable index */
4325 SCIPsortPtrReal((void**)activevars, activescalars, SCIPvarComp, nactivevars);
4326
4327 /* eliminate duplicates and count required size */
4328 v = nactivevars - 1;
4329 while( v > 0 )
4330 {
4331 /* combine both variable since they are the same */
4332 if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
4333 {
4334 if( activescalars[v - 1] + activescalars[v] != 0.0 )
4335 {
4336 activescalars[v - 1] += activescalars[v];
4337 --nactivevars;
4338 activevars[v] = activevars[nactivevars];
4339 activescalars[v] = activescalars[nactivevars];
4340 }
4341 else
4342 {
4343 --nactivevars;
4344 activevars[v] = activevars[nactivevars];
4345 activescalars[v] = activescalars[nactivevars];
4346 --nactivevars;
4347 --v;
4348 activevars[v] = activevars[nactivevars];
4349 activescalars[v] = activescalars[nactivevars];
4350 }
4351 }
4352 --v;
4353 }
4354 }
4355 /* the variables were added in reverse order, we revert the order now;
4356 * this should not be necessary, but not doing this changes the behavior sometimes
4357 */
4358 else
4359 {
4360 SCIP_VAR* tmpvar;
4361 SCIP_Real tmpscalar;
4362
4363 for( v = 0; v < nactivevars / 2; ++v )
4364 {
4365 tmpvar = activevars[v];
4366 tmpscalar = activescalars[v];
4367 activevars[v] = activevars[nactivevars - 1 - v];
4368 activescalars[v] = activescalars[nactivevars - 1 - v];
4369 activevars[nactivevars - 1 - v] = tmpvar;
4370 activescalars[nactivevars - 1 - v] = tmpscalar;
4371 }
4372 }
4373 }
4374 *requiredsize = nactivevars;
4375
4376 if( varssize >= *requiredsize )
4377 {
4378 assert(vars != NULL);
4379
4380 *nvars = *requiredsize;
4381
4382 if( !SCIPsetIsInfinity(set, *constant) && !SCIPsetIsInfinity(set, -(*constant)) )
4383 {
4384 /* if the activeconstant is infinite, the constant pointer gets the same value, otherwise add the value */
4385 if( activeconstantinf )
4386 (*constant) = activeconstant;
4387 else
4388 (*constant) += activeconstant;
4389 }
4390#ifndef NDEBUG
4391 else
4392 {
4393 assert(!SCIPsetIsInfinity(set, (*constant)) || !SCIPsetIsInfinity(set, -activeconstant));
4394 assert(!SCIPsetIsInfinity(set, -(*constant)) || !SCIPsetIsInfinity(set, activeconstant));
4395 }
4396#endif
4397
4398 /* copy active variable and scalar array to the given arrays */
4399 for( v = 0; v < *nvars; ++v )
4400 {
4401 vars[v] = activevars[v];
4402 scalars[v] = activescalars[v]; /*lint !e613*/
4403 }
4404 }
4405
4406 assert(SCIPsetIsInfinity(set, *constant) == ((*constant) == SCIPsetInfinity(set))); /*lint !e777*/
4407 assert(SCIPsetIsInfinity(set, -(*constant)) == ((*constant) == -SCIPsetInfinity(set))); /*lint !e777*/
4408
4409 SCIPsetFreeBufferArray(set, &tmpscalars);
4410 SCIPsetFreeBufferArray(set, &tmpvars);
4411 SCIPsetFreeBufferArray(set, &activescalars);
4412 SCIPsetFreeBufferArray(set, &activevars);
4413 SCIPsetFreeBufferArray(set, &tmpscalars2);
4414 SCIPsetFreeBufferArray(set, &tmpvars2);
4415
4416 return SCIP_OKAY;
4417}
4418
4419
4420/** flattens aggregation graph of multi-aggregated variable in order to avoid exponential recursion later on */
4422 SCIP_VAR* var, /**< problem variable */
4423 BMS_BLKMEM* blkmem, /**< block memory */
4424 SCIP_SET* set, /**< global SCIP settings */
4425 SCIP_EVENTQUEUE* eventqueue /**< event queue */
4426 )
4427{
4428 int nlocksup[NLOCKTYPES];
4429 int nlocksdown[NLOCKTYPES];
4430 SCIP_Real multconstant;
4431 int multvarssize;
4432 int nmultvars;
4433 int multrequiredsize;
4434 int i;
4435
4436 assert( var != NULL );
4437 assert( SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR );
4438 assert(var->scip == set->scip);
4439
4440 /* in order to update the locks on the active representation of the multi-aggregated variable, we remove all locks
4441 * on the current representation now and re-add the locks once the variable graph has been flattened, which
4442 * may lead to duplicate occurences of the same variable being merged
4443 *
4444 * Here is an example. Assume we have the multi-aggregation z = x + y.
4445 * z occures with positive coefficient in a <= constraint c1, so it has an uplock from there.
4446 * When the multi-aggregation is performed, all locks are added to the active representation,
4447 * so x and y both get an uplock from c1. However, z was not yet replaced by x + y in c1.
4448 * Next, a negation y = 1 - x is identified. Again, locks are moved, so that the uplock of y originating
4449 * from c1 is added to x as a downlock. Thus, x has both an up- and downlock from c1.
4450 * The multi-aggregation changes to z = x + 1 - x, which corresponds to the locks.
4451 * However, before z is replaced by that sum, SCIPvarFlattenAggregationGraph() is called
4452 * which changes z = x + y = x + 1 - x = 1, since it merges multiple occurences of the same variable.
4453 * The up- and downlock of x, however, is not removed when replacing z in c1 by its active representation,
4454 * because it is just 1 now. Therefore, we need to update locks when flattening the aggregation graph.
4455 * For this, the multi-aggregated variable knows its locks in addition to adding them to the active
4456 * representation, which corresponds to the locks from constraints where the variable was not replaced yet.
4457 * By removing the locks here, based on the old representation and adding them again after flattening,
4458 * we ensure that the locks are correct afterwards if coefficients were merged.
4459 */
4460 for( i = 0; i < NLOCKTYPES; ++i )
4461 {
4462 nlocksup[i] = var->nlocksup[i];
4463 nlocksdown[i] = var->nlocksdown[i];
4464
4465 SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, -nlocksdown[i], -nlocksup[i]) );
4466 }
4467
4468 multconstant = var->data.multaggr.constant;
4469 nmultvars = var->data.multaggr.nvars;
4470 multvarssize = var->data.multaggr.varssize;
4471
4472 SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize, TRUE) );
4473
4474 if( multrequiredsize > multvarssize )
4475 {
4476 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.vars), multvarssize, multrequiredsize) );
4477 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.scalars), multvarssize, multrequiredsize) );
4478 multvarssize = multrequiredsize;
4479 SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize, TRUE) );
4480 assert( multrequiredsize <= multvarssize );
4481 }
4482 /**@note After the flattening the multi aggregation might resolve to be in fact an aggregation (or even a fixing?).
4483 * This issue is not resolved right now, since var->data.multaggr.nvars < 2 should not cause troubles. However, one
4484 * may loose performance hereby, since aggregated variables are easier to handle.
4485 *
4486 * Note, that there are two cases where SCIPvarFlattenAggregationGraph() is called: The easier one is that it is
4487 * called while installing the multi-aggregation. in principle, the described issue could be handled straightforward
4488 * in this case by aggregating or fixing the variable instead. The more complicated case is the one, when the
4489 * multi-aggregation is used, e.g., in linear presolving (and the variable is already declared to be multi-aggregated).
4490 *
4491 * By now, it is not allowed to fix or aggregate multi-aggregated variables which would be necessary in this case.
4492 *
4493 * The same issue appears in the SCIPvarGetProbvar...() methods.
4494 */
4495
4496 var->data.multaggr.constant = multconstant;
4497 var->data.multaggr.nvars = nmultvars;
4498 var->data.multaggr.varssize = multvarssize;
4499
4500 for( i = 0; i < NLOCKTYPES; ++i )
4501 {
4502 SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
4503 }
4504
4505 return SCIP_OKAY;
4506}
4507
4508/** merge two variable histories together; a typical use case is that \p othervar is an image of the target variable
4509 * in a SCIP copy. Method should be applied with care, especially because no internal checks are performed whether
4510 * the history merge is reasonable
4511 *
4512 * @note Do not use this method if the two variables originate from two SCIP's with different objective functions, since
4513 * this corrupts the variable pseudo costs
4514 * @note Apply with care; no internal checks are performed if the two variables should be merged
4515 */
4517 SCIP_VAR* targetvar, /**< the variable that should contain both histories afterwards */
4518 SCIP_VAR* othervar, /**< the variable whose history is to be merged with that of the target variable */
4519 SCIP_STAT* stat /**< problem statistics */
4520 )
4521{
4522 /* merge only the history of the current run into the target history */
4523 SCIPhistoryUnite(targetvar->history, othervar->historycrun, FALSE);
4524
4525 /* apply the changes also to the global history */
4526 SCIPhistoryUnite(stat->glbhistory, othervar->historycrun, FALSE);
4527}
4528
4529/** sets the history of a variable; this method is typically used within reoptimization to keep and update the variable
4530 * history over several iterations
4531 */
4533 SCIP_VAR* var, /**< variable */
4534 SCIP_HISTORY* history, /**< the history which is to set */
4535 SCIP_STAT* stat /**< problem statistics */
4536 )
4537{
4538 /* merge only the history of the current run into the target history */
4539 SCIPhistoryUnite(var->history, history, FALSE);
4540
4541 /* apply the changes also to the global history */
4542 SCIPhistoryUnite(stat->glbhistory, history, FALSE);
4543}
4544
4545/** tightens the bounds of both variables in aggregation x = a*y + c */
4546static
4548 SCIP_VAR* var, /**< problem variable */
4549 BMS_BLKMEM* blkmem, /**< block memory */
4550 SCIP_SET* set, /**< global SCIP settings */
4551 SCIP_STAT* stat, /**< problem statistics */
4552 SCIP_PROB* transprob, /**< tranformed problem data */
4553 SCIP_PROB* origprob, /**< original problem data */
4554 SCIP_PRIMAL* primal, /**< primal data */
4555 SCIP_TREE* tree, /**< branch and bound tree */
4556 SCIP_REOPT* reopt, /**< reoptimization data structure */
4557 SCIP_LP* lp, /**< current LP data */
4558 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4559 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4560 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4561 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4562 SCIP_VAR* aggvar, /**< variable y in aggregation x = a*y + c */
4563 SCIP_Real scalar, /**< multiplier a in aggregation x = a*y + c */
4564 SCIP_Real constant, /**< constant shift c in aggregation x = a*y + c */
4565 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4566 SCIP_Bool* fixed /**< pointer to store whether the variables were fixed */
4567 )
4568{
4569 SCIP_Real varlb;
4570 SCIP_Real varub;
4571 SCIP_Real aggvarlb;
4572 SCIP_Real aggvarub;
4573 SCIP_Bool aggvarbdschanged;
4574
4575 assert(var != NULL);
4576 assert(var->scip == set->scip);
4577 assert(aggvar != NULL);
4578 assert(!SCIPsetIsZero(set, scalar));
4579 assert(infeasible != NULL);
4580 assert(fixed != NULL);
4581
4582 *infeasible = FALSE;
4583 *fixed = FALSE;
4584
4585 SCIPsetDebugMsg(set, "updating bounds of variables in aggregation <%s> == %g*<%s> %+g\n", var->name, scalar, aggvar->name, constant);
4586 SCIPsetDebugMsg(set, " old bounds: <%s> [%g,%g] <%s> [%g,%g]\n",
4587 var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
4588
4589 /* loop as long additional changes may be found */
4590 do
4591 {
4592 aggvarbdschanged = FALSE;
4593
4594 /* update the bounds of the aggregated variable x in x = a*y + c */
4595 if( scalar > 0.0 )
4596 {
4597 if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
4598 varlb = -SCIPsetInfinity(set);
4599 else
4600 varlb = aggvar->glbdom.lb * scalar + constant;
4601 if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
4602 varub = SCIPsetInfinity(set);
4603 else
4604 varub = aggvar->glbdom.ub * scalar + constant;
4605 }
4606 else
4607 {
4608 if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
4609 varub = SCIPsetInfinity(set);
4610 else
4611 varub = aggvar->glbdom.lb * scalar + constant;
4612 if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
4613 varlb = -SCIPsetInfinity(set);
4614 else
4615 varlb = aggvar->glbdom.ub * scalar + constant;
4616 }
4617 varlb = MAX(varlb, var->glbdom.lb);
4618 varub = MIN(varub, var->glbdom.ub);
4619 SCIPvarAdjustLb(var, set, &varlb);
4620 SCIPvarAdjustUb(var, set, &varub);
4621
4622 /* check the new bounds */
4623 if( SCIPsetIsGT(set, varlb, varub) )
4624 {
4625 /* the aggregation is infeasible */
4626 *infeasible = TRUE;
4627 return SCIP_OKAY;
4628 }
4629 else if( SCIPsetIsEQ(set, varlb, varub) )
4630 {
4631 /* the aggregated variable is fixed -> fix both variables */
4632 SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4633 eventfilter, eventqueue, cliquetable, varlb, infeasible, fixed) );
4634 if( !(*infeasible) )
4635 {
4636 SCIP_Bool aggfixed;
4637
4638 SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4639 eventfilter, eventqueue, cliquetable, (varlb-constant)/scalar, infeasible, &aggfixed) );
4640 assert(*fixed == aggfixed);
4641 }
4642 return SCIP_OKAY;
4643 }
4644 else
4645 {
4646 if( SCIPsetIsGT(set, varlb, var->glbdom.lb) )
4647 {
4648 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, varlb) );
4649 }
4650 if( SCIPsetIsLT(set, varub, var->glbdom.ub) )
4651 {
4652 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, varub) );
4653 }
4654
4655 /* update the hole list of the aggregation variable */
4656 /**@todo update hole list of aggregation variable */
4657 }
4658
4659 /* update the bounds of the aggregation variable y in x = a*y + c -> y = (x-c)/a */
4660 if( scalar > 0.0 )
4661 {
4662 if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
4663 aggvarlb = -SCIPsetInfinity(set);
4664 else
4665 aggvarlb = (var->glbdom.lb - constant) / scalar;
4666 if( SCIPsetIsInfinity(set, var->glbdom.ub) )
4667 aggvarub = SCIPsetInfinity(set);
4668 else
4669 aggvarub = (var->glbdom.ub - constant) / scalar;
4670 }
4671 else
4672 {
4673 if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
4674 aggvarub = SCIPsetInfinity(set);
4675 else
4676 aggvarub = (var->glbdom.lb - constant) / scalar;
4677 if( SCIPsetIsInfinity(set, var->glbdom.ub) )
4678 aggvarlb = -SCIPsetInfinity(set);
4679 else
4680 aggvarlb = (var->glbdom.ub - constant) / scalar;
4681 }
4682 aggvarlb = MAX(aggvarlb, aggvar->glbdom.lb);
4683 aggvarub = MIN(aggvarub, aggvar->glbdom.ub);
4684 SCIPvarAdjustLb(aggvar, set, &aggvarlb);
4685 SCIPvarAdjustUb(aggvar, set, &aggvarub);
4686
4687 /* check the new bounds */
4688 if( SCIPsetIsGT(set, aggvarlb, aggvarub) )
4689 {
4690 /* the aggregation is infeasible */
4691 *infeasible = TRUE;
4692 return SCIP_OKAY;
4693 }
4694 else if( SCIPsetIsEQ(set, aggvarlb, aggvarub) )
4695 {
4696 /* the aggregation variable is fixed -> fix both variables */
4697 SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4698 eventfilter, eventqueue, cliquetable, aggvarlb, infeasible, fixed) );
4699 if( !(*infeasible) )
4700 {
4701 SCIP_Bool varfixed;
4702
4703 SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4704 eventfilter, eventqueue, cliquetable, aggvarlb * scalar + constant, infeasible, &varfixed) );
4705 assert(*fixed == varfixed);
4706 }
4707 return SCIP_OKAY;
4708 }
4709 else
4710 {
4711 SCIP_Real oldbd;
4712 if( SCIPsetIsGT(set, aggvarlb, aggvar->glbdom.lb) )
4713 {
4714 oldbd = aggvar->glbdom.lb;
4715 SCIP_CALL( SCIPvarChgLbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, aggvarlb) );
4716 aggvarbdschanged = !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.lb);
4717 }
4718 if( SCIPsetIsLT(set, aggvarub, aggvar->glbdom.ub) )
4719 {
4720 oldbd = aggvar->glbdom.ub;
4721 SCIP_CALL( SCIPvarChgUbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, aggvarub) );
4722 aggvarbdschanged = aggvarbdschanged || !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.ub);
4723 }
4724
4725 /* update the hole list of the aggregation variable */
4726 /**@todo update hole list of aggregation variable */
4727 }
4728 }
4729 while( aggvarbdschanged );
4730
4731 SCIPsetDebugMsg(set, " new bounds: <%s> [%g,%g] <%s> [%g,%g]\n",
4732 var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
4733
4734 return SCIP_OKAY;
4735}
4736
4737/** converts loose variable into aggregated variable */
4739 SCIP_VAR* var, /**< loose problem variable */
4740 BMS_BLKMEM* blkmem, /**< block memory */
4741 SCIP_SET* set, /**< global SCIP settings */
4742 SCIP_STAT* stat, /**< problem statistics */
4743 SCIP_PROB* transprob, /**< tranformed problem data */
4744 SCIP_PROB* origprob, /**< original problem data */
4745 SCIP_PRIMAL* primal, /**< primal data */
4746 SCIP_TREE* tree, /**< branch and bound tree */
4747 SCIP_REOPT* reopt, /**< reoptimization data structure */
4748 SCIP_LP* lp, /**< current LP data */
4749 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4750 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4751 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4752 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4753 SCIP_VAR* aggvar, /**< loose variable y in aggregation x = a*y + c */
4754 SCIP_Real scalar, /**< multiplier a in aggregation x = a*y + c */
4755 SCIP_Real constant, /**< constant shift c in aggregation x = a*y + c */
4756 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4757 SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
4758 )
4759{
4760 SCIP_VAR** vars;
4761 SCIP_Real* coefs;
4762 SCIP_Real* constants;
4763 SCIP_Real obj;
4764 SCIP_Real branchfactor;
4765 SCIP_Bool fixed;
4766 int branchpriority;
4767 int nlocksdown[NLOCKTYPES];
4768 int nlocksup[NLOCKTYPES];
4769 int nvbds;
4770 int i;
4771 int j;
4772
4773 assert(var != NULL);
4774 assert(aggvar != NULL);
4775 assert(var->scip == set->scip);
4776 assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
4777 assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
4778 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
4779 assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
4780 assert(infeasible != NULL);
4781 assert(aggregated != NULL);
4782
4783 *infeasible = FALSE;
4784 *aggregated = FALSE;
4785
4786 /* get active problem variable of aggregation variable */
4787 SCIP_CALL( SCIPvarGetProbvarSum(&aggvar, set, &scalar, &constant) );
4788
4789 /* aggregation is a fixing, if the scalar is zero */
4790 if( SCIPsetIsZero(set, scalar) )
4791 {
4792 SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventfilter,
4793 eventqueue, cliquetable, constant, infeasible, aggregated) );
4794 goto TERMINATE;
4795 }
4796
4797 /* don't perform the aggregation if the aggregation variable is multi-aggregated itself */
4799 return SCIP_OKAY;
4800
4801 /**@todo currently we don't perform the aggregation if the aggregation variable has a non-empty hole list; this
4802 * should be changed in the future
4803 */
4804 if( SCIPvarGetHolelistGlobal(var) != NULL )
4805 return SCIP_OKAY;
4806
4807 /* if the variable is not allowed to be aggregated */
4808 if( SCIPvarDoNotAggr(var) )
4809 {
4810 SCIPsetDebugMsg(set, "variable is not allowed to be aggregated.\n");
4811 return SCIP_OKAY;
4812 }
4813
4814 assert(aggvar->glbdom.lb == aggvar->locdom.lb); /*lint !e777*/
4815 assert(aggvar->glbdom.ub == aggvar->locdom.ub); /*lint !e777*/
4816 assert(SCIPvarGetStatus(aggvar) == SCIP_VARSTATUS_LOOSE);
4817
4818 SCIPsetDebugMsg(set, "aggregate variable <%s>[%g,%g] == %g*<%s>[%g,%g] %+g\n", var->name, var->glbdom.lb, var->glbdom.ub,
4819 scalar, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub, constant);
4820
4821 /* if variable and aggregation variable are equal, the variable can be fixed: x == a*x + c => x == c/(1-a) */
4822 if( var == aggvar )
4823 {
4824 if( SCIPsetIsEQ(set, scalar, 1.0) )
4825 *infeasible = !SCIPsetIsZero(set, constant);
4826 else
4827 {
4828 SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4829 eventfilter, eventqueue, cliquetable, constant/(1.0-scalar), infeasible, aggregated) );
4830 }
4831 goto TERMINATE;
4832 }
4833
4834 /* tighten the bounds of aggregated and aggregation variable */
4835 SCIP_CALL( varUpdateAggregationBounds(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
4836 branchcand, eventfilter, eventqueue, cliquetable, aggvar, scalar, constant, infeasible, &fixed) );
4837 if( *infeasible || fixed )
4838 {
4839 *aggregated = fixed;
4840 goto TERMINATE;
4841 }
4842
4843 /* delete implications and variable bounds of the aggregated variable from other variables, but keep them in the
4844 * aggregated variable
4845 */
4846 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, FALSE) );
4847
4848 /* set the aggregated variable's objective value to 0.0 */
4849 obj = var->obj;
4850 SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
4851
4852 /* unlock all locks */
4853 for( i = 0; i < NLOCKTYPES; i++ )
4854 {
4855 nlocksdown[i] = var->nlocksdown[i];
4856 nlocksup[i] = var->nlocksup[i];
4857
4858 var->nlocksdown[i] = 0;
4859 var->nlocksup[i] = 0;
4860 }
4861
4862 /* check, if variable should be used as NEGATED variable of the aggregation variable */
4863 if( SCIPvarIsBinary(var) && SCIPvarIsBinary(aggvar)
4864 && var->negatedvar == NULL && aggvar->negatedvar == NULL
4865 && SCIPsetIsEQ(set, scalar, -1.0) && SCIPsetIsEQ(set, constant, 1.0) )
4866 {
4867 /* link both variables as negation pair */
4868 var->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
4869 var->data.negate.constant = 1.0;
4870 var->negatedvar = aggvar;
4871 aggvar->negatedvar = var;
4872
4873 /* copy donot(mult)aggr status */
4874 aggvar->donotaggr |= var->donotaggr;
4875 aggvar->donotmultaggr |= var->donotmultaggr;
4876
4877 /* mark both variables to be non-deletable */
4880 }
4881 else
4882 {
4883 /* convert variable into aggregated variable */
4884 var->varstatus = SCIP_VARSTATUS_AGGREGATED; /*lint !e641*/
4885 var->data.aggregate.var = aggvar;
4886 var->data.aggregate.scalar = scalar;
4887 var->data.aggregate.constant = constant;
4888
4889 /* copy donot(mult)aggr status */
4890 aggvar->donotaggr |= var->donotaggr;
4891 aggvar->donotmultaggr |= var->donotmultaggr;
4892
4893 /* mark both variables to be non-deletable */
4896 }
4897
4898 /* make aggregated variable a parent of the aggregation variable */
4899 SCIP_CALL( varAddParent(aggvar, blkmem, set, var) );
4900
4901 /* relock the variable, thus increasing the locks of the aggregation variable */
4902 for( i = 0; i < NLOCKTYPES; i++ )
4903 {
4904 SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
4905 }
4906
4907 /* move the variable bounds to the aggregation variable:
4908 * - add all variable bounds again to the variable, thus adding it to the aggregation variable
4909 * - free the variable bounds data structures
4910 */
4911 if( var->vlbs != NULL )
4912 {
4913 nvbds = SCIPvboundsGetNVbds(var->vlbs);
4914 vars = SCIPvboundsGetVars(var->vlbs);
4915 coefs = SCIPvboundsGetCoefs(var->vlbs);
4916 constants = SCIPvboundsGetConstants(var->vlbs);
4917 for( i = 0; i < nvbds && !(*infeasible); ++i )
4918 {
4919 SCIP_CALL( SCIPvarAddVlb(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
4920 eventqueue, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
4921 }
4922 }
4923 if( var->vubs != NULL )
4924 {
4925 nvbds = SCIPvboundsGetNVbds(var->vubs);
4926 vars = SCIPvboundsGetVars(var->vubs);
4927 coefs = SCIPvboundsGetCoefs(var->vubs);
4928 constants = SCIPvboundsGetConstants(var->vubs);
4929 for( i = 0; i < nvbds && !(*infeasible); ++i )
4930 {
4931 SCIP_CALL( SCIPvarAddVub(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
4932 eventqueue, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
4933 }
4934 }
4935 SCIPvboundsFree(&var->vlbs, blkmem);
4936 SCIPvboundsFree(&var->vubs, blkmem);
4937
4938 /* move the implications to the aggregation variable:
4939 * - add all implications again to the variable, thus adding it to the aggregation variable
4940 * - free the implications data structures
4941 */
4942 if( var->implics != NULL && SCIPvarGetType(aggvar) == SCIP_VARTYPE_BINARY )
4943 {
4944 assert(SCIPvarIsBinary(var));
4945 for( i = 0; i < 2; ++i )
4946 {
4947 SCIP_VAR** implvars;
4948 SCIP_BOUNDTYPE* impltypes;
4949 SCIP_Real* implbounds;
4950 int nimpls;
4951
4952 nimpls = SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i);
4953 implvars = SCIPimplicsGetVars(var->implics, (SCIP_Bool)i);
4954 impltypes = SCIPimplicsGetTypes(var->implics, (SCIP_Bool)i);
4955 implbounds = SCIPimplicsGetBounds(var->implics, (SCIP_Bool)i);
4956
4957 for( j = 0; j < nimpls && !(*infeasible); ++j )
4958 {
4959 /* @todo can't we omit transitive closure, because it should already have been done when adding the
4960 * implication to the aggregated variable?
4961 */
4962 SCIP_CALL( SCIPvarAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
4963 branchcand, eventqueue, (SCIP_Bool)i, implvars[j], impltypes[j], implbounds[j], FALSE, infeasible,
4964 NULL) );
4965 assert(nimpls == SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i));
4966 }
4967 }
4968 }
4969 SCIPimplicsFree(&var->implics, blkmem);
4970
4971 /* add the history entries to the aggregation variable and clear the history of the aggregated variable */
4972 SCIPhistoryUnite(aggvar->history, var->history, scalar < 0.0);
4973 SCIPhistoryUnite(aggvar->historycrun, var->historycrun, scalar < 0.0);
4976
4977 /* update flags of aggregation variable */
4978 aggvar->removable &= var->removable;
4979
4980 /* update branching factors and priorities of both variables to be the maximum of both variables */
4981 branchfactor = MAX(aggvar->branchfactor, var->branchfactor);
4982 branchpriority = MAX(aggvar->branchpriority, var->branchpriority);
4983 SCIP_CALL( SCIPvarChgBranchFactor(aggvar, set, branchfactor) );
4984 SCIP_CALL( SCIPvarChgBranchPriority(aggvar, branchpriority) );
4985 SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
4986 SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
4987
4988 /* update branching direction of both variables to agree to a single direction */
4989 if( scalar >= 0.0 )
4990 {
4992 {
4994 }
4996 {
4998 }
4999 else if( var->branchdirection != aggvar->branchdirection )
5000 {
5002 }
5003 }
5004 else
5005 {
5007 {
5009 }
5011 {
5013 }
5014 else if( var->branchdirection != aggvar->branchdirection )
5015 {
5017 }
5018 }
5019
5020 if( var->probindex != -1 )
5021 {
5022 /* inform problem about the variable's status change */
5023 SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
5024 }
5025
5026 /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
5027 * variable and the problem's objective offset
5028 */
5029 SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventfilter, eventqueue, obj) );
5030
5031 /* issue VARFIXED event */
5032 SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 1) );
5033
5034 *aggregated = TRUE;
5035
5036TERMINATE:
5037 /* check aggregation on debugging solution */
5038 if( *infeasible || *aggregated )
5039 SCIP_CALL( SCIPdebugCheckAggregation(set, var, &aggvar, &scalar, constant, 1) ); /*lint !e506 !e774*/
5040
5041 return SCIP_OKAY;
5042}
5043
5044/** Tries to aggregate an equality a*x + b*y == c consisting of two (implicit) integral active problem variables x and
5045 * y. An integer aggregation (i.e. integral coefficients a' and b', such that a'*x + b'*y == c') is searched.
5046 *
5047 * This can lead to the detection of infeasibility (e.g. if c' is fractional), or to a rejection of the aggregation
5048 * (denoted by aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
5049 */
5050static
5052 SCIP_SET* set, /**< global SCIP settings */
5053 BMS_BLKMEM* blkmem, /**< block memory */
5054 SCIP_STAT* stat, /**< problem statistics */
5055 SCIP_PROB* transprob, /**< tranformed problem data */
5056 SCIP_PROB* origprob, /**< original problem data */
5057 SCIP_PRIMAL* primal, /**< primal data */
5058 SCIP_TREE* tree, /**< branch and bound tree */
5059 SCIP_REOPT* reopt, /**< reoptimization data structure */
5060 SCIP_LP* lp, /**< current LP data */
5061 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5062 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5063 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
5064 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5065 SCIP_VAR* varx, /**< integral variable x in equality a*x + b*y == c */
5066 SCIP_VAR* vary, /**< integral variable y in equality a*x + b*y == c */
5067 SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
5068 SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
5069 SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
5070 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
5071 SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
5072 )
5073{
5074 SCIP_VAR* aggvar;
5075 char aggvarname[SCIP_MAXSTRLEN];
5076 SCIP_Longint scalarxn = 0;
5077 SCIP_Longint scalarxd = 0;
5078 SCIP_Longint scalaryn = 0;
5079 SCIP_Longint scalaryd = 0;
5082 SCIP_Longint c;
5083 SCIP_Longint scm;
5084 SCIP_Longint gcd;
5085 SCIP_Longint currentclass;
5086 SCIP_Longint classstep;
5087 SCIP_Longint xsol;
5088 SCIP_Longint ysol;
5089 SCIP_Bool success;
5090 SCIP_VARTYPE vartype;
5091
5092#define MAXDNOM 1000000LL
5093
5094 assert(set != NULL);
5095 assert(blkmem != NULL);
5096 assert(stat != NULL);
5097 assert(transprob != NULL);
5098 assert(origprob != NULL);
5099 assert(tree != NULL);
5100 assert(lp != NULL);
5101 assert(cliquetable != NULL);
5102 assert(branchcand != NULL);
5103 assert(eventqueue != NULL);
5104 assert(varx != NULL);
5105 assert(vary != NULL);
5106 assert(varx != vary);
5107 assert(infeasible != NULL);
5108 assert(aggregated != NULL);
5110 assert(SCIPvarGetStatus(varx) == SCIP_VARSTATUS_LOOSE);
5112 assert(SCIPvarGetStatus(vary) == SCIP_VARSTATUS_LOOSE);
5114 assert(!SCIPsetIsZero(set, scalarx));
5115 assert(!SCIPsetIsZero(set, scalary));
5116
5117 *infeasible = FALSE;
5118 *aggregated = FALSE;
5119
5120 /* if the variable is not allowed to be aggregated */
5121 if( SCIPvarDoNotAggr(varx) )
5122 {
5123 SCIPsetDebugMsg(set, "variable is not allowed to be aggregated.\n");
5124 return SCIP_OKAY;
5125 }
5126
5127 /* get rational representation of coefficients */
5128 success = SCIPrealToRational(scalarx, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalarxn, &scalarxd);
5129 if( success )
5130 success = SCIPrealToRational(scalary, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalaryn, &scalaryd);
5131 if( !success )
5132 return SCIP_OKAY;
5133 assert(scalarxd >= 1);
5134 assert(scalaryd >= 1);
5135
5136 /* multiply equality with smallest common denominator */
5137 scm = SCIPcalcSmaComMul(scalarxd, scalaryd);
5138 a = (scm/scalarxd)*scalarxn;
5139 b = (scm/scalaryd)*scalaryn;
5140 rhs *= scm;
5141
5142 /* divide equality by the greatest common divisor of a and b */
5143 gcd = SCIPcalcGreComDiv(ABS(a), ABS(b));
5144 a /= gcd;
5145 b /= gcd;
5146 rhs /= gcd;
5147 assert(a != 0);
5148 assert(b != 0);
5149
5150 /* check, if right hand side is integral */
5151 if( !SCIPsetIsFeasIntegral(set, rhs) )
5152 {
5153 *infeasible = TRUE;
5154 return SCIP_OKAY;
5155 }
5156 c = (SCIP_Longint)(SCIPsetFeasFloor(set, rhs));
5157
5158 /* check that the scalar and constant in the aggregation are not too large to avoid numerical problems */
5159 if( REALABS((SCIP_Real)(c/a)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) /*lint !e653*/
5160 || REALABS((SCIP_Real)(b)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) /*lint !e653*/
5161 || REALABS((SCIP_Real)(a)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
5162 {
5163 return SCIP_OKAY;
5164 }
5165
5166 /* check, if we are in an easy case with either |a| = 1 or |b| = 1 */
5167 if( (a == 1 || a == -1) && SCIPvarGetType(vary) == SCIP_VARTYPE_INTEGER )
5168 {
5169 /* aggregate x = - b/a*y + c/a */
5170 /*lint --e{653}*/
5171 SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5172 branchcand, eventfilter, eventqueue, vary, (SCIP_Real)(-b/a), (SCIP_Real)(c/a), infeasible, aggregated) );
5173 assert(*aggregated);
5174 return SCIP_OKAY;
5175 }
5176 if( (b == 1 || b == -1) && SCIPvarGetType(varx) == SCIP_VARTYPE_INTEGER )
5177 {
5178 /* aggregate y = - a/b*x + c/b */
5179 /*lint --e{653}*/
5180 SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5181 branchcand, eventfilter, eventqueue, varx, (SCIP_Real)(-a/b), (SCIP_Real)(c/b), infeasible, aggregated) );
5182 assert(*aggregated);
5183 return SCIP_OKAY;
5184 }
5185
5186 /* Both variables are integers, their coefficients are not multiples of each other, and they don't have any
5187 * common divisor. Let (x',y') be a solution of the equality
5188 * a*x + b*y == c -> a*x == c - b*y
5189 * Then x = -b*z + x', y = a*z + y' with z integral gives all solutions to the equality.
5190 */
5191
5192 /* find initial solution (x',y'):
5193 * - find y' such that c - b*y' is a multiple of a
5194 * - start in equivalence class c%a
5195 * - step through classes, where each step increases class number by (-b)%a, until class 0 is visited
5196 * - if equivalence class 0 is visited, we are done: y' equals the number of steps taken
5197 * - 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
5198 * - calculate x' with x' = (c - b*y')/a (which must be integral)
5199 *
5200 * Algorithm works for a > 0 only.
5201 */
5202 if( a < 0 )
5203 {
5204 a = -a;
5205 b = -b;
5206 c = -c;
5207 }
5208 assert(a > 0);
5209
5210 /* search upwards from ysol = 0 */
5211 ysol = 0;
5212 currentclass = c % a;
5213 if( currentclass < 0 )
5214 currentclass += a;
5215 assert(0 <= currentclass && currentclass < a);
5216
5217 classstep = (-b) % a;
5218
5219 if( classstep < 0 )
5220 classstep += a;
5221 assert(0 <= classstep && classstep < a);
5222
5223 while( currentclass != 0 )
5224 {
5225 assert(0 <= currentclass && currentclass < a);
5226 currentclass += classstep;
5227 if( currentclass >= a )
5228 currentclass -= a;
5229 ysol++;
5230 }
5231 assert(ysol < a);
5232 assert(((c - b*ysol) % a) == 0);
5233
5234 xsol = (c - b*ysol)/a;
5235
5236 /* determine variable type for new artificial variable:
5237 *
5238 * if both variables are implicit integer the new variable can be implicit too, because the integer implication on
5239 * these both variables should be enforced by some other variables, otherwise the new variable needs to be of
5240 * integral type
5241 */
5244
5245 /* feasible solutions are (x,y) = (x',y') + z*(-b,a)
5246 * - create new integer variable z with infinite bounds
5247 * - aggregate variable x = -b*z + x'
5248 * - aggregate variable y = a*z + y'
5249 * - the bounds of z are calculated automatically during aggregation
5250 */
5251 (void) SCIPsnprintf(aggvarname, SCIP_MAXSTRLEN, "agg%d", stat->nvaridx);
5252 SCIP_CALL( SCIPvarCreateTransformed(&aggvar, blkmem, set, stat,
5253 aggvarname, -SCIPsetInfinity(set), SCIPsetInfinity(set), 0.0, vartype,
5255 NULL, NULL, NULL, NULL, NULL) );
5256
5257 SCIP_CALL( SCIPprobAddVar(transprob, blkmem, set, lp, branchcand, eventfilter, eventqueue, aggvar) );
5258
5259 SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5260 branchcand, eventfilter, eventqueue, aggvar, (SCIP_Real)(-b), (SCIP_Real)xsol, infeasible, aggregated) );
5261 assert(*aggregated || *infeasible);
5262
5263 if( !(*infeasible) )
5264 {
5265 SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5266 branchcand, eventfilter, eventqueue, aggvar, (SCIP_Real)a, (SCIP_Real)ysol, infeasible, aggregated) );
5267 assert(*aggregated || *infeasible);
5268 }
5269
5270 /* release z */
5271 SCIP_CALL( SCIPvarRelease(&aggvar, blkmem, set, eventqueue, lp) );
5272
5273 return SCIP_OKAY; /*lint !e438*/
5274}
5275
5276/** performs second step of SCIPaggregateVars():
5277 * the variable to be aggregated is chosen among active problem variables x' and y', preferring a less strict variable
5278 * type as aggregation variable (i.e. continuous variables are preferred over implicit integers, implicit integers
5279 * or integers over binaries). If none of the variables is continuous, it is tried to find an integer
5280 * aggregation (i.e. integral coefficients a'' and b'', such that a''*x' + b''*y' == c''). This can lead to
5281 * the detection of infeasibility (e.g. if c'' is fractional), or to a rejection of the aggregation (denoted by
5282 * aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
5283 *
5284 * @todo check for fixings, infeasibility, bound changes, or domain holes:
5285 * a) if there is no easy aggregation and we have one binary variable and another integer/implicit/binary variable
5286 * b) for implicit integer variables with fractional aggregation scalar (we cannot (for technical reasons) and do
5287 * not want to aggregate implicit integer variables, since we loose the corresponding divisibility property)
5288 */
5290 SCIP_SET* set, /**< global SCIP settings */
5291 BMS_BLKMEM* blkmem, /**< block memory */
5292 SCIP_STAT* stat, /**< problem statistics */
5293 SCIP_PROB* transprob, /**< tranformed problem data */
5294 SCIP_PROB* origprob, /**< original problem data */
5295 SCIP_PRIMAL* primal, /**< primal data */
5296 SCIP_TREE* tree, /**< branch and bound tree */
5297 SCIP_REOPT* reopt, /**< reoptimization data structure */
5298 SCIP_LP* lp, /**< current LP data */
5299 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5300 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5301 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
5302 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5303 SCIP_VAR* varx, /**< variable x in equality a*x + b*y == c */
5304 SCIP_VAR* vary, /**< variable y in equality a*x + b*y == c */
5305 SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
5306 SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
5307 SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
5308 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
5309 SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
5310 )
5311{
5312 SCIP_Bool easyaggr;
5313
5314 assert(set != NULL);
5315 assert(blkmem != NULL);
5316 assert(stat != NULL);
5317 assert(transprob != NULL);
5318 assert(origprob != NULL);
5319 assert(tree != NULL);
5320 assert(lp != NULL);
5321 assert(cliquetable != NULL);
5322 assert(branchcand != NULL);
5323 assert(eventqueue != NULL);
5324 assert(varx != NULL);
5325 assert(vary != NULL);
5326 assert(varx != vary);
5327 assert(infeasible != NULL);
5328 assert(aggregated != NULL);
5330 assert(SCIPvarGetStatus(varx) == SCIP_VARSTATUS_LOOSE);
5331 assert(SCIPvarGetStatus(vary) == SCIP_VARSTATUS_LOOSE);
5332 assert(!SCIPsetIsZero(set, scalarx));
5333 assert(!SCIPsetIsZero(set, scalary));
5334
5335 *infeasible = FALSE;
5336 *aggregated = FALSE;
5337
5338 if( SCIPsetIsZero(set, scalarx / scalary) || SCIPsetIsZero(set, scalary / scalarx) )
5339 return SCIP_OKAY;
5340
5341 /* prefer aggregating the variable of more general type (preferred aggregation variable is varx) */
5342 if( SCIPvarGetType(vary) > SCIPvarGetType(varx) ||
5343 (SCIPvarGetType(vary) == SCIPvarGetType(varx) && !SCIPvarIsBinary(vary) && SCIPvarIsBinary(varx)) )
5344 {
5345 SCIP_VAR* var;
5346 SCIP_Real scalar;
5347
5348 /* switch the variables, such that varx is the variable of more general type (cont > implint > int > bin) */
5349 var = vary;
5350 vary = varx;
5351 varx = var;
5352 scalar = scalary;
5353 scalary = scalarx;
5354 scalarx = scalar;
5355 }
5356
5357 /* don't aggregate if the aggregation would lead to a binary variable aggregated to a non-binary variable */
5358 if( SCIPvarIsBinary(varx) && !SCIPvarIsBinary(vary) )
5359 return SCIP_OKAY;
5360
5361 assert(SCIPvarGetType(varx) >= SCIPvarGetType(vary));
5362
5363 /* figure out, which variable should be aggregated */
5364 easyaggr = FALSE;
5365
5366 /* check if it is an easy aggregation */
5368 {
5369 easyaggr = TRUE;
5370 }
5371 else if( SCIPsetIsFeasIntegral(set, scalary/scalarx) )
5372 {
5373 easyaggr = TRUE;
5374 }
5375 else if( SCIPsetIsFeasIntegral(set, scalarx/scalary) && SCIPvarGetType(vary) == SCIPvarGetType(varx) )
5376 {
5377 /* we have an easy aggregation if we flip the variables x and y */
5378 SCIP_VAR* var;
5379 SCIP_Real scalar;
5380
5381 /* switch the variables, such that varx is the aggregated variable */
5382 var = vary;
5383 vary = varx;
5384 varx = var;
5385 scalar = scalary;
5386 scalary = scalarx;
5387 scalarx = scalar;
5388 easyaggr = TRUE;
5389 }
5390 else if( SCIPvarGetType(varx) == SCIP_VARTYPE_CONTINUOUS )
5391 {
5392 /* the aggregation is still easy if both variables are continuous */
5393 assert(SCIPvarGetType(vary) == SCIP_VARTYPE_CONTINUOUS); /* otherwise we are in the first case */
5394 easyaggr = TRUE;
5395 }
5396
5397 /* did we find an "easy" aggregation? */
5398 if( easyaggr )
5399 {
5400 SCIP_Real scalar;
5401 SCIP_Real constant;
5402
5403 assert(SCIPvarGetType(varx) >= SCIPvarGetType(vary));
5404
5405 /* calculate aggregation scalar and constant: a*x + b*y == c => x == -b/a * y + c/a */
5406 scalar = -scalary/scalarx;
5407 constant = rhs/scalarx;
5408
5409 if( REALABS(constant) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
5410 return SCIP_OKAY;
5411
5412 /* check aggregation for integer feasibility */
5415 && SCIPsetIsFeasIntegral(set, scalar) && !SCIPsetIsFeasIntegral(set, constant) )
5416 {
5417 *infeasible = TRUE;
5418 return SCIP_OKAY;
5419 }
5420
5421 /* if the aggregation scalar is fractional, we cannot (for technical reasons) and do not want to aggregate implicit integer variables,
5422 * since then we would loose the corresponding divisibility property
5423 */
5424 assert(SCIPvarGetType(varx) != SCIP_VARTYPE_IMPLINT || SCIPsetIsFeasIntegral(set, scalar));
5425
5426 /* aggregate the variable */
5427 SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5428 branchcand, eventfilter, eventqueue, vary, scalar, constant, infeasible, aggregated) );
5429 assert(*aggregated || *infeasible || SCIPvarDoNotAggr(varx));
5430 }
5433 {
5434 /* the variables are both integral: we have to try to find an integer aggregation */
5435 SCIP_CALL( tryAggregateIntVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5436 branchcand, eventfilter, eventqueue, varx, vary, scalarx, scalary, rhs, infeasible, aggregated) );
5437 }
5438
5439 return SCIP_OKAY;
5440}
5441
5442/** converts variable into multi-aggregated variable */
5444 SCIP_VAR* var, /**< problem variable */
5445 BMS_BLKMEM* blkmem, /**< block memory */
5446 SCIP_SET* set, /**< global SCIP settings */
5447 SCIP_STAT* stat, /**< problem statistics */
5448 SCIP_PROB* transprob, /**< tranformed problem data */
5449 SCIP_PROB* origprob, /**< original problem data */
5450 SCIP_PRIMAL* primal, /**< primal data */
5451 SCIP_TREE* tree, /**< branch and bound tree */
5452 SCIP_REOPT* reopt, /**< reoptimization data structure */
5453 SCIP_LP* lp, /**< current LP data */
5454 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5455 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5456 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
5457 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5458 int naggvars, /**< number n of variables in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5459 SCIP_VAR** aggvars, /**< variables y_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5460 SCIP_Real* scalars, /**< multipliers a_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5461 SCIP_Real constant, /**< constant shift c in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5462 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
5463 SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
5464 )
5465{
5466 SCIP_VAR** tmpvars;
5467 SCIP_Real* tmpscalars;
5468 SCIP_Real obj;
5469 SCIP_Real branchfactor;
5470 int branchpriority;
5471 SCIP_BRANCHDIR branchdirection;
5472 int nlocksdown[NLOCKTYPES];
5473 int nlocksup[NLOCKTYPES];
5474 int v;
5475 SCIP_Real tmpconstant;
5476 SCIP_Real tmpscalar;
5477 int ntmpvars;
5478 int tmpvarssize;
5479 int tmprequiredsize;
5480 int i;
5481
5482 assert(var != NULL);
5483 assert(var->scip == set->scip);
5484 assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
5485 assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
5486 assert(naggvars == 0 || aggvars != NULL);
5487 assert(naggvars == 0 || scalars != NULL);
5488 assert(infeasible != NULL);
5489 assert(aggregated != NULL);
5490
5491 SCIPsetDebugMsg(set, "trying multi-aggregating variable <%s> == ...%d vars... %+g\n", var->name, naggvars, constant);
5492
5493 *infeasible = FALSE;
5494 *aggregated = FALSE;
5495
5496 switch( SCIPvarGetStatus(var) )
5497 {
5499 if( var->data.original.transvar == NULL )
5500 {
5501 SCIPerrorMessage("cannot multi-aggregate an untransformed original variable\n");
5502 return SCIP_INVALIDDATA;
5503 }
5504 SCIP_CALL( SCIPvarMultiaggregate(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
5505 reopt, lp, cliquetable, branchcand, eventfilter, eventqueue, naggvars, aggvars, scalars, constant, infeasible, aggregated) );
5506 break;
5507
5509 assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
5510
5511 /* check if we would create a self-reference */
5512 ntmpvars = naggvars;
5513 tmpvarssize = naggvars;
5514 tmpconstant = constant;
5515 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpvars, aggvars, ntmpvars) );
5516 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpscalars, scalars, ntmpvars) );
5517
5518 /* get all active variables for multi-aggregation */
5519 SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize, FALSE) );
5520 if( tmprequiredsize > tmpvarssize )
5521 {
5522 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpvars, tmpvarssize, tmprequiredsize) );
5523 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize, tmprequiredsize) );
5524 tmpvarssize = tmprequiredsize;
5525 SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize, FALSE) );
5526 assert( tmprequiredsize <= tmpvarssize );
5527 }
5528
5529 tmpscalar = 0.0;
5530
5531 /* iterate over all active variables of the multi-aggregation and filter all variables which are equal to the
5532 * possible multi-aggregated variable
5533 */
5534 for( v = ntmpvars - 1; v >= 0; --v )
5535 {
5536 assert(tmpvars[v] != NULL);
5537 assert(SCIPvarGetStatus(tmpvars[v]) == SCIP_VARSTATUS_LOOSE);
5538
5539 if( tmpvars[v]->index == var->index )
5540 {
5541 tmpscalar += tmpscalars[v];
5542 tmpvars[v] = tmpvars[ntmpvars - 1];
5543 tmpscalars[v] = tmpscalars[ntmpvars - 1];
5544 --ntmpvars;
5545 }
5546 }
5547
5548 /* this means that x = x + a_1*y_1 + ... + a_n*y_n + c */
5549 if( SCIPsetIsEQ(set, tmpscalar, 1.0) )
5550 {
5551 if( ntmpvars == 0 )
5552 {
5553 if( SCIPsetIsZero(set, tmpconstant) ) /* x = x */
5554 {
5555 SCIPsetDebugMsg(set, "Possible multi-aggregation was completely resolved and detected to be redundant.\n");
5556 goto TERMINATE;
5557 }
5558 else /* 0 = c and c != 0 */
5559 {
5560 SCIPsetDebugMsg(set, "Multi-aggregation was completely resolved and led to infeasibility.\n");
5561 *infeasible = TRUE;
5562 goto TERMINATE;
5563 }
5564 }
5565 else if( ntmpvars == 1 ) /* 0 = a*y + c => y = -c/a */
5566 {
5567 assert(tmpscalars[0] != 0.0);
5568 assert(tmpvars[0] != NULL);
5569
5570 SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(tmpvars[0]), -constant/tmpscalars[0]);
5571 SCIP_CALL( SCIPvarFix(tmpvars[0], blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5572 branchcand, eventfilter, eventqueue, cliquetable, -constant/tmpscalars[0], infeasible, aggregated) );
5573 goto TERMINATE;
5574 }
5575 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 */
5576 {
5577 /* both variables are different active problem variables, and both scalars are non-zero: try to aggregate them */
5578 SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
5579 SCIPvarGetName(tmpvars[0]), SCIPvarGetName(tmpvars[1]), tmpscalars[0], tmpscalars[1], -tmpconstant);
5580
5581 SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
5582 cliquetable, branchcand, eventfilter, eventqueue, tmpvars[0], tmpvars[1], tmpscalars[0],
5583 tmpscalars[1], -tmpconstant, infeasible, aggregated) );
5584
5585 goto TERMINATE;
5586 }
5587 else
5588 /* @todo: it is possible to multi-aggregate another variable, does it make sense?,
5589 * rest looks like 0 = a_1*y_1 + ... + a_n*y_n + c and has at least three variables
5590 */
5591 goto TERMINATE;
5592 }
5593 /* this means that x = b*x + a_1*y_1 + ... + a_n*y_n + c */
5594 else if( !SCIPsetIsZero(set, tmpscalar) )
5595 {
5596 tmpscalar = 1 - tmpscalar;
5597 tmpconstant /= tmpscalar;
5598 for( v = ntmpvars - 1; v >= 0; --v )
5599 tmpscalars[v] /= tmpscalar;
5600 }
5601
5602 /* check, if we are in one of the simple cases */
5603 if( ntmpvars == 0 )
5604 {
5605 SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(var), tmpconstant);
5606 SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
5607 eventfilter, eventqueue, cliquetable, tmpconstant, infeasible, aggregated) );
5608 goto TERMINATE;
5609 }
5610
5611 /* if only one aggregation variable is left, we perform a normal aggregation instead of a multi-aggregation */
5612 if( ntmpvars == 1 )
5613 {
5614 SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
5615 SCIPvarGetName(var), SCIPvarGetName(tmpvars[0]), 1.0, -tmpscalars[0], tmpconstant);
5616
5617 SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
5618 cliquetable, branchcand, eventfilter, eventqueue, var, tmpvars[0], 1.0, -tmpscalars[0], tmpconstant,
5619 infeasible, aggregated) );
5620
5621 goto TERMINATE;
5622 }
5623
5624 /**@todo currently we don't perform the multi aggregation if the multi aggregation variable has a non
5625 * empty hole list; this should be changed in the future */
5626 if( SCIPvarGetHolelistGlobal(var) != NULL )
5627 goto TERMINATE;
5628
5629 /* if the variable is not allowed to be multi-aggregated */
5630 if( SCIPvarDoNotMultaggr(var) )
5631 {
5632 SCIPsetDebugMsg(set, "variable is not allowed to be multi-aggregated.\n");
5633 goto TERMINATE;
5634 }
5635
5636 /* if the variable to be multi-aggregated has implications or variable bounds (i.e. is the implied variable or
5637 * variable bound variable of another variable), we have to remove it from the other variables implications or
5638 * variable bounds
5639 */
5640 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
5641 assert(var->vlbs == NULL);
5642 assert(var->vubs == NULL);
5643 assert(var->implics == NULL);
5644
5645 /* set the aggregated variable's objective value to 0.0 */
5646 obj = var->obj;
5647 SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
5648
5649 /* since we change the variable type form loose to multi aggregated, we have to adjust the number of loose
5650 * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
5651 * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
5652 * objective of this variable is set to zero
5653 */
5655
5656 /* unlock all rounding locks */
5657 for( i = 0; i < NLOCKTYPES; i++ )
5658 {
5659 nlocksdown[i] = var->nlocksdown[i];
5660 nlocksup[i] = var->nlocksup[i];
5661
5662 var->nlocksdown[i] = 0;
5663 var->nlocksup[i] = 0;
5664 }
5665
5666 /* convert variable into multi-aggregated variable */
5667 var->varstatus = SCIP_VARSTATUS_MULTAGGR; /*lint !e641*/
5668 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.vars, tmpvars, ntmpvars) );
5669 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.scalars, tmpscalars, ntmpvars) );
5670 var->data.multaggr.constant = tmpconstant;
5671 var->data.multaggr.nvars = ntmpvars;
5672 var->data.multaggr.varssize = ntmpvars;
5673
5674 /* mark variable to be non-deletable */
5676
5677 /* relock the variable, thus increasing the locks of the aggregation variables */
5678 for( i = 0; i < NLOCKTYPES; i++ )
5679 {
5680 SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
5681 }
5682
5683 /* update flags and branching factors and priorities of aggregation variables;
5684 * update preferred branching direction of all aggregation variables that don't have a preferred direction yet
5685 */
5686 branchfactor = var->branchfactor;
5687 branchpriority = var->branchpriority;
5688 branchdirection = (SCIP_BRANCHDIR)var->branchdirection;
5689
5690 for( v = 0; v < ntmpvars; ++v )
5691 {
5692 assert(tmpvars[v] != NULL);
5693 tmpvars[v]->removable &= var->removable;
5694 branchfactor = MAX(tmpvars[v]->branchfactor, branchfactor);
5695 branchpriority = MAX(tmpvars[v]->branchpriority, branchpriority);
5696
5697 /* mark variable to be non-deletable */
5698 SCIPvarMarkNotDeletable(tmpvars[v]);
5699 }
5700 for( v = 0; v < ntmpvars; ++v )
5701 {
5702 SCIP_CALL( SCIPvarChgBranchFactor(tmpvars[v], set, branchfactor) );
5703 SCIP_CALL( SCIPvarChgBranchPriority(tmpvars[v], branchpriority) );
5704 if( (SCIP_BRANCHDIR)tmpvars[v]->branchdirection == SCIP_BRANCHDIR_AUTO )
5705 {
5706 if( tmpscalars[v] >= 0.0 )
5707 {
5708 SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], branchdirection) );
5709 }
5710 else
5711 {
5712 SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], SCIPbranchdirOpposite(branchdirection)) );
5713 }
5714 }
5715 }
5716 SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
5717 SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
5718
5719 if( var->probindex != -1 )
5720 {
5721 /* inform problem about the variable's status change */
5722 SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
5723 }
5724
5725 /* issue VARFIXED event */
5726 SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 2) );
5727
5728 /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
5729 * variables and the problem's objective offset
5730 */
5731 SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventfilter, eventqueue, obj) );
5732
5733 *aggregated = TRUE;
5734
5735 TERMINATE:
5736 BMSfreeBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize);
5737 BMSfreeBlockMemoryArray(blkmem, &tmpvars, tmpvarssize);
5738
5739 break;
5740
5742 SCIPerrorMessage("cannot multi-aggregate a column variable\n");
5743 return SCIP_INVALIDDATA;
5744
5746 SCIPerrorMessage("cannot multi-aggregate a fixed variable\n");
5747 return SCIP_INVALIDDATA;
5748
5750 SCIPerrorMessage("cannot multi-aggregate an aggregated variable\n");
5751 return SCIP_INVALIDDATA;
5752
5754 SCIPerrorMessage("cannot multi-aggregate a multiple aggregated variable again\n");
5755 return SCIP_INVALIDDATA;
5756
5758 /* aggregate negation variable x in x' = offset - x, instead of aggregating x' directly:
5759 * x' = a_1*y_1 + ... + a_n*y_n + c -> x = offset - x' = offset - a_1*y_1 - ... - a_n*y_n - c
5760 */
5761 assert(SCIPsetIsZero(set, var->obj));
5762 assert(var->negatedvar != NULL);
5764 assert(var->negatedvar->negatedvar == var);
5765
5766 /* switch the signs of the aggregation scalars */
5767 for( v = 0; v < naggvars; ++v )
5768 scalars[v] *= -1.0;
5769
5770 /* perform the multi aggregation on the negation variable */
5771 SCIP_CALL( SCIPvarMultiaggregate(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5772 cliquetable, branchcand, eventfilter, eventqueue, naggvars, aggvars, scalars,
5773 var->data.negate.constant - constant, infeasible, aggregated) );
5774
5775 /* switch the signs of the aggregation scalars again, to reset them to their original values */
5776 for( v = 0; v < naggvars; ++v )
5777 scalars[v] *= -1.0;
5778 break;
5779
5780 default:
5781 SCIPerrorMessage("unknown variable status\n");
5782 return SCIP_INVALIDDATA;
5783 }
5784
5785 /* check multi-aggregation on debugging solution */
5786 if( *infeasible || *aggregated )
5787 SCIP_CALL( SCIPdebugCheckAggregation(set, var, aggvars, scalars, constant, naggvars) ); /*lint !e506 !e774*/
5788
5789 return SCIP_OKAY;
5790}
5791
5792/** transformed variables are resolved to their active, fixed, or multi-aggregated problem variable of a variable,
5793 * or for original variables the same variable is returned
5794 */
5795static
5797 SCIP_VAR* var /**< problem variable */
5798 )
5799{
5800 SCIP_VAR* retvar;
5801
5802 assert(var != NULL);
5803
5804 retvar = var;
5805
5806 SCIPdebugMessage("get active variable of <%s>\n", var->name);
5807
5808 while( TRUE ) /*lint !e716 */
5809 {
5810 assert(retvar != NULL);
5811
5812 switch( SCIPvarGetStatus(retvar) )
5813 {
5818 return retvar;
5819
5821 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
5822 if ( retvar->data.multaggr.nvars == 1 )
5823 retvar = retvar->data.multaggr.vars[0];
5824 else
5825 return retvar;
5826 break;
5827
5829 retvar = retvar->data.aggregate.var;
5830 break;
5831
5833 retvar = retvar->negatedvar;
5834 break;
5835
5836 default:
5837 SCIPerrorMessage("unknown variable status\n");
5838 SCIPABORT();
5839 return NULL; /*lint !e527*/
5840 }
5841 }
5842}
5843
5844/** returns whether variable is not allowed to be aggregated */
5846 SCIP_VAR* var /**< problem variable */
5847 )
5848{
5849 SCIP_VAR* retvar;
5850
5851 assert(var != NULL);
5852
5853 retvar = varGetActiveVar(var);
5854 assert(retvar != NULL);
5855
5856 switch( SCIPvarGetStatus(retvar) )
5857 {
5862 return retvar->donotaggr;
5863
5865 return FALSE;
5866
5869 default:
5870 /* aggregated and negated variables should be resolved by varGetActiveVar() */
5871 SCIPerrorMessage("wrong variable status\n");
5872 SCIPABORT();
5873 return FALSE; /*lint !e527 */
5874 }
5875}
5876
5877/** returns whether variable is not allowed to be multi-aggregated */
5879 SCIP_VAR* var /**< problem variable */
5880 )
5881{
5882 SCIP_VAR* retvar;
5883
5884 assert(var != NULL);
5885
5886 retvar = varGetActiveVar(var);
5887 assert(retvar != NULL);
5888
5889 switch( SCIPvarGetStatus(retvar) )
5890 {
5895 return retvar->donotmultaggr;
5896
5898 return FALSE;
5899
5902 default:
5903 /* aggregated and negated variables should be resolved by varGetActiveVar() */
5904 SCIPerrorMessage("wrong variable status\n");
5905 SCIPABORT();
5906 return FALSE; /*lint !e527 */
5907 }
5908}
5909
5910/** gets negated variable x' = offset - x of problem variable x; the negated variable is created if not yet existing;
5911 * the negation offset of binary variables is always 1, the offset of other variables is fixed to lb + ub when the
5912 * negated variable is created
5913 */
5915 SCIP_VAR* var, /**< problem variable to negate */
5916 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
5917 SCIP_SET* set, /**< global SCIP settings */
5918 SCIP_STAT* stat, /**< problem statistics */
5919 SCIP_VAR** negvar /**< pointer to store the negated variable */
5920 )
5921{
5922 assert(var != NULL);
5923 assert(var->scip == set->scip);
5924 assert(negvar != NULL);
5925
5926 /* check, if we already created the negated variable */
5927 if( var->negatedvar == NULL )
5928 {
5929 char negvarname[SCIP_MAXSTRLEN];
5930
5932
5933 SCIPsetDebugMsg(set, "creating negated variable of <%s>\n", var->name);
5934
5935 /* negation is only possible for bounded variables */
5937 {
5938 SCIPerrorMessage("cannot negate unbounded variable\n");
5939 return SCIP_INVALIDDATA;
5940 }
5941
5942 (void) SCIPsnprintf(negvarname, SCIP_MAXSTRLEN, "%s_neg", var->name);
5943
5944 /* create negated variable */
5945 SCIP_CALL( varCreate(negvar, blkmem, set, stat, negvarname, var->glbdom.lb, var->glbdom.ub, 0.0,
5946 SCIPvarGetType(var), var->initial, var->removable, NULL, NULL, NULL, NULL, NULL) );
5947 (*negvar)->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
5948 if( SCIPvarIsBinary(var) )
5949 (*negvar)->data.negate.constant = 1.0;
5950 else
5951 (*negvar)->data.negate.constant = var->glbdom.lb + var->glbdom.ub;
5952
5953 /* create event filter for transformed variable */
5954 if( SCIPvarIsTransformed(var) )
5955 {
5956 SCIP_CALL( SCIPeventfilterCreate(&(*negvar)->eventfilter, blkmem) );
5957 }
5958
5959 /* set the bounds corresponding to the negation variable */
5960 (*negvar)->glbdom.lb = (*negvar)->data.negate.constant - var->glbdom.ub;
5961 (*negvar)->glbdom.ub = (*negvar)->data.negate.constant - var->glbdom.lb;
5962 (*negvar)->locdom.lb = (*negvar)->data.negate.constant - var->locdom.ub;
5963 (*negvar)->locdom.ub = (*negvar)->data.negate.constant - var->locdom.lb;
5964 /**@todo create holes in the negated variable corresponding to the holes of the negation variable */
5965
5966 /* link the variables together */
5967 var->negatedvar = *negvar;
5968 (*negvar)->negatedvar = var;
5969
5970 /* mark both variables to be non-deletable */
5972 SCIPvarMarkNotDeletable(*negvar);
5973
5974 /* copy the branch factor and priority, and use the negative preferred branching direction */
5975 (*negvar)->branchfactor = var->branchfactor;
5976 (*negvar)->branchpriority = var->branchpriority;
5977 (*negvar)->branchdirection = SCIPbranchdirOpposite((SCIP_BRANCHDIR)var->branchdirection); /*lint !e641*/
5978
5979 /* copy donot(mult)aggr status */
5980 (*negvar)->donotaggr = var->donotaggr;
5981 (*negvar)->donotmultaggr = var->donotmultaggr;
5982
5983 /* copy lazy bounds (they have to be flipped) */
5984 (*negvar)->lazylb = (*negvar)->data.negate.constant - var->lazyub;
5985 (*negvar)->lazyub = (*negvar)->data.negate.constant - var->lazylb;
5986
5987 /* make negated variable a parent of the negation variable (negated variable is captured as a parent) */
5988 SCIP_CALL( varAddParent(var, blkmem, set, *negvar) );
5989 assert((*negvar)->nuses == 1);
5990 }
5991 assert(var->negatedvar != NULL);
5992
5993 /* return the negated variable */
5994 *negvar = var->negatedvar;
5995
5996 /* exactly one variable of the negation pair has to be marked as negated variable */
5998
5999 return SCIP_OKAY;
6000}
6001
6002/** informs variable that its position in problem's vars array changed */
6003static
6005 SCIP_VAR* var, /**< problem variable */
6006 int probindex /**< new problem index of variable (-1 for removal) */
6007 )
6008{
6009 assert(var != NULL);
6010 assert(probindex >= 0 || var->vlbs == NULL);
6011 assert(probindex >= 0 || var->vubs == NULL);
6012 assert(probindex >= 0 || var->implics == NULL);
6013
6014 var->probindex = probindex;
6016 {
6017 assert(var->data.col != NULL);
6018 var->data.col->var_probindex = probindex;
6019 }
6020}
6021
6022/** informs variable that its position in problem's vars array changed */
6024 SCIP_VAR* var, /**< problem variable */
6025 int probindex /**< new problem index of variable */
6026 )
6027{
6028 assert(var != NULL);
6029 assert(probindex >= 0);
6030
6031 varSetProbindex(var, probindex);
6032}
6033
6034/** gives the variable a new name
6035 *
6036 * @note the old pointer is overwritten, which might result in a memory leakage
6037 */
6039 SCIP_VAR* var, /**< problem variable */
6040 const char* name /**< new name of variable */
6041 )
6042{
6043 assert(var != NULL);
6044 assert(name != NULL);
6045
6046 var->name = (char*)name;
6047}
6048
6049/** informs variable that it will be removed from the problem; adjusts probindex and removes variable from the
6050 * implication graph;
6051 * If 'final' is TRUE, the thorough implication graph removal is not performed. Instead, only the
6052 * variable bounds and implication data structures of the variable are freed. Since in the final removal
6053 * of all variables from the transformed problem, this deletes the implication graph completely and is faster
6054 * than removing the variables one by one, each time updating all lists of the other variables.
6055 */
6057 SCIP_VAR* var, /**< problem variable */
6058 BMS_BLKMEM* blkmem, /**< block memory buffer */
6059 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6060 SCIP_SET* set, /**< global SCIP settings */
6061 SCIP_Bool final /**< is this the final removal of all problem variables? */
6062 )
6063{
6064 assert(SCIPvarGetProbindex(var) >= 0);
6065 assert(var->scip == set->scip);
6066
6067 /* if the variable is active in the transformed problem, remove it from the implication graph */
6068 if( SCIPvarIsTransformed(var)
6070 {
6071 if( final )
6072 {
6073 /* just destroy the data structures */
6074 SCIPvboundsFree(&var->vlbs, blkmem);
6075 SCIPvboundsFree(&var->vubs, blkmem);
6076 SCIPimplicsFree(&var->implics, blkmem);
6077 }
6078 else
6079 {
6080 /* unlink the variable from all other variables' lists and free the data structures */
6081 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
6082 }
6083 }
6084
6085 /* mark the variable to be no longer a member of the problem */
6086 varSetProbindex(var, -1);
6087
6088 return SCIP_OKAY;
6089}
6090
6091/** marks the variable to be deleted from the problem */
6093 SCIP_VAR* var /**< problem variable */
6094 )
6095{
6096 assert(var != NULL);
6097 assert(var->probindex != -1);
6098
6099 var->deleted = TRUE;
6100}
6101
6102/** marks the variable to not to be aggregated */
6104 SCIP_VAR* var /**< problem variable */
6105 )
6106{
6107 SCIP_VAR* retvar;
6108
6109 assert(var != NULL);
6110
6111 retvar = varGetActiveVar(var);
6112 assert(retvar != NULL);
6113
6114 switch( SCIPvarGetStatus(retvar) )
6115 {
6120 retvar->donotaggr = TRUE;
6121 break;
6122
6124 SCIPerrorMessage("cannot mark a multi-aggregated variable to not be aggregated.\n");
6125 return SCIP_INVALIDDATA;
6126
6129 default:
6130 /* aggregated and negated variables should be resolved by varGetActiveVar() */
6131 SCIPerrorMessage("wrong variable status\n");
6132 return SCIP_INVALIDDATA;
6133 }
6134
6135 return SCIP_OKAY;
6136}
6137
6138/** marks the variable to not to be multi-aggregated */
6140 SCIP_VAR* var /**< problem variable */
6141 )
6142{
6143 SCIP_VAR* retvar;
6144
6145 assert(var != NULL);
6146
6147 retvar = varGetActiveVar(var);
6148 assert(retvar != NULL);
6149
6150 switch( SCIPvarGetStatus(retvar) )
6151 {
6156 retvar->donotmultaggr = TRUE;
6157 break;
6158
6160 SCIPerrorMessage("cannot mark a multi-aggregated variable to not be multi-aggregated.\n");
6161 return SCIP_INVALIDDATA;
6162
6165 default:
6166 /* aggregated and negated variables should be resolved by varGetActiveVar() */
6167 SCIPerrorMessage("wrong variable status\n");
6168 return SCIP_INVALIDDATA;
6169 }
6170
6171 return SCIP_OKAY;
6172}
6173
6174/** changes type of variable; cannot be called, if var belongs to a problem */
6176 SCIP_VAR* var, /**< problem variable to change */
6177 BMS_BLKMEM* blkmem, /**< block memory */
6178 SCIP_SET* set, /**< global SCIP settings */
6179 SCIP_PRIMAL* primal, /**< primal data */
6180 SCIP_LP* lp, /**< current LP data */
6181 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6182 SCIP_VARTYPE vartype /**< new type of variable */
6183 )
6184{
6185 SCIP_EVENT* event;
6186 SCIP_VARTYPE oldtype;
6187
6188 assert(var != NULL);
6189
6190 SCIPdebugMessage("change type of <%s> from %d to %d\n", var->name, SCIPvarGetType(var), vartype);
6191
6192 if( var->probindex >= 0 )
6193 {
6194 SCIPerrorMessage("cannot change type of variable already in the problem\n");
6195 return SCIP_INVALIDDATA;
6196 }
6197
6198 oldtype = (SCIP_VARTYPE)var->vartype;
6199 var->vartype = vartype; /*lint !e641*/
6200
6202 {
6203 SCIP_CALL( SCIPeventCreateTypeChanged(&event, blkmem, var, oldtype, vartype) );
6204 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
6205 }
6206
6207 if( var->negatedvar != NULL )
6208 {
6209 assert(oldtype == (SCIP_VARTYPE)var->negatedvar->vartype
6210 || SCIPvarIsBinary(var) == SCIPvarIsBinary(var->negatedvar));
6211
6212 var->negatedvar->vartype = vartype; /*lint !e641*/
6213
6215 {
6216 SCIP_CALL( SCIPeventCreateTypeChanged(&event, blkmem, var->negatedvar, oldtype, vartype) );
6217 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
6218 }
6219 }
6220
6221 return SCIP_OKAY;
6222}
6223
6224/** appends OBJCHANGED event to the event queue */
6225static
6227 SCIP_VAR* var, /**< problem variable to change */
6228 BMS_BLKMEM* blkmem, /**< block memory */
6229 SCIP_SET* set, /**< global SCIP settings */
6230 SCIP_PRIMAL* primal, /**< primal data */
6231 SCIP_LP* lp, /**< current LP data */
6232 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6233 SCIP_Real oldobj, /**< old objective value for variable */
6234 SCIP_Real newobj /**< new objective value for variable */
6235 )
6236{
6237 SCIP_EVENT* event;
6238
6239 assert(var != NULL);
6240 assert(var->scip == set->scip);
6241 assert(var->eventfilter != NULL);
6243 assert(SCIPvarIsTransformed(var));
6244
6245 /* In the case where the objcetive value of a variable is very close to epsilon, and it is aggregated
6246 * into a variable with a big objective value, round-off errors might make the assert oldobj != newobj fail.
6247 * Hence, we relax it by letting it pass if the variables are percieved the same and we use very large values
6248 * that make comparison with values close to epsilon inaccurate.
6249 */
6250 assert(!SCIPsetIsEQ(set, oldobj, newobj) ||
6251 (SCIPsetIsEQ(set, oldobj, newobj) && REALABS(newobj) > 1e+15 * SCIPsetEpsilon(set))
6252 );
6253
6254 SCIP_CALL( SCIPeventCreateObjChanged(&event, blkmem, var, oldobj, newobj) );
6255 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
6256
6257 return SCIP_OKAY;
6258}
6259
6260/** changes objective value of variable */
6262 SCIP_VAR* var, /**< variable to change */
6263 BMS_BLKMEM* blkmem, /**< block memory */
6264 SCIP_SET* set, /**< global SCIP settings */
6265 SCIP_PROB* prob, /**< problem data */
6266 SCIP_PRIMAL* primal, /**< primal data */
6267 SCIP_LP* lp, /**< current LP data */
6268 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6269 SCIP_Real newobj /**< new objective value for variable */
6270 )
6271{
6272 SCIP_Real oldobj;
6273
6274 assert(var != NULL);
6275 assert(set != NULL);
6276 assert(var->scip == set->scip);
6277
6278 SCIPsetDebugMsg(set, "changing objective value of <%s> from %g to %g\n", var->name, var->obj, newobj);
6279
6280 if( !SCIPsetIsEQ(set, var->obj, newobj) )
6281 {
6282 switch( SCIPvarGetStatus(var) )
6283 {
6285 if( var->data.original.transvar != NULL )
6286 {
6287 assert(SCIPprobIsTransformed(prob));
6288
6289 SCIP_CALL( SCIPvarChgObj(var->data.original.transvar, blkmem, set, prob, primal, lp, eventqueue,
6290 (SCIP_Real) prob->objsense * newobj/prob->objscale) );
6291 }
6292 else
6293 assert(set->stage == SCIP_STAGE_PROBLEM);
6294
6295 var->obj = newobj;
6296 var->unchangedobj = newobj;
6297
6298 break;
6299
6302 oldobj = var->obj;
6303 var->obj = newobj;
6304
6305 /* update unchanged objective value of variable */
6306 if( !lp->divingobjchg )
6307 var->unchangedobj = newobj;
6308
6309 /* update the number of variables with non-zero objective coefficient;
6310 * we only want to do the update, if the variable is added to the problem;
6311 * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
6312 */
6313 if( SCIPvarIsActive(var) )
6314 SCIPprobUpdateNObjVars(prob, set, oldobj, var->obj);
6315
6316 SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
6317 break;
6318
6323 SCIPerrorMessage("cannot change objective value of a fixed, aggregated, multi-aggregated, or negated variable\n");
6324 return SCIP_INVALIDDATA;
6325
6326 default:
6327 SCIPerrorMessage("unknown variable status\n");
6328 return SCIP_INVALIDDATA;
6329 }
6330 }
6331
6332 return SCIP_OKAY;
6333}
6334
6335/** adds value to objective value of variable */
6337 SCIP_VAR* var, /**< variable to change */
6338 BMS_BLKMEM* blkmem, /**< block memory */
6339 SCIP_SET* set, /**< global SCIP settings */
6340 SCIP_STAT* stat, /**< problem statistics */
6341 SCIP_PROB* transprob, /**< transformed problem data */
6342 SCIP_PROB* origprob, /**< original problem data */
6343 SCIP_PRIMAL* primal, /**< primal data */
6344 SCIP_TREE* tree, /**< branch and bound tree */
6345 SCIP_REOPT* reopt, /**< reoptimization data structure */
6346 SCIP_LP* lp, /**< current LP data */
6347 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
6348 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6349 SCIP_Real addobj /**< additional objective value for variable */
6350 )
6351{
6352 assert(var != NULL);
6353 assert(set != NULL);
6354 assert(var->scip == set->scip);
6355 assert(set->stage < SCIP_STAGE_INITSOLVE);
6356
6357 SCIPsetDebugMsg(set, "adding %g to objective value %g of <%s>\n", addobj, var->obj, var->name);
6358
6359 if( !SCIPsetIsZero(set, addobj) )
6360 {
6361 SCIP_Real oldobj;
6362 int i;
6363
6364 switch( SCIPvarGetStatus(var) )
6365 {
6367 if( var->data.original.transvar != NULL )
6368 {
6369 SCIP_CALL( SCIPvarAddObj(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
6370 reopt, lp, eventfilter, eventqueue, (SCIP_Real) transprob->objsense * addobj/transprob->objscale) );
6371 }
6372 else
6373 assert(set->stage == SCIP_STAGE_PROBLEM);
6374
6375 var->obj += addobj;
6376 var->unchangedobj += addobj;
6377 assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
6378
6379 break;
6380
6383 oldobj = var->obj;
6384 var->obj += addobj;
6385
6386 /* update unchanged objective value of variable */
6387 if( !lp->divingobjchg )
6388 {
6389 var->unchangedobj += addobj;
6390 assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
6391 }
6392
6393 /* update the number of variables with non-zero objective coefficient;
6394 * we only want to do the update, if the variable is added to the problem;
6395 * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
6396 */
6397 if( SCIPvarIsActive(var) )
6398 SCIPprobUpdateNObjVars(transprob, set, oldobj, var->obj);
6399
6400 SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
6401 break;
6402
6404 assert(SCIPsetIsEQ(set, var->locdom.lb, var->locdom.ub));
6405 SCIPprobAddObjoffset(transprob, var->locdom.lb * addobj);
6406 SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6407 break;
6408
6410 assert(!var->donotaggr);
6411 /* x = a*y + c -> add a*addobj to obj. val. of y, and c*addobj to obj. offset of problem */
6412 SCIPprobAddObjoffset(transprob, var->data.aggregate.constant * addobj);
6413 SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6414 SCIP_CALL( SCIPvarAddObj(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
6415 lp, eventfilter, eventqueue, var->data.aggregate.scalar * addobj) );
6416 break;
6417
6419 assert(!var->donotmultaggr);
6420 /* 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 */
6421 SCIPprobAddObjoffset(transprob, var->data.multaggr.constant * addobj);
6422 SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6423 for( i = 0; i < var->data.multaggr.nvars; ++i )
6424 {
6425 SCIP_CALL( SCIPvarAddObj(var->data.multaggr.vars[i], blkmem, set, stat, transprob, origprob, primal, tree,
6426 reopt, lp, eventfilter, eventqueue, var->data.multaggr.scalars[i] * addobj) );
6427 }
6428 break;
6429
6431 /* x' = offset - x -> add -addobj to obj. val. of x and offset*addobj to obj. offset of problem */
6432 assert(var->negatedvar != NULL);
6434 assert(var->negatedvar->negatedvar == var);
6435 SCIPprobAddObjoffset(transprob, var->data.negate.constant * addobj);
6436 SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6437 SCIP_CALL( SCIPvarAddObj(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
6438 eventfilter, eventqueue, -addobj) );
6439 break;
6440
6441 default:
6442 SCIPerrorMessage("unknown variable status\n");
6443 return SCIP_INVALIDDATA;
6444 }
6445 }
6446
6447 return SCIP_OKAY;
6448}
6449
6450/** changes objective value of variable in current dive */
6452 SCIP_VAR* var, /**< problem variable to change */
6453 SCIP_SET* set, /**< global SCIP settings */
6454 SCIP_LP* lp, /**< current LP data */
6455 SCIP_Real newobj /**< new objective value for variable */
6456 )
6457{
6458 assert(var != NULL);
6459 assert(set != NULL);
6460 assert(var->scip == set->scip);
6461 assert(lp != NULL);
6462
6463 SCIPsetDebugMsg(set, "changing objective of <%s> to %g in current dive\n", var->name, newobj);
6464
6465 if( SCIPsetIsZero(set, newobj) )
6466 newobj = 0.0;
6467
6468 /* change objective value of attached variables */
6469 switch( SCIPvarGetStatus(var) )
6470 {
6472 assert(var->data.original.transvar != NULL);
6473 SCIP_CALL( SCIPvarChgObjDive(var->data.original.transvar, set, lp, newobj) );
6474 break;
6475
6477 assert(var->data.col != NULL);
6478 SCIP_CALL( SCIPcolChgObj(var->data.col, set, lp, newobj) );
6479 break;
6480
6483 /* nothing to do here: only the constant shift in objective function would change */
6484 break;
6485
6486 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6487 assert(var->data.aggregate.var != NULL);
6488 assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
6489 SCIP_CALL( SCIPvarChgObjDive(var->data.aggregate.var, set, lp, newobj / var->data.aggregate.scalar) );
6490 /* the constant can be ignored, because it would only affect the objective shift */
6491 break;
6492
6494 SCIPerrorMessage("cannot change diving objective value of a multi-aggregated variable\n");
6495 return SCIP_INVALIDDATA;
6496
6497 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6498 assert(var->negatedvar != NULL);
6500 assert(var->negatedvar->negatedvar == var);
6501 SCIP_CALL( SCIPvarChgObjDive(var->negatedvar, set, lp, -newobj) );
6502 /* the offset can be ignored, because it would only affect the objective shift */
6503 break;
6504
6505 default:
6506 SCIPerrorMessage("unknown variable status\n");
6507 return SCIP_INVALIDDATA;
6508 }
6509
6510 return SCIP_OKAY;
6511}
6512
6513/** adjust lower bound to integral value, if variable is integral */
6515 SCIP_VAR* var, /**< problem variable */
6516 SCIP_SET* set, /**< global SCIP settings */
6517 SCIP_Real* lb /**< pointer to lower bound to adjust */
6518 )
6519{
6520 assert(var != NULL);
6521 assert(set != NULL);
6522 assert(var->scip == set->scip);
6523 assert(lb != NULL);
6524
6525 SCIPsetDebugMsg(set, "adjust lower bound %g of <%s>\n", *lb, var->name);
6526
6527 *lb = adjustedLb(set, SCIPvarGetType(var), *lb);
6528}
6529
6530/** adjust upper bound to integral value, if variable is integral */
6532 SCIP_VAR* var, /**< problem variable */
6533 SCIP_SET* set, /**< global SCIP settings */
6534 SCIP_Real* ub /**< pointer to upper bound to adjust */
6535 )
6536{
6537 assert(var != NULL);
6538 assert(set != NULL);
6539 assert(var->scip == set->scip);
6540 assert(ub != NULL);
6541
6542 SCIPsetDebugMsg(set, "adjust upper bound %g of <%s>\n", *ub, var->name);
6543
6544 *ub = adjustedUb(set, SCIPvarGetType(var), *ub);
6545}
6546
6547/** adjust lower or upper bound to integral value, if variable is integral */
6549 SCIP_VAR* var, /**< problem variable */
6550 SCIP_SET* set, /**< global SCIP settings */
6551 SCIP_BOUNDTYPE boundtype, /**< type of bound to adjust */
6552 SCIP_Real* bd /**< pointer to bound to adjust */
6553 )
6554{
6555 assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
6556
6557 if( boundtype == SCIP_BOUNDTYPE_LOWER )
6558 SCIPvarAdjustLb(var, set, bd);
6559 else
6560 SCIPvarAdjustUb(var, set, bd);
6561}
6562
6563/** changes lower bound of original variable in original problem */
6565 SCIP_VAR* var, /**< problem variable to change */
6566 SCIP_SET* set, /**< global SCIP settings */
6567 SCIP_Real newbound /**< new bound for variable */
6568 )
6569{
6570 int i;
6571
6572 assert(var != NULL);
6573 assert(!SCIPvarIsTransformed(var));
6575 assert(set != NULL);
6576 assert(var->scip == set->scip);
6577 assert(set->stage == SCIP_STAGE_PROBLEM);
6578
6579 /* check that the bound is feasible */
6581 /* adjust bound to integral value if variable is of integral type */
6582 newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6583
6584 if( SCIPsetIsZero(set, newbound) )
6585 newbound = 0.0;
6586
6587 /* original domains are only stored for ORIGINAL variables, not for NEGATED */
6589 {
6590 SCIPsetDebugMsg(set, "changing original lower bound of <%s> from %g to %g\n",
6591 var->name, var->data.original.origdom.lb, newbound);
6592
6593 if( SCIPsetIsEQ(set, var->data.original.origdom.lb, newbound) )
6594 return SCIP_OKAY;
6595
6596 /* change the bound */
6597 var->data.original.origdom.lb = newbound;
6598 }
6599 else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
6600 {
6601 assert( var->negatedvar != NULL );
6602 SCIP_CALL( SCIPvarChgUbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
6603 }
6604
6605 /* process parent variables */
6606 for( i = 0; i < var->nparentvars; ++i )
6607 {
6608 SCIP_VAR* parentvar;
6609
6610 parentvar = var->parentvars[i];
6611 assert(parentvar != NULL);
6612 assert(SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_NEGATED);
6613 assert(parentvar->negatedvar == var);
6614 assert(var->negatedvar == parentvar);
6615
6616 SCIP_CALL( SCIPvarChgUbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
6617 }
6618
6619 return SCIP_OKAY;
6620}
6621
6622/** changes upper bound of original variable in original problem */
6624 SCIP_VAR* var, /**< problem variable to change */
6625 SCIP_SET* set, /**< global SCIP settings */
6626 SCIP_Real newbound /**< new bound for variable */
6627 )
6628{
6629 int i;
6630
6631 assert(var != NULL);
6632 assert(!SCIPvarIsTransformed(var));
6634 assert(set != NULL);
6635 assert(var->scip == set->scip);
6636 assert(set->stage == SCIP_STAGE_PROBLEM);
6637
6638 /* check that the bound is feasible */
6640 /* adjust bound to integral value if variable is of integral type */
6641 newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
6642
6643 if( SCIPsetIsZero(set, newbound) )
6644 newbound = 0.0;
6645
6646 /* original domains are only stored for ORIGINAL variables, not for NEGATED */
6648 {
6649 SCIPsetDebugMsg(set, "changing original upper bound of <%s> from %g to %g\n",
6650 var->name, var->data.original.origdom.ub, newbound);
6651
6652 if( SCIPsetIsEQ(set, var->data.original.origdom.ub, newbound) )
6653 return SCIP_OKAY;
6654
6655 /* change the bound */
6656 var->data.original.origdom.ub = newbound;
6657 }
6658 else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
6659 {
6660 assert( var->negatedvar != NULL );
6661 SCIP_CALL( SCIPvarChgLbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
6662 }
6663
6664 /* process parent variables */
6665 for( i = 0; i < var->nparentvars; ++i )
6666 {
6667 SCIP_VAR* parentvar;
6668
6669 parentvar = var->parentvars[i];
6670 assert(parentvar != NULL);
6671 assert(SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_NEGATED);
6672 assert(parentvar->negatedvar == var);
6673 assert(var->negatedvar == parentvar);
6674
6675 SCIP_CALL( SCIPvarChgLbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
6676 }
6677
6678 return SCIP_OKAY;
6679}
6680
6681/** appends GLBCHANGED event to the event queue */
6682static
6684 SCIP_VAR* var, /**< problem variable to change */
6685 BMS_BLKMEM* blkmem, /**< block memory */
6686 SCIP_SET* set, /**< global SCIP settings */
6687 SCIP_LP* lp, /**< current LP data */
6688 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6689 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6690 SCIP_Real oldbound, /**< old lower bound for variable */
6691 SCIP_Real newbound /**< new lower bound for variable */
6692 )
6693{
6694 assert(var != NULL);
6695 assert(var->eventfilter != NULL);
6696 assert(SCIPvarIsTransformed(var));
6697 assert(!SCIPsetIsEQ(set, oldbound, newbound) || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
6698 assert(set != NULL);
6699 assert(var->scip == set->scip);
6700
6701 /* check, if the variable is being tracked for bound changes
6702 * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
6703 */
6704 if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GLBCHANGED) != 0)
6707 {
6708 SCIP_EVENT* event;
6709
6710 SCIPsetDebugMsg(set, "issue GLBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
6711
6712 SCIP_CALL( SCIPeventCreateGlbChanged(&event, blkmem, var, oldbound, newbound) );
6713 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
6714 }
6715
6716 return SCIP_OKAY;
6717}
6718
6719/** appends GUBCHANGED event to the event queue */
6720static
6722 SCIP_VAR* var, /**< problem variable to change */
6723 BMS_BLKMEM* blkmem, /**< block memory */
6724 SCIP_SET* set, /**< global SCIP settings */
6725 SCIP_LP* lp, /**< current LP data */
6726 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6727 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6728 SCIP_Real oldbound, /**< old lower bound for variable */
6729 SCIP_Real newbound /**< new lower bound for variable */
6730 )
6731{
6732 assert(var != NULL);
6733 assert(var->eventfilter != NULL);
6734 assert(SCIPvarIsTransformed(var));
6735 assert(!SCIPsetIsEQ(set, oldbound, newbound) || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
6736 assert(set != NULL);
6737 assert(var->scip == set->scip);
6738
6739 /* check, if the variable is being tracked for bound changes
6740 * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
6741 */
6742 if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GUBCHANGED) != 0)
6745 {
6746 SCIP_EVENT* event;
6747
6748 SCIPsetDebugMsg(set, "issue GUBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
6749
6750 SCIP_CALL( SCIPeventCreateGubChanged(&event, blkmem, var, oldbound, newbound) );
6751 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
6752 }
6753
6754 return SCIP_OKAY;
6755}
6756
6757/** appends GHOLEADDED event to the event queue */
6758static
6760 SCIP_VAR* var, /**< problem variable to change */
6761 BMS_BLKMEM* blkmem, /**< block memory */
6762 SCIP_SET* set, /**< global SCIP settings */
6763 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6764 SCIP_Real left, /**< left bound of open interval in new hole */
6765 SCIP_Real right /**< right bound of open interval in new hole */
6766 )
6767{
6768 assert(var != NULL);
6769 assert(var->eventfilter != NULL);
6770 assert(SCIPvarIsTransformed(var));
6771 assert(set != NULL);
6772 assert(var->scip == set->scip);
6773 assert(SCIPsetIsLT(set, left, right));
6774
6775 /* check, if the variable is being tracked for bound changes */
6776 if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GHOLEADDED) != 0) )
6777 {
6778 SCIP_EVENT* event;
6779
6780 SCIPsetDebugMsg(set, "issue GHOLEADDED event for variable <%s>: (%.15g,%.15g)\n", var->name, left, right);
6781
6782 SCIP_CALL( SCIPeventCreateGholeAdded(&event, blkmem, var, left, right) );
6783 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
6784 }
6785
6786 return SCIP_OKAY;
6787}
6788
6789/** increases root bound change statistics after a global bound change */
6790static
6792 SCIP_VAR* var, /**< problem variable to change */
6793 SCIP_SET* set, /**< global SCIP settings */
6794 SCIP_STAT* stat /**< problem statistics */
6795 )
6796{
6797 assert(var != NULL);
6798 assert(set != NULL);
6799 assert(var->scip == set->scip);
6800 assert(stat != NULL);
6801
6802 if( SCIPvarIsActive(var) && SCIPvarIsTransformed(var) && set->stage == SCIP_STAGE_SOLVING )
6803 {
6804 stat->nrootboundchgs++;
6805 stat->nrootboundchgsrun++;
6806 if( SCIPvarIsIntegral(var) && SCIPvarGetLbGlobal(var) + 0.5 > SCIPvarGetUbGlobal(var) )
6807 {
6808 stat->nrootintfixings++;
6809 stat->nrootintfixingsrun++;
6810 }
6811 }
6812}
6813
6814/* forward declaration, because both methods call each other recursively */
6815
6816/* performs the current change in upper bound, changes all parents accordingly */
6817static
6819 SCIP_VAR* var, /**< problem variable to change */
6820 BMS_BLKMEM* blkmem, /**< block memory */
6821 SCIP_SET* set, /**< global SCIP settings */
6822 SCIP_STAT* stat, /**< problem statistics */
6823 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6824 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6825 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6826 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6827 SCIP_Real newbound /**< new bound for variable */
6828 );
6829
6830/** performs the current change in lower bound, changes all parents accordingly */
6831static
6833 SCIP_VAR* var, /**< problem variable to change */
6834 BMS_BLKMEM* blkmem, /**< block memory */
6835 SCIP_SET* set, /**< global SCIP settings */
6836 SCIP_STAT* stat, /**< problem statistics */
6837 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6838 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6839 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6840 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6841 SCIP_Real newbound /**< new bound for variable */
6842 )
6843{
6844 SCIP_VAR* parentvar;
6845 SCIP_Real oldbound;
6846 int i;
6847
6848 assert(var != NULL);
6849 /* local domains can violate global bounds but not more than feasibility epsilon */
6850 assert(SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb));
6851 assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
6852 assert(blkmem != NULL);
6853 assert(set != NULL);
6854 assert(var->scip == set->scip);
6855 assert(stat != NULL);
6856
6857 /* adjust bound to integral value if variable is of integral type */
6858 newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6859
6860 /* check that the bound is feasible */
6861 if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound > var->glbdom.ub )
6862 {
6863 /* due to numerics we only want to be feasible in feasibility tolerance */
6864 assert(SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
6865 newbound = var->glbdom.ub;
6866 }
6868
6869 assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
6870
6871 SCIPsetDebugMsg(set, "process changing global lower bound of <%s> from %f to %f\n", var->name, var->glbdom.lb, newbound);
6872
6873 if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) && !(newbound != var->glbdom.lb && newbound * var->glbdom.lb <= 0.0) ) /*lint !e777*/
6874 return SCIP_OKAY;
6875
6876 /* check bound on debugging solution */
6877 SCIP_CALL( SCIPdebugCheckLbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
6878
6879 /* change the bound */
6880 oldbound = var->glbdom.lb;
6881 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
6882 var->glbdom.lb = newbound;
6883 assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
6884 assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
6885
6887 {
6888 /* merges overlapping holes into single holes, moves bounds respectively */
6889 domMerge(&var->glbdom, blkmem, set, &newbound, NULL);
6890 }
6891
6892 /* update the root bound changes counters */
6893 varIncRootboundchgs(var, set, stat);
6894
6895 /* update the lbchginfos array by replacing worse local bounds with the new global bound and changing the
6896 * redundant bound changes to be branching decisions
6897 */
6898 for( i = 0; i < var->nlbchginfos; ++i )
6899 {
6900 assert(var->lbchginfos[i].var == var);
6901
6902 if( var->lbchginfos[i].oldbound < var->glbdom.lb )
6903 {
6904 SCIPsetDebugMsg(set, " -> adjust lower bound change <%s>: %g -> %g due to new global lower bound %g\n",
6905 SCIPvarGetName(var), var->lbchginfos[i].oldbound, var->lbchginfos[i].newbound, var->glbdom.lb);
6906 var->lbchginfos[i].oldbound = var->glbdom.lb;
6907 if( SCIPsetIsLE(set, var->lbchginfos[i].newbound, var->glbdom.lb) )
6908 {
6909 /* this bound change is redundant due to the new global bound */
6910 var->lbchginfos[i].newbound = var->glbdom.lb;
6911 var->lbchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
6912 var->lbchginfos[i].redundant = TRUE;
6913 }
6914 else
6915 break; /* from now on, the remaining local bound changes are not redundant */
6916 }
6917 else
6918 break; /* from now on, the remaining local bound changes are not redundant */
6919 }
6920
6921 /* remove redundant implications and variable bounds */
6923 && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
6924 {
6925 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
6926 }
6927
6928 /* issue bound change event */
6929 assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
6931 {
6932 SCIP_CALL( varEventGlbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
6933 }
6934
6935 /* process parent variables */
6936 for( i = 0; i < var->nparentvars; ++i )
6937 {
6938 parentvar = var->parentvars[i];
6939 assert(parentvar != NULL);
6940
6941 switch( SCIPvarGetStatus(parentvar) )
6942 {
6944 SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6945 break;
6946
6951 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
6952 return SCIP_INVALIDDATA;
6953
6954 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6955 assert(parentvar->data.aggregate.var == var);
6956 if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
6957 {
6958 SCIP_Real parentnewbound;
6959
6960 /* a > 0 -> change lower bound of y */
6961 assert(SCIPsetIsInfinity(set, -parentvar->glbdom.lb) || SCIPsetIsInfinity(set, -oldbound)
6962 || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
6963 || (SCIPsetIsZero(set, parentvar->glbdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
6964
6965 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6966 parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6967 else
6968 parentnewbound = newbound;
6969 SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6970 }
6971 else
6972 {
6973 SCIP_Real parentnewbound;
6974
6975 /* a < 0 -> change upper bound of y */
6976 assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
6977 assert(SCIPsetIsInfinity(set, parentvar->glbdom.ub) || SCIPsetIsInfinity(set, -oldbound)
6978 || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
6979 || (SCIPsetIsZero(set, parentvar->glbdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
6980
6981 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6982 parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6983 else
6984 parentnewbound = -newbound;
6985 SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6986 }
6987 break;
6988
6989 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6990 assert(parentvar->negatedvar != NULL);
6991 assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
6992 assert(parentvar->negatedvar->negatedvar == parentvar);
6993 SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6994 parentvar->data.negate.constant - newbound) );
6995 break;
6996
6997 default:
6998 SCIPerrorMessage("unknown variable status\n");
6999 return SCIP_INVALIDDATA;
7000 }
7001 }
7002
7003 return SCIP_OKAY;
7004}
7005
7006/** performs the current change in upper bound, changes all parents accordingly */
7007static
7009 SCIP_VAR* var, /**< problem variable to change */
7010 BMS_BLKMEM* blkmem, /**< block memory */
7011 SCIP_SET* set, /**< global SCIP settings */
7012 SCIP_STAT* stat, /**< problem statistics */
7013 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7014 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7015 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7016 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7017 SCIP_Real newbound /**< new bound for variable */
7018 )
7019{
7020 SCIP_VAR* parentvar;
7021 SCIP_Real oldbound;
7022 int i;
7023
7024 assert(var != NULL);
7025 /* local domains can violate global bounds but not more than feasibility epsilon */
7026 assert(SCIPsetIsFeasLE(set, var->glbdom.lb , var->locdom.lb));
7027 assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
7028 assert(blkmem != NULL);
7029 assert(set != NULL);
7030 assert(var->scip == set->scip);
7031 assert(stat != NULL);
7032
7033 /* adjust bound to integral value if variable is of integral type */
7034 newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7035
7036 /* check that the bound is feasible */
7037 if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound < var->glbdom.lb )
7038 {
7039 /* due to numerics we only want to be feasible in feasibility tolerance */
7040 assert(SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
7041 newbound = var->glbdom.lb;
7042 }
7044
7045 assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
7046
7047 SCIPsetDebugMsg(set, "process changing global upper bound of <%s> from %f to %f\n", var->name, var->glbdom.ub, newbound);
7048
7049 if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) && !(newbound != var->glbdom.ub && newbound * var->glbdom.ub <= 0.0) ) /*lint !e777*/
7050 return SCIP_OKAY;
7051
7052 /* check bound on debugging solution */
7053 SCIP_CALL( SCIPdebugCheckUbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
7054
7055 /* change the bound */
7056 oldbound = var->glbdom.ub;
7057 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
7058 var->glbdom.ub = newbound;
7059 assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
7060 assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
7061
7063 {
7064 /* merges overlapping holes into single holes, moves bounds respectively */
7065 domMerge(&var->glbdom, blkmem, set, NULL, &newbound);
7066 }
7067
7068 /* update the root bound changes counters */
7069 varIncRootboundchgs(var, set, stat);
7070
7071 /* update the ubchginfos array by replacing worse local bounds with the new global bound and changing the
7072 * redundant bound changes to be branching decisions
7073 */
7074 for( i = 0; i < var->nubchginfos; ++i )
7075 {
7076 assert(var->ubchginfos[i].var == var);
7077 if( var->ubchginfos[i].oldbound > var->glbdom.ub )
7078 {
7079 SCIPsetDebugMsg(set, " -> adjust upper bound change <%s>: %g -> %g due to new global upper bound %g\n",
7080 SCIPvarGetName(var), var->ubchginfos[i].oldbound, var->ubchginfos[i].newbound, var->glbdom.ub);
7081 var->ubchginfos[i].oldbound = var->glbdom.ub;
7082 if( SCIPsetIsGE(set, var->ubchginfos[i].newbound, var->glbdom.ub) )
7083 {
7084 /* this bound change is redundant due to the new global bound */
7085 var->ubchginfos[i].newbound = var->glbdom.ub;
7086 var->ubchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
7087 var->ubchginfos[i].redundant = TRUE;
7088 }
7089 else
7090 break; /* from now on, the remaining local bound changes are not redundant */
7091 }
7092 else
7093 break; /* from now on, the remaining local bound changes are not redundant */
7094 }
7095
7096 /* remove redundant implications and variable bounds */
7098 && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
7099 {
7100 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
7101 }
7102
7103 /* issue bound change event */
7104 assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7106 {
7107 SCIP_CALL( varEventGubChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7108 }
7109
7110 /* process parent variables */
7111 for( i = 0; i < var->nparentvars; ++i )
7112 {
7113 parentvar = var->parentvars[i];
7114 assert(parentvar != NULL);
7115
7116 switch( SCIPvarGetStatus(parentvar) )
7117 {
7119 SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7120 break;
7121
7126 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7127 return SCIP_INVALIDDATA;
7128
7129 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7130 assert(parentvar->data.aggregate.var == var);
7131 if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7132 {
7133 SCIP_Real parentnewbound;
7134
7135 /* a > 0 -> change upper bound of y */
7136 assert(SCIPsetIsInfinity(set, parentvar->glbdom.ub) || SCIPsetIsInfinity(set, oldbound)
7137 || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub,
7138 oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7139 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7140 parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7141 else
7142 parentnewbound = newbound;
7143 SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
7144 }
7145 else
7146 {
7147 SCIP_Real parentnewbound;
7148
7149 /* a < 0 -> change lower bound of y */
7150 assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7151 assert(SCIPsetIsInfinity(set, -parentvar->glbdom.lb) || SCIPsetIsInfinity(set, oldbound)
7152 || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb,
7153 oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7154 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7155 parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7156 else
7157 parentnewbound = -newbound;
7158 SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
7159 }
7160 break;
7161
7162 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7163 assert(parentvar->negatedvar != NULL);
7164 assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7165 assert(parentvar->negatedvar->negatedvar == parentvar);
7166 SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7167 parentvar->data.negate.constant - newbound) );
7168 break;
7169
7170 default:
7171 SCIPerrorMessage("unknown variable status\n");
7172 return SCIP_INVALIDDATA;
7173 }
7174 }
7175
7176 return SCIP_OKAY;
7177}
7178
7179/** changes global lower bound of variable; if possible, adjusts bound to integral value;
7180 * updates local lower bound if the global bound is tighter
7181 */
7183 SCIP_VAR* var, /**< problem variable to change */
7184 BMS_BLKMEM* blkmem, /**< block memory */
7185 SCIP_SET* set, /**< global SCIP settings */
7186 SCIP_STAT* stat, /**< problem statistics */
7187 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7188 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7189 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7190 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7191 SCIP_Real newbound /**< new bound for variable */
7192 )
7193{
7194 assert(var != NULL);
7195 assert(blkmem != NULL);
7196 assert(set != NULL);
7197 assert(var->scip == set->scip);
7198
7199 /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7200 * of the domain within feastol
7201 */
7202 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
7203
7204 /* adjust bound to integral value if variable is of integral type */
7205 newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7206
7207 /* check that the adjusted bound is feasible
7208 * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
7209 * here because we reset bounds to their original value!
7210 */
7211 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
7212
7214 {
7215 /* we do not want to exceed the upperbound, which could have happened due to numerics */
7216 newbound = MIN(newbound, var->glbdom.ub);
7217 }
7219
7220 /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
7221 * SCIPvarFix() allows fixings that are outside of the domain within feastol
7222 */
7223 assert(lp == NULL || SCIPsetIsFeasLE(set, var->glbdom.lb, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
7224
7225 SCIPsetDebugMsg(set, "changing global lower bound of <%s> from %g to %g\n", var->name, var->glbdom.lb, newbound);
7226
7227 if( SCIPsetIsEQ(set, var->glbdom.lb, newbound) && !(newbound != var->glbdom.lb && newbound * var->glbdom.lb <= 0.0) ) /*lint !e777*/
7228 return SCIP_OKAY;
7229
7230 /* change bounds of attached variables */
7231 switch( SCIPvarGetStatus(var) )
7232 {
7234 if( var->data.original.transvar != NULL )
7235 {
7236 SCIP_CALL( SCIPvarChgLbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
7237 cliquetable, newbound) );
7238 }
7239 else
7240 {
7241 assert(set->stage == SCIP_STAGE_PROBLEM);
7242 if( newbound > SCIPvarGetLbLocal(var) )
7243 {
7244 SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7245 }
7246 SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7247 }
7248 break;
7249
7252 if( newbound > SCIPvarGetLbLocal(var) )
7253 {
7254 /* ensure that the local bound change is not blocked */
7255 if( newbound > SCIPvarGetUbLocal(var) )
7256 {
7257 SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7258 }
7259 SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7260 }
7261 SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7262 break;
7263
7265 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7266 return SCIP_INVALIDDATA;
7267
7268 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7269 assert(var->data.aggregate.var != NULL);
7271 {
7272 SCIP_Real childnewbound;
7273
7274 /* a > 0 -> change lower bound of y */
7276 || SCIPsetIsFeasEQ(set, var->glbdom.lb,
7278 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7279 childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7280 else
7281 childnewbound = newbound;
7282 SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7283 childnewbound) );
7284 }
7285 else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7286 {
7287 SCIP_Real childnewbound;
7288
7289 /* a < 0 -> change upper bound of y */
7291 || SCIPsetIsFeasEQ(set, var->glbdom.lb,
7293 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7294 childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7295 else
7296 childnewbound = -newbound;
7297 SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7298 childnewbound) );
7299 }
7300 else
7301 {
7302 SCIPerrorMessage("scalar is zero in aggregation\n");
7303 return SCIP_INVALIDDATA;
7304 }
7305 break;
7306
7308 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7309 return SCIP_INVALIDDATA;
7310
7311 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7312 assert(var->negatedvar != NULL);
7314 assert(var->negatedvar->negatedvar == var);
7315 SCIP_CALL( SCIPvarChgUbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7316 var->data.negate.constant - newbound) );
7317 break;
7318
7319 default:
7320 SCIPerrorMessage("unknown variable status\n");
7321 return SCIP_INVALIDDATA;
7322 }
7323
7324 return SCIP_OKAY;
7325}
7326
7327/** changes global upper bound of variable; if possible, adjusts bound to integral value;
7328 * updates local upper bound if the global bound is tighter
7329 */
7331 SCIP_VAR* var, /**< problem variable to change */
7332 BMS_BLKMEM* blkmem, /**< block memory */
7333 SCIP_SET* set, /**< global SCIP settings */
7334 SCIP_STAT* stat, /**< problem statistics */
7335 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7336 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7337 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7338 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7339 SCIP_Real newbound /**< new bound for variable */
7340 )
7341{
7342 assert(var != NULL);
7343 assert(blkmem != NULL);
7344 assert(set != NULL);
7345 assert(var->scip == set->scip);
7346
7347 /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7348 * of the domain within feastol
7349 */
7350 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
7351
7352 /* adjust bound to integral value if variable is of integral type */
7353 newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7354
7355 /* check that the adjusted bound is feasible
7356 * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
7357 * here because we reset bounds to their original value!
7358 */
7359 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
7360
7362 {
7363 /* we do not want to undercut the lowerbound, which could have happened due to numerics */
7364 newbound = MAX(newbound, var->glbdom.lb);
7365 }
7367
7368 /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
7369 * SCIPvarFix() allows fixings that are outside of the domain within feastol
7370 */
7371 assert(lp == NULL || SCIPsetIsFeasGE(set, var->glbdom.ub, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
7372
7373 SCIPsetDebugMsg(set, "changing global upper bound of <%s> from %g to %g\n", var->name, var->glbdom.ub, newbound);
7374
7375 if( SCIPsetIsEQ(set, var->glbdom.ub, newbound) && !(newbound != var->glbdom.ub && newbound * var->glbdom.ub <= 0.0) ) /*lint !e777*/
7376 return SCIP_OKAY;
7377
7378 /* change bounds of attached variables */
7379 switch( SCIPvarGetStatus(var) )
7380 {
7382 if( var->data.original.transvar != NULL )
7383 {
7384 SCIP_CALL( SCIPvarChgUbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7385 newbound) );
7386 }
7387 else
7388 {
7389 assert(set->stage == SCIP_STAGE_PROBLEM);
7390 if( newbound < SCIPvarGetUbLocal(var) )
7391 {
7392 SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7393 }
7394 SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7395 }
7396 break;
7397
7400 if( newbound < SCIPvarGetUbLocal(var) )
7401 {
7402 /* ensure that the local bound change is not blocked */
7403 if( newbound < SCIPvarGetLbLocal(var) )
7404 {
7405 SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7406 }
7407 SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7408 }
7409 SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7410 break;
7411
7413 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7414 return SCIP_INVALIDDATA;
7415
7416 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7417 assert(var->data.aggregate.var != NULL);
7419 {
7420 SCIP_Real childnewbound;
7421
7422 /* a > 0 -> change lower bound of y */
7424 || SCIPsetIsFeasEQ(set, var->glbdom.ub,
7426 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7427 childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7428 else
7429 childnewbound = newbound;
7430 SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7431 childnewbound) );
7432 }
7433 else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7434 {
7435 SCIP_Real childnewbound;
7436
7437 /* a < 0 -> change upper bound of y */
7439 || SCIPsetIsFeasEQ(set, var->glbdom.ub,
7441 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7442 childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7443 else
7444 childnewbound = -newbound;
7445 SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7446 childnewbound) );
7447 }
7448 else
7449 {
7450 SCIPerrorMessage("scalar is zero in aggregation\n");
7451 return SCIP_INVALIDDATA;
7452 }
7453 break;
7454
7456 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7457 return SCIP_INVALIDDATA;
7458
7459 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7460 assert(var->negatedvar != NULL);
7462 assert(var->negatedvar->negatedvar == var);
7463 SCIP_CALL( SCIPvarChgLbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7464 var->data.negate.constant - newbound) );
7465 break;
7466
7467 default:
7468 SCIPerrorMessage("unknown variable status\n");
7469 return SCIP_INVALIDDATA;
7470 }
7471
7472 return SCIP_OKAY;
7473}
7474
7475/** changes lazy lower bound of the variable, this is only possible if the variable is not in the LP yet */
7477 SCIP_VAR* var, /**< problem variable */
7478 SCIP_SET* set, /**< global SCIP settings */
7479 SCIP_Real lazylb /**< the lazy lower bound to be set */
7480 )
7481{
7482 assert(var != NULL);
7483 assert(var->probindex != -1);
7484 assert(SCIPsetIsFeasGE(set, var->glbdom.ub, lazylb));
7485 assert(SCIPsetIsFeasGE(set, var->lazyub, lazylb));
7486 assert(set != NULL);
7487 assert(var->scip == set->scip);
7488
7489 /* variable should not be in the LP */
7491 return SCIP_INVALIDCALL;
7492
7493 var->lazylb = lazylb;
7494
7495 return SCIP_OKAY;
7496}
7497
7498/** changes lazy upper bound of the variable, this is only possible if the variable is not in the LP yet */
7500 SCIP_VAR* var, /**< problem variable */
7501 SCIP_SET* set, /**< global SCIP settings */
7502 SCIP_Real lazyub /**< the lazy lower bound to be set */
7503 )
7504{
7505 assert(var != NULL);
7506 assert(var->probindex != -1);
7507 assert(SCIPsetIsFeasGE(set, lazyub, var->glbdom.lb));
7508 assert(SCIPsetIsFeasGE(set, lazyub, var->lazylb));
7509 assert(set != NULL);
7510 assert(var->scip == set->scip);
7511
7512 /* variable should not be in the LP */
7514 return SCIP_INVALIDCALL;
7515
7516 var->lazyub = lazyub;
7517
7518 return SCIP_OKAY;
7519}
7520
7521
7522/** changes global bound of variable; if possible, adjusts bound to integral value;
7523 * updates local bound if the global bound is tighter
7524 */
7526 SCIP_VAR* var, /**< problem variable to change */
7527 BMS_BLKMEM* blkmem, /**< block memory */
7528 SCIP_SET* set, /**< global SCIP settings */
7529 SCIP_STAT* stat, /**< problem statistics */
7530 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7531 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7532 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7533 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7534 SCIP_Real newbound, /**< new bound for variable */
7535 SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
7536 )
7537{
7538 /* apply bound change to the LP data */
7539 switch( boundtype )
7540 {
7542 return SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
7544 return SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
7545 default:
7546 SCIPerrorMessage("unknown bound type\n");
7547 return SCIP_INVALIDDATA;
7548 }
7549}
7550
7551/** appends LBTIGHTENED or LBRELAXED event to the event queue */
7552static
7554 SCIP_VAR* var, /**< problem variable to change */
7555 BMS_BLKMEM* blkmem, /**< block memory */
7556 SCIP_SET* set, /**< global SCIP settings */
7557 SCIP_LP* lp, /**< current LP data */
7558 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7559 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7560 SCIP_Real oldbound, /**< old lower bound for variable */
7561 SCIP_Real newbound /**< new lower bound for variable */
7562 )
7563{
7564 assert(var != NULL);
7565 assert(var->eventfilter != NULL);
7566 assert(SCIPvarIsTransformed(var));
7567 assert(!SCIPsetIsEQ(set, oldbound, newbound) || newbound == var->glbdom.lb || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
7568 assert(set != NULL);
7569 assert(var->scip == set->scip);
7570
7571 /* check, if the variable is being tracked for bound changes
7572 * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
7573 */
7574 if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_LBCHANGED) != 0)
7577 {
7578 SCIP_EVENT* event;
7579
7580 SCIPsetDebugMsg(set, "issue LBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
7581
7582 SCIP_CALL( SCIPeventCreateLbChanged(&event, blkmem, var, oldbound, newbound) );
7583 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
7584 }
7585
7586 return SCIP_OKAY;
7587}
7588
7589/** appends UBTIGHTENED or UBRELAXED event to the event queue */
7590static
7592 SCIP_VAR* var, /**< problem variable to change */
7593 BMS_BLKMEM* blkmem, /**< block memory */
7594 SCIP_SET* set, /**< global SCIP settings */
7595 SCIP_LP* lp, /**< current LP data */
7596 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7597 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7598 SCIP_Real oldbound, /**< old upper bound for variable */
7599 SCIP_Real newbound /**< new upper bound for variable */
7600 )
7601{
7602 assert(var != NULL);
7603 assert(var->eventfilter != NULL);
7604 assert(SCIPvarIsTransformed(var));
7605 assert(!SCIPsetIsEQ(set, oldbound, newbound) || newbound == var->glbdom.ub || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
7606 assert(set != NULL);
7607 assert(var->scip == set->scip);
7608
7609 /* check, if the variable is being tracked for bound changes
7610 * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
7611 */
7612 if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_UBCHANGED) != 0)
7615 {
7616 SCIP_EVENT* event;
7617
7618 SCIPsetDebugMsg(set, "issue UBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
7619
7620 SCIP_CALL( SCIPeventCreateUbChanged(&event, blkmem, var, oldbound, newbound) );
7621 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
7622 }
7623
7624 return SCIP_OKAY;
7625}
7626
7627/* forward declaration, because both methods call each other recursively */
7628
7629/* performs the current change in upper bound, changes all parents accordingly */
7630static
7632 SCIP_VAR* var, /**< problem variable to change */
7633 BMS_BLKMEM* blkmem, /**< block memory */
7634 SCIP_SET* set, /**< global SCIP settings */
7635 SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7636 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7637 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7638 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7639 SCIP_Real newbound /**< new bound for variable */
7640 );
7641
7642/** performs the current change in lower bound, changes all parents accordingly */
7643static
7645 SCIP_VAR* var, /**< problem variable to change */
7646 BMS_BLKMEM* blkmem, /**< block memory */
7647 SCIP_SET* set, /**< global SCIP settings */
7648 SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7649 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7650 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7651 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7652 SCIP_Real newbound /**< new bound for variable */
7653 )
7654{
7655 SCIP_VAR* parentvar;
7656 SCIP_Real oldbound;
7657 int i;
7658
7659 assert(var != NULL);
7660 assert(set != NULL);
7661 assert(var->scip == set->scip);
7662 assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)
7663 || SCIPsetIsEQ(set, newbound, var->locdom.ub)))
7665 || SCIPsetIsEQ(set, newbound, var->locdom.ub)))
7667
7668 /* check that the bound is feasible */
7669 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsLE(set, newbound, var->glbdom.ub));
7670 /* adjust bound to integral value if variable is of integral type */
7671 newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7672
7674 {
7675 /* we do not want to exceed the upper bound, which could have happened due to numerics */
7676 newbound = MIN(newbound, var->locdom.ub);
7677
7678 /* we do not want to undercut the global lower bound, which could have happened due to numerics */
7679 newbound = MAX(newbound, var->glbdom.lb);
7680 }
7682
7683 SCIPsetDebugMsg(set, "process changing lower bound of <%s> from %g to %g\n", var->name, var->locdom.lb, newbound);
7684
7685 if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) && var->glbdom.lb != var->locdom.lb ) /*lint !e777*/
7686 newbound = var->glbdom.lb;
7687 else if( SCIPsetIsEQ(set, newbound, var->locdom.lb) && !(newbound != var->locdom.lb && newbound * var->locdom.lb <= 0.0) ) /*lint !e777*/
7688 return SCIP_OKAY;
7689
7690 /* change the bound */
7691 oldbound = var->locdom.lb;
7692 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->locdom.ub));
7693 var->locdom.lb = newbound;
7694
7695 /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
7696 * once update the statistic
7697 */
7698 if( stat != NULL )
7699 SCIPstatIncrement(stat, set, domchgcount);
7700
7702 {
7703 /* merges overlapping holes into single holes, moves bounds respectively */
7704 domMerge(&var->locdom, blkmem, set, &newbound, NULL);
7705 }
7706
7707 /* issue bound change event */
7708 assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7710 {
7711 SCIP_CALL( varEventLbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7712 }
7713
7714 /* process parent variables */
7715 for( i = 0; i < var->nparentvars; ++i )
7716 {
7717 parentvar = var->parentvars[i];
7718 assert(parentvar != NULL);
7719
7720 switch( SCIPvarGetStatus(parentvar) )
7721 {
7723 SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
7724 break;
7725
7730 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7731 return SCIP_INVALIDDATA;
7732
7733 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7734 assert(parentvar->data.aggregate.var == var);
7735 if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7736 {
7737 SCIP_Real parentnewbound;
7738
7739 /* a > 0 -> change lower bound of y */
7740 assert(SCIPsetIsInfinity(set, -parentvar->locdom.lb) || SCIPsetIsInfinity(set, -oldbound)
7741 || SCIPsetIsFeasEQ(set, parentvar->locdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
7742 || (SCIPsetIsZero(set, parentvar->locdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
7743
7744 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7745 {
7746 parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7747 /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
7748 * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
7749 * as a result, the parent's lower bound is set to it's upper bound, and not above
7750 */
7751 if( parentnewbound > parentvar->glbdom.ub )
7752 {
7753 /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7754 assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
7755 parentnewbound = parentvar->glbdom.ub;
7756 }
7757 }
7758 else
7759 parentnewbound = newbound;
7760 SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7761 }
7762 else
7763 {
7764 SCIP_Real parentnewbound;
7765
7766 /* a < 0 -> change upper bound of y */
7767 assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7768 assert(SCIPsetIsInfinity(set, parentvar->locdom.ub) || SCIPsetIsInfinity(set, -oldbound)
7769 || SCIPsetIsFeasEQ(set, parentvar->locdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
7770 || (SCIPsetIsZero(set, parentvar->locdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
7771
7772 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7773 {
7774 parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7775 /* 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
7776 * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
7777 * as a result, the parent's upper bound is set to it's lower bound, and not below
7778 */
7779 if( parentnewbound < parentvar->glbdom.lb )
7780 {
7781 /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7782 assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
7783 parentnewbound = parentvar->glbdom.lb;
7784 }
7785 }
7786 else
7787 parentnewbound = -newbound;
7788 SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7789 }
7790 break;
7791
7792 case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
7793 assert(parentvar->negatedvar != NULL);
7794 assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7795 assert(parentvar->negatedvar->negatedvar == parentvar);
7796 SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
7797 parentvar->data.negate.constant - newbound) );
7798 break;
7799
7800 default:
7801 SCIPerrorMessage("unknown variable status\n");
7802 return SCIP_INVALIDDATA;
7803 }
7804 }
7805
7806 return SCIP_OKAY;
7807}
7808
7809/** performs the current change in upper bound, changes all parents accordingly */
7810static
7812 SCIP_VAR* var, /**< problem variable to change */
7813 BMS_BLKMEM* blkmem, /**< block memory */
7814 SCIP_SET* set, /**< global SCIP settings */
7815 SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7816 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7817 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7818 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7819 SCIP_Real newbound /**< new bound for variable */
7820 )
7821{
7822 SCIP_VAR* parentvar;
7823 SCIP_Real oldbound;
7824 int i;
7825
7826 assert(var != NULL);
7827 assert(set != NULL);
7828 assert(var->scip == set->scip);
7829 assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)
7830 || SCIPsetIsEQ(set, newbound, var->locdom.lb)))
7832 || SCIPsetIsEQ(set, newbound, var->locdom.lb)))
7834
7835 /* check that the bound is feasible */
7836 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsGE(set, newbound, var->glbdom.lb));
7837 /* adjust bound to integral value if variable is of integral type */
7838 newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7839
7841 {
7842 /* we do not want to undercut the lower bound, which could have happened due to numerics */
7843 newbound = MAX(newbound, var->locdom.lb);
7844
7845 /* we do not want to exceed the global upper bound, which could have happened due to numerics */
7846 newbound = MIN(newbound, var->glbdom.ub);
7847 }
7849
7850 SCIPsetDebugMsg(set, "process changing upper bound of <%s> from %g to %g\n", var->name, var->locdom.ub, newbound);
7851
7852 if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) && var->glbdom.ub != var->locdom.ub ) /*lint !e777*/
7853 newbound = var->glbdom.ub;
7854 else if( SCIPsetIsEQ(set, newbound, var->locdom.ub) && !(newbound != var->locdom.ub && newbound * var->locdom.ub <= 0.0) ) /*lint !e777*/
7855 return SCIP_OKAY;
7856
7857 /* change the bound */
7858 oldbound = var->locdom.ub;
7859 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->locdom.lb));
7860 var->locdom.ub = newbound;
7861
7862 /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
7863 * once update the statistic
7864 */
7865 if( stat != NULL )
7866 SCIPstatIncrement(stat, set, domchgcount);
7867
7869 {
7870 /* merges overlapping holes into single holes, moves bounds respectively */
7871 domMerge(&var->locdom, blkmem, set, NULL, &newbound);
7872 }
7873
7874 /* issue bound change event */
7875 assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7877 {
7878 SCIP_CALL( varEventUbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7879 }
7880
7881 /* process parent variables */
7882 for( i = 0; i < var->nparentvars; ++i )
7883 {
7884 parentvar = var->parentvars[i];
7885 assert(parentvar != NULL);
7886
7887 switch( SCIPvarGetStatus(parentvar) )
7888 {
7890 SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
7891 break;
7892
7897 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7898 return SCIP_INVALIDDATA;
7899
7900 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7901 assert(parentvar->data.aggregate.var == var);
7902 if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7903 {
7904 SCIP_Real parentnewbound;
7905
7906 /* a > 0 -> change upper bound of x */
7907 assert(SCIPsetIsInfinity(set, parentvar->locdom.ub) || SCIPsetIsInfinity(set, oldbound)
7908 || SCIPsetIsFeasEQ(set, parentvar->locdom.ub,
7909 oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7910 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7911 {
7912 parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7913 /* 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
7914 * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
7915 * as a result, the parent's upper bound is set to it's lower bound, and not below
7916 */
7917 if( parentnewbound < parentvar->glbdom.lb )
7918 {
7919 /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7920 assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
7921 parentnewbound = parentvar->glbdom.lb;
7922 }
7923 }
7924 else
7925 parentnewbound = newbound;
7926 SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7927 }
7928 else
7929 {
7930 SCIP_Real parentnewbound;
7931
7932 /* a < 0 -> change lower bound of x */
7933 assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7934 assert(SCIPsetIsInfinity(set, -parentvar->locdom.lb) || SCIPsetIsInfinity(set, oldbound)
7935 || SCIPsetIsFeasEQ(set, parentvar->locdom.lb,
7936 oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7937 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7938 {
7939 parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7940 /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
7941 * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
7942 * as a result, the parent's lower bound is set to it's upper bound, and not above
7943 */
7944 if( parentnewbound > parentvar->glbdom.ub )
7945 {
7946 /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7947 assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
7948 parentnewbound = parentvar->glbdom.ub;
7949 }
7950 }
7951 else
7952 parentnewbound = -newbound;
7953 SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7954 }
7955 break;
7956
7957 case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
7958 assert(parentvar->negatedvar != NULL);
7959 assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7960 assert(parentvar->negatedvar->negatedvar == parentvar);
7961 SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
7962 parentvar->data.negate.constant - newbound) );
7963 break;
7964
7965 default:
7966 SCIPerrorMessage("unknown variable status\n");
7967 return SCIP_INVALIDDATA;
7968 }
7969 }
7970
7971 return SCIP_OKAY;
7972}
7973
7974/** changes current local lower bound of variable; if possible, adjusts bound to integral value; stores inference
7975 * information in variable
7976 */
7978 SCIP_VAR* var, /**< problem variable to change */
7979 BMS_BLKMEM* blkmem, /**< block memory */
7980 SCIP_SET* set, /**< global SCIP settings */
7981 SCIP_STAT* stat, /**< problem statistics */
7982 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7983 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7984 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7985 SCIP_Real newbound /**< new bound for variable */
7986 )
7987{
7988 assert(var != NULL);
7989 assert(blkmem != NULL);
7990 assert(set != NULL);
7991 assert(var->scip == set->scip);
7992
7993 /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7994 * of the domain within feastol
7995 */
7996 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
7997
7998 /* adjust bound to integral value if variable is of integral type */
7999 newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
8000
8001 /* check that the adjusted bound is feasible */
8002 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
8003
8005 {
8006 /* we do not want to exceed the upperbound, which could have happened due to numerics */
8007 newbound = MIN(newbound, var->locdom.ub);
8008 }
8010
8011 SCIPsetDebugMsg(set, "changing lower bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
8012
8013 if( SCIPsetIsEQ(set, var->locdom.lb, newbound) && (!SCIPsetIsEQ(set, var->glbdom.lb, newbound) || var->locdom.lb == newbound) /*lint !e777*/
8014 && !(newbound != var->locdom.lb && newbound * var->locdom.lb <= 0.0) ) /*lint !e777*/
8015 return SCIP_OKAY;
8016
8017 /* change bounds of attached variables */
8018 switch( SCIPvarGetStatus(var) )
8019 {
8021 if( var->data.original.transvar != NULL )
8022 {
8023 SCIP_CALL( SCIPvarChgLbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
8024 newbound) );
8025 }
8026 else
8027 {
8028 assert(set->stage == SCIP_STAGE_PROBLEM);
8029 SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8030 }
8031 break;
8032
8035 SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8036 break;
8037
8039 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8040 return SCIP_INVALIDDATA;
8041
8042 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8043 assert(var->data.aggregate.var != NULL);
8045 {
8046 SCIP_Real childnewbound;
8047
8048 /* a > 0 -> change lower bound of y */
8050 || SCIPsetIsFeasEQ(set, var->locdom.lb,
8052 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8053 childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8054 else
8055 childnewbound = newbound;
8056 SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
8057 childnewbound) );
8058 }
8059 else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8060 {
8061 SCIP_Real childnewbound;
8062
8063 /* a < 0 -> change upper bound of y */
8065 || SCIPsetIsFeasEQ(set, var->locdom.lb,
8067 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8068 childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8069 else
8070 childnewbound = -newbound;
8071 SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
8072 childnewbound) );
8073 }
8074 else
8075 {
8076 SCIPerrorMessage("scalar is zero in aggregation\n");
8077 return SCIP_INVALIDDATA;
8078 }
8079 break;
8080
8082 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8083 return SCIP_INVALIDDATA;
8084
8085 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8086 assert(var->negatedvar != NULL);
8088 assert(var->negatedvar->negatedvar == var);
8089 SCIP_CALL( SCIPvarChgUbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
8090 var->data.negate.constant - newbound) );
8091 break;
8092
8093 default:
8094 SCIPerrorMessage("unknown variable status\n");
8095 return SCIP_INVALIDDATA;
8096 }
8097
8098 return SCIP_OKAY;
8099}
8100
8101/** changes current local upper bound of variable; if possible, adjusts bound to integral value; stores inference
8102 * information in variable
8103 */
8105 SCIP_VAR* var, /**< problem variable to change */
8106 BMS_BLKMEM* blkmem, /**< block memory */
8107 SCIP_SET* set, /**< global SCIP settings */
8108 SCIP_STAT* stat, /**< problem statistics */
8109 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
8110 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
8111 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8112 SCIP_Real newbound /**< new bound for variable */
8113 )
8114{
8115 assert(var != NULL);
8116 assert(blkmem != NULL);
8117 assert(set != NULL);
8118 assert(var->scip == set->scip);
8119
8120 /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
8121 * of the domain within feastol
8122 */
8123 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
8124
8125 /* adjust bound to integral value if variable is of integral type */
8126 newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
8127
8128 /* check that the adjusted bound is feasible */
8129 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
8130
8132 {
8133 /* we do not want to undercut the lowerbound, which could have happened due to numerics */
8134 newbound = MAX(newbound, var->locdom.lb);
8135 }
8137
8138 SCIPsetDebugMsg(set, "changing upper bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
8139
8140 if( SCIPsetIsEQ(set, var->locdom.ub, newbound) && (!SCIPsetIsEQ(set, var->glbdom.ub, newbound) || var->locdom.ub == newbound) /*lint !e777*/
8141 && !(newbound != var->locdom.ub && newbound * var->locdom.ub <= 0.0) ) /*lint !e777*/
8142 return SCIP_OKAY;
8143
8144 /* change bounds of attached variables */
8145 switch( SCIPvarGetStatus(var) )
8146 {
8148 if( var->data.original.transvar != NULL )
8149 {
8150 SCIP_CALL( SCIPvarChgUbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8151 }
8152 else
8153 {
8154 assert(set->stage == SCIP_STAGE_PROBLEM);
8155 SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8156 }
8157 break;
8158
8161 SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
8162 break;
8163
8165 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8166 return SCIP_INVALIDDATA;
8167
8168 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8169 assert(var->data.aggregate.var != NULL);
8171 {
8172 SCIP_Real childnewbound;
8173
8174 /* a > 0 -> change upper bound of y */
8176 || SCIPsetIsFeasEQ(set, var->locdom.ub,
8178 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8179 childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8180 else
8181 childnewbound = newbound;
8182 SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
8183 childnewbound) );
8184 }
8185 else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8186 {
8187 SCIP_Real childnewbound;
8188
8189 /* a < 0 -> change lower bound of y */
8191 || SCIPsetIsFeasEQ(set, var->locdom.ub,
8193 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8194 childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8195 else
8196 childnewbound = -newbound;
8197 SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
8198 childnewbound) );
8199 }
8200 else
8201 {
8202 SCIPerrorMessage("scalar is zero in aggregation\n");
8203 return SCIP_INVALIDDATA;
8204 }
8205 break;
8206
8208 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8209 return SCIP_INVALIDDATA;
8210
8211 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8212 assert(var->negatedvar != NULL);
8214 assert(var->negatedvar->negatedvar == var);
8215 SCIP_CALL( SCIPvarChgLbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
8216 var->data.negate.constant - newbound) );
8217 break;
8218
8219 default:
8220 SCIPerrorMessage("unknown variable status\n");
8221 return SCIP_INVALIDDATA;
8222 }
8223
8224 return SCIP_OKAY;
8225}
8226
8227/** changes current local bound of variable; if possible, adjusts bound to integral value; stores inference
8228 * information in variable
8229 */
8231 SCIP_VAR* var, /**< problem variable to change */
8232 BMS_BLKMEM* blkmem, /**< block memory */
8233 SCIP_SET* set, /**< global SCIP settings */
8234 SCIP_STAT* stat, /**< problem statistics */
8235 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
8236 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
8237 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8238 SCIP_Real newbound, /**< new bound for variable */
8239 SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
8240 )
8241{
8242 /* apply bound change to the LP data */
8243 switch( boundtype )
8244 {
8246 return SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
8248 return SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
8249 default:
8250 SCIPerrorMessage("unknown bound type\n");
8251 return SCIP_INVALIDDATA;
8252 }
8253}
8254
8255/** changes lower bound of variable in current dive; if possible, adjusts bound to integral value */
8257 SCIP_VAR* var, /**< problem variable to change */
8258 SCIP_SET* set, /**< global SCIP settings */
8259 SCIP_LP* lp, /**< current LP data */
8260 SCIP_Real newbound /**< new bound for variable */
8261 )
8262{
8263 assert(var != NULL);
8264 assert(set != NULL);
8265 assert(var->scip == set->scip);
8266 assert(lp != NULL);
8267 assert(SCIPlpDiving(lp));
8268
8269 /* adjust bound for integral variables */
8270 SCIPvarAdjustLb(var, set, &newbound);
8271
8272 SCIPsetDebugMsg(set, "changing lower bound of <%s> to %g in current dive\n", var->name, newbound);
8273
8274 /* change bounds of attached variables */
8275 switch( SCIPvarGetStatus(var) )
8276 {
8278 assert(var->data.original.transvar != NULL);
8279 SCIP_CALL( SCIPvarChgLbDive(var->data.original.transvar, set, lp, newbound) );
8280 break;
8281
8283 assert(var->data.col != NULL);
8284 SCIP_CALL( SCIPcolChgLb(var->data.col, set, lp, newbound) );
8285 break;
8286
8288 SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
8289 return SCIP_INVALIDDATA;
8290
8292 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8293 return SCIP_INVALIDDATA;
8294
8295 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8296 assert(var->data.aggregate.var != NULL);
8298 {
8299 SCIP_Real childnewbound;
8300
8301 /* a > 0 -> change lower bound of y */
8302 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8303 childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8304 else
8305 childnewbound = newbound;
8306 SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
8307 }
8308 else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8309 {
8310 SCIP_Real childnewbound;
8311
8312 /* a < 0 -> change upper bound of y */
8313 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8314 childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8315 else
8316 childnewbound = -newbound;
8317 SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
8318 }
8319 else
8320 {
8321 SCIPerrorMessage("scalar is zero in aggregation\n");
8322 return SCIP_INVALIDDATA;
8323 }
8324 break;
8325
8327 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8328 return SCIP_INVALIDDATA;
8329
8330 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8331 assert(var->negatedvar != NULL);
8333 assert(var->negatedvar->negatedvar == var);
8334 SCIP_CALL( SCIPvarChgUbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
8335 break;
8336
8337 default:
8338 SCIPerrorMessage("unknown variable status\n");
8339 return SCIP_INVALIDDATA;
8340 }
8341
8342 return SCIP_OKAY;
8343}
8344
8345/** changes upper bound of variable in current dive; if possible, adjusts bound to integral value */
8347 SCIP_VAR* var, /**< problem variable to change */
8348 SCIP_SET* set, /**< global SCIP settings */
8349 SCIP_LP* lp, /**< current LP data */
8350 SCIP_Real newbound /**< new bound for variable */
8351 )
8352{
8353 assert(var != NULL);
8354 assert(set != NULL);
8355 assert(var->scip == set->scip);
8356 assert(lp != NULL);
8357 assert(SCIPlpDiving(lp));
8358
8359 /* adjust bound for integral variables */
8360 SCIPvarAdjustUb(var, set, &newbound);
8361
8362 SCIPsetDebugMsg(set, "changing upper bound of <%s> to %g in current dive\n", var->name, newbound);
8363
8364 /* change bounds of attached variables */
8365 switch( SCIPvarGetStatus(var) )
8366 {
8368 assert(var->data.original.transvar != NULL);
8369 SCIP_CALL( SCIPvarChgUbDive(var->data.original.transvar, set, lp, newbound) );
8370 break;
8371
8373 assert(var->data.col != NULL);
8374 SCIP_CALL( SCIPcolChgUb(var->data.col, set, lp, newbound) );
8375 break;
8376
8378 SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
8379 return SCIP_INVALIDDATA;
8380
8382 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8383 return SCIP_INVALIDDATA;
8384
8385 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8386 assert(var->data.aggregate.var != NULL);
8388 {
8389 SCIP_Real childnewbound;
8390
8391 /* a > 0 -> change upper bound of y */
8392 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8393 childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8394 else
8395 childnewbound = newbound;
8396 SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
8397 }
8398 else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8399 {
8400 SCIP_Real childnewbound;
8401
8402 /* a < 0 -> change lower bound of y */
8403 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8404 childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8405 else
8406 childnewbound = -newbound;
8407 SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
8408 }
8409 else
8410 {
8411 SCIPerrorMessage("scalar is zero in aggregation\n");
8412 return SCIP_INVALIDDATA;
8413 }
8414 break;
8415
8417 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8418 return SCIP_INVALIDDATA;
8419
8420 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8421 assert(var->negatedvar != NULL);
8423 assert(var->negatedvar->negatedvar == var);
8424 SCIP_CALL( SCIPvarChgLbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
8425 break;
8426
8427 default:
8428 SCIPerrorMessage("unknown variable status\n");
8429 return SCIP_INVALIDDATA;
8430 }
8431
8432 return SCIP_OKAY;
8433}
8434
8435/** for a multi-aggregated variable, gives the local lower bound computed by adding the local bounds from all
8436 * aggregation variables, this lower bound may be tighter than the one given by SCIPvarGetLbLocal, since the latter is
8437 * not updated if bounds of aggregation variables are changing
8438 *
8439 * calling this function for a non-multi-aggregated variable is not allowed
8440 */
8442 SCIP_VAR* var, /**< problem variable */
8443 SCIP_SET* set /**< global SCIP settings */
8444 )
8445{
8446 int i;
8447 SCIP_Real lb;
8448 SCIP_Real bnd;
8449 SCIP_VAR* aggrvar;
8450 SCIP_Bool posinf;
8451 SCIP_Bool neginf;
8452
8453 assert(var != NULL);
8454 assert(set != NULL);
8455 assert(var->scip == set->scip);
8457
8458 posinf = FALSE;
8459 neginf = FALSE;
8460 lb = var->data.multaggr.constant;
8461 for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8462 {
8463 aggrvar = var->data.multaggr.vars[i];
8464 if( var->data.multaggr.scalars[i] > 0.0 )
8465 {
8467
8468 if( SCIPsetIsInfinity(set, bnd) )
8469 posinf = TRUE;
8470 else if( SCIPsetIsInfinity(set, -bnd) )
8471 neginf = TRUE;
8472 else
8473 lb += var->data.multaggr.scalars[i] * bnd;
8474 }
8475 else
8476 {
8478
8479 if( SCIPsetIsInfinity(set, -bnd) )
8480 posinf = TRUE;
8481 else if( SCIPsetIsInfinity(set, bnd) )
8482 neginf = TRUE;
8483 else
8484 lb += var->data.multaggr.scalars[i] * bnd;
8485 }
8486
8487 /* stop if two diffrent infinities (or a -infinity) were found and return local lower bound of multi aggregated
8488 * variable
8489 */
8490 if( neginf )
8491 return SCIPvarGetLbLocal(var);
8492 }
8493
8494 /* if positive infinity flag was set to true return infinity */
8495 if( posinf )
8496 return SCIPsetInfinity(set);
8497
8498 return (MAX(lb, SCIPvarGetLbLocal(var))); /*lint !e666*/
8499}
8500
8501/** for a multi-aggregated variable, gives the local upper bound computed by adding the local bounds from all
8502 * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbLocal, since the latter is
8503 * not updated if bounds of aggregation variables are changing
8504 *
8505 * calling this function for a non-multi-aggregated variable is not allowed
8506 */
8508 SCIP_VAR* var, /**< problem variable */
8509 SCIP_SET* set /**< global SCIP settings */
8510 )
8511{
8512 int i;
8513 SCIP_Real ub;
8514 SCIP_Real bnd;
8515 SCIP_VAR* aggrvar;
8516 SCIP_Bool posinf;
8517 SCIP_Bool neginf;
8518
8519 assert(var != NULL);
8520 assert(set != NULL);
8521 assert(var->scip == set->scip);
8523
8524 posinf = FALSE;
8525 neginf = FALSE;
8526 ub = var->data.multaggr.constant;
8527 for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8528 {
8529 aggrvar = var->data.multaggr.vars[i];
8530 if( var->data.multaggr.scalars[i] > 0.0 )
8531 {
8533
8534 if( SCIPsetIsInfinity(set, bnd) )
8535 posinf = TRUE;
8536 else if( SCIPsetIsInfinity(set, -bnd) )
8537 neginf = TRUE;
8538 else
8539 ub += var->data.multaggr.scalars[i] * bnd;
8540 }
8541 else
8542 {
8544
8545 if( SCIPsetIsInfinity(set, -bnd) )
8546 posinf = TRUE;
8547 else if( SCIPsetIsInfinity(set, bnd) )
8548 neginf = TRUE;
8549 else
8550 ub += var->data.multaggr.scalars[i] * bnd;
8551 }
8552
8553 /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
8554 * variable
8555 */
8556 if( posinf )
8557 return SCIPvarGetUbLocal(var);
8558 }
8559
8560 /* if negative infinity flag was set to true return -infinity */
8561 if( neginf )
8562 return -SCIPsetInfinity(set);
8563
8564 return (MIN(ub, SCIPvarGetUbLocal(var))); /*lint !e666*/
8565}
8566
8567/** for a multi-aggregated variable, gives the global lower bound computed by adding the global bounds from all
8568 * aggregation variables, this global bound may be tighter than the one given by SCIPvarGetLbGlobal, since the latter is
8569 * not updated if bounds of aggregation variables are changing
8570 *
8571 * calling this function for a non-multi-aggregated variable is not allowed
8572 */
8574 SCIP_VAR* var, /**< problem variable */
8575 SCIP_SET* set /**< global SCIP settings */
8576 )
8577{
8578 int i;
8579 SCIP_Real lb;
8580 SCIP_Real bnd;
8581 SCIP_VAR* aggrvar;
8582 SCIP_Bool posinf;
8583 SCIP_Bool neginf;
8584
8585 assert(var != NULL);
8586 assert(set != NULL);
8587 assert(var->scip == set->scip);
8589
8590 posinf = FALSE;
8591 neginf = FALSE;
8592 lb = var->data.multaggr.constant;
8593 for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8594 {
8595 aggrvar = var->data.multaggr.vars[i];
8596 if( var->data.multaggr.scalars[i] > 0.0 )
8597 {
8599
8600 if( SCIPsetIsInfinity(set, bnd) )
8601 posinf = TRUE;
8602 else if( SCIPsetIsInfinity(set, -bnd) )
8603 neginf = TRUE;
8604 else
8605 lb += var->data.multaggr.scalars[i] * bnd;
8606 }
8607 else
8608 {
8610
8611 if( SCIPsetIsInfinity(set, -bnd) )
8612 posinf = TRUE;
8613 else if( SCIPsetIsInfinity(set, bnd) )
8614 neginf = TRUE;
8615 else
8616 lb += var->data.multaggr.scalars[i] * bnd;
8617 }
8618
8619 /* stop if two diffrent infinities (or a -infinity) were found and return global lower bound of multi aggregated
8620 * variable
8621 */
8622 if( neginf )
8623 return SCIPvarGetLbGlobal(var);
8624 }
8625
8626 /* if positive infinity flag was set to true return infinity */
8627 if( posinf )
8628 return SCIPsetInfinity(set);
8629
8630 return (MAX(lb, SCIPvarGetLbGlobal(var))); /*lint !e666*/
8631}
8632
8633/** for a multi-aggregated variable, gives the global upper bound computed by adding the global bounds from all
8634 * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbGlobal, since the latter is
8635 * not updated if bounds of aggregation variables are changing
8636 *
8637 * calling this function for a non-multi-aggregated variable is not allowed
8638 */
8640 SCIP_VAR* var, /**< problem variable */
8641 SCIP_SET* set /**< global SCIP settings */
8642 )
8643{
8644 int i;
8645 SCIP_Real ub;
8646 SCIP_Real bnd;
8647 SCIP_VAR* aggrvar;
8648 SCIP_Bool posinf;
8649 SCIP_Bool neginf;
8650
8651 assert(var != NULL);
8652 assert(set != NULL);
8653 assert(var->scip == set->scip);
8655
8656 posinf = FALSE;
8657 neginf = FALSE;
8658 ub = var->data.multaggr.constant;
8659 for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8660 {
8661 aggrvar = var->data.multaggr.vars[i];
8662 if( var->data.multaggr.scalars[i] > 0.0 )
8663 {
8665
8666 if( SCIPsetIsInfinity(set, bnd) )
8667 posinf = TRUE;
8668 else if( SCIPsetIsInfinity(set, -bnd) )
8669 neginf = TRUE;
8670 else
8671 ub += var->data.multaggr.scalars[i] * bnd;
8672 }
8673 else
8674 {
8676
8677 if( SCIPsetIsInfinity(set, -bnd) )
8678 posinf = TRUE;
8679 else if( SCIPsetIsInfinity(set, bnd) )
8680 neginf = TRUE;
8681 else
8682 ub += var->data.multaggr.scalars[i] * bnd;
8683 }
8684
8685 /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
8686 * variable
8687 */
8688 if( posinf )
8689 return SCIPvarGetUbGlobal(var);
8690 }
8691
8692 /* if negative infinity flag was set to true return -infinity */
8693 if( neginf )
8694 return -SCIPsetInfinity(set);
8695
8696 return (MIN(ub, SCIPvarGetUbGlobal(var))); /*lint !e666*/
8697}
8698
8699/** adds a hole to the original domain of the variable */
8701 SCIP_VAR* var, /**< problem variable */
8702 BMS_BLKMEM* blkmem, /**< block memory */
8703 SCIP_SET* set, /**< global SCIP settings */
8704 SCIP_Real left, /**< left bound of open interval in new hole */
8705 SCIP_Real right /**< right bound of open interval in new hole */
8706 )
8707{
8708 SCIP_Bool added;
8709
8710 assert(var != NULL);
8711 assert(!SCIPvarIsTransformed(var));
8714 assert(set != NULL);
8715 assert(var->scip == set->scip);
8716 assert(set->stage == SCIP_STAGE_PROBLEM);
8717
8718 SCIPsetDebugMsg(set, "adding original hole (%g,%g) to <%s>\n", left, right, var->name);
8719
8720 if( SCIPsetIsEQ(set, left, right) )
8721 return SCIP_OKAY;
8722
8723 /* the interval should not be empty */
8724 assert(SCIPsetIsLT(set, left, right));
8725
8726 /* the the interval bound should already be adjusted */
8727 assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8728 assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8729
8730 /* the the interval should lay between the lower and upper bound */
8731 assert(SCIPsetIsGE(set, left, SCIPvarGetLbOriginal(var)));
8732 assert(SCIPsetIsLE(set, right, SCIPvarGetUbOriginal(var)));
8733
8734 /* add domain hole */
8735 SCIP_CALL( domAddHole(&var->data.original.origdom, blkmem, set, left, right, &added) );
8736
8737 /* merges overlapping holes into single holes, moves bounds respectively if hole was added */
8738 if( added )
8739 {
8740 domMerge(&var->data.original.origdom, blkmem, set, NULL, NULL);
8741 }
8742
8743 /**@todo add hole in parent and child variables (just like with bound changes);
8744 * warning! original vars' holes are in original blkmem, transformed vars' holes in transformed blkmem
8745 */
8746
8747 return SCIP_OKAY;
8748}
8749
8750/** performs the current add of domain, changes all parents accordingly */
8751static
8753 SCIP_VAR* var, /**< problem variable */
8754 BMS_BLKMEM* blkmem, /**< block memory */
8755 SCIP_SET* set, /**< global SCIP settings */
8756 SCIP_STAT* stat, /**< problem statistics */
8757 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8758 SCIP_Real left, /**< left bound of open interval in new hole */
8759 SCIP_Real right, /**< right bound of open interval in new hole */
8760 SCIP_Bool* added /**< pointer to store whether the hole was added */
8761 )
8762{
8763 SCIP_VAR* parentvar;
8764 SCIP_Real newlb;
8765 SCIP_Real newub;
8766 int i;
8767
8768 assert(var != NULL);
8769 assert(added != NULL);
8770 assert(blkmem != NULL);
8771
8772 /* the interval should not be empty */
8773 assert(SCIPsetIsLT(set, left, right));
8774
8775 /* the interval bound should already be adjusted */
8776 assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8777 assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8778
8779 /* the interval should lay between the lower and upper bound */
8780 assert(SCIPsetIsGE(set, left, SCIPvarGetLbGlobal(var)));
8781 assert(SCIPsetIsLE(set, right, SCIPvarGetUbGlobal(var)));
8782
8783 /* @todo add debugging mechanism for holes when using a debugging solution */
8784
8785 /* add hole to hole list */
8786 SCIP_CALL( domAddHole(&var->glbdom, blkmem, set, left, right, added) );
8787
8788 /* check if the hole is redundant */
8789 if( !(*added) )
8790 return SCIP_OKAY;
8791
8792 /* current bounds */
8793 newlb = var->glbdom.lb;
8794 newub = var->glbdom.ub;
8795
8796 /* merge domain holes */
8797 domMerge(&var->glbdom, blkmem, set, &newlb, &newub);
8798
8799 /* the bound should not be changed */
8800 assert(SCIPsetIsEQ(set, newlb, var->glbdom.lb));
8801 assert(SCIPsetIsEQ(set, newub, var->glbdom.ub));
8802
8803 /* issue bound change event */
8804 assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
8805 if( var->eventfilter != NULL )
8806 {
8807 SCIP_CALL( varEventGholeAdded(var, blkmem, set, eventqueue, left, right) );
8808 }
8809
8810 /* process parent variables */
8811 for( i = 0; i < var->nparentvars; ++i )
8812 {
8813 SCIP_Real parentnewleft;
8814 SCIP_Real parentnewright;
8815 SCIP_Bool localadded;
8816
8817 parentvar = var->parentvars[i];
8818 assert(parentvar != NULL);
8819
8820 switch( SCIPvarGetStatus(parentvar) )
8821 {
8823 parentnewleft = left;
8824 parentnewright = right;
8825 break;
8826
8831 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
8832 return SCIP_INVALIDDATA;
8833
8834 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8835 assert(parentvar->data.aggregate.var == var);
8836
8837 if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
8838 {
8839 /* a > 0 -> change upper bound of x */
8840 parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8841 parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8842 }
8843 else
8844 {
8845 /* a < 0 -> change lower bound of x */
8846 assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
8847
8848 parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8849 parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8850 }
8851 break;
8852
8853 case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
8854 assert(parentvar->negatedvar != NULL);
8855 assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
8856 assert(parentvar->negatedvar->negatedvar == parentvar);
8857
8858 parentnewright = -left + parentvar->data.negate.constant;
8859 parentnewleft = -right + parentvar->data.negate.constant;
8860 break;
8861
8862 default:
8863 SCIPerrorMessage("unknown variable status\n");
8864 return SCIP_INVALIDDATA;
8865 }
8866
8867 SCIPsetDebugMsg(set, "add global hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
8868
8869 /* perform hole added for parent variable */
8870 assert(blkmem != NULL);
8871 assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
8872 SCIP_CALL( varProcessAddHoleGlobal(parentvar, blkmem, set, stat, eventqueue,
8873 parentnewleft, parentnewright, &localadded) );
8874 assert(localadded);
8875 }
8876
8877 return SCIP_OKAY;
8878}
8879
8880/** adds a hole to the variable's global and local domain */
8882 SCIP_VAR* var, /**< problem variable */
8883 BMS_BLKMEM* blkmem, /**< block memory */
8884 SCIP_SET* set, /**< global SCIP settings */
8885 SCIP_STAT* stat, /**< problem statistics */
8886 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8887 SCIP_Real left, /**< left bound of open interval in new hole */
8888 SCIP_Real right, /**< right bound of open interval in new hole */
8889 SCIP_Bool* added /**< pointer to store whether the hole was added */
8890 )
8891{
8892 SCIP_Real childnewleft;
8893 SCIP_Real childnewright;
8894
8895 assert(var != NULL);
8897 assert(blkmem != NULL);
8898 assert(added != NULL);
8899
8900 SCIPsetDebugMsg(set, "adding global hole (%g,%g) to <%s>\n", left, right, var->name);
8901
8902 /* the interval should not be empty */
8903 assert(SCIPsetIsLT(set, left, right));
8904
8905 /* the the interval bound should already be adjusted */
8906 assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8907 assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8908
8909 /* the the interval should lay between the lower and upper bound */
8910 assert(SCIPsetIsGE(set, left, SCIPvarGetLbGlobal(var)));
8911 assert(SCIPsetIsLE(set, right, SCIPvarGetUbGlobal(var)));
8912
8913 /* change bounds of attached variables */
8914 switch( SCIPvarGetStatus(var) )
8915 {
8917 if( var->data.original.transvar != NULL )
8918 {
8919 SCIP_CALL( SCIPvarAddHoleGlobal(var->data.original.transvar, blkmem, set, stat, eventqueue,
8920 left, right, added) );
8921 }
8922 else
8923 {
8924 assert(set->stage == SCIP_STAGE_PROBLEM);
8925
8926 SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
8927 if( *added )
8928 {
8929 SCIP_Bool localadded;
8930
8931 SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
8932 }
8933 }
8934 break;
8935
8938 SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
8939 if( *added )
8940 {
8941 SCIP_Bool localadded;
8942
8943 SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
8944 }
8945 break;
8946
8948 SCIPerrorMessage("cannot add hole of a fixed variable\n");
8949 return SCIP_INVALIDDATA;
8950
8951 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8952 assert(var->data.aggregate.var != NULL);
8953
8955 {
8956 /* a > 0 -> change lower bound of y */
8957 childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8958 childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8959 }
8960 else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8961 {
8962 childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8963 childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8964 }
8965 else
8966 {
8967 SCIPerrorMessage("scalar is zero in aggregation\n");
8968 return SCIP_INVALIDDATA;
8969 }
8970 SCIP_CALL( SCIPvarAddHoleGlobal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
8971 childnewleft, childnewright, added) );
8972 break;
8973
8975 SCIPerrorMessage("cannot add a hole of a multi-aggregated variable.\n");
8976 return SCIP_INVALIDDATA;
8977
8978 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8979 assert(var->negatedvar != NULL);
8981 assert(var->negatedvar->negatedvar == var);
8982
8983 childnewright = -left + var->data.negate.constant;
8984 childnewleft = -right + var->data.negate.constant;
8985
8986 SCIP_CALL( SCIPvarAddHoleGlobal(var->negatedvar, blkmem, set, stat, eventqueue,
8987 childnewleft, childnewright, added) );
8988 break;
8989
8990 default:
8991 SCIPerrorMessage("unknown variable status\n");
8992 return SCIP_INVALIDDATA;
8993 }
8994
8995 return SCIP_OKAY;
8996}
8997
8998/** performs the current add of domain, changes all parents accordingly */
8999static
9001 SCIP_VAR* var, /**< problem variable */
9002 BMS_BLKMEM* blkmem, /**< block memory */
9003 SCIP_SET* set, /**< global SCIP settings */
9004 SCIP_STAT* stat, /**< problem statistics */
9005 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
9006 SCIP_Real left, /**< left bound of open interval in new hole */
9007 SCIP_Real right, /**< right bound of open interval in new hole */
9008 SCIP_Bool* added /**< pointer to store whether the hole was added, or NULL */
9009 )
9010{
9011 SCIP_VAR* parentvar;
9012 SCIP_Real newlb;
9013 SCIP_Real newub;
9014 int i;
9015
9016 assert(var != NULL);
9017 assert(added != NULL);
9018 assert(blkmem != NULL);
9019
9020 /* the interval should not be empty */
9021 assert(SCIPsetIsLT(set, left, right));
9022
9023 /* the the interval bound should already be adjusted */
9024 assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
9025 assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
9026
9027 /* the the interval should lay between the lower and upper bound */
9028 assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
9029 assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
9030
9031 /* add hole to hole list */
9032 SCIP_CALL( domAddHole(&var->locdom, blkmem, set, left, right, added) );
9033
9034 /* check if the hole is redundant */
9035 if( !(*added) )
9036 return SCIP_OKAY;
9037
9038 /* current bounds */
9039 newlb = var->locdom.lb;
9040 newub = var->locdom.ub;
9041
9042 /* merge domain holes */
9043 domMerge(&var->locdom, blkmem, set, &newlb, &newub);
9044
9045 /* the bound should not be changed */
9046 assert(SCIPsetIsEQ(set, newlb, var->locdom.lb));
9047 assert(SCIPsetIsEQ(set, newub, var->locdom.ub));
9048
9049#ifdef SCIP_DISABLED_CODE
9050 /* issue LHOLEADDED event */
9051 SCIP_EVENT event;
9052 assert(var->eventfilter != NULL);
9054 SCIP_CALL( SCIPeventProcess(&event, set, NULL, NULL, NULL, var->eventfilter) );
9055#endif
9056
9057 /* process parent variables */
9058 for( i = 0; i < var->nparentvars; ++i )
9059 {
9060 SCIP_Real parentnewleft;
9061 SCIP_Real parentnewright;
9062 SCIP_Bool localadded;
9063
9064 parentvar = var->parentvars[i];
9065 assert(parentvar != NULL);
9066
9067 switch( SCIPvarGetStatus(parentvar) )
9068 {
9070 parentnewleft = left;
9071 parentnewright = right;
9072 break;
9073
9078 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
9079 return SCIP_INVALIDDATA;
9080
9081 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
9082 assert(parentvar->data.aggregate.var == var);
9083
9084 if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
9085 {
9086 /* a > 0 -> change upper bound of x */
9087 parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
9088 parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
9089 }
9090 else
9091 {
9092 /* a < 0 -> change lower bound of x */
9093 assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
9094
9095 parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
9096 parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
9097 }
9098 break;
9099
9100 case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
9101 assert(parentvar->negatedvar != NULL);
9102 assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
9103 assert(parentvar->negatedvar->negatedvar == parentvar);
9104
9105 parentnewright = -left + parentvar->data.negate.constant;
9106 parentnewleft = -right + parentvar->data.negate.constant;
9107 break;
9108
9109 default:
9110 SCIPerrorMessage("unknown variable status\n");
9111 return SCIP_INVALIDDATA;
9112 }
9113
9114 SCIPsetDebugMsg(set, "add local hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
9115
9116 /* perform hole added for parent variable */
9117 assert(blkmem != NULL);
9118 assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
9119 SCIP_CALL( varProcessAddHoleLocal(parentvar, blkmem, set, stat, eventqueue,
9120 parentnewleft, parentnewright, &localadded) );
9121 assert(localadded);
9122 }
9123
9124 return SCIP_OKAY;
9125}
9126
9127/** adds a hole to the variable's current local domain */
9129 SCIP_VAR* var, /**< problem variable */
9130 BMS_BLKMEM* blkmem, /**< block memory */
9131 SCIP_SET* set, /**< global SCIP settings */
9132 SCIP_STAT* stat, /**< problem statistics */
9133 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
9134 SCIP_Real left, /**< left bound of open interval in new hole */
9135 SCIP_Real right, /**< right bound of open interval in new hole */
9136 SCIP_Bool* added /**< pointer to store whether the hole was added */
9137 )
9138{
9139 SCIP_Real childnewleft;
9140 SCIP_Real childnewright;
9141
9142 assert(var != NULL);
9143
9144 SCIPsetDebugMsg(set, "adding local hole (%g,%g) to <%s>\n", left, right, var->name);
9145
9146 assert(set != NULL);
9147 assert(var->scip == set->scip);
9149 assert(blkmem != NULL);
9150 assert(added != NULL);
9151
9152 /* the interval should not be empty */
9153 assert(SCIPsetIsLT(set, left, right));
9154
9155 /* the the interval bound should already be adjusted */
9156 assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
9157 assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
9158
9159 /* the the interval should lay between the lower and upper bound */
9160 assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
9161 assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
9162
9163 /* change bounds of attached variables */
9164 switch( SCIPvarGetStatus(var) )
9165 {
9167 if( var->data.original.transvar != NULL )
9168 {
9169 SCIP_CALL( SCIPvarAddHoleLocal(var->data.original.transvar, blkmem, set, stat, eventqueue,
9170 left, right, added) );
9171 }
9172 else
9173 {
9174 assert(set->stage == SCIP_STAGE_PROBLEM);
9175 SCIPstatIncrement(stat, set, domchgcount);
9176 SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
9177 }
9178 break;
9179
9182 SCIPstatIncrement(stat, set, domchgcount);
9183 SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
9184 break;
9185
9187 SCIPerrorMessage("cannot add domain hole to a fixed variable\n");
9188 return SCIP_INVALIDDATA;
9189
9190 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
9191 assert(var->data.aggregate.var != NULL);
9192
9194 {
9195 /* a > 0 -> change lower bound of y */
9196 childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
9197 childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
9198 }
9199 else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
9200 {
9201 childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
9202 childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
9203 }
9204 else
9205 {
9206 SCIPerrorMessage("scalar is zero in aggregation\n");
9207 return SCIP_INVALIDDATA;
9208 }
9209 SCIP_CALL( SCIPvarAddHoleLocal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
9210 childnewleft, childnewright, added) );
9211 break;
9212
9214 SCIPerrorMessage("cannot add domain hole to a multi-aggregated variable.\n");
9215 return SCIP_INVALIDDATA;
9216
9217 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
9218 assert(var->negatedvar != NULL);
9220 assert(var->negatedvar->negatedvar == var);
9221
9222 childnewright = -left + var->data.negate.constant;
9223 childnewleft = -right + var->data.negate.constant;
9224
9225 SCIP_CALL( SCIPvarAddHoleLocal(var->negatedvar, blkmem, set, stat, eventqueue, childnewleft, childnewright, added) );
9226 break;
9227
9228 default:
9229 SCIPerrorMessage("unknown variable status\n");
9230 return SCIP_INVALIDDATA;
9231 }
9232
9233 return SCIP_OKAY;
9234}
9235
9236/** resets the global and local bounds of original variable to their original values */
9238 SCIP_VAR* var, /**< problem variable */
9239 BMS_BLKMEM* blkmem, /**< block memory */
9240 SCIP_SET* set, /**< global SCIP settings */
9241 SCIP_STAT* stat /**< problem statistics */
9242 )
9243{
9244 assert(var != NULL);
9245 assert(set != NULL);
9246 assert(var->scip == set->scip);
9247 assert(SCIPvarIsOriginal(var));
9248 /* resetting of bounds on original variables which have a transformed counterpart easily fails if, e.g.,
9249 * the transformed variable has been fixed */
9250 assert(SCIPvarGetTransVar(var) == NULL);
9251
9252 /* copy the original bounds back to the global and local bounds */
9253 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.lb) );
9254 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.ub) );
9255 SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.lb) );
9256 SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.ub) );
9257
9258 /* free the global and local holelists and duplicate the original ones */
9259 /**@todo this has also to be called recursively with methods similar to SCIPvarChgLbGlobal() */
9260 holelistFree(&var->glbdom.holelist, blkmem);
9261 holelistFree(&var->locdom.holelist, blkmem);
9264
9265 return SCIP_OKAY;
9266}
9267
9268/** issues a IMPLADDED event on the given variable */
9269static
9271 SCIP_VAR* var, /**< problem variable to change */
9272 BMS_BLKMEM* blkmem, /**< block memory */
9273 SCIP_SET* set, /**< global SCIP settings */
9274 SCIP_EVENTQUEUE* eventqueue /**< event queue */
9275 )
9276{
9277 SCIP_EVENT* event;
9278
9279 assert(var != NULL);
9280
9281 /* issue IMPLADDED event on variable */
9282 SCIP_CALL( SCIPeventCreateImplAdded(&event, blkmem, var) );
9283 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
9284
9285 return SCIP_OKAY;
9286}
9287
9288/** actually performs the addition of a variable bound to the variable's vbound arrays */
9289static
9291 SCIP_VAR* var, /**< problem variable x in x <= b*z + d or x >= b*z + d */
9292 BMS_BLKMEM* blkmem, /**< block memory */
9293 SCIP_SET* set, /**< global SCIP settings */
9294 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9295 SCIP_BOUNDTYPE vbtype, /**< type of variable bound (LOWER or UPPER) */
9296 SCIP_VAR* vbvar, /**< variable z in x <= b*z + d or x >= b*z + d */
9297 SCIP_Real vbcoef, /**< coefficient b in x <= b*z + d or x >= b*z + d */
9298 SCIP_Real vbconstant /**< constant d in x <= b*z + d or x >= b*z + d */
9299 )
9300{
9301 SCIP_Bool added;
9302
9303 /* It can happen that the variable "var" and the variable "vbvar" are the same variable. For example if a variable
9304 * gets aggregated, the variable bounds (vbound) of that variable are copied to the other variable. A variable bound
9305 * variable of the aggregated variable might be the same as the one its gets aggregated too.
9306 *
9307 * If the variable "var" and the variable "vbvar" are the same, the variable bound which should be added here has to
9308 * be redundant. This is the case since an infeasibility should have be detected in the previous methods. As well as
9309 * the bounds of the variable which should be also already be tightened in the previous methods. Therefore, the
9310 * variable bound can be ignored.
9311 *
9312 * From the way the the variable bound system is implemented (detecting infeasibility, tighten bounds), the
9313 * equivalence of the variables should be checked here.
9314 */
9315 if( var == vbvar )
9316 {
9317 /* in this case the variable bound has to be redundant, this means for possible assignments to this variable; this
9318 * can be checked via the global bounds of the variable */
9319#ifndef NDEBUG
9320 SCIP_Real lb;
9321 SCIP_Real ub;
9322
9323 lb = SCIPvarGetLbGlobal(var);
9324 ub = SCIPvarGetUbGlobal(var);
9325
9326 if(vbtype == SCIP_BOUNDTYPE_LOWER)
9327 {
9328 if( vbcoef > 0.0 )
9329 {
9330 assert(SCIPsetIsGE(set, lb, lb * vbcoef + vbconstant) );
9331 assert(SCIPsetIsGE(set, ub, ub * vbcoef + vbconstant) );
9332 }
9333 else
9334 {
9335 assert(SCIPsetIsGE(set, lb, ub * vbcoef + vbconstant) );
9336 assert(SCIPsetIsGE(set, ub, lb * vbcoef + vbconstant) );
9337 }
9338 }
9339 else
9340 {
9341 assert(vbtype == SCIP_BOUNDTYPE_UPPER);
9342 if( vbcoef > 0.0 )
9343 {
9344 assert(SCIPsetIsLE(set, lb, lb * vbcoef + vbconstant) );
9345 assert(SCIPsetIsLE(set, ub, ub * vbcoef + vbconstant) );
9346 }
9347 else
9348 {
9349 assert(SCIPsetIsLE(set, lb, ub * vbcoef + vbconstant) );
9350 assert(SCIPsetIsLE(set, ub, lb * vbcoef + vbconstant) );
9351 }
9352 }
9353#endif
9354 SCIPsetDebugMsg(set, "redundant variable bound: <%s> %s %g<%s> %+g\n",
9355 SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
9356
9357 return SCIP_OKAY;
9358 }
9359
9360 SCIPsetDebugMsg(set, "adding variable bound: <%s> %s %g<%s> %+g\n",
9361 SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
9362
9363 /* check variable bound on debugging solution */
9364 SCIP_CALL( SCIPdebugCheckVbound(set, var, vbtype, vbvar, vbcoef, vbconstant) ); /*lint !e506 !e774*/
9365
9366 /* perform the addition */
9367 if( vbtype == SCIP_BOUNDTYPE_LOWER )
9368 {
9369 SCIP_CALL( SCIPvboundsAdd(&var->vlbs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
9370 }
9371 else
9372 {
9373 SCIP_CALL( SCIPvboundsAdd(&var->vubs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
9374 }
9375 var->closestvblpcount = -1;
9376
9377 if( added )
9378 {
9379 /* issue IMPLADDED event */
9380 SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
9381 }
9382
9383 return SCIP_OKAY;
9384}
9385
9386/** checks whether the given implication is redundant or infeasible w.r.t. the implied variables global bounds */
9387static
9389 SCIP_SET* set, /**< global SCIP settings */
9390 SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9391 SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9392 SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9393 SCIP_Bool* redundant, /**< pointer to store whether the implication is redundant */
9394 SCIP_Bool* infeasible /**< pointer to store whether the implication is infeasible */
9395 )
9396{
9397 SCIP_Real impllb;
9398 SCIP_Real implub;
9399
9400 assert(redundant != NULL);
9401 assert(infeasible != NULL);
9402
9403 impllb = SCIPvarGetLbGlobal(implvar);
9404 implub = SCIPvarGetUbGlobal(implvar);
9405 if( impltype == SCIP_BOUNDTYPE_LOWER )
9406 {
9407 *infeasible = SCIPsetIsFeasGT(set, implbound, implub);
9408 *redundant = SCIPsetIsFeasLE(set, implbound, impllb);
9409 }
9410 else
9411 {
9412 *infeasible = SCIPsetIsFeasLT(set, implbound, impllb);
9413 *redundant = SCIPsetIsFeasGE(set, implbound, implub);
9414 }
9415}
9416
9417/** applies the given implication, if it is not redundant */
9418static
9420 BMS_BLKMEM* blkmem, /**< block memory */
9421 SCIP_SET* set, /**< global SCIP settings */
9422 SCIP_STAT* stat, /**< problem statistics */
9423 SCIP_PROB* transprob, /**< transformed problem */
9424 SCIP_PROB* origprob, /**< original problem */
9425 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9426 SCIP_REOPT* reopt, /**< reoptimization data structure */
9427 SCIP_LP* lp, /**< current LP data */
9428 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9429 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9430 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9431 SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9432 SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9433 SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9434 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9435 int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9436 )
9437{
9438 SCIP_Real implub;
9439 SCIP_Real impllb;
9440
9441 assert(infeasible != NULL);
9442
9443 *infeasible = FALSE;
9444
9445 implub = SCIPvarGetUbGlobal(implvar);
9446 impllb = SCIPvarGetLbGlobal(implvar);
9447 if( impltype == SCIP_BOUNDTYPE_LOWER )
9448 {
9449 if( SCIPsetIsFeasGT(set, implbound, implub) )
9450 {
9451 /* the implication produces a conflict: the problem is infeasible */
9452 *infeasible = TRUE;
9453 }
9454 else if( SCIPsetIsFeasGT(set, implbound, impllb) )
9455 {
9456 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9457 * with the local bound, in this case we need to store the bound change as pending bound change
9458 */
9460 {
9461 assert(tree != NULL);
9462 assert(transprob != NULL);
9463 assert(SCIPprobIsTransformed(transprob));
9464
9465 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9466 tree, reopt, lp, branchcand, eventqueue, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
9467 }
9468 else
9469 {
9470 SCIP_CALL( SCIPvarChgLbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
9471 }
9472
9473 if( nbdchgs != NULL )
9474 (*nbdchgs)++;
9475 }
9476 }
9477 else
9478 {
9479 if( SCIPsetIsFeasLT(set, implbound, impllb) )
9480 {
9481 /* the implication produces a conflict: the problem is infeasible */
9482 *infeasible = TRUE;
9483 }
9484 else if( SCIPsetIsFeasLT(set, implbound, implub) )
9485 {
9486 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9487 * with the local bound, in this case we need to store the bound change as pending bound change
9488 */
9490 {
9491 assert(tree != NULL);
9492 assert(transprob != NULL);
9493 assert(SCIPprobIsTransformed(transprob));
9494
9495 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9496 tree, reopt, lp, branchcand, eventqueue, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
9497 }
9498 else
9499 {
9500 SCIP_CALL( SCIPvarChgUbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
9501 }
9502
9503 if( nbdchgs != NULL )
9504 (*nbdchgs)++;
9505 }
9506 }
9507
9508 return SCIP_OKAY;
9509}
9510
9511/** actually performs the addition of an implication to the variable's implication arrays,
9512 * and adds the corresponding implication or variable bound to the implied variable;
9513 * if the implication is conflicting, the variable is fixed to the opposite value;
9514 * if the variable is already fixed to the given value, the implication is performed immediately;
9515 * if the implication is redundant with respect to the variables' global bounds, it is ignored
9516 */
9517static
9519 SCIP_VAR* var, /**< problem variable */
9520 BMS_BLKMEM* blkmem, /**< block memory */
9521 SCIP_SET* set, /**< global SCIP settings */
9522 SCIP_STAT* stat, /**< problem statistics */
9523 SCIP_PROB* transprob, /**< transformed problem */
9524 SCIP_PROB* origprob, /**< original problem */
9525 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9526 SCIP_REOPT* reopt, /**< reoptimization data structure */
9527 SCIP_LP* lp, /**< current LP data */
9528 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9529 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9530 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9531 SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9532 SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9533 SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9534 SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9535 SCIP_Bool isshortcut, /**< is the implication a shortcut, i.e., added as part of the transitive closure of another implication? */
9536 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9537 int* nbdchgs, /**< pointer to count the number of performed bound changes, or NULL */
9538 SCIP_Bool* added /**< pointer to store whether an implication was added */
9539 )
9540{
9541 SCIP_Bool redundant;
9542 SCIP_Bool conflict;
9543
9544 assert(var != NULL);
9545 assert(SCIPvarIsActive(var));
9547 assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
9548 assert(SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED);
9549 assert(infeasible != NULL);
9550 assert(added != NULL);
9551
9552 /* check implication on debugging solution */
9553 SCIP_CALL( SCIPdebugCheckImplic(set, var, varfixing, implvar, impltype, implbound) ); /*lint !e506 !e774*/
9554
9555 *infeasible = FALSE;
9556 *added = FALSE;
9557
9558 /* check, if the implication is redundant or infeasible */
9559 checkImplic(set, implvar, impltype, implbound, &redundant, &conflict);
9560 assert(!redundant || !conflict);
9561 if( redundant )
9562 return SCIP_OKAY;
9563
9564 if( var == implvar )
9565 {
9566 /* special cases appear were a bound to a variable implies itself to be outside the bounds:
9567 * x == varfixing => x < 0 or x > 1
9568 */
9569 if( SCIPsetIsLT(set, implbound, 0.0) || SCIPsetIsGT(set, implbound, 1.0) )
9570 conflict = TRUE;
9571 else
9572 {
9573 /* variable implies itself: x == varfixing => x == (impltype == SCIP_BOUNDTYPE_LOWER) */
9574 assert(SCIPsetIsZero(set, implbound) || SCIPsetIsEQ(set, implbound, 1.0));
9575 assert(SCIPsetIsZero(set, implbound) == (impltype == SCIP_BOUNDTYPE_UPPER));
9576 assert(SCIPsetIsEQ(set, implbound, 1.0) == (impltype == SCIP_BOUNDTYPE_LOWER));
9577 conflict = conflict || ((varfixing == TRUE) == (impltype == SCIP_BOUNDTYPE_UPPER));
9578 if( !conflict )
9579 return SCIP_OKAY;
9580 }
9581 }
9582
9583 /* check, if the variable is already fixed */
9584 if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
9585 {
9586 /* if the variable is fixed to the given value, perform the implication; otherwise, ignore the implication */
9587 if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
9588 {
9589 SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
9590 cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
9591 }
9592 return SCIP_OKAY;
9593 }
9594
9595 assert((impltype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, implbound, SCIPvarGetLbGlobal(implvar)))
9596 || (impltype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, implbound, SCIPvarGetUbGlobal(implvar))));
9597
9598 if( !conflict )
9599 {
9600 assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9601
9602 if( SCIPvarIsBinary(implvar) )
9603 {
9604 SCIP_VAR* vars[2];
9605 SCIP_Bool vals[2];
9606
9607 assert(SCIPsetIsFeasEQ(set, implbound, 1.0) || SCIPsetIsFeasZero(set, implbound));
9608 assert((impltype == SCIP_BOUNDTYPE_UPPER) == SCIPsetIsFeasZero(set, implbound));
9609
9610 vars[0] = var;
9611 vars[1] = implvar;
9612 vals[0] = varfixing;
9613 vals[1] = (impltype == SCIP_BOUNDTYPE_UPPER);
9614
9615 /* add the clique to the clique table */
9616 SCIP_CALL( SCIPcliquetableAdd(cliquetable, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
9617 eventqueue, vars, vals, 2, FALSE, &conflict, nbdchgs) );
9618
9619 if( !conflict )
9620 return SCIP_OKAY;
9621 }
9622 else
9623 {
9624 /* add implication x == 0/1 -> y <= b / y >= b to the implications list of x */
9625 SCIPsetDebugMsg(set, "adding implication: <%s> == %u ==> <%s> %s %g\n",
9626 SCIPvarGetName(var), varfixing,
9627 SCIPvarGetName(implvar), impltype == SCIP_BOUNDTYPE_UPPER ? "<=" : ">=", implbound);
9628 SCIP_CALL( SCIPimplicsAdd(&var->implics, blkmem, set, stat, varfixing, implvar, impltype, implbound,
9629 isshortcut, &conflict, added) );
9630 }
9631 }
9632 assert(!conflict || !(*added));
9633
9634 /* on conflict, fix the variable to the opposite value */
9635 if( conflict )
9636 {
9637 SCIPsetDebugMsg(set, " -> implication yields a conflict: fix <%s> == %d\n", SCIPvarGetName(var), !varfixing);
9638
9639 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9640 * with the local bound, in this case we need to store the bound change as pending bound change
9641 */
9643 {
9644 assert(tree != NULL);
9645 assert(transprob != NULL);
9646 assert(SCIPprobIsTransformed(transprob));
9647
9648 if( varfixing )
9649 {
9650 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9651 tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
9652 }
9653 else
9654 {
9655 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9656 tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
9657 }
9658 }
9659 else
9660 {
9661 if( varfixing )
9662 {
9663 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
9664 }
9665 else
9666 {
9667 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
9668 }
9669 }
9670 if( nbdchgs != NULL )
9671 (*nbdchgs)++;
9672
9673 return SCIP_OKAY;
9674 }
9675 else if( *added )
9676 {
9677 /* issue IMPLADDED event */
9678 SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
9679 }
9680 else
9681 {
9682 /* the implication was redundant: the inverse is also redundant */
9683 return SCIP_OKAY;
9684 }
9685
9686 assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9687
9688 /* check, whether implied variable is binary */
9689 if( !SCIPvarIsBinary(implvar) )
9690 {
9691 SCIP_Real lb;
9692 SCIP_Real ub;
9693
9694 /* add inverse variable bound to the variable bounds of y with global bounds y \in [lb,ub]:
9695 * x == 0 -> y <= b <-> y <= (ub - b)*x + b
9696 * x == 1 -> y <= b <-> y <= (b - ub)*x + ub
9697 * x == 0 -> y >= b <-> y >= (lb - b)*x + b
9698 * x == 1 -> y >= b <-> y >= (b - lb)*x + lb
9699 * for numerical reasons, ignore variable bounds with large absolute coefficient
9700 */
9701 lb = SCIPvarGetLbGlobal(implvar);
9702 ub = SCIPvarGetUbGlobal(implvar);
9703 if( impltype == SCIP_BOUNDTYPE_UPPER )
9704 {
9705 if( REALABS(implbound - ub) <= MAXABSVBCOEF )
9706 {
9707 SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, var,
9708 varfixing ? implbound - ub : ub - implbound, varfixing ? ub : implbound) );
9709 }
9710 }
9711 else
9712 {
9713 if( REALABS(implbound - lb) <= MAXABSVBCOEF )
9714 {
9715 SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, var,
9716 varfixing ? implbound - lb : lb - implbound, varfixing ? lb : implbound) );
9717 }
9718 }
9719 }
9720
9721 return SCIP_OKAY;
9722}
9723
9724/** adds transitive closure for binary implication x = a -> y = b */
9725static
9727 SCIP_VAR* var, /**< problem variable */
9728 BMS_BLKMEM* blkmem, /**< block memory */
9729 SCIP_SET* set, /**< global SCIP settings */
9730 SCIP_STAT* stat, /**< problem statistics */
9731 SCIP_PROB* transprob, /**< transformed problem */
9732 SCIP_PROB* origprob, /**< original problem */
9733 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9734 SCIP_REOPT* reopt, /**< reoptimization data structure */
9735 SCIP_LP* lp, /**< current LP data */
9736 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9737 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9738 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9739 SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9740 SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9741 SCIP_Bool implvarfixing, /**< fixing b in implication */
9742 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9743 int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9744 )
9745{
9746 SCIP_VAR** implvars;
9747 SCIP_BOUNDTYPE* impltypes;
9748 SCIP_Real* implbounds;
9749 int nimpls;
9750 int i;
9751
9752 *infeasible = FALSE;
9753
9754 /* binary variable: implications of implvar */
9755 nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
9756 implvars = SCIPimplicsGetVars(implvar->implics, implvarfixing);
9757 impltypes = SCIPimplicsGetTypes(implvar->implics, implvarfixing);
9758 implbounds = SCIPimplicsGetBounds(implvar->implics, implvarfixing);
9759
9760 /* if variable has too many implications, the implication graph may become too dense */
9761 i = MIN(nimpls, MAXIMPLSCLOSURE) - 1;
9762
9763 /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9764 * implvars[i] is fixed, s.t. the implication y == varfixing -> z <= b / z >= b is deleted; this affects the
9765 * array over which we currently iterate; the only thing that can happen, is that elements of the array are
9766 * deleted; in this case, the subsequent elements are moved to the front; if we iterate from back to front, the
9767 * only thing that can happen is that we add the same implication twice - this does no harm
9768 */
9769 while ( i >= 0 && !(*infeasible) )
9770 {
9771 SCIP_Bool added;
9772
9773 assert(implvars[i] != implvar);
9774
9775 /* we have x == varfixing -> y == implvarfixing -> z <= b / z >= b:
9776 * add implication x == varfixing -> z <= b / z >= b to the implications list of x
9777 */
9778 if( SCIPvarIsActive(implvars[i]) )
9779 {
9780 SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
9781 eventqueue, varfixing, implvars[i], impltypes[i], implbounds[i], TRUE, infeasible, nbdchgs, &added) );
9782 assert(SCIPimplicsGetNImpls(implvar->implics, implvarfixing) <= nimpls);
9783 nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
9784 i = MIN(i, nimpls); /* some elements from the array could have been removed */
9785 }
9786 --i;
9787 }
9788
9789 return SCIP_OKAY;
9790}
9791
9792/** adds given implication to the variable's implication list, and adds all implications directly implied by this
9793 * implication to the variable's implication list;
9794 * if the implication is conflicting, the variable is fixed to the opposite value;
9795 * if the variable is already fixed to the given value, the implication is performed immediately;
9796 * if the implication is redundant with respect to the variables' global bounds, it is ignored
9797 */
9798static
9800 SCIP_VAR* var, /**< problem variable */
9801 BMS_BLKMEM* blkmem, /**< block memory */
9802 SCIP_SET* set, /**< global SCIP settings */
9803 SCIP_STAT* stat, /**< problem statistics */
9804 SCIP_PROB* transprob, /**< transformed problem */
9805 SCIP_PROB* origprob, /**< original problem */
9806 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9807 SCIP_REOPT* reopt, /**< reoptimization data structure */
9808 SCIP_LP* lp, /**< current LP data */
9809 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9810 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9811 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9812 SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9813 SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9814 SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9815 SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9816 SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
9817 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9818 int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9819 )
9820{
9821 SCIP_Bool added;
9822
9823 assert(var != NULL);
9824 assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
9825 assert(SCIPvarIsActive(var));
9826 assert(implvar != NULL);
9827 assert(SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED);
9828 assert(infeasible != NULL);
9829
9830 /* add implication x == varfixing -> y <= b / y >= b to the implications list of x */
9831 SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
9832 eventqueue, varfixing, implvar, impltype, implbound, FALSE, infeasible, nbdchgs, &added) );
9833
9834 if( *infeasible || var == implvar || !transitive || !added )
9835 return SCIP_OKAY;
9836
9837 assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9838
9839 /* add transitive closure */
9840 if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
9841 {
9842 SCIP_Bool implvarfixing;
9843
9844 implvarfixing = (impltype == SCIP_BOUNDTYPE_LOWER);
9845
9846 /* binary variable: implications of implvar */
9847 SCIP_CALL( varAddTransitiveBinaryClosureImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9848 cliquetable, branchcand, eventqueue, varfixing, implvar, implvarfixing, infeasible, nbdchgs) );
9849
9850 /* inverse implication */
9851 if( !(*infeasible) )
9852 {
9853 SCIP_CALL( varAddTransitiveBinaryClosureImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9854 cliquetable, branchcand, eventqueue, !implvarfixing, var, !varfixing, infeasible, nbdchgs) );
9855 }
9856 }
9857 else
9858 {
9859 /* non-binary variable: variable lower bounds of implvar */
9860 if( impltype == SCIP_BOUNDTYPE_UPPER && implvar->vlbs != NULL )
9861 {
9862 SCIP_VAR** vlbvars;
9863 SCIP_Real* vlbcoefs;
9864 SCIP_Real* vlbconstants;
9865 int nvlbvars;
9866 int i;
9867
9868 nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
9869 vlbvars = SCIPvboundsGetVars(implvar->vlbs);
9870 vlbcoefs = SCIPvboundsGetCoefs(implvar->vlbs);
9871 vlbconstants = SCIPvboundsGetConstants(implvar->vlbs);
9872
9873 /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9874 * vlbvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
9875 * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
9876 * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
9877 * is that we add the same implication twice - this does no harm
9878 */
9879 i = nvlbvars-1;
9880 while ( i >= 0 && !(*infeasible) )
9881 {
9882 assert(vlbvars[i] != implvar);
9883 assert(!SCIPsetIsZero(set, vlbcoefs[i]));
9884
9885 /* we have x == varfixing -> y <= b and y >= c*z + d:
9886 * c > 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
9887 * c < 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
9888 *
9889 * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
9890 * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
9891 * aggregation variable (the one which will stay active);
9892 *
9893 * W.l.o.g. we consider the variable upper bounds for now. Let "vubvar" be a variable upper bound of
9894 * the aggregated variable "aggvar"; During that copying of that variable upper bound variable
9895 * "vubvar" the variable lower and upper bounds of this variable "vubvar" are also considered; note
9896 * that the "aggvar" can be a variable lower bound variable of the variable "vubvar"; Due to that
9897 * situation it can happen that we reach that code place where "vlbvars[i] == aggvar". In particular
9898 * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
9899 * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
9900 * have to explicitly check that the active variable has not a variable status
9901 * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
9902 */
9903 if( SCIPvarIsActive(vlbvars[i]) && SCIPvarGetStatus(vlbvars[i]) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(vlbvars[i]) != SCIP_VARSTATUS_NEGATED )
9904 {
9905 SCIP_Real vbimplbound;
9906
9907 vbimplbound = (implbound - vlbconstants[i])/vlbcoefs[i];
9908 if( vlbcoefs[i] >= 0.0 )
9909 {
9910 vbimplbound = adjustedUb(set, SCIPvarGetType(vlbvars[i]), vbimplbound);
9911 SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9912 branchcand, eventqueue, varfixing, vlbvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
9913 infeasible, nbdchgs, &added) );
9914 }
9915 else
9916 {
9917 vbimplbound = adjustedLb(set, SCIPvarGetType(vlbvars[i]), vbimplbound);
9918 SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9919 branchcand, eventqueue, varfixing, vlbvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
9920 infeasible, nbdchgs, &added) );
9921 }
9922 nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
9923 i = MIN(i, nvlbvars); /* some elements from the array could have been removed */
9924 }
9925 --i;
9926 }
9927 }
9928
9929 /* non-binary variable: variable upper bounds of implvar */
9930 if( impltype == SCIP_BOUNDTYPE_LOWER && implvar->vubs != NULL )
9931 {
9932 SCIP_VAR** vubvars;
9933 SCIP_Real* vubcoefs;
9934 SCIP_Real* vubconstants;
9935 int nvubvars;
9936 int i;
9937
9938 nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
9939 vubvars = SCIPvboundsGetVars(implvar->vubs);
9940 vubcoefs = SCIPvboundsGetCoefs(implvar->vubs);
9941 vubconstants = SCIPvboundsGetConstants(implvar->vubs);
9942
9943 /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9944 * vubvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
9945 * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
9946 * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
9947 * is that we add the same implication twice - this does no harm
9948 */
9949 i = nvubvars-1;
9950 while ( i >= 0 && !(*infeasible) )
9951 {
9952 assert(vubvars[i] != implvar);
9953 assert(!SCIPsetIsZero(set, vubcoefs[i]));
9954
9955 /* we have x == varfixing -> y >= b and y <= c*z + d:
9956 * c > 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
9957 * c < 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
9958 *
9959 * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
9960 * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
9961 * aggregation variable (the one which will stay active);
9962 *
9963 * W.l.o.g. we consider the variable lower bounds for now. Let "vlbvar" be a variable lower bound of
9964 * the aggregated variable "aggvar"; During that copying of that variable lower bound variable
9965 * "vlbvar" the variable lower and upper bounds of this variable "vlbvar" are also considered; note
9966 * that the "aggvar" can be a variable upper bound variable of the variable "vlbvar"; Due to that
9967 * situation it can happen that we reach that code place where "vubvars[i] == aggvar". In particular
9968 * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
9969 * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
9970 * have to explicitly check that the active variable has not a variable status
9971 * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
9972 */
9973 if( SCIPvarIsActive(vubvars[i]) && SCIPvarGetStatus(vubvars[i]) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(vubvars[i]) != SCIP_VARSTATUS_NEGATED )
9974 {
9975 SCIP_Real vbimplbound;
9976
9977 vbimplbound = (implbound - vubconstants[i])/vubcoefs[i];
9978 if( vubcoefs[i] >= 0.0 )
9979 {
9980 vbimplbound = adjustedLb(set, SCIPvarGetType(vubvars[i]), vbimplbound);
9981 SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9982 branchcand, eventqueue, varfixing, vubvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
9983 infeasible, nbdchgs, &added) );
9984 }
9985 else
9986 {
9987 vbimplbound = adjustedUb(set, SCIPvarGetType(vubvars[i]), vbimplbound);
9988 SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9989 branchcand, eventqueue, varfixing, vubvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
9990 infeasible, nbdchgs, &added) );
9991 }
9992 nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
9993 i = MIN(i, nvubvars); /* some elements from the array could have been removed */
9994 }
9995 --i;
9996 }
9997 }
9998 }
9999
10000 return SCIP_OKAY;
10001}
10002
10003/** informs variable x about a globally valid variable lower bound x >= b*z + d with integer variable z;
10004 * if z is binary, the corresponding valid implication for z is also added;
10005 * improves the global bounds of the variable and the vlb variable if possible
10006 */
10008 SCIP_VAR* var, /**< problem variable */
10009 BMS_BLKMEM* blkmem, /**< block memory */
10010 SCIP_SET* set, /**< global SCIP settings */
10011 SCIP_STAT* stat, /**< problem statistics */
10012 SCIP_PROB* transprob, /**< transformed problem */
10013 SCIP_PROB* origprob, /**< original problem */
10014 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10015 SCIP_REOPT* reopt, /**< reoptimization data structure */
10016 SCIP_LP* lp, /**< current LP data */
10017 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10018 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10019 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10020 SCIP_VAR* vlbvar, /**< variable z in x >= b*z + d */
10021 SCIP_Real vlbcoef, /**< coefficient b in x >= b*z + d */
10022 SCIP_Real vlbconstant, /**< constant d in x >= b*z + d */
10023 SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
10024 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10025 int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
10026 )
10027{
10028 assert(var != NULL);
10029 assert(set != NULL);
10030 assert(var->scip == set->scip);
10031 assert(SCIPvarGetType(vlbvar) != SCIP_VARTYPE_CONTINUOUS);
10032 assert(infeasible != NULL);
10033
10034 SCIPsetDebugMsg(set, "adding variable lower bound <%s> >= %g<%s> + %g\n", SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
10035
10036 *infeasible = FALSE;
10037 if( nbdchgs != NULL )
10038 *nbdchgs = 0;
10039
10040 switch( SCIPvarGetStatus(var) )
10041 {
10043 assert(var->data.original.transvar != NULL);
10044 SCIP_CALL( SCIPvarAddVlb(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10045 cliquetable, branchcand, eventqueue, vlbvar, vlbcoef, vlbconstant, transitive, infeasible, nbdchgs) );
10046 break;
10047
10051 /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
10052 SCIP_CALL( SCIPvarGetProbvarSum(&vlbvar, set, &vlbcoef, &vlbconstant) );
10053 SCIPsetDebugMsg(set, " -> transformed to variable lower bound <%s> >= %g<%s> + %g\n",
10054 SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
10055
10056 /* if the variables are the same, just update the corresponding bound */
10057 if( var == vlbvar )
10058 {
10059 /* if the variables cancel out, the variable bound constraint is redundant or proves global infeasibility */
10060 if( SCIPsetIsEQ(set, vlbcoef, 1.0) )
10061 {
10062 if( SCIPsetIsFeasPositive(set, vlbconstant) )
10063 *infeasible = TRUE;
10064 }
10065 else
10066 {
10067 SCIP_Real lb = SCIPvarGetLbGlobal(var);
10068 SCIP_Real ub = SCIPvarGetUbGlobal(var);
10069
10070 /* the variable bound constraint defines a new upper bound */
10071 if( SCIPsetIsGT(set, vlbcoef, 1.0) )
10072 {
10073 SCIP_Real newub = vlbconstant / (1.0 - vlbcoef);
10074
10075 if( SCIPsetIsFeasLT(set, newub, lb) )
10076 {
10077 *infeasible = TRUE;
10078 return SCIP_OKAY;
10079 }
10080 else if( SCIPsetIsFeasLT(set, newub, ub) )
10081 {
10082 /* bound might be adjusted due to integrality condition */
10083 newub = adjustedUb(set, SCIPvarGetType(var), newub);
10084
10085 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10086 * with the local bound, in this case we need to store the bound change as pending bound change
10087 */
10089 {
10090 assert(tree != NULL);
10091 assert(transprob != NULL);
10092 assert(SCIPprobIsTransformed(transprob));
10093
10094 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10095 tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10096 }
10097 else
10098 {
10099 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newub) );
10100 }
10101
10102 if( nbdchgs != NULL )
10103 (*nbdchgs)++;
10104 }
10105 }
10106 /* the variable bound constraint defines a new lower bound */
10107 else
10108 {
10109 SCIP_Real newlb;
10110
10111 assert(SCIPsetIsLT(set, vlbcoef, 1.0));
10112
10113 newlb = vlbconstant / (1.0 - vlbcoef);
10114
10115 if( SCIPsetIsFeasGT(set, newlb, ub) )
10116 {
10117 *infeasible = TRUE;
10118 return SCIP_OKAY;
10119 }
10120 else if( SCIPsetIsFeasGT(set, newlb, lb) )
10121 {
10122 /* bound might be adjusted due to integrality condition */
10123 newlb = adjustedLb(set, SCIPvarGetType(var), newlb);
10124
10125 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10126 * with the local bound, in this case we need to store the bound change as pending bound change
10127 */
10129 {
10130 assert(tree != NULL);
10131 assert(transprob != NULL);
10132 assert(SCIPprobIsTransformed(transprob));
10133
10134 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10135 tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10136 }
10137 else
10138 {
10139 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newlb) );
10140 }
10141
10142 if( nbdchgs != NULL )
10143 (*nbdchgs)++;
10144 }
10145 }
10146 }
10147 }
10148 /* if the vlb coefficient is zero, just update the lower bound of the variable */
10149 else if( SCIPsetIsZero(set, vlbcoef) )
10150 {
10151 if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetUbGlobal(var)) )
10152 *infeasible = TRUE;
10153 else if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetLbGlobal(var)) )
10154 {
10155 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10156 * with the local bound, in this case we need to store the bound change as pending bound change
10157 */
10159 {
10160 assert(tree != NULL);
10161 assert(transprob != NULL);
10162 assert(SCIPprobIsTransformed(transprob));
10163
10164 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10165 tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vlbconstant, SCIP_BOUNDTYPE_LOWER, FALSE) );
10166 }
10167 else
10168 {
10169 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vlbconstant) );
10170 }
10171
10172 if( nbdchgs != NULL )
10173 (*nbdchgs)++;
10174 }
10175 }
10176 else if( SCIPvarIsActive(vlbvar) )
10177 {
10178 SCIP_Real xlb;
10179 SCIP_Real xub;
10180 SCIP_Real zlb;
10181 SCIP_Real zub;
10182 SCIP_Real minvlb;
10183 SCIP_Real maxvlb;
10184
10186 assert(vlbcoef != 0.0);
10187
10188 minvlb = -SCIPsetInfinity(set);
10189 maxvlb = SCIPsetInfinity(set);
10190
10191 xlb = SCIPvarGetLbGlobal(var);
10192 xub = SCIPvarGetUbGlobal(var);
10193 zlb = SCIPvarGetLbGlobal(vlbvar);
10194 zub = SCIPvarGetUbGlobal(vlbvar);
10195
10196 /* improve global bounds of vlb variable, and calculate minimal and maximal value of variable bound */
10197 if( vlbcoef >= 0.0 )
10198 {
10199 SCIP_Real newzub;
10200
10201 if( !SCIPsetIsInfinity(set, xub) )
10202 {
10203 /* x >= b*z + d -> z <= (x-d)/b */
10204 newzub = (xub - vlbconstant)/vlbcoef;
10205
10206 /* return if the new bound is less than -infinity */
10207 if( SCIPsetIsInfinity(set, REALABS(newzub)) )
10208 return SCIP_OKAY;
10209
10210 if( SCIPsetIsFeasLT(set, newzub, zlb) )
10211 {
10212 *infeasible = TRUE;
10213 return SCIP_OKAY;
10214 }
10215 if( SCIPsetIsFeasLT(set, newzub, zub) )
10216 {
10217 /* bound might be adjusted due to integrality condition */
10218 newzub = adjustedUb(set, SCIPvarGetType(vlbvar), newzub);
10219
10220 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10221 * with the local bound, in this case we need to store the bound change as pending bound change
10222 */
10224 {
10225 assert(tree != NULL);
10226 assert(transprob != NULL);
10227 assert(SCIPprobIsTransformed(transprob));
10228
10229 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10230 tree, reopt, lp, branchcand, eventqueue, cliquetable, vlbvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10231 }
10232 else
10233 {
10234 SCIP_CALL( SCIPvarChgUbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
10235 }
10236 zub = newzub;
10237
10238 if( nbdchgs != NULL )
10239 (*nbdchgs)++;
10240 }
10241 maxvlb = vlbcoef * zub + vlbconstant;
10242 if( !SCIPsetIsInfinity(set, -zlb) )
10243 minvlb = vlbcoef * zlb + vlbconstant;
10244 }
10245 else
10246 {
10247 if( !SCIPsetIsInfinity(set, zub) )
10248 maxvlb = vlbcoef * zub + vlbconstant;
10249 if( !SCIPsetIsInfinity(set, -zlb) )
10250 minvlb = vlbcoef * zlb + vlbconstant;
10251 }
10252 }
10253 else
10254 {
10255 SCIP_Real newzlb;
10256
10257 if( !SCIPsetIsInfinity(set, xub) )
10258 {
10259 /* x >= b*z + d -> z >= (x-d)/b */
10260 newzlb = (xub - vlbconstant)/vlbcoef;
10261
10262 /* return if the new bound is larger than infinity */
10263 if( SCIPsetIsInfinity(set, REALABS(newzlb)) )
10264 return SCIP_OKAY;
10265
10266 if( SCIPsetIsFeasGT(set, newzlb, zub) )
10267 {
10268 *infeasible = TRUE;
10269 return SCIP_OKAY;
10270 }
10271 if( SCIPsetIsFeasGT(set, newzlb, zlb) )
10272 {
10273 /* bound might be adjusted due to integrality condition */
10274 newzlb = adjustedLb(set, SCIPvarGetType(vlbvar), newzlb);
10275
10276 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10277 * with the local bound, in this case we need to store the bound change as pending bound change
10278 */
10280 {
10281 assert(tree != NULL);
10282 assert(transprob != NULL);
10283 assert(SCIPprobIsTransformed(transprob));
10284
10285 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10286 tree, reopt, lp, branchcand, eventqueue, cliquetable, vlbvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10287 }
10288 else
10289 {
10290 SCIP_CALL( SCIPvarChgLbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
10291 }
10292 zlb = newzlb;
10293
10294 if( nbdchgs != NULL )
10295 (*nbdchgs)++;
10296 }
10297 maxvlb = vlbcoef * zlb + vlbconstant;
10298 if( !SCIPsetIsInfinity(set, zub) )
10299 minvlb = vlbcoef * zub + vlbconstant;
10300 }
10301 else
10302 {
10303 if( !SCIPsetIsInfinity(set, -zlb) )
10304 maxvlb = vlbcoef * zlb + vlbconstant;
10305 if( !SCIPsetIsInfinity(set, zub) )
10306 minvlb = vlbcoef * zub + vlbconstant;
10307 }
10308 }
10309 if( maxvlb < minvlb )
10310 maxvlb = minvlb;
10311
10312 /* adjust bounds due to integrality of variable */
10313 minvlb = adjustedLb(set, SCIPvarGetType(var), minvlb);
10314 maxvlb = adjustedLb(set, SCIPvarGetType(var), maxvlb);
10315
10316 /* check bounds for feasibility */
10317 if( SCIPsetIsFeasGT(set, minvlb, xub) )
10318 {
10319 *infeasible = TRUE;
10320 return SCIP_OKAY;
10321 }
10322 /* improve global lower bound of variable */
10323 if( SCIPsetIsFeasGT(set, minvlb, xlb) )
10324 {
10325 /* bound might be adjusted due to integrality condition */
10326 minvlb = adjustedLb(set, SCIPvarGetType(var), minvlb);
10327
10328 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10329 * with the local bound, in this case we need to store the bound change as pending bound change
10330 */
10332 {
10333 assert(tree != NULL);
10334 assert(transprob != NULL);
10335 assert(SCIPprobIsTransformed(transprob));
10336
10337 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10338 tree, reopt, lp, branchcand, eventqueue, cliquetable, var, minvlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10339 }
10340 else
10341 {
10342 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, minvlb) );
10343 }
10344 xlb = minvlb;
10345
10346 if( nbdchgs != NULL )
10347 (*nbdchgs)++;
10348 }
10349 minvlb = xlb;
10350
10351 /* improve variable bound for binary z by moving the variable's global bound to the vlb constant */
10352 if( SCIPvarGetType(vlbvar) == SCIP_VARTYPE_BINARY )
10353 {
10354 /* b > 0: x >= (maxvlb - minvlb) * z + minvlb
10355 * b < 0: x >= (minvlb - maxvlb) * z + maxvlb
10356 */
10357
10358 assert(!SCIPsetIsInfinity(set, maxvlb) && !SCIPsetIsInfinity(set, -minvlb));
10359
10360 if( vlbcoef >= 0.0 )
10361 {
10362 vlbcoef = maxvlb - minvlb;
10363 vlbconstant = minvlb;
10364 }
10365 else
10366 {
10367 vlbcoef = minvlb - maxvlb;
10368 vlbconstant = maxvlb;
10369 }
10370 }
10371
10372 /* add variable bound to the variable bounds list */
10373 if( SCIPsetIsFeasGT(set, maxvlb, xlb) )
10374 {
10375 assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED);
10376 assert(!SCIPsetIsZero(set, vlbcoef));
10377
10378 /* if one of the variables is binary, add the corresponding implication to the variable's implication
10379 * list, thereby also adding the variable bound (or implication) to the other variable
10380 */
10381 if( SCIPvarGetType(vlbvar) == SCIP_VARTYPE_BINARY )
10382 {
10383 /* add corresponding implication:
10384 * b > 0, x >= b*z + d <-> z == 1 -> x >= b+d
10385 * b < 0, x >= b*z + d <-> z == 0 -> x >= d
10386 */
10387 SCIP_CALL( varAddTransitiveImplic(vlbvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10388 cliquetable, branchcand, eventqueue, (vlbcoef >= 0.0), var, SCIP_BOUNDTYPE_LOWER, maxvlb, transitive,
10389 infeasible, nbdchgs) );
10390 }
10391 else if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
10392 {
10393 /* add corresponding implication:
10394 * b > 0, x >= b*z + d <-> x == 0 -> z <= -d/b
10395 * b < 0, x >= b*z + d <-> x == 0 -> z >= -d/b
10396 */
10397 SCIP_Real implbound;
10398 implbound = -vlbconstant/vlbcoef;
10399
10400 /* tighten the implication bound if the variable is integer */
10401 if( SCIPvarIsIntegral(vlbvar) )
10402 {
10403 if( vlbcoef >= 0 )
10404 implbound = SCIPsetFloor(set, implbound);
10405 else
10406 implbound = SCIPsetCeil(set, implbound);
10407 }
10408 SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10409 cliquetable, branchcand, eventqueue, FALSE, vlbvar, (vlbcoef >= 0.0 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER),
10410 implbound, transitive, infeasible, nbdchgs) );
10411 }
10412 else
10413 {
10414 SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, vlbvar, vlbcoef, vlbconstant) );
10415 }
10416 }
10417 }
10418 break;
10419
10421 /* x = a*y + c: x >= b*z + d <=> a*y + c >= b*z + d <=> y >= b/a * z + (d-c)/a, if a > 0
10422 * y <= b/a * z + (d-c)/a, if a < 0
10423 */
10424
10425 /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
10426 SCIP_CALL( SCIPvarGetProbvarSum(&vlbvar, set, &vlbcoef, &vlbconstant) );
10427
10428 /* if the variables cancel out, the variable bound constraint is redundant or proves global infeasibility */
10429 assert(var->data.aggregate.var != NULL);
10430 if( var->data.aggregate.var == vlbvar && SCIPsetIsEQ(set, var->data.aggregate.scalar, vlbcoef) )
10431 {
10432 if( SCIPsetIsFeasLT(set, var->data.aggregate.constant, vlbconstant) )
10433 *infeasible = TRUE;
10434 }
10435 else if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
10436 {
10437 /* a > 0 -> add variable lower bound */
10438 SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10439 cliquetable, branchcand, eventqueue, vlbvar, vlbcoef/var->data.aggregate.scalar,
10440 (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10441 }
10442 else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
10443 {
10444 /* a < 0 -> add variable upper bound */
10445 SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10446 cliquetable, branchcand, eventqueue, vlbvar, vlbcoef/var->data.aggregate.scalar,
10447 (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10448 }
10449 else
10450 {
10451 SCIPerrorMessage("scalar is zero in aggregation\n");
10452 return SCIP_INVALIDDATA;
10453 }
10454 break;
10455
10457 /* nothing to do here */
10458 break;
10459
10461 /* x = offset - x': x >= b*z + d <=> offset - x' >= b*z + d <=> x' <= -b*z + (offset-d) */
10462 assert(var->negatedvar != NULL);
10464 assert(var->negatedvar->negatedvar == var);
10465 SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10466 branchcand, eventqueue, vlbvar, -vlbcoef, var->data.negate.constant - vlbconstant, transitive, infeasible,
10467 nbdchgs) );
10468 break;
10469
10470 default:
10471 SCIPerrorMessage("unknown variable status\n");
10472 return SCIP_INVALIDDATA;
10473 }
10474
10475 return SCIP_OKAY;
10476}
10477
10478/** informs variable x about a globally valid variable upper bound x <= b*z + d with integer variable z;
10479 * if z is binary, the corresponding valid implication for z is also added;
10480 * updates the global bounds of the variable and the vub variable correspondingly
10481 */
10483 SCIP_VAR* var, /**< problem variable */
10484 BMS_BLKMEM* blkmem, /**< block memory */
10485 SCIP_SET* set, /**< global SCIP settings */
10486 SCIP_STAT* stat, /**< problem statistics */
10487 SCIP_PROB* transprob, /**< transformed problem */
10488 SCIP_PROB* origprob, /**< original problem */
10489 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10490 SCIP_REOPT* reopt, /**< reoptimization data structure */
10491 SCIP_LP* lp, /**< current LP data */
10492 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10493 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10494 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10495 SCIP_VAR* vubvar, /**< variable z in x <= b*z + d */
10496 SCIP_Real vubcoef, /**< coefficient b in x <= b*z + d */
10497 SCIP_Real vubconstant, /**< constant d in x <= b*z + d */
10498 SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
10499 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10500 int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
10501 )
10502{
10503 assert(var != NULL);
10504 assert(set != NULL);
10505 assert(var->scip == set->scip);
10506 assert(SCIPvarGetType(vubvar) != SCIP_VARTYPE_CONTINUOUS);
10507 assert(infeasible != NULL);
10508
10509 SCIPsetDebugMsg(set, "adding variable upper bound <%s> <= %g<%s> + %g\n", SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
10510
10511 *infeasible = FALSE;
10512 if( nbdchgs != NULL )
10513 *nbdchgs = 0;
10514
10515 switch( SCIPvarGetStatus(var) )
10516 {
10518 assert(var->data.original.transvar != NULL);
10519 SCIP_CALL( SCIPvarAddVub(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10520 cliquetable, branchcand, eventqueue, vubvar, vubcoef, vubconstant, transitive, infeasible, nbdchgs) );
10521 break;
10522
10526 /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
10527 SCIP_CALL( SCIPvarGetProbvarSum(&vubvar, set, &vubcoef, &vubconstant) );
10528 SCIPsetDebugMsg(set, " -> transformed to variable upper bound <%s> <= %g<%s> + %g\n",
10529 SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
10530
10531 /* if the variables are the same, just update the corresponding bound */
10532 if( var == vubvar )
10533 {
10534 /* if the variables cancel out, the variable bound constraint is redundant or proves global infeasibility */
10535 if( SCIPsetIsEQ(set, vubcoef, 1.0) )
10536 {
10537 if( SCIPsetIsFeasNegative(set, vubconstant) )
10538 *infeasible = TRUE;
10539 }
10540 else
10541 {
10542 SCIP_Real lb = SCIPvarGetLbGlobal(var);
10543 SCIP_Real ub = SCIPvarGetUbGlobal(var);
10544
10545 /* the variable bound constraint defines a new lower bound */
10546 if( SCIPsetIsGT(set, vubcoef, 1.0) )
10547 {
10548 SCIP_Real newlb = vubconstant / (1.0 - vubcoef);
10549
10550 if( SCIPsetIsFeasGT(set, newlb, ub) )
10551 {
10552 *infeasible = TRUE;
10553 return SCIP_OKAY;
10554 }
10555 else if( SCIPsetIsFeasGT(set, newlb, lb) )
10556 {
10557 /* bound might be adjusted due to integrality condition */
10558 newlb = adjustedLb(set, SCIPvarGetType(var), newlb);
10559
10560 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10561 * with the local bound, in this case we need to store the bound change as pending bound change
10562 */
10564 {
10565 assert(tree != NULL);
10566 assert(transprob != NULL);
10567 assert(SCIPprobIsTransformed(transprob));
10568
10569 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10570 tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10571 }
10572 else
10573 {
10574 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newlb) );
10575 }
10576
10577 if( nbdchgs != NULL )
10578 (*nbdchgs)++;
10579 }
10580 }
10581 /* the variable bound constraint defines a new upper bound */
10582 else
10583 {
10584 SCIP_Real newub;
10585
10586 assert(SCIPsetIsLT(set, vubcoef, 1.0));
10587
10588 newub = vubconstant / (1.0 - vubcoef);
10589
10590 if( SCIPsetIsFeasLT(set, newub, lb) )
10591 {
10592 *infeasible = TRUE;
10593 return SCIP_OKAY;
10594 }
10595 else if( SCIPsetIsFeasLT(set, newub, ub) )
10596 {
10597 /* bound might be adjusted due to integrality condition */
10598 newub = adjustedUb(set, SCIPvarGetType(var), newub);
10599
10600 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10601 * with the local bound, in this case we need to store the bound change as pending bound change
10602 */
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 /* if the vub coefficient is zero, just update the upper bound of the variable */
10624 else if( SCIPsetIsZero(set, vubcoef) )
10625 {
10626 if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetLbGlobal(var)) )
10627 *infeasible = TRUE;
10628 else if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetUbGlobal(var)) )
10629 {
10630 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10631 * with the local bound, in this case we need to store the bound change as pending bound change
10632 */
10634 {
10635 assert(tree != NULL);
10636 assert(transprob != NULL);
10637 assert(SCIPprobIsTransformed(transprob));
10638
10639 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10640 tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vubconstant, SCIP_BOUNDTYPE_UPPER, FALSE) );
10641 }
10642 else
10643 {
10644 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vubconstant) );
10645 }
10646
10647 if( nbdchgs != NULL )
10648 (*nbdchgs)++;
10649 }
10650 }
10651 else if( SCIPvarIsActive(vubvar) )
10652 {
10653 SCIP_Real xlb;
10654 SCIP_Real xub;
10655 SCIP_Real zlb;
10656 SCIP_Real zub;
10657 SCIP_Real minvub;
10658 SCIP_Real maxvub;
10659
10661 assert(vubcoef != 0.0);
10662
10663 minvub = -SCIPsetInfinity(set);
10664 maxvub = SCIPsetInfinity(set);
10665
10666 xlb = SCIPvarGetLbGlobal(var);
10667 xub = SCIPvarGetUbGlobal(var);
10668 zlb = SCIPvarGetLbGlobal(vubvar);
10669 zub = SCIPvarGetUbGlobal(vubvar);
10670
10671 /* improve global bounds of vub variable, and calculate minimal and maximal value of variable bound */
10672 if( vubcoef >= 0.0 )
10673 {
10674 SCIP_Real newzlb;
10675
10676 if( !SCIPsetIsInfinity(set, -xlb) )
10677 {
10678 /* x <= b*z + d -> z >= (x-d)/b */
10679 newzlb = (xlb - vubconstant)/vubcoef;
10680 if( SCIPsetIsFeasGT(set, newzlb, zub) )
10681 {
10682 *infeasible = TRUE;
10683 return SCIP_OKAY;
10684 }
10685 if( SCIPsetIsFeasGT(set, newzlb, zlb) )
10686 {
10687 /* bound might be adjusted due to integrality condition */
10688 newzlb = adjustedLb(set, SCIPvarGetType(vubvar), newzlb);
10689
10690 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10691 * with the local bound, in this case we need to store the bound change as pending bound change
10692 */
10694 {
10695 assert(tree != NULL);
10696 assert(transprob != NULL);
10697 assert(SCIPprobIsTransformed(transprob));
10698
10699 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10700 tree, reopt, lp, branchcand, eventqueue, cliquetable, vubvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10701 }
10702 else
10703 {
10704 SCIP_CALL( SCIPvarChgLbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
10705 }
10706 zlb = newzlb;
10707
10708 if( nbdchgs != NULL )
10709 (*nbdchgs)++;
10710 }
10711 minvub = vubcoef * zlb + vubconstant;
10712 if( !SCIPsetIsInfinity(set, zub) )
10713 maxvub = vubcoef * zub + vubconstant;
10714 }
10715 else
10716 {
10717 if( !SCIPsetIsInfinity(set, zub) )
10718 maxvub = vubcoef * zub + vubconstant;
10719 if( !SCIPsetIsInfinity(set, -zlb) )
10720 minvub = vubcoef * zlb + vubconstant;
10721 }
10722 }
10723 else
10724 {
10725 SCIP_Real newzub;
10726
10727 if( !SCIPsetIsInfinity(set, -xlb) )
10728 {
10729 /* x <= b*z + d -> z <= (x-d)/b */
10730 newzub = (xlb - vubconstant)/vubcoef;
10731 if( SCIPsetIsFeasLT(set, newzub, zlb) )
10732 {
10733 *infeasible = TRUE;
10734 return SCIP_OKAY;
10735 }
10736 if( SCIPsetIsFeasLT(set, newzub, zub) )
10737 {
10738 /* bound might be adjusted due to integrality condition */
10739 newzub = adjustedUb(set, SCIPvarGetType(vubvar), newzub);
10740
10741 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10742 * with the local bound, in this case we need to store the bound change as pending bound change
10743 */
10745 {
10746 assert(tree != NULL);
10747 assert(transprob != NULL);
10748 assert(SCIPprobIsTransformed(transprob));
10749
10750 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10751 tree, reopt, lp, branchcand, eventqueue, cliquetable, vubvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10752 }
10753 else
10754 {
10755 SCIP_CALL( SCIPvarChgUbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
10756 }
10757 zub = newzub;
10758
10759 if( nbdchgs != NULL )
10760 (*nbdchgs)++;
10761 }
10762 minvub = vubcoef * zub + vubconstant;
10763 if( !SCIPsetIsInfinity(set, -zlb) )
10764 maxvub = vubcoef * zlb + vubconstant;
10765 }
10766 else
10767 {
10768 if( !SCIPsetIsInfinity(set, zub) )
10769 minvub = vubcoef * zub + vubconstant;
10770 if( !SCIPsetIsInfinity(set, -zlb) )
10771 maxvub = vubcoef * zlb + vubconstant;
10772 }
10773 }
10774 if( minvub > maxvub )
10775 minvub = maxvub;
10776
10777 /* adjust bounds due to integrality of vub variable */
10778 minvub = adjustedUb(set, SCIPvarGetType(var), minvub);
10779 maxvub = adjustedUb(set, SCIPvarGetType(var), maxvub);
10780
10781 /* check bounds for feasibility */
10782 if( SCIPsetIsFeasLT(set, maxvub, xlb) )
10783 {
10784 *infeasible = TRUE;
10785 return SCIP_OKAY;
10786 }
10787
10788 /* improve global upper bound of variable */
10789 if( SCIPsetIsFeasLT(set, maxvub, xub) )
10790 {
10791 /* bound might be adjusted due to integrality condition */
10792 maxvub = adjustedUb(set, SCIPvarGetType(var), maxvub);
10793
10794 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10795 * with the local bound, in this case we need to store the bound change as pending bound change
10796 */
10798 {
10799 assert(tree != NULL);
10800 assert(transprob != NULL);
10801 assert(SCIPprobIsTransformed(transprob));
10802
10803 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10804 tree, reopt, lp, branchcand, eventqueue, cliquetable, var, maxvub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10805 }
10806 else
10807 {
10808 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, maxvub) );
10809 }
10810 xub = maxvub;
10811
10812 if( nbdchgs != NULL )
10813 (*nbdchgs)++;
10814 }
10815 maxvub = xub;
10816
10817 /* improve variable bound for binary z by moving the variable's global bound to the vub constant */
10818 if( SCIPvarIsBinary(vubvar) )
10819 {
10820 /* b > 0: x <= (maxvub - minvub) * z + minvub
10821 * b < 0: x <= (minvub - maxvub) * z + maxvub
10822 */
10823
10824 assert(!SCIPsetIsInfinity(set, maxvub) && !SCIPsetIsInfinity(set, -minvub));
10825
10826 if( vubcoef >= 0.0 )
10827 {
10828 vubcoef = maxvub - minvub;
10829 vubconstant = minvub;
10830 }
10831 else
10832 {
10833 vubcoef = minvub - maxvub;
10834 vubconstant = maxvub;
10835 }
10836 }
10837
10838 /* add variable bound to the variable bounds list */
10839 if( SCIPsetIsFeasLT(set, minvub, xub) )
10840 {
10841 assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED);
10842 assert(!SCIPsetIsZero(set, vubcoef));
10843
10844 /* if one of the variables is binary, add the corresponding implication to the variable's implication
10845 * list, thereby also adding the variable bound (or implication) to the other variable
10846 */
10847 if( SCIPvarGetType(vubvar) == SCIP_VARTYPE_BINARY )
10848 {
10849 /* add corresponding implication:
10850 * b > 0, x <= b*z + d <-> z == 0 -> x <= d
10851 * b < 0, x <= b*z + d <-> z == 1 -> x <= b+d
10852 */
10853 SCIP_CALL( varAddTransitiveImplic(vubvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10854 cliquetable, branchcand, eventqueue, (vubcoef < 0.0), var, SCIP_BOUNDTYPE_UPPER, minvub, transitive,
10855 infeasible, nbdchgs) );
10856 }
10857 else if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
10858 {
10859 /* add corresponding implication:
10860 * b > 0, x <= b*z + d <-> x == 1 -> z >= (1-d)/b
10861 * b < 0, x <= b*z + d <-> x == 1 -> z <= (1-d)/b
10862 */
10863 SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10864 cliquetable, branchcand, eventqueue, TRUE, vubvar, (vubcoef >= 0.0 ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER),
10865 (1.0-vubconstant)/vubcoef, transitive, infeasible, nbdchgs) );
10866 }
10867 else
10868 {
10869 SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, vubvar, vubcoef, vubconstant) );
10870 }
10871 }
10872 }
10873 break;
10874
10876 /* x = a*y + c: x <= b*z + d <=> a*y + c <= b*z + d <=> y <= b/a * z + (d-c)/a, if a > 0
10877 * y >= b/a * z + (d-c)/a, if a < 0
10878 */
10879
10880 /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
10881 SCIP_CALL( SCIPvarGetProbvarSum(&vubvar, set, &vubcoef, &vubconstant) );
10882
10883 /* if the variables cancel out, the variable bound constraint is redundant or proves global infeasibility */
10884 assert(var->data.aggregate.var != NULL);
10885 if( var->data.aggregate.var == vubvar && SCIPsetIsEQ(set, var->data.aggregate.scalar, vubcoef) )
10886 {
10887 if( SCIPsetIsFeasGT(set, var->data.aggregate.constant, vubconstant) )
10888 *infeasible = TRUE;
10889 }
10890 else if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
10891 {
10892 /* a > 0 -> add variable upper bound */
10893 SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10894 cliquetable, branchcand, eventqueue, vubvar, vubcoef/var->data.aggregate.scalar,
10895 (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10896 }
10897 else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
10898 {
10899 /* a < 0 -> add variable lower bound */
10900 SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10901 cliquetable, branchcand, eventqueue, vubvar, vubcoef/var->data.aggregate.scalar,
10902 (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10903 }
10904 else
10905 {
10906 SCIPerrorMessage("scalar is zero in aggregation\n");
10907 return SCIP_INVALIDDATA;
10908 }
10909 break;
10910
10912 /* nothing to do here */
10913 break;
10914
10916 /* x = offset - x': x <= b*z + d <=> offset - x' <= b*z + d <=> x' >= -b*z + (offset-d) */
10917 assert(var->negatedvar != NULL);
10919 assert(var->negatedvar->negatedvar == var);
10920 SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10921 branchcand, eventqueue, vubvar, -vubcoef, var->data.negate.constant - vubconstant, transitive, infeasible,
10922 nbdchgs) );
10923 break;
10924
10925 default:
10926 SCIPerrorMessage("unknown variable status\n");
10927 return SCIP_INVALIDDATA;
10928 }
10929
10930 return SCIP_OKAY;
10931}
10932
10933/** informs binary variable x about a globally valid implication: x == 0 or x == 1 ==> y <= b or y >= b;
10934 * also adds the corresponding implication or variable bound to the implied variable;
10935 * if the implication is conflicting, the variable is fixed to the opposite value;
10936 * if the variable is already fixed to the given value, the implication is performed immediately;
10937 * if the implication is redundant with respect to the variables' global bounds, it is ignored
10938 */
10940 SCIP_VAR* var, /**< problem variable */
10941 BMS_BLKMEM* blkmem, /**< block memory */
10942 SCIP_SET* set, /**< global SCIP settings */
10943 SCIP_STAT* stat, /**< problem statistics */
10944 SCIP_PROB* transprob, /**< transformed problem */
10945 SCIP_PROB* origprob, /**< original problem */
10946 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10947 SCIP_REOPT* reopt, /**< reoptimization data structure */
10948 SCIP_LP* lp, /**< current LP data */
10949 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10950 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10951 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10952 SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
10953 SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
10954 SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
10955 SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
10956 SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
10957 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10958 int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
10959 )
10960{
10961 assert(var != NULL);
10962 assert(set != NULL);
10963 assert(var->scip == set->scip);
10964 assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
10965 assert(infeasible != NULL);
10966
10967 *infeasible = FALSE;
10968 if( nbdchgs != NULL )
10969 *nbdchgs = 0;
10970
10971 switch( SCIPvarGetStatus(var) )
10972 {
10974 assert(var->data.original.transvar != NULL);
10975 SCIP_CALL( SCIPvarAddImplic(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10976 cliquetable, branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible,
10977 nbdchgs) );
10978 break;
10979
10982 /* if the variable is fixed (although it has no FIXED status), and varfixing corresponds to the fixed value of
10983 * the variable, the implication can be applied directly;
10984 * otherwise, add implication to the implications list (and add inverse of implication to the implied variable)
10985 */
10986 if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
10987 {
10988 if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
10989 {
10990 SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
10991 cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
10992 }
10993 }
10994 else
10995 {
10996 SCIP_CALL( SCIPvarGetProbvarBound(&implvar, &implbound, &impltype) );
10997 SCIPvarAdjustBd(implvar, set, impltype, &implbound);
10998 if( SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED )
10999 {
11000 SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
11001 branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
11002 }
11003 }
11004 break;
11005
11007 /* if varfixing corresponds to the fixed value of the variable, the implication can be applied directly */
11008 if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
11009 {
11010 SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
11011 cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
11012 }
11013 break;
11014
11016 /* implication added for x == 1:
11017 * x == 1 && x = 1*z + 0 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
11018 * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
11019 * implication added for x == 0:
11020 * x == 0 && x = 1*z + 0 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
11021 * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
11022 *
11023 * use only binary variables z
11024 */
11025 assert(var->data.aggregate.var != NULL);
11026 if( SCIPvarIsBinary(var->data.aggregate.var) )
11027 {
11028 assert( (SCIPsetIsEQ(set, var->data.aggregate.scalar, 1.0) && SCIPsetIsZero(set, var->data.aggregate.constant))
11029 || (SCIPsetIsEQ(set, var->data.aggregate.scalar, -1.0) && SCIPsetIsEQ(set, var->data.aggregate.constant, 1.0)) );
11030
11031 if( var->data.aggregate.scalar > 0 )
11032 {
11033 SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11034 cliquetable, branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible,
11035 nbdchgs) );
11036 }
11037 else
11038 {
11039 SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11040 cliquetable, branchcand, eventqueue, !varfixing, implvar, impltype, implbound, transitive, infeasible,
11041 nbdchgs) );
11042 }
11043 }
11044 break;
11045
11047 /* nothing to do here */
11048 break;
11049
11051 /* implication added for x == 1:
11052 * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
11053 * implication added for x == 0:
11054 * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
11055 */
11056 assert(var->negatedvar != NULL);
11058 assert(var->negatedvar->negatedvar == var);
11059 assert(SCIPvarIsBinary(var->negatedvar));
11060
11062 {
11063 SCIP_CALL( SCIPvarAddImplic(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11064 cliquetable, branchcand, eventqueue, !varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
11065 }
11066 /* in case one both variables are not of binary type we have to add the implication as variable bounds */
11067 else
11068 {
11069 /* if the implied variable is of binary type exchange the variables */
11070 if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
11071 {
11072 SCIP_CALL( SCIPvarAddImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
11073 branchcand, eventqueue, (impltype == SCIP_BOUNDTYPE_UPPER) ? TRUE : FALSE, var->negatedvar,
11074 varfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER, varfixing ? 1.0 : 0.0, transitive,
11075 infeasible, nbdchgs) );
11076 }
11077 else
11078 {
11079 /* both variables are not of binary type but are implicit binary; in that case we can only add this
11080 * implication as variable bounds
11081 */
11082
11083 /* add variable lower bound on the negation of var */
11084 if( varfixing )
11085 {
11086 /* (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
11087 * as variable lower bound
11088 */
11089 SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11090 cliquetable, branchcand, eventqueue, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : -1.0,
11091 (impltype == SCIP_BOUNDTYPE_UPPER) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
11092 }
11093 else
11094 {
11095 /* (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
11096 * as variable upper bound
11097 */
11098 SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
11099 cliquetable, branchcand, eventqueue, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? -1.0 : 1.0,
11100 (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : 0.0, transitive, infeasible, nbdchgs) );
11101 }
11102
11103 /* add variable bound on implvar */
11104 if( impltype == SCIP_BOUNDTYPE_UPPER )
11105 {
11106 /* (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
11107 * as variable upper bound
11108 */
11109 SCIP_CALL( SCIPvarAddVub(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
11110 branchcand, eventqueue, var->negatedvar, (varfixing) ? 1.0 : -1.0,
11111 (varfixing) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
11112 }
11113 else
11114 {
11115 /* (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
11116 * as variable upper bound
11117 */
11118 SCIP_CALL( SCIPvarAddVlb(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
11119 branchcand, eventqueue, var->negatedvar, (varfixing) ? -1.0 : 1.0, (varfixing) ? 1.0 : 0.0,
11120 transitive, infeasible, nbdchgs) );
11121 }
11122 }
11123 }
11124 break;
11125
11126 default:
11127 SCIPerrorMessage("unknown variable status\n");
11128 return SCIP_INVALIDDATA;
11129 }
11130
11131 return SCIP_OKAY;
11132}
11133
11134/** returns whether there is an implication x == varfixing -> y <= b or y >= b in the implication graph;
11135 * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
11136 * both variables must be active, variable x must be binary
11137 */
11139 SCIP_VAR* var, /**< problem variable x */
11140 SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
11141 SCIP_VAR* implvar, /**< variable y to search for */
11142 SCIP_BOUNDTYPE impltype /**< type of implication y <=/>= b to search for */
11143 )
11144{
11145 assert(var != NULL);
11146 assert(implvar != NULL);
11147 assert(SCIPvarIsActive(var));
11148 assert(SCIPvarIsActive(implvar));
11149 assert(SCIPvarIsBinary(var));
11150
11151 return var->implics != NULL && SCIPimplicsContainsImpl(var->implics, varfixing, implvar, impltype);
11152}
11153
11154/** returns whether there is an implication x == varfixing -> y == implvarfixing in the implication graph;
11155 * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
11156 * both variables must be active binary variables
11157 */
11159 SCIP_VAR* var, /**< problem variable x */
11160 SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
11161 SCIP_VAR* implvar, /**< variable y to search for */
11162 SCIP_Bool implvarfixing /**< value of the implied variable to search for */
11163 )
11164{
11165 assert(SCIPvarIsBinary(implvar));
11166
11167 return SCIPvarHasImplic(var, varfixing, implvar, implvarfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER);
11168}
11169
11170/** gets the values of b in implications x == varfixing -> y <= b or y >= b in the implication graph;
11171 * the values are set to SCIP_INVALID if there is no implied bound
11172 */
11174 SCIP_VAR* var, /**< problem variable x */
11175 SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
11176 SCIP_VAR* implvar, /**< variable y to search for */
11177 SCIP_Real* lb, /**< buffer to store the value of the implied lower bound */
11178 SCIP_Real* ub /**< buffer to store the value of the implied upper bound */
11179 )
11180{
11181 int lowerpos;
11182 int upperpos;
11183 SCIP_Real* bounds;
11184
11185 assert(lb != NULL);
11186 assert(ub != NULL);
11187
11188 *lb = SCIP_INVALID;
11189 *ub = SCIP_INVALID;
11190
11191 if( var->implics == NULL )
11192 return;
11193
11194 SCIPimplicsGetVarImplicPoss(var->implics, varfixing, implvar, &lowerpos, &upperpos);
11195 bounds = SCIPvarGetImplBounds(var, varfixing);
11196
11197 if( bounds == NULL )
11198 return;
11199
11200 if( lowerpos >= 0 )
11201 *lb = bounds[lowerpos];
11202
11203 if( upperpos >= 0 )
11204 *ub = bounds[upperpos];
11205}
11206
11207
11208/** fixes the bounds of a binary variable to the given value, counting bound changes and detecting infeasibility */
11210 SCIP_VAR* var, /**< problem variable */
11211 BMS_BLKMEM* blkmem, /**< block memory */
11212 SCIP_SET* set, /**< global SCIP settings */
11213 SCIP_STAT* stat, /**< problem statistics */
11214 SCIP_PROB* transprob, /**< transformed problem */
11215 SCIP_PROB* origprob, /**< original problem */
11216 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
11217 SCIP_REOPT* reopt, /**< reoptimization data structure */
11218 SCIP_LP* lp, /**< current LP data */
11219 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
11220 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
11221 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11222 SCIP_Bool value, /**< value to fix variable to */
11223 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
11224 int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
11225 )
11226{
11227 assert(var != NULL);
11228 assert(set != NULL);
11229 assert(var->scip == set->scip);
11230 assert(infeasible != NULL);
11231
11232 *infeasible = FALSE;
11233
11234 if( value == FALSE )
11235 {
11236 if( var->glbdom.lb > 0.5 )
11237 *infeasible = TRUE;
11238 else if( var->glbdom.ub > 0.5 )
11239 {
11240 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
11241 * with the local bound, in this case we need to store the bound change as pending bound change
11242 */
11244 {
11245 assert(tree != NULL);
11246 assert(transprob != NULL);
11247 assert(SCIPprobIsTransformed(transprob));
11248
11249 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
11250 tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
11251 }
11252 else
11253 {
11254 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
11255 }
11256
11257 if( nbdchgs != NULL )
11258 (*nbdchgs)++;
11259 }
11260 }
11261 else
11262 {
11263 if( var->glbdom.ub < 0.5 )
11264 *infeasible = TRUE;
11265 else if( var->glbdom.lb < 0.5 )
11266 {
11267 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
11268 * with the local bound, in this case we need to store the bound change as pending bound change
11269 */
11271 {
11272 assert(tree != NULL);
11273 assert(transprob != NULL);
11274 assert(SCIPprobIsTransformed(transprob));
11275
11276 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
11277 tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
11278 }
11279 else
11280 {
11281 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
11282 }
11283
11284 if( nbdchgs != NULL )
11285 (*nbdchgs)++;
11286 }
11287 }
11288
11289 return SCIP_OKAY;
11290}
11291
11292/** adds the variable to the given clique and updates the list of cliques the binary variable is member of;
11293 * if the variable now appears twice in the clique with the same value, it is fixed to the opposite value;
11294 * if the variable now appears twice in the clique with opposite values, all other variables are fixed to
11295 * the opposite of the value they take in the clique
11296 */
11298 SCIP_VAR* var, /**< problem variable */
11299 BMS_BLKMEM* blkmem, /**< block memory */
11300 SCIP_SET* set, /**< global SCIP settings */
11301 SCIP_STAT* stat, /**< problem statistics */
11302 SCIP_PROB* transprob, /**< transformed problem */
11303 SCIP_PROB* origprob, /**< original problem */
11304 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
11305 SCIP_REOPT* reopt, /**< reoptimization data structure */
11306 SCIP_LP* lp, /**< current LP data */
11307 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
11308 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
11309 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11310 SCIP_Bool value, /**< value of the variable in the clique */
11311 SCIP_CLIQUE* clique, /**< clique the variable should be added to */
11312 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
11313 int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
11314 )
11315{
11316 assert(var != NULL);
11317 assert(set != NULL);
11318 assert(var->scip == set->scip);
11319 assert(SCIPvarIsBinary(var));
11320 assert(infeasible != NULL);
11321
11322 *infeasible = FALSE;
11323
11324 /* get corresponding active problem variable */
11325 SCIP_CALL( SCIPvarGetProbvarBinary(&var, &value) );
11330 assert(SCIPvarIsBinary(var));
11331
11332 /* only column and loose variables may be member of a clique */
11334 {
11335 SCIP_Bool doubleentry;
11336 SCIP_Bool oppositeentry;
11337
11338 /* add variable to clique */
11339 SCIP_CALL( SCIPcliqueAddVar(clique, blkmem, set, var, value, &doubleentry, &oppositeentry) );
11340
11341 /* add clique to variable's clique list */
11342 SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
11343
11344 /* check consistency of cliquelist */
11346
11347 /* if the variable now appears twice with the same value in the clique, it can be fixed to the opposite value */
11348 if( doubleentry )
11349 {
11350 SCIP_CALL( SCIPvarFixBinary(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
11351 eventqueue, cliquetable, !value, infeasible, nbdchgs) );
11352 }
11353
11354 /* if the variable appears with both values in the clique, all other variables of the clique can be fixed
11355 * to the opposite of the value they take in the clique
11356 */
11357 if( oppositeentry )
11358 {
11359 SCIP_VAR** vars;
11360 SCIP_Bool* values;
11361 int nvars;
11362 int i;
11363
11364 nvars = SCIPcliqueGetNVars(clique);
11365 vars = SCIPcliqueGetVars(clique);
11366 values = SCIPcliqueGetValues(clique);
11367 for( i = 0; i < nvars && !(*infeasible); ++i )
11368 {
11369 if( vars[i] == var )
11370 continue;
11371
11372 SCIP_CALL( SCIPvarFixBinary(vars[i], blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
11373 eventqueue, cliquetable, !values[i], infeasible, nbdchgs) );
11374 }
11375 }
11376 }
11377
11378 return SCIP_OKAY;
11379}
11380
11381/** adds a filled clique to the cliquelists of all corresponding variables */
11383 SCIP_VAR** vars, /**< problem variables */
11384 SCIP_Bool* values, /**< values of the variables in the clique */
11385 int nvars, /**< number of problem variables */
11386 BMS_BLKMEM* blkmem, /**< block memory */
11387 SCIP_SET* set, /**< global SCIP settings */
11388 SCIP_CLIQUE* clique /**< clique that contains all given variables and values */
11389 )
11390{
11391 SCIP_VAR* var;
11392 int v;
11393
11394 assert(vars != NULL);
11395 assert(values != NULL);
11396 assert(nvars > 0);
11397 assert(set != NULL);
11398 assert(blkmem != NULL);
11399 assert(clique != NULL);
11400
11401 for( v = nvars - 1; v >= 0; --v )
11402 {
11403 var = vars[v];
11404 assert(SCIPvarIsBinary(var));
11406
11407 /* add clique to variable's clique list */
11408 SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, values[v], clique) );
11409
11410 /* check consistency of cliquelist */
11412 }
11413
11414 return SCIP_OKAY;
11415}
11416
11417/** adds a clique to the list of cliques of the given binary variable, but does not change the clique
11418 * itself
11419 */
11421 SCIP_VAR* var, /**< problem variable */
11422 BMS_BLKMEM* blkmem, /**< block memory */
11423 SCIP_SET* set, /**< global SCIP settings */
11424 SCIP_Bool value, /**< value of the variable in the clique */
11425 SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
11426 )
11427{
11428 assert(var != NULL);
11429 assert(SCIPvarIsBinary(var));
11431
11432 /* add clique to variable's clique list */
11433 SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
11434
11435 return SCIP_OKAY;
11436}
11437
11438
11439/** deletes a clique from the list of cliques the binary variable is member of, but does not change the clique
11440 * itself
11441 */
11443 SCIP_VAR* var, /**< problem variable */
11444 BMS_BLKMEM* blkmem, /**< block memory */
11445 SCIP_Bool value, /**< value of the variable in the clique */
11446 SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
11447 )
11448{
11449 assert(var != NULL);
11450 assert(SCIPvarIsBinary(var));
11451
11452 /* delete clique from variable's clique list */
11453 SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
11454
11455 return SCIP_OKAY;
11456}
11457
11458/** deletes the variable from the given clique and updates the list of cliques the binary variable is member of */
11460 SCIP_VAR* var, /**< problem variable */
11461 BMS_BLKMEM* blkmem, /**< block memory */
11462 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11463 SCIP_Bool value, /**< value of the variable in the clique */
11464 SCIP_CLIQUE* clique /**< clique the variable should be removed from */
11465 )
11466{
11467 assert(var != NULL);
11468 assert(SCIPvarIsBinary(var));
11469
11470 /* get corresponding active problem variable */
11471 SCIP_CALL( SCIPvarGetProbvarBinary(&var, &value) );
11476 assert(SCIPvarIsBinary(var));
11477
11478 /* only column and loose variables may be member of a clique */
11480 {
11481 /* delete clique from variable's clique list */
11482 SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
11483
11484 /* delete variable from clique */
11485 SCIPcliqueDelVar(clique, cliquetable, var, value);
11486
11487 /* check consistency of cliquelist */
11489 }
11490
11491 return SCIP_OKAY;
11492}
11493
11494/** returns whether there is a clique that contains both given variable/value pairs;
11495 * the variables must be active binary variables;
11496 * if regardimplics is FALSE, only the cliques in the clique table are looked at;
11497 * if regardimplics is TRUE, both the cliques and the implications of the implication graph are regarded
11498 *
11499 * @note a variable with it's negated variable are NOT! in a clique
11500 * @note a variable with itself are in a clique
11501 */
11503 SCIP_VAR* var1, /**< first variable */
11504 SCIP_Bool value1, /**< value of first variable */
11505 SCIP_VAR* var2, /**< second variable */
11506 SCIP_Bool value2, /**< value of second variable */
11507 SCIP_Bool regardimplics /**< should the implication graph also be searched for a clique? */
11508 )
11509{
11510 assert(var1 != NULL);
11511 assert(var2 != NULL);
11512 assert(SCIPvarIsActive(var1));
11513 assert(SCIPvarIsActive(var2));
11514 assert(SCIPvarIsBinary(var1));
11515 assert(SCIPvarIsBinary(var2));
11516
11517 return (SCIPcliquelistsHaveCommonClique(var1->cliquelist, value1, var2->cliquelist, value2)
11518 || (regardimplics && SCIPvarHasImplic(var1, value1, var2, value2 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER)));
11519}
11520
11521/** actually changes the branch factor of the variable and of all parent variables */
11522static
11524 SCIP_VAR* var, /**< problem variable */
11525 SCIP_SET* set, /**< global SCIP settings */
11526 SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
11527 )
11528{
11529 SCIP_VAR* parentvar;
11530 SCIP_Real eps;
11531 int i;
11532
11533 assert(var != NULL);
11534 assert(set != NULL);
11535 assert(var->scip == set->scip);
11536
11537 /* only use positive values */
11539 branchfactor = MAX(branchfactor, eps);
11540
11541 SCIPsetDebugMsg(set, "process changing branch factor of <%s> from %f to %f\n", var->name, var->branchfactor, branchfactor);
11542
11543 if( SCIPsetIsEQ(set, branchfactor, var->branchfactor) )
11544 return SCIP_OKAY;
11545
11546 /* change the branch factor */
11547 var->branchfactor = branchfactor;
11548
11549 /* process parent variables */
11550 for( i = 0; i < var->nparentvars; ++i )
11551 {
11552 parentvar = var->parentvars[i];
11553 assert(parentvar != NULL);
11554
11555 switch( SCIPvarGetStatus(parentvar) )
11556 {
11558 /* do not change priorities across the border between transformed and original problem */
11559 break;
11560
11565 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11566 SCIPABORT();
11567 return SCIP_INVALIDDATA; /*lint !e527*/
11568
11571 SCIP_CALL( varProcessChgBranchFactor(parentvar, set, branchfactor) );
11572 break;
11573
11574 default:
11575 SCIPerrorMessage("unknown variable status\n");
11576 SCIPABORT();
11577 return SCIP_ERROR; /*lint !e527*/
11578 }
11579 }
11580
11581 return SCIP_OKAY;
11582}
11583
11584/** sets the branch factor of the variable; this value can be used in the branching methods to scale the score
11585 * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
11586 */
11588 SCIP_VAR* var, /**< problem variable */
11589 SCIP_SET* set, /**< global SCIP settings */
11590 SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
11591 )
11592{
11593 int v;
11594
11595 assert(var != NULL);
11596 assert(set != NULL);
11597 assert(var->scip == set->scip);
11598 assert(branchfactor >= 0.0);
11599
11600 SCIPdebugMessage("changing branch factor of <%s> from %g to %g\n", var->name, var->branchfactor, branchfactor);
11601
11602 if( SCIPsetIsEQ(set, var->branchfactor, branchfactor) )
11603 return SCIP_OKAY;
11604
11605 /* change priorities of attached variables */
11606 switch( SCIPvarGetStatus(var) )
11607 {
11609 if( var->data.original.transvar != NULL )
11610 {
11611 SCIP_CALL( SCIPvarChgBranchFactor(var->data.original.transvar, set, branchfactor) );
11612 }
11613 else
11614 {
11615 assert(set->stage == SCIP_STAGE_PROBLEM);
11616 var->branchfactor = branchfactor;
11617 }
11618 break;
11619
11623 SCIP_CALL( varProcessChgBranchFactor(var, set, branchfactor) );
11624 break;
11625
11627 assert(!var->donotaggr);
11628 assert(var->data.aggregate.var != NULL);
11629 SCIP_CALL( SCIPvarChgBranchFactor(var->data.aggregate.var, set, branchfactor) );
11630 break;
11631
11633 assert(!var->donotmultaggr);
11634 for( v = 0; v < var->data.multaggr.nvars; ++v )
11635 {
11636 SCIP_CALL( SCIPvarChgBranchFactor(var->data.multaggr.vars[v], set, branchfactor) );
11637 }
11638 break;
11639
11641 assert(var->negatedvar != NULL);
11643 assert(var->negatedvar->negatedvar == var);
11644 SCIP_CALL( SCIPvarChgBranchFactor(var->negatedvar, set, branchfactor) );
11645 break;
11646
11647 default:
11648 SCIPerrorMessage("unknown variable status\n");
11649 SCIPABORT();
11650 return SCIP_ERROR; /*lint !e527*/
11651 }
11652
11653 return SCIP_OKAY;
11654}
11655
11656/** actually changes the branch priority of the variable and of all parent variables */
11657static
11659 SCIP_VAR* var, /**< problem variable */
11660 int branchpriority /**< branching priority of the variable */
11661 )
11662{
11663 SCIP_VAR* parentvar;
11664 int i;
11665
11666 assert(var != NULL);
11667
11668 SCIPdebugMessage("process changing branch priority of <%s> from %d to %d\n",
11669 var->name, var->branchpriority, branchpriority);
11670
11671 if( branchpriority == var->branchpriority )
11672 return SCIP_OKAY;
11673
11674 /* change the branch priority */
11675 var->branchpriority = branchpriority;
11676
11677 /* process parent variables */
11678 for( i = 0; i < var->nparentvars; ++i )
11679 {
11680 parentvar = var->parentvars[i];
11681 assert(parentvar != NULL);
11682
11683 switch( SCIPvarGetStatus(parentvar) )
11684 {
11686 /* do not change priorities across the border between transformed and original problem */
11687 break;
11688
11693 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11694 SCIPABORT();
11695 return SCIP_INVALIDDATA; /*lint !e527*/
11696
11699 SCIP_CALL( varProcessChgBranchPriority(parentvar, branchpriority) );
11700 break;
11701
11702 default:
11703 SCIPerrorMessage("unknown variable status\n");
11704 return SCIP_ERROR;
11705 }
11706 }
11707
11708 return SCIP_OKAY;
11709}
11710
11711/** sets the branch priority of the variable; variables with higher branch priority are always preferred to variables
11712 * with lower priority in selection of branching variable
11713 */
11715 SCIP_VAR* var, /**< problem variable */
11716 int branchpriority /**< branching priority of the variable */
11717 )
11718{
11719 int v;
11720
11721 assert(var != NULL);
11722
11723 SCIPdebugMessage("changing branch priority of <%s> from %d to %d\n", var->name, var->branchpriority, branchpriority);
11724
11725 if( var->branchpriority == branchpriority )
11726 return SCIP_OKAY;
11727
11728 /* change priorities of attached variables */
11729 switch( SCIPvarGetStatus(var) )
11730 {
11732 if( var->data.original.transvar != NULL )
11733 {
11734 SCIP_CALL( SCIPvarChgBranchPriority(var->data.original.transvar, branchpriority) );
11735 }
11736 else
11737 var->branchpriority = branchpriority;
11738 break;
11739
11743 SCIP_CALL( varProcessChgBranchPriority(var, branchpriority) );
11744 break;
11745
11747 assert(!var->donotaggr);
11748 assert(var->data.aggregate.var != NULL);
11749 SCIP_CALL( SCIPvarChgBranchPriority(var->data.aggregate.var, branchpriority) );
11750 break;
11751
11753 assert(!var->donotmultaggr);
11754 for( v = 0; v < var->data.multaggr.nvars; ++v )
11755 {
11756 SCIP_CALL( SCIPvarChgBranchPriority(var->data.multaggr.vars[v], branchpriority) );
11757 }
11758 break;
11759
11761 assert(var->negatedvar != NULL);
11763 assert(var->negatedvar->negatedvar == var);
11764 SCIP_CALL( SCIPvarChgBranchPriority(var->negatedvar, branchpriority) );
11765 break;
11766
11767 default:
11768 SCIPerrorMessage("unknown variable status\n");
11769 SCIPABORT();
11770 return SCIP_ERROR; /*lint !e527*/
11771 }
11772
11773 return SCIP_OKAY;
11774}
11775
11776/** actually changes the branch direction of the variable and of all parent variables */
11777static
11779 SCIP_VAR* var, /**< problem variable */
11780 SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
11781 )
11782{
11783 SCIP_VAR* parentvar;
11784 int i;
11785
11786 assert(var != NULL);
11787
11788 SCIPdebugMessage("process changing branch direction of <%s> from %u to %d\n",
11789 var->name, var->branchdirection, branchdirection);
11790
11791 if( branchdirection == (SCIP_BRANCHDIR)var->branchdirection )
11792 return SCIP_OKAY;
11793
11794 /* change the branch direction */
11795 var->branchdirection = branchdirection; /*lint !e641*/
11796
11797 /* process parent variables */
11798 for( i = 0; i < var->nparentvars; ++i )
11799 {
11800 parentvar = var->parentvars[i];
11801 assert(parentvar != NULL);
11802
11803 switch( SCIPvarGetStatus(parentvar) )
11804 {
11806 /* do not change directions across the border between transformed and original problem */
11807 break;
11808
11813 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11814 SCIPABORT();
11815 return SCIP_INVALIDDATA; /*lint !e527*/
11816
11818 if( parentvar->data.aggregate.scalar > 0.0 )
11819 {
11820 SCIP_CALL( varProcessChgBranchDirection(parentvar, branchdirection) );
11821 }
11822 else
11823 {
11824 SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
11825 }
11826 break;
11827
11829 SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
11830 break;
11831
11832 default:
11833 SCIPerrorMessage("unknown variable status\n");
11834 SCIPABORT();
11835 return SCIP_ERROR; /*lint !e527*/
11836 }
11837 }
11838
11839 return SCIP_OKAY;
11840}
11841
11842/** sets the branch direction of the variable; variables with higher branch direction are always preferred to variables
11843 * with lower direction in selection of branching variable
11844 */
11846 SCIP_VAR* var, /**< problem variable */
11847 SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
11848 )
11849{
11850 int v;
11851
11852 assert(var != NULL);
11853
11854 SCIPdebugMessage("changing branch direction of <%s> from %u to %d\n", var->name, var->branchdirection, branchdirection);
11855
11856 if( (SCIP_BRANCHDIR)var->branchdirection == branchdirection )
11857 return SCIP_OKAY;
11858
11859 /* change directions of attached variables */
11860 switch( SCIPvarGetStatus(var) )
11861 {
11863 if( var->data.original.transvar != NULL )
11864 {
11865 SCIP_CALL( SCIPvarChgBranchDirection(var->data.original.transvar, branchdirection) );
11866 }
11867 else
11868 var->branchdirection = branchdirection; /*lint !e641*/
11869 break;
11870
11874 SCIP_CALL( varProcessChgBranchDirection(var, branchdirection) );
11875 break;
11876
11878 assert(!var->donotaggr);
11879 assert(var->data.aggregate.var != NULL);
11880 if( var->data.aggregate.scalar > 0.0 )
11881 {
11882 SCIP_CALL( SCIPvarChgBranchDirection(var->data.aggregate.var, branchdirection) );
11883 }
11884 else
11885 {
11887 }
11888 break;
11889
11891 assert(!var->donotmultaggr);
11892 for( v = 0; v < var->data.multaggr.nvars; ++v )
11893 {
11894 /* only update branching direction of aggregation variables, if they don't have a preferred direction yet */
11895 assert(var->data.multaggr.vars[v] != NULL);
11897 {
11898 if( var->data.multaggr.scalars[v] > 0.0 )
11899 {
11900 SCIP_CALL( SCIPvarChgBranchDirection(var->data.multaggr.vars[v], branchdirection) );
11901 }
11902 else
11903 {
11905 }
11906 }
11907 }
11908 break;
11909
11911 assert(var->negatedvar != NULL);
11913 assert(var->negatedvar->negatedvar == var);
11915 break;
11916
11917 default:
11918 SCIPerrorMessage("unknown variable status\n");
11919 SCIPABORT();
11920 return SCIP_ERROR; /*lint !e527*/
11921 }
11922
11923 return SCIP_OKAY;
11924}
11925
11926/** compares the index of two variables, only active, fixed or negated variables are allowed, if a variable
11927 * is negated then the index of the corresponding active variable is taken, returns -1 if first is
11928 * smaller than, and +1 if first is greater than second variable index; returns 0 if both indices
11929 * 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);
11940
11942 var1 = SCIPvarGetNegatedVar(var1);
11944 var2 = SCIPvarGetNegatedVar(var2);
11945
11946 assert(var1 != NULL);
11947 assert(var2 != NULL);
11948
11949 if( SCIPvarGetIndex(var1) < SCIPvarGetIndex(var2) )
11950 return -1;
11951 else if( SCIPvarGetIndex(var1) > SCIPvarGetIndex(var2) )
11952 return +1;
11953
11954 assert(var1 == var2);
11955 return 0;
11956}
11957
11958/** comparison method for sorting active and negated variables by non-decreasing index, active and negated
11959 * variables are handled as the same variables
11960 */
11961SCIP_DECL_SORTPTRCOMP(SCIPvarCompActiveAndNegated)
11962{
11963 return SCIPvarCompareActiveAndNegated((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
11964}
11965
11966/** compares the index of two variables, returns -1 if first is smaller than, and +1 if first is greater than second
11967 * variable index; returns 0 if both indices are equal, which means both variables are equal
11968 */
11970 SCIP_VAR* var1, /**< first problem variable */
11971 SCIP_VAR* var2 /**< second problem variable */
11972 )
11973{
11974 assert(var1 != NULL);
11975 assert(var2 != NULL);
11976
11977 if( var1->index < var2->index )
11978 return -1;
11979 else if( var1->index > var2->index )
11980 return +1;
11981 else
11982 {
11983 assert(var1 == var2);
11984 return 0;
11985 }
11986}
11987
11988/** comparison method for sorting variables by non-decreasing index */
11990{
11991 return SCIPvarCompare((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
11992}
11993
11994/** comparison method for sorting variables by non-decreasing objective coefficient */
11996{
11997 SCIP_Real obj1;
11998 SCIP_Real obj2;
11999
12000 obj1 = SCIPvarGetObj((SCIP_VAR*)elem1);
12001 obj2 = SCIPvarGetObj((SCIP_VAR*)elem2);
12002
12003 if( obj1 < obj2 )
12004 return -1;
12005 else if( obj1 > obj2 )
12006 return +1;
12007 else
12008 return 0;
12009}
12010
12011/** hash key retrieval function for variables */
12012SCIP_DECL_HASHGETKEY(SCIPvarGetHashkey)
12013{ /*lint --e{715}*/
12014 return elem;
12015}
12016
12017/** returns TRUE iff the indices of both variables are equal */
12018SCIP_DECL_HASHKEYEQ(SCIPvarIsHashkeyEq)
12019{ /*lint --e{715}*/
12020 if( key1 == key2 )
12021 return TRUE;
12022 return FALSE;
12023}
12024
12025/** returns the hash value of the key */
12026SCIP_DECL_HASHKEYVAL(SCIPvarGetHashkeyVal)
12027{ /*lint --e{715}*/
12028 assert( SCIPvarGetIndex((SCIP_VAR*) key) >= 0 );
12029 return (unsigned int) SCIPvarGetIndex((SCIP_VAR*) key);
12030}
12031
12032/** return for given variables all their active counterparts; all active variables will be pairwise different */
12034 SCIP_SET* set, /**< global SCIP settings */
12035 SCIP_VAR** vars, /**< variable array with given variables and as output all active
12036 * variables, if enough slots exist
12037 */
12038 int* nvars, /**< number of given variables, and as output number of active variables,
12039 * if enough slots exist
12040 */
12041 int varssize, /**< available slots in vars array */
12042 int* requiredsize /**< pointer to store the required array size for the active variables */
12043 )
12044{
12045 SCIP_VAR** activevars;
12046 int nactivevars;
12047 int activevarssize;
12048
12049 SCIP_VAR* var;
12050 int v;
12051
12052 SCIP_VAR** tmpvars;
12053 SCIP_VAR** multvars;
12054 int tmpvarssize;
12055 int ntmpvars;
12056 int noldtmpvars;
12057 int nmultvars;
12058
12059 assert(set != NULL);
12060 assert(nvars != NULL);
12061 assert(vars != NULL || *nvars == 0);
12062 assert(varssize >= *nvars);
12063 assert(requiredsize != NULL);
12064
12065 *requiredsize = 0;
12066
12067 if( *nvars == 0 )
12068 return SCIP_OKAY;
12069
12070 nactivevars = 0;
12071 activevarssize = *nvars;
12072 ntmpvars = *nvars;
12073 tmpvarssize = *nvars;
12074
12075 /* temporary memory */
12076 SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
12077 /* coverity[copy_paste_error] */
12078 SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
12079
12080 noldtmpvars = ntmpvars;
12081
12082 /* sort all variables to combine equal variables easily */
12083 SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
12084 for( v = ntmpvars - 1; v > 0; --v )
12085 {
12086 /* combine same variables */
12087 if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
12088 {
12089 --ntmpvars;
12090 tmpvars[v] = tmpvars[ntmpvars];
12091 }
12092 }
12093 /* sort all variables again to combine equal variables later on */
12094 if( noldtmpvars > ntmpvars )
12095 SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
12096
12097 /* collect for each variable the representation in active variables */
12098 while( ntmpvars >= 1 )
12099 {
12100 --ntmpvars;
12101 var = tmpvars[ntmpvars];
12102 assert( var != NULL );
12103
12104 switch( SCIPvarGetStatus(var) )
12105 {
12107 if( var->data.original.transvar == NULL )
12108 {
12109 SCIPerrorMessage("original variable has no transformed variable attached\n");
12110 SCIPABORT();
12111 return SCIP_INVALIDDATA; /*lint !e527*/
12112 }
12113 tmpvars[ntmpvars] = var->data.original.transvar;
12114 ++ntmpvars;
12115 break;
12116
12118 tmpvars[ntmpvars] = var->data.aggregate.var;
12119 ++ntmpvars;
12120 break;
12121
12123 tmpvars[ntmpvars] = var->negatedvar;
12124 ++ntmpvars;
12125 break;
12126
12129 /* check for space in temporary memory */
12130 if( nactivevars >= activevarssize )
12131 {
12132 activevarssize *= 2;
12133 SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
12134 assert(nactivevars < activevarssize);
12135 }
12136 activevars[nactivevars] = var;
12137 nactivevars++;
12138 break;
12139
12141 /* x = a_1*y_1 + ... + a_n*y_n + c */
12142 nmultvars = var->data.multaggr.nvars;
12143 multvars = var->data.multaggr.vars;
12144
12145 /* check for space in temporary memory */
12146 if( nmultvars + ntmpvars > tmpvarssize )
12147 {
12148 while( nmultvars + ntmpvars > tmpvarssize )
12149 tmpvarssize *= 2;
12150 SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
12151 assert(nmultvars + ntmpvars <= tmpvarssize);
12152 }
12153
12154 /* copy all multi-aggregation variables into our working array */
12155 BMScopyMemoryArray(&tmpvars[ntmpvars], multvars, nmultvars); /*lint !e866*/
12156
12157 /* get active, fixed or multi-aggregated corresponding variables for all new ones */
12158 SCIPvarsGetProbvar(&tmpvars[ntmpvars], nmultvars);
12159
12160 ntmpvars += nmultvars;
12161 noldtmpvars = ntmpvars;
12162
12163 /* sort all variables to combine equal variables easily */
12164 SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
12165 for( v = ntmpvars - 1; v > 0; --v )
12166 {
12167 /* combine same variables */
12168 if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
12169 {
12170 --ntmpvars;
12171 tmpvars[v] = tmpvars[ntmpvars];
12172 }
12173 }
12174 /* sort all variables again to combine equal variables later on */
12175 if( noldtmpvars > ntmpvars )
12176 SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
12177
12178 break;
12179
12181 /* no need for memorizing fixed variables */
12182 break;
12183
12184 default:
12185 SCIPerrorMessage("unknown variable status\n");
12186 SCIPABORT();
12187 return SCIP_INVALIDDATA; /*lint !e527*/
12188 }
12189 }
12190
12191 /* sort variable array by variable index */
12192 SCIPsortPtr((void**)activevars, SCIPvarComp, nactivevars);
12193
12194 /* eliminate duplicates and count required size */
12195 v = nactivevars - 1;
12196 while( v > 0 )
12197 {
12198 /* combine both variable since they are the same */
12199 if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
12200 {
12201 --nactivevars;
12202 activevars[v] = activevars[nactivevars];
12203 }
12204 --v;
12205 }
12206 *requiredsize = nactivevars;
12207
12208 if( varssize >= *requiredsize )
12209 {
12210 assert(vars != NULL);
12211
12212 *nvars = *requiredsize;
12213 BMScopyMemoryArray(vars, activevars, nactivevars);
12214 }
12215
12216 SCIPsetFreeBufferArray(set, &tmpvars);
12217 SCIPsetFreeBufferArray(set, &activevars);
12218
12219 return SCIP_OKAY;
12220}
12221
12222/** gets corresponding active, fixed, or multi-aggregated problem variables of given variables,
12223 * @note the content of the given array will/might change
12224 */
12226 SCIP_VAR** vars, /**< array of problem variables */
12227 int nvars /**< number of variables */
12228 )
12229{
12230 int v;
12231
12232 assert(vars != NULL || nvars == 0);
12233
12234 for( v = nvars - 1; v >= 0; --v )
12235 {
12236 assert(vars != NULL);
12237 assert(vars[v] != NULL);
12238
12239 vars[v] = SCIPvarGetProbvar(vars[v]);
12240 assert(vars[v] != NULL);
12241 }
12242}
12243
12244/** gets corresponding active, fixed, or multi-aggregated problem variable of a variable */
12246 SCIP_VAR* var /**< problem variable */
12247 )
12248{
12249 SCIP_VAR* retvar;
12250
12251 assert(var != NULL);
12252
12253 retvar = var;
12254
12255 SCIPdebugMessage("get problem variable of <%s>\n", var->name);
12256
12257 while( TRUE ) /*lint !e716 */
12258 {
12259 assert(retvar != NULL);
12260
12261 switch( SCIPvarGetStatus(retvar) )
12262 {
12264 if( retvar->data.original.transvar == NULL )
12265 {
12266 SCIPerrorMessage("original variable has no transformed variable attached\n");
12267 SCIPABORT();
12268 return NULL; /*lint !e527 */
12269 }
12270 retvar = retvar->data.original.transvar;
12271 break;
12272
12276 return retvar;
12277
12279 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12280 if ( retvar->data.multaggr.nvars == 1 )
12281 retvar = retvar->data.multaggr.vars[0];
12282 else
12283 return retvar;
12284 break;
12285
12287 retvar = retvar->data.aggregate.var;
12288 break;
12289
12291 retvar = retvar->negatedvar;
12292 break;
12293
12294 default:
12295 SCIPerrorMessage("unknown variable status\n");
12296 SCIPABORT();
12297 return NULL; /*lint !e527*/
12298 }
12299 }
12300}
12301
12302/** gets corresponding active, fixed, or multi-aggregated problem variables of binary variables and updates the given
12303 * negation status of each variable
12304 */
12306 SCIP_VAR*** vars, /**< pointer to binary problem variables */
12307 SCIP_Bool** negatedarr, /**< pointer to corresponding array to update the negation status */
12308 int nvars /**< number of variables and values in vars and negated array */
12309 )
12310{
12311 SCIP_VAR** var;
12312 SCIP_Bool* negated;
12313 int v;
12314
12315 assert(vars != NULL);
12316 assert(*vars != NULL || nvars == 0);
12317 assert(negatedarr != NULL);
12318 assert(*negatedarr != NULL || nvars == 0);
12319
12320 for( v = nvars - 1; v >= 0; --v )
12321 {
12322 var = &((*vars)[v]);
12323 negated = &((*negatedarr)[v]);
12324
12325 /* get problem variable */
12326 SCIP_CALL( SCIPvarGetProbvarBinary(var, negated) );
12327 }
12328
12329 return SCIP_OKAY;
12330}
12331
12332
12333/** gets corresponding active, fixed, or multi-aggregated problem variable of a binary variable and updates the given
12334 * negation status (this means you have to assign a value to SCIP_Bool negated before calling this method, usually
12335 * FALSE is used)
12336 */
12338 SCIP_VAR** var, /**< pointer to binary problem variable */
12339 SCIP_Bool* negated /**< pointer to update the negation status */
12340 )
12341{
12343#ifndef NDEBUG
12344 SCIP_Real constant = 0.0;
12345 SCIP_Bool orignegated;
12346#endif
12347
12348 assert(var != NULL);
12349 assert(*var != NULL);
12350 assert(negated != NULL);
12351 assert(SCIPvarIsBinary(*var));
12352
12353#ifndef NDEBUG
12354 orignegated = *negated;
12355#endif
12356
12357 while( !active && *var != NULL )
12358 {
12359 switch( SCIPvarGetStatus(*var) )
12360 {
12362 if( (*var)->data.original.transvar == NULL )
12363 return SCIP_OKAY;
12364 *var = (*var)->data.original.transvar;
12365 break;
12366
12370 active = TRUE;
12371 break;
12372
12374 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12375 if ( (*var)->data.multaggr.nvars == 1 )
12376 {
12377 assert( (*var)->data.multaggr.vars != NULL );
12378 assert( (*var)->data.multaggr.scalars != NULL );
12379 assert( SCIPvarIsBinary((*var)->data.multaggr.vars[0]) );
12380 assert(!EPSZ((*var)->data.multaggr.scalars[0], 1e-06));
12381
12382 /* if not all variables were fully propagated, it might happen that a variable is multi-aggregated to
12383 * another variable which needs to be fixed
12384 *
12385 * e.g. x = y - 1 => (x = 0 && y = 1)
12386 * e.g. x = y + 1 => (x = 1 && y = 0)
12387 *
12388 * is this special case we need to return the muti-aggregation
12389 */
12390 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)) )
12391 {
12392 assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06));
12393 }
12394 else
12395 {
12396 /* @note due to fixations, a multi-aggregation can have a constant of zero and a negative scalar or even
12397 * a scalar in absolute value unequal to one, in this case this aggregation variable needs to be
12398 * fixed to zero, but this should be done by another enforcement; so not depending on the scalar,
12399 * we will return the aggregated variable;
12400 */
12401 if( !EPSEQ(REALABS((*var)->data.multaggr.scalars[0]), 1.0, 1e-06) )
12402 {
12403 active = TRUE;
12404 break;
12405 }
12406
12407 /* @note it may also happen that the constant is larger than 1 or smaller than 0, in that case the
12408 * aggregation variable needs to be fixed to one, but this should be done by another enforcement;
12409 * so if this is the case, we will return the aggregated variable
12410 */
12411 assert(EPSZ((*var)->data.multaggr.constant, 1e-06) || EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06)
12412 || EPSZ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1e-06)
12413 || EPSEQ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1.0, 1e-06));
12414
12415 if( !EPSZ((*var)->data.multaggr.constant, 1e-06) && !EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06) )
12416 {
12417 active = TRUE;
12418 break;
12419 }
12420
12421 assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06) || EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
12422
12423 if( EPSZ((*var)->data.multaggr.constant, 1e-06) )
12424 {
12425 /* if the scalar is negative, either the aggregation variable is already fixed to zero or has at
12426 * least one uplock (that hopefully will enforce this fixation to zero); can it happen that this
12427 * variable itself is multi-aggregated again?
12428 */
12429 assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06) ?
12430 ((SCIPvarGetUbGlobal((*var)->data.multaggr.vars[0]) < 0.5) ||
12431 SCIPvarGetNLocksUpType((*var)->data.multaggr.vars[0], SCIP_LOCKTYPE_MODEL) > 0) : TRUE);
12432 }
12433 else
12434 {
12435 assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
12436#ifndef NDEBUG
12437 constant += (*negated) != orignegated ? -1.0 : 1.0;
12438#endif
12439
12440 *negated = !(*negated);
12441 }
12442 *var = (*var)->data.multaggr.vars[0];
12443 break;
12444 }
12445 }
12446 active = TRUE; /*lint !e838*/
12447 break;
12448
12449 case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
12450 assert((*var)->data.aggregate.var != NULL);
12451 assert(EPSEQ((*var)->data.aggregate.scalar, 1.0, 1e-06) || EPSEQ((*var)->data.aggregate.scalar, -1.0, 1e-06));
12452 assert(EPSLE((*var)->data.aggregate.var->glbdom.ub - (*var)->data.aggregate.var->glbdom.lb, 1.0, 1e-06));
12453#ifndef NDEBUG
12454 constant += (*negated) != orignegated ? -(*var)->data.aggregate.constant : (*var)->data.aggregate.constant;
12455#endif
12456
12457 *negated = ((*var)->data.aggregate.scalar > 0.0) ? *negated : !(*negated);
12458 *var = (*var)->data.aggregate.var;
12459 break;
12460
12461 case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
12462 assert((*var)->negatedvar != NULL);
12463#ifndef NDEBUG
12464 constant += (*negated) != orignegated ? -1.0 : 1.0;
12465#endif
12466
12467 *negated = !(*negated);
12468 *var = (*var)->negatedvar;
12469 break;
12470
12471 default:
12472 SCIPerrorMessage("unknown variable status\n");
12473 return SCIP_INVALIDDATA;
12474 }
12475 }
12476 assert(active == (*var != NULL));
12477
12478 if( active )
12479 {
12480 assert(SCIPvarIsBinary(*var));
12481 assert(EPSZ(constant, 1e-06) || EPSEQ(constant, 1.0, 1e-06));
12482 assert(EPSZ(constant, 1e-06) == ((*negated) == orignegated));
12483
12484 return SCIP_OKAY;
12485 }
12486 else
12487 {
12488 SCIPerrorMessage("active variable path leads to NULL pointer\n");
12489 return SCIP_INVALIDDATA;
12490 }
12491}
12492
12493/** transforms given variable, boundtype and bound to the corresponding active, fixed, or multi-aggregated variable
12494 * values
12495 */
12497 SCIP_VAR** var, /**< pointer to problem variable */
12498 SCIP_Real* bound, /**< pointer to bound value to transform */
12499 SCIP_BOUNDTYPE* boundtype /**< pointer to type of bound: lower or upper bound */
12500 )
12501{
12502 assert(var != NULL);
12503 assert(*var != NULL);
12504 assert(bound != NULL);
12505 assert(boundtype != NULL);
12506
12507 SCIPdebugMessage("get probvar bound %g of type %d of variable <%s>\n", *bound, *boundtype, (*var)->name);
12508
12509 switch( SCIPvarGetStatus(*var) )
12510 {
12512 if( (*var)->data.original.transvar == NULL )
12513 {
12514 SCIPerrorMessage("original variable has no transformed variable attached\n");
12515 return SCIP_INVALIDDATA;
12516 }
12517 *var = (*var)->data.original.transvar;
12518 SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12519 break;
12520
12524 break;
12525
12527 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12528 if ( (*var)->data.multaggr.nvars == 1 )
12529 {
12530 assert( (*var)->data.multaggr.vars != NULL );
12531 assert( (*var)->data.multaggr.scalars != NULL );
12532 assert( (*var)->data.multaggr.scalars[0] != 0.0 );
12533
12534 (*bound) /= (*var)->data.multaggr.scalars[0];
12535 (*bound) -= (*var)->data.multaggr.constant/(*var)->data.multaggr.scalars[0];
12536 if ( (*var)->data.multaggr.scalars[0] < 0.0 )
12537 {
12538 if ( *boundtype == SCIP_BOUNDTYPE_LOWER )
12539 *boundtype = SCIP_BOUNDTYPE_UPPER;
12540 else
12541 *boundtype = SCIP_BOUNDTYPE_LOWER;
12542 }
12543 *var = (*var)->data.multaggr.vars[0];
12544 SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12545 }
12546 break;
12547
12548 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
12549 assert((*var)->data.aggregate.var != NULL);
12550 assert((*var)->data.aggregate.scalar != 0.0);
12551
12552 (*bound) /= (*var)->data.aggregate.scalar;
12553 (*bound) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12554 if( (*var)->data.aggregate.scalar < 0.0 )
12555 {
12556 if( *boundtype == SCIP_BOUNDTYPE_LOWER )
12557 *boundtype = SCIP_BOUNDTYPE_UPPER;
12558 else
12559 *boundtype = SCIP_BOUNDTYPE_LOWER;
12560 }
12561 *var = (*var)->data.aggregate.var;
12562 SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12563 break;
12564
12565 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12566 assert((*var)->negatedvar != NULL);
12567 assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12568 assert((*var)->negatedvar->negatedvar == *var);
12569 (*bound) = (*var)->data.negate.constant - *bound;
12570 if( *boundtype == SCIP_BOUNDTYPE_LOWER )
12571 *boundtype = SCIP_BOUNDTYPE_UPPER;
12572 else
12573 *boundtype = SCIP_BOUNDTYPE_LOWER;
12574 *var = (*var)->negatedvar;
12575 SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12576 break;
12577
12578 default:
12579 SCIPerrorMessage("unknown variable status\n");
12580 return SCIP_INVALIDDATA;
12581 }
12582
12583 return SCIP_OKAY;
12584}
12585
12586/** transforms given variable and domain hole to the corresponding active, fixed, or multi-aggregated variable
12587 * values
12588 */
12590 SCIP_VAR** var, /**< pointer to problem variable */
12591 SCIP_Real* left, /**< pointer to left bound of open interval in hole to transform */
12592 SCIP_Real* right /**< pointer to right bound of open interval in hole to transform */
12593 )
12594{
12595 assert(var != NULL);
12596 assert(*var != NULL);
12597 assert(left != NULL);
12598 assert(right != NULL);
12599
12600 SCIPdebugMessage("get probvar hole (%g,%g) of variable <%s>\n", *left, *right, (*var)->name);
12601
12602 switch( SCIPvarGetStatus(*var) )
12603 {
12605 if( (*var)->data.original.transvar == NULL )
12606 {
12607 SCIPerrorMessage("original variable has no transformed variable attached\n");
12608 return SCIP_INVALIDDATA;
12609 }
12610 *var = (*var)->data.original.transvar;
12611 SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
12612 break;
12613
12618 break;
12619
12620 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
12621 assert((*var)->data.aggregate.var != NULL);
12622 assert((*var)->data.aggregate.scalar != 0.0);
12623
12624 /* scale back */
12625 (*left) /= (*var)->data.aggregate.scalar;
12626 (*right) /= (*var)->data.aggregate.scalar;
12627
12628 /* shift back */
12629 (*left) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12630 (*right) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12631
12632 *var = (*var)->data.aggregate.var;
12633
12634 /* check if the interval bounds have to swapped */
12635 if( (*var)->data.aggregate.scalar < 0.0 )
12636 {
12637 SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
12638 }
12639 else
12640 {
12641 SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
12642 }
12643 break;
12644
12645 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12646 assert((*var)->negatedvar != NULL);
12647 assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12648 assert((*var)->negatedvar->negatedvar == *var);
12649
12650 /* shift and scale back */
12651 (*left) = (*var)->data.negate.constant - (*left);
12652 (*right) = (*var)->data.negate.constant - (*right);
12653
12654 *var = (*var)->negatedvar;
12655
12656 /* through the negated variable the left and right interval bound have to swapped */
12657 SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
12658 break;
12659
12660 default:
12661 SCIPerrorMessage("unknown variable status\n");
12662 return SCIP_INVALIDDATA;
12663 }
12664
12665 return SCIP_OKAY;
12666}
12667
12668/** transforms given variable, scalar and constant to the corresponding active, fixed, or
12669 * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed variable,
12670 * "scalar" will be 0.0 and the value of the sum will be stored in "constant"; a multi-aggregation
12671 * with only one active variable (this can happen due to fixings after the multi-aggregation),
12672 * is treated like an aggregation; if the multi-aggregation constant is infinite, "scalar" will be 0.0
12673 */
12675 SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
12676 SCIP_SET* set, /**< global SCIP settings */
12677 SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
12678 SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
12679 )
12680{
12681 assert(var != NULL);
12682 assert(scalar != NULL);
12683 assert(constant != NULL);
12684
12685 while( *var != NULL )
12686 {
12687 switch( SCIPvarGetStatus(*var) )
12688 {
12690 if( (*var)->data.original.transvar == NULL )
12691 {
12692 SCIPerrorMessage("original variable has no transformed variable attached\n");
12693 return SCIP_INVALIDDATA;
12694 }
12695 *var = (*var)->data.original.transvar;
12696 break;
12697
12700 return SCIP_OKAY;
12701
12702 case SCIP_VARSTATUS_FIXED: /* x = c' => a*x + c == (a*c' + c) */
12703 if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12704 {
12705 if( SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)) )
12706 {
12707 assert(*scalar != 0.0);
12708 if( (*scalar) * (*var)->glbdom.lb > 0.0 )
12709 (*constant) = SCIPsetInfinity(set);
12710 else
12711 (*constant) = -SCIPsetInfinity(set);
12712 }
12713 else
12714 (*constant) += *scalar * (*var)->glbdom.lb;
12715 }
12716#ifndef NDEBUG
12717 else
12718 {
12719 assert(!SCIPsetIsInfinity(set, (*constant)) || !((*scalar) * (*var)->glbdom.lb < 0.0 &&
12720 (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
12721 assert(!SCIPsetIsInfinity(set, -(*constant)) || !((*scalar) * (*var)->glbdom.lb > 0.0 &&
12722 (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
12723 }
12724#endif
12725 *scalar = 0.0;
12726 return SCIP_OKAY;
12727
12729 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12730 if ( (*var)->data.multaggr.nvars == 1 )
12731 {
12732 assert((*var)->data.multaggr.vars != NULL);
12733 assert((*var)->data.multaggr.scalars != NULL);
12734 assert((*var)->data.multaggr.vars[0] != NULL);
12735 if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12736 {
12737 /* the multi-aggregation constant can be infinite, if one of the multi-aggregation variables
12738 * was fixed to +/-infinity; ensure that the constant is set to +/-infinity, too, and the scalar
12739 * is set to 0.0, because the multi-aggregated variable can be seen as fixed, too
12740 */
12741 if( SCIPsetIsInfinity(set, (*var)->data.multaggr.constant)
12742 || SCIPsetIsInfinity(set, -((*var)->data.multaggr.constant)) )
12743 {
12744 if( (*scalar) * (*var)->data.multaggr.constant > 0 )
12745 {
12746 assert(!SCIPsetIsInfinity(set, -(*constant)));
12747 (*constant) = SCIPsetInfinity(set);
12748 }
12749 else
12750 {
12751 assert(!SCIPsetIsInfinity(set, *constant));
12752 (*constant) = -SCIPsetInfinity(set);
12753 }
12754 (*scalar) = 0.0;
12755 }
12756 else
12757 (*constant) += *scalar * (*var)->data.multaggr.constant;
12758 }
12759 (*scalar) *= (*var)->data.multaggr.scalars[0];
12760 *var = (*var)->data.multaggr.vars[0];
12761 break;
12762 }
12763 return SCIP_OKAY;
12764
12765 case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
12766 assert((*var)->data.aggregate.var != NULL);
12767 assert(!SCIPsetIsInfinity(set, (*var)->data.aggregate.constant)
12768 && !SCIPsetIsInfinity(set, (*var)->data.aggregate.constant));
12769 if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12770 (*constant) += *scalar * (*var)->data.aggregate.constant;
12771 (*scalar) *= (*var)->data.aggregate.scalar;
12772 *var = (*var)->data.aggregate.var;
12773 break;
12774
12775 case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
12776 assert((*var)->negatedvar != NULL);
12777 assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12778 assert((*var)->negatedvar->negatedvar == *var);
12779 assert(!SCIPsetIsInfinity(set, (*var)->data.negate.constant)
12780 && !SCIPsetIsInfinity(set, (*var)->data.negate.constant));
12781 if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12782 (*constant) += *scalar * (*var)->data.negate.constant;
12783 (*scalar) *= -1.0;
12784 *var = (*var)->negatedvar;
12785 break;
12786
12787 default:
12788 SCIPerrorMessage("unknown variable status\n");
12789 SCIPABORT();
12790 return SCIP_INVALIDDATA; /*lint !e527*/
12791 }
12792 }
12793 *scalar = 0.0;
12794
12795 return SCIP_OKAY;
12796}
12797
12798/** retransforms given variable, scalar and constant to the corresponding original variable, scalar
12799 * and constant, if possible; if the retransformation is impossible, NULL is returned as variable
12800 */
12802 SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
12803 SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
12804 SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
12805 )
12806{
12807 SCIP_VAR* parentvar;
12808
12809 assert(var != NULL);
12810 assert(*var != NULL);
12811 assert(scalar != NULL);
12812 assert(constant != NULL);
12813
12814 while( !SCIPvarIsOriginal(*var) )
12815 {
12816 /* if the variable has no parent variables, it was generated during solving and has no corresponding original
12817 * var
12818 */
12819 if( (*var)->nparentvars == 0 )
12820 {
12821 /* negated variables do not need to have a parent variables, and negated variables can exist in original
12822 * space
12823 */
12825 ((*var)->negatedvar->nparentvars == 0 || (*var)->negatedvar->parentvars[0] != *var) )
12826 {
12827 *scalar *= -1.0;
12828 *constant -= (*var)->data.negate.constant * (*scalar);
12829 *var = (*var)->negatedvar;
12830
12831 continue;
12832 }
12833 /* if the variables does not have any parent the variables was created during solving and has no original
12834 * counterpart
12835 */
12836 else
12837 {
12838 *var = NULL;
12839
12840 return SCIP_OKAY;
12841 }
12842 }
12843
12844 /* follow the link to the first parent variable */
12845 parentvar = (*var)->parentvars[0];
12846 assert(parentvar != NULL);
12847
12848 switch( SCIPvarGetStatus(parentvar) )
12849 {
12851 break;
12852
12857 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
12858 return SCIP_INVALIDDATA;
12859
12860 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + b -> y = (x-b)/a, s*y + c = (s/a)*x + c-b*s/a */
12861 assert(parentvar->data.aggregate.var == *var);
12862 assert(parentvar->data.aggregate.scalar != 0.0);
12863 *scalar /= parentvar->data.aggregate.scalar;
12864 *constant -= parentvar->data.aggregate.constant * (*scalar);
12865 break;
12866
12867 case SCIP_VARSTATUS_NEGATED: /* x = b - y -> y = b - x, s*y + c = -s*x + c+b*s */
12868 assert(parentvar->negatedvar != NULL);
12869 assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
12870 assert(parentvar->negatedvar->negatedvar == parentvar);
12871 *scalar *= -1.0;
12872 *constant -= parentvar->data.negate.constant * (*scalar);
12873 break;
12874
12875 default:
12876 SCIPerrorMessage("unknown variable status\n");
12877 return SCIP_INVALIDDATA;
12878 }
12879
12880 assert( parentvar != NULL );
12881 *var = parentvar;
12882 }
12883
12884 return SCIP_OKAY;
12885}
12886
12887/** returns whether the given variable is the direct counterpart of an original problem variable */
12889 SCIP_VAR* var /**< problem variable */
12890 )
12891{
12892 SCIP_VAR* parentvar;
12893 assert(var != NULL);
12894
12895 if( !SCIPvarIsTransformed(var) || var->nparentvars < 1 )
12896 return FALSE;
12897
12898 assert(var->parentvars != NULL);
12899 parentvar = var->parentvars[0];
12900 assert(parentvar != NULL);
12901
12902 /* we follow the aggregation tree to the root unless an original variable has been found - the first entries in the parentlist are candidates */
12903 while( parentvar->nparentvars >= 1 && SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL )
12904 parentvar = parentvar->parentvars[0];
12905 assert( parentvar != NULL );
12906
12907 return ( SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_ORIGINAL );
12908}
12909
12910/** gets objective value of variable in current SCIP_LP; the value can be different from the objective value stored in
12911 * the variable's own data due to diving, that operate only on the LP without updating the variables
12912 */
12914 SCIP_VAR* var /**< problem variable */
12915 )
12916{
12917 assert(var != NULL);
12918
12919 /* get bounds of attached variables */
12920 switch( SCIPvarGetStatus(var) )
12921 {
12923 assert(var->data.original.transvar != NULL);
12925
12927 assert(var->data.col != NULL);
12928 return SCIPcolGetObj(var->data.col);
12929
12932 return var->obj;
12933
12934 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12935 assert(var->data.aggregate.var != NULL);
12937
12939 SCIPerrorMessage("cannot get the objective value of a multiple aggregated variable\n");
12940 SCIPABORT();
12941 return 0.0; /*lint !e527*/
12942
12943 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12944 assert(var->negatedvar != NULL);
12946 assert(var->negatedvar->negatedvar == var);
12947 return -SCIPvarGetObjLP(var->negatedvar);
12948
12949 default:
12950 SCIPerrorMessage("unknown variable status\n");
12951 SCIPABORT();
12952 return 0.0; /*lint !e527*/
12953 }
12954}
12955
12956/** gets lower bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
12957 * data due to diving or conflict analysis, that operate only on the LP without updating the variables
12958 */
12960 SCIP_VAR* var, /**< problem variable */
12961 SCIP_SET* set /**< global SCIP settings */
12962 )
12963{
12964 assert(var != NULL);
12965 assert(set != NULL);
12966 assert(var->scip == set->scip);
12967
12968 /* get bounds of attached variables */
12969 switch( SCIPvarGetStatus(var) )
12970 {
12972 assert(var->data.original.transvar != NULL);
12973 return SCIPvarGetLbLP(var->data.original.transvar, set);
12974
12976 assert(var->data.col != NULL);
12977 return SCIPcolGetLb(var->data.col);
12978
12981 return var->locdom.lb;
12982
12983 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12984 assert(var->data.aggregate.var != NULL);
12987 {
12988 return -SCIPsetInfinity(set);
12989 }
12990 else if( var->data.aggregate.scalar > 0.0 )
12991 {
12992 /* a > 0 -> get lower bound of y */
12994 }
12995 else if( var->data.aggregate.scalar < 0.0 )
12996 {
12997 /* a < 0 -> get upper bound of y */
12999 }
13000 else
13001 {
13002 SCIPerrorMessage("scalar is zero in aggregation\n");
13003 SCIPABORT();
13004 return SCIP_INVALID; /*lint !e527*/
13005 }
13006
13008 /**@todo get the sides of the corresponding linear constraint */
13009 SCIPerrorMessage("getting the bounds of a multiple aggregated variable is not implemented yet\n");
13010 SCIPABORT();
13011 return SCIP_INVALID; /*lint !e527*/
13012
13013 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13014 assert(var->negatedvar != NULL);
13016 assert(var->negatedvar->negatedvar == var);
13017 return var->data.negate.constant - SCIPvarGetUbLP(var->negatedvar, set);
13018
13019 default:
13020 SCIPerrorMessage("unknown variable status\n");
13021 SCIPABORT();
13022 return SCIP_INVALID; /*lint !e527*/
13023 }
13024}
13025
13026/** gets upper bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
13027 * data due to diving or conflict analysis, that operate only on the LP without updating the variables
13028 */
13030 SCIP_VAR* var, /**< problem variable */
13031 SCIP_SET* set /**< global SCIP settings */
13032 )
13033{
13034 assert(var != NULL);
13035 assert(set != NULL);
13036 assert(var->scip == set->scip);
13037
13038 /* get bounds of attached variables */
13039 switch( SCIPvarGetStatus(var) )
13040 {
13042 assert(var->data.original.transvar != NULL);
13043 return SCIPvarGetUbLP(var->data.original.transvar, set);
13044
13046 assert(var->data.col != NULL);
13047 return SCIPcolGetUb(var->data.col);
13048
13051 return var->locdom.ub;
13052
13053 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
13054 assert(var->data.aggregate.var != NULL);
13057 {
13058 return SCIPsetInfinity(set);
13059 }
13060 if( var->data.aggregate.scalar > 0.0 )
13061 {
13062 /* a > 0 -> get upper bound of y */
13064 }
13065 else if( var->data.aggregate.scalar < 0.0 )
13066 {
13067 /* a < 0 -> get lower bound of y */
13069 }
13070 else
13071 {
13072 SCIPerrorMessage("scalar is zero in aggregation\n");
13073 SCIPABORT();
13074 return SCIP_INVALID; /*lint !e527*/
13075 }
13076
13078 SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
13079 SCIPABORT();
13080 return SCIP_INVALID; /*lint !e527*/
13081
13082 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13083 assert(var->negatedvar != NULL);
13085 assert(var->negatedvar->negatedvar == var);
13086 return var->data.negate.constant - SCIPvarGetLbLP(var->negatedvar, set);
13087
13088 default:
13089 SCIPerrorMessage("unknown variable status\n");
13090 SCIPABORT();
13091 return SCIP_INVALID; /*lint !e527*/
13092 }
13093}
13094
13095/** gets primal LP solution value of variable */
13097 SCIP_VAR* var /**< problem variable */
13098 )
13099{
13100 assert(var != NULL);
13101
13102 switch( SCIPvarGetStatus(var) )
13103 {
13105 if( var->data.original.transvar == NULL )
13106 return SCIP_INVALID;
13108
13110 return SCIPvarGetBestBoundLocal(var);
13111
13113 assert(var->data.col != NULL);
13114 return SCIPcolGetPrimsol(var->data.col);
13115
13117 assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13118 return var->locdom.lb;
13119
13121 {
13122 SCIP_Real lpsolval;
13123
13124 assert(!var->donotaggr);
13125 assert(var->data.aggregate.var != NULL);
13126 lpsolval = SCIPvarGetLPSol(var->data.aggregate.var);
13127
13128 /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13129 * corresponding infinity value instead of performing an arithmetical transformation (compare method
13130 * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13131 * (or is called by) a public interface method; instead, we only assert that values are finite
13132 * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13133 * positives and negatives if the parameter <numerics/infinity> is modified by the user
13134 */
13135 assert(lpsolval > -SCIP_DEFAULT_INFINITY);
13136 assert(lpsolval < +SCIP_DEFAULT_INFINITY);
13137 return var->data.aggregate.scalar * lpsolval + var->data.aggregate.constant;
13138 }
13140 {
13141 SCIP_Real primsol;
13142 int i;
13143
13144 assert(!var->donotmultaggr);
13145 assert(var->data.multaggr.vars != NULL);
13146 assert(var->data.multaggr.scalars != NULL);
13147 /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13148 * assert(var->data.multaggr.nvars >= 2);
13149 */
13150 primsol = var->data.multaggr.constant;
13151 for( i = 0; i < var->data.multaggr.nvars; ++i )
13152 primsol += var->data.multaggr.scalars[i] * SCIPvarGetLPSol(var->data.multaggr.vars[i]);
13153 return primsol;
13154 }
13155 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13156 assert(var->negatedvar != NULL);
13158 assert(var->negatedvar->negatedvar == var);
13159 return var->data.negate.constant - SCIPvarGetLPSol(var->negatedvar);
13160
13161 default:
13162 SCIPerrorMessage("unknown variable status\n");
13163 SCIPABORT();
13164 return SCIP_INVALID; /*lint !e527*/
13165 }
13166}
13167
13168/** gets primal NLP solution value of variable */
13170 SCIP_VAR* var /**< problem variable */
13171 )
13172{
13173 SCIP_Real solval;
13174 int i;
13175
13176 assert(var != NULL);
13177
13178 /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
13179 switch( SCIPvarGetStatus(var) )
13180 {
13183
13186 return var->nlpsol;
13187
13189 assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
13190 assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
13191 assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
13192 return SCIPvarGetLbGlobal(var);
13193
13194 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13195 solval = SCIPvarGetNLPSol(var->data.aggregate.var);
13196 return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
13197
13199 solval = var->data.multaggr.constant;
13200 for( i = 0; i < var->data.multaggr.nvars; ++i )
13201 solval += var->data.multaggr.scalars[i] * SCIPvarGetNLPSol(var->data.multaggr.vars[i]);
13202 return solval;
13203
13205 solval = SCIPvarGetNLPSol(var->negatedvar);
13206 return var->data.negate.constant - solval;
13207
13208 default:
13209 SCIPerrorMessage("unknown variable status\n");
13210 SCIPABORT();
13211 return SCIP_INVALID; /*lint !e527*/
13212 }
13213}
13214
13215/** gets pseudo solution value of variable at current node */
13216static
13218 SCIP_VAR* var /**< problem variable */
13219 )
13220{
13221 SCIP_Real pseudosol;
13222 int i;
13223
13224 assert(var != NULL);
13225
13226 switch( SCIPvarGetStatus(var) )
13227 {
13229 if( var->data.original.transvar == NULL )
13230 return SCIP_INVALID;
13232
13235 return SCIPvarGetBestBoundLocal(var);
13236
13238 assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13239 return var->locdom.lb;
13240
13242 {
13243 SCIP_Real pseudosolval;
13244 assert(!var->donotaggr);
13245 assert(var->data.aggregate.var != NULL);
13246 /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13247 * corresponding infinity value instead of performing an arithmetical transformation (compare method
13248 * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13249 * (or is called by) a public interface method; instead, we only assert that values are finite
13250 * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13251 * positives and negatives if the parameter <numerics/infinity> is modified by the user
13252 */
13253 pseudosolval = SCIPvarGetPseudoSol(var->data.aggregate.var);
13254 assert(pseudosolval > -SCIP_DEFAULT_INFINITY);
13255 assert(pseudosolval < +SCIP_DEFAULT_INFINITY);
13256 return var->data.aggregate.scalar * pseudosolval + var->data.aggregate.constant;
13257 }
13259 assert(!var->donotmultaggr);
13260 assert(var->data.multaggr.vars != NULL);
13261 assert(var->data.multaggr.scalars != NULL);
13262 /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13263 * assert(var->data.multaggr.nvars >= 2);
13264 */
13265 pseudosol = var->data.multaggr.constant;
13266 for( i = 0; i < var->data.multaggr.nvars; ++i )
13267 pseudosol += var->data.multaggr.scalars[i] * SCIPvarGetPseudoSol(var->data.multaggr.vars[i]);
13268 return pseudosol;
13269
13270 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13271 assert(var->negatedvar != NULL);
13273 assert(var->negatedvar->negatedvar == var);
13275
13276 default:
13277 SCIPerrorMessage("unknown variable status\n");
13278 SCIPABORT();
13279 return SCIP_INVALID; /*lint !e527*/
13280 }
13281}
13282
13283/** gets current LP or pseudo solution value of variable */
13285 SCIP_VAR* var, /**< problem variable */
13286 SCIP_Bool getlpval /**< should the LP solution value be returned? */
13287 )
13288{
13289 if( getlpval )
13290 return SCIPvarGetLPSol(var);
13291 else
13292 return SCIPvarGetPseudoSol(var);
13293}
13294
13295/** remembers the current solution as root solution in the problem variables */
13297 SCIP_VAR* var, /**< problem variable */
13298 SCIP_Bool roothaslp /**< is the root solution from LP? */
13299 )
13300{
13301 assert(var != NULL);
13302
13303 var->rootsol = SCIPvarGetSol(var, roothaslp);
13304}
13305
13306/** updates the current solution as best root solution of the given variable if it is better */
13308 SCIP_VAR* var, /**< problem variable */
13309 SCIP_SET* set, /**< global SCIP settings */
13310 SCIP_Real rootsol, /**< root solution value */
13311 SCIP_Real rootredcost, /**< root reduced cost */
13312 SCIP_Real rootlpobjval /**< objective value of the root LP */
13313 )
13314{
13315 assert(var != NULL);
13316 assert(set != NULL);
13317 assert(var->scip == set->scip);
13318
13319 /* if reduced cost are zero nothing to update */
13320 if( SCIPsetIsDualfeasZero(set, rootredcost) )
13321 return;
13322
13323 /* check if we have already a best combination stored */
13325 {
13326 SCIP_Real currcutoffbound;
13327 SCIP_Real cutoffbound;
13329
13330 /* compute the cutoff bound which would improve the corresponding bound with the current stored root solution,
13331 * root reduced cost, and root LP objective value combination
13332 */
13333 if( var->bestrootredcost > 0.0 )
13335 else
13337
13338 currcutoffbound = (bound - var->bestrootsol) * var->bestrootredcost + var->bestrootlpobjval;
13339
13340 /* compute the cutoff bound which would improve the corresponding bound with new root solution, root reduced
13341 * cost, and root LP objective value combination
13342 */
13343 if( rootredcost > 0.0 )
13345 else
13347
13348 cutoffbound = (bound - rootsol) * rootredcost + rootlpobjval;
13349
13350 /* check if an improving root solution, root reduced cost, and root LP objective value is at hand */
13351 if( cutoffbound > currcutoffbound )
13352 {
13353 SCIPsetDebugMsg(set, "-> <%s> update potential cutoff bound <%g> -> <%g>\n",
13354 SCIPvarGetName(var), currcutoffbound, cutoffbound);
13355
13356 var->bestrootsol = rootsol;
13357 var->bestrootredcost = rootredcost;
13358 var->bestrootlpobjval = rootlpobjval;
13359 }
13360 }
13361 else
13362 {
13363 SCIPsetDebugMsg(set, "-> <%s> initialize best root reduced cost information\n", SCIPvarGetName(var));
13364 SCIPsetDebugMsg(set, " -> rootsol <%g>\n", rootsol);
13365 SCIPsetDebugMsg(set, " -> rootredcost <%g>\n", rootredcost);
13366 SCIPsetDebugMsg(set, " -> rootlpobjval <%g>\n", rootlpobjval);
13367
13368 var->bestrootsol = rootsol;
13369 var->bestrootredcost = rootredcost;
13370 var->bestrootlpobjval = rootlpobjval;
13371 }
13372}
13373
13374/** returns the solution of the variable in the last root node's relaxation, if the root relaxation is not yet
13375 * completely solved, zero is returned
13376 */
13378 SCIP_VAR* var /**< problem variable */
13379 )
13380{
13381 SCIP_Real rootsol;
13382 int i;
13383
13384 assert(var != NULL);
13385
13386 switch( SCIPvarGetStatus(var) )
13387 {
13389 if( var->data.original.transvar == NULL )
13390 return 0.0;
13392
13395 return var->rootsol;
13396
13398 assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13399 return var->locdom.lb;
13400
13402 assert(!var->donotaggr);
13403 assert(var->data.aggregate.var != NULL);
13404 /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13405 * corresponding infinity value instead of performing an arithmetical transformation (compare method
13406 * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13407 * (or is called by) a public interface method; instead, we only assert that values are finite
13408 * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13409 * positives and negatives if the parameter <numerics/infinity> is modified by the user
13410 */
13414
13416 assert(!var->donotmultaggr);
13417 assert(var->data.multaggr.vars != NULL);
13418 assert(var->data.multaggr.scalars != NULL);
13419 /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13420 * assert(var->data.multaggr.nvars >= 2);
13421 */
13422 rootsol = var->data.multaggr.constant;
13423 for( i = 0; i < var->data.multaggr.nvars; ++i )
13424 rootsol += var->data.multaggr.scalars[i] * SCIPvarGetRootSol(var->data.multaggr.vars[i]);
13425 return rootsol;
13426
13427 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13428 assert(var->negatedvar != NULL);
13430 assert(var->negatedvar->negatedvar == var);
13431 return var->data.negate.constant - SCIPvarGetRootSol(var->negatedvar);
13432
13433 default:
13434 SCIPerrorMessage("unknown variable status\n");
13435 SCIPABORT();
13436 return SCIP_INVALID; /*lint !e527*/
13437 }
13438}
13439
13440/** returns for given variable the reduced cost */
13441static
13443 SCIP_VAR* var, /**< problem variable */
13444 SCIP_SET* set, /**< global SCIP settings */
13445 SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
13446 SCIP_STAT* stat, /**< problem statistics */
13447 SCIP_LP* lp /**< current LP data */
13448 )
13449{
13451 {
13452 SCIP_COL* col;
13453 SCIP_Real primsol;
13454 SCIP_BASESTAT basestat;
13455 SCIP_Bool lpissolbasic;
13456
13457 col = SCIPvarGetCol(var);
13458 assert(col != NULL);
13459
13460 basestat = SCIPcolGetBasisStatus(col);
13461 lpissolbasic = SCIPlpIsSolBasic(lp);
13462 primsol = SCIPcolGetPrimsol(col);
13463
13464 if( (lpissolbasic && (basestat == SCIP_BASESTAT_LOWER || basestat == SCIP_BASESTAT_UPPER)) ||
13465 (!lpissolbasic && (SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol) || SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol))) )
13466 {
13467 SCIP_Real redcost = SCIPcolGetRedcost(col, stat, lp);
13468
13469 assert(((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)) ||
13470 (lpissolbasic && basestat == SCIP_BASESTAT_LOWER)) ? (!SCIPsetIsDualfeasNegative(set, redcost) ||
13472 assert(((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)) ||
13473 (lpissolbasic && basestat == SCIP_BASESTAT_UPPER)) ? (!SCIPsetIsDualfeasPositive(set, redcost) ||
13475
13476 if( (varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_LOWER) ||
13477 (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)))) ||
13478 (!varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_UPPER) ||
13479 (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)))) )
13480 return redcost;
13481 else
13482 return 0.0;
13483 }
13484
13485 return 0.0;
13486 }
13487
13488 return 0.0;
13489}
13490
13491#define MAX_CLIQUELENGTH 50
13492/** returns for the given binary variable the reduced cost which are given by the variable itself and its implication if
13493 * the binary variable is fixed to the given value
13494 */
13496 SCIP_VAR* var, /**< problem variable */
13497 SCIP_SET* set, /**< global SCIP settings */
13498 SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
13499 SCIP_STAT* stat, /**< problem statistics */
13500 SCIP_PROB* prob, /**< transformed problem, or NULL */
13501 SCIP_LP* lp /**< current LP data */
13502 )
13503{
13504 SCIP_Real implredcost;
13505 int ncliques;
13506 int nvars;
13507
13508 assert(SCIPvarIsBinary(var));
13510
13511 /* get reduced cost of given variable */
13512 implredcost = getImplVarRedcost(var, set, varfixing, stat, lp);
13513
13514#ifdef SCIP_MORE_DEBUG
13515 SCIPsetDebugMsg(set, "variable <%s> itself has reduced cost of %g\n", SCIPvarGetName(var), implredcost);
13516#endif
13517
13518 /* the following algorithm is expensive */
13519 ncliques = SCIPvarGetNCliques(var, varfixing);
13520
13521 if( ncliques > 0 )
13522 {
13523 SCIP_CLIQUE** cliques;
13524 SCIP_CLIQUE* clique;
13525 SCIP_VAR** clqvars;
13526 SCIP_VAR** probvars;
13527 SCIP_VAR* clqvar;
13528 SCIP_Bool* clqvalues;
13529 int* entries;
13530 int* ids;
13531 SCIP_Real redcost;
13532 SCIP_Bool cleanedup;
13533 int nclqvars;
13534 int nentries;
13535 int nids;
13536 int id;
13537 int c;
13538 int v;
13539
13540 assert(prob != NULL);
13541 assert(SCIPprobIsTransformed(prob));
13542
13543 nentries = SCIPprobGetNVars(prob) - SCIPprobGetNContVars(prob) + 1;
13544
13545 SCIP_CALL_ABORT( SCIPsetAllocBufferArray(set, &ids, nentries) );
13546 nids = 0;
13547 SCIP_CALL_ABORT( SCIPsetAllocCleanBufferArray(set, &entries, nentries) );
13548
13549 cliques = SCIPvarGetCliques(var, varfixing);
13550 assert(cliques != NULL);
13551
13552 for( c = ncliques - 1; c >= 0; --c )
13553 {
13554 clique = cliques[c];
13555 assert(clique != NULL);
13556 nclqvars = SCIPcliqueGetNVars(clique);
13557 assert(nclqvars > 0);
13558
13559 if( nclqvars > MAX_CLIQUELENGTH )
13560 continue;
13561
13562 clqvars = SCIPcliqueGetVars(clique);
13563 clqvalues = SCIPcliqueGetValues(clique);
13564 assert(clqvars != NULL);
13565 assert(clqvalues != NULL);
13566
13567 cleanedup = SCIPcliqueIsCleanedUp(clique);
13568
13569 for( v = nclqvars - 1; v >= 0; --v )
13570 {
13571 clqvar = clqvars[v];
13572 assert(clqvar != NULL);
13573
13574 /* ignore binary variable which are fixed */
13575 if( clqvar != var && (cleanedup || SCIPvarIsActive(clqvar)) &&
13576 (SCIPvarGetLbLocal(clqvar) < 0.5 && SCIPvarGetUbLocal(clqvar) > 0.5) )
13577 {
13578 int probindex = SCIPvarGetProbindex(clqvar) + 1;
13579 assert(0 < probindex && probindex < nentries);
13580
13581#ifdef SCIP_DISABLED_CODE
13582 /* check that the variable was not yet visited or does not appear with two contradicting implications, ->
13583 * can appear since there is no guarantee that all these infeasible bounds were found
13584 */
13585 assert(!entries[probindex] || entries[probindex] == (clqvalues[v] ? probindex : -probindex));
13586#endif
13587 if( entries[probindex] == 0 )
13588 {
13589 ids[nids] = probindex;
13590 ++nids;
13591
13592 /* mark variable as visited */
13593 entries[probindex] = (clqvalues[v] ? probindex : -probindex);
13594 }
13595 }
13596 }
13597 }
13598
13599 probvars = SCIPprobGetVars(prob);
13600 assert(probvars != NULL);
13601
13602 /* add all implied reduced cost */
13603 for( v = nids - 1; v >= 0; --v )
13604 {
13605 id = ids[v];
13606 assert(0 < id && id < nentries);
13607 assert(entries[id] != 0);
13608 assert(probvars[id - 1] != NULL);
13609 assert(SCIPvarIsActive(probvars[id - 1]));
13610 assert(SCIPvarIsBinary(probvars[id - 1]));
13611 assert(SCIPvarGetLbLocal(probvars[id - 1]) < 0.5 && SCIPvarGetUbLocal(probvars[id - 1]) > 0.5);
13612
13613 if( (entries[id] > 0) != varfixing )
13614 redcost = getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
13615 else
13616 redcost = -getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
13617
13618 if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
13619 implredcost += redcost;
13620
13621 /* reset entries clear buffer array */
13622 entries[id] = 0;
13623 }
13624
13627 }
13628
13629#ifdef SCIP_MORE_DEBUG
13630 SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) has implied reduced cost of %g\n", SCIPvarGetName(var), ncliques,
13631 implredcost);
13632#endif
13633
13634 /* collect non-binary implication information */
13635 nvars = SCIPimplicsGetNImpls(var->implics, varfixing);
13636
13637 if( nvars > 0 )
13638 {
13639 SCIP_VAR** vars;
13640 SCIP_VAR* implvar;
13641 SCIP_COL* col;
13642 SCIP_Real* bounds;
13643 SCIP_BOUNDTYPE* boundtypes;
13644 SCIP_Real redcost;
13645 SCIP_Real lb;
13646 SCIP_Real ub;
13647 SCIP_Bool lpissolbasic;
13648 int v;
13649
13650 vars = SCIPimplicsGetVars(var->implics, varfixing);
13651 boundtypes = SCIPimplicsGetTypes(var->implics, varfixing);
13652 bounds = SCIPimplicsGetBounds(var->implics, varfixing);
13653 lpissolbasic = SCIPlpIsSolBasic(lp);
13654
13655 for( v = nvars - 1; v >= 0; --v )
13656 {
13657 implvar = vars[v];
13658 assert(implvar != NULL);
13659
13660 lb = SCIPvarGetLbLocal(implvar);
13661 ub = SCIPvarGetUbLocal(implvar);
13662
13663 /* ignore binary variable which are fixed or not of column status */
13664 if( SCIPvarGetStatus(implvar) != SCIP_VARSTATUS_COLUMN || SCIPsetIsFeasEQ(set, lb, ub) )
13665 continue;
13666
13667 col = SCIPvarGetCol(implvar);
13668 assert(col != NULL);
13669 redcost = 0.0;
13670
13671 /* solved lp with basis information or not? */
13672 if( lpissolbasic )
13673 {
13674 SCIP_BASESTAT basestat = SCIPcolGetBasisStatus(col);
13675
13676 /* check if the implication is not not yet applied */
13677 if( basestat == SCIP_BASESTAT_LOWER && boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGT(set, bounds[v], lb) )
13678 {
13679 redcost = SCIPcolGetRedcost(col, stat, lp);
13680 assert(!SCIPsetIsDualfeasNegative(set, redcost));
13681
13682 if( !varfixing )
13683 redcost *= (lb - bounds[v]);
13684 else
13685 redcost *= (bounds[v] - lb);
13686 }
13687 else if( basestat == SCIP_BASESTAT_UPPER && boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLT(set, bounds[v], ub) )
13688 {
13689 redcost = SCIPcolGetRedcost(col, stat, lp);
13690 assert(!SCIPsetIsDualfeasPositive(set, redcost));
13691
13692 if( varfixing )
13693 redcost *= (bounds[v] - ub);
13694 else
13695 redcost *= (ub - bounds[v]);
13696 }
13697 }
13698 else
13699 {
13700 SCIP_Real primsol = SCIPcolGetPrimsol(col);
13701
13702 /* check if the implication is not not yet applied */
13703 if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasEQ(set, lb, primsol) && SCIPsetIsFeasGT(set, bounds[v], lb) )
13704 {
13705 redcost = SCIPcolGetRedcost(col, stat, lp);
13706 assert(!SCIPsetIsDualfeasNegative(set, redcost));
13707
13708 if( varfixing )
13709 redcost *= (lb - bounds[v]);
13710 else
13711 redcost *= (bounds[v] - lb);
13712 }
13713 else if( boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasEQ(set, ub, primsol) && SCIPsetIsFeasLT(set, bounds[v], ub) )
13714 {
13715 redcost = SCIPcolGetRedcost(col, stat, lp);
13716 assert(!SCIPsetIsDualfeasPositive(set, redcost));
13717
13718 if( varfixing )
13719 redcost *= (bounds[v] - ub);
13720 else
13721 redcost *= (ub - bounds[v]);
13722 }
13723 }
13724
13725 /* improve implied reduced cost */
13726 if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
13727 implredcost += redcost;
13728 }
13729 }
13730
13731#ifdef SCIP_MORE_DEBUG
13732 SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) and implications (%d) has implied reduced cost of %g\n",
13733 SCIPvarGetName(var), ncliques, nvars, implredcost);
13734#endif
13735
13736 return implredcost;
13737}
13738
13739/** returns the best solution (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation, if
13740 * the root relaxation is not yet completely solved, zero is returned
13741 */
13743 SCIP_VAR* var /**< problem variable */
13744 )
13745{
13746 SCIP_Real rootsol;
13747 int i;
13748
13749 assert(var != NULL);
13750
13751 switch( SCIPvarGetStatus(var) )
13752 {
13754 if( var->data.original.transvar == NULL )
13755 return 0.0;
13757
13760 return var->bestrootsol;
13761
13763 assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13764 return var->locdom.lb;
13765
13767 assert(!var->donotaggr);
13768 assert(var->data.aggregate.var != NULL);
13769 /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13770 * corresponding infinity value instead of performing an arithmetical transformation (compare method
13771 * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13772 * (or is called by) a public interface method; instead, we only assert that values are finite
13773 * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13774 * positives and negatives if the parameter <numerics/infinity> is modified by the user
13775 */
13779
13781 assert(!var->donotmultaggr);
13782 assert(var->data.multaggr.vars != NULL);
13783 assert(var->data.multaggr.scalars != NULL);
13784 /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13785 * assert(var->data.multaggr.nvars >= 2);
13786 */
13787 rootsol = var->data.multaggr.constant;
13788 for( i = 0; i < var->data.multaggr.nvars; ++i )
13789 rootsol += var->data.multaggr.scalars[i] * SCIPvarGetBestRootSol(var->data.multaggr.vars[i]);
13790 return rootsol;
13791
13792 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13793 assert(var->negatedvar != NULL);
13795 assert(var->negatedvar->negatedvar == var);
13797
13798 default:
13799 SCIPerrorMessage("unknown variable status\n");
13800 SCIPABORT();
13801 return 0.0; /*lint !e527*/
13802 }
13803}
13804
13805/** returns the best reduced costs (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation,
13806 * if the root relaxation is not yet completely solved, or the variable was no column of the root LP, SCIP_INVALID is
13807 * returned
13808 */
13810 SCIP_VAR* var /**< problem variable */
13811 )
13812{
13813 assert(var != NULL);
13814
13815 switch( SCIPvarGetStatus(var) )
13816 {
13818 if( var->data.original.transvar == NULL )
13819 return SCIP_INVALID;
13821
13824 return var->bestrootredcost;
13825
13830 return 0.0;
13831
13832 default:
13833 SCIPerrorMessage("unknown variable status\n");
13834 SCIPABORT();
13835 return 0.0; /*lint !e527*/
13836 }
13837}
13838
13839/** returns the best objective value (w.r.t. root reduced cost propagation) of the root LP which belongs the root
13840 * reduced cost which is accessible via SCIPvarGetRootRedcost() or the variable was no column of the root LP,
13841 * SCIP_INVALID is returned
13842 */
13844 SCIP_VAR* var /**< problem variable */
13845 )
13846{
13847 assert(var != NULL);
13848
13849 switch( SCIPvarGetStatus(var) )
13850 {
13852 if( var->data.original.transvar == NULL )
13853 return SCIP_INVALID;
13855
13858 return var->bestrootlpobjval;
13859
13864 return SCIP_INVALID;
13865
13866 default:
13867 SCIPerrorMessage("unknown variable status\n");
13868 SCIPABORT();
13869 return SCIP_INVALID; /*lint !e527*/
13870 }
13871}
13872
13873/** set the given solution as the best root solution w.r.t. root reduced cost propagation in the variables */
13875 SCIP_VAR* var, /**< problem variable */
13876 SCIP_Real rootsol, /**< root solution value */
13877 SCIP_Real rootredcost, /**< root reduced cost */
13878 SCIP_Real rootlpobjval /**< objective value of the root LP */
13879 )
13880{
13881 assert(var != NULL);
13882
13883 var->bestrootsol = rootsol;
13884 var->bestrootredcost = rootredcost;
13885 var->bestrootlpobjval = rootlpobjval;
13886}
13887
13888/** stores the solution value as relaxation solution in the problem variable */
13890 SCIP_VAR* var, /**< problem variable */
13891 SCIP_SET* set, /**< global SCIP settings */
13892 SCIP_RELAXATION* relaxation, /**< global relaxation data */
13893 SCIP_Real solval, /**< solution value in the current relaxation solution */
13894 SCIP_Bool updateobj /**< should the objective value be updated? */
13895 )
13896{
13897 assert(var != NULL);
13898 assert(relaxation != NULL);
13899 assert(set != NULL);
13900 assert(var->scip == set->scip);
13901
13902 /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
13903 switch( SCIPvarGetStatus(var) )
13904 {
13906 SCIP_CALL( SCIPvarSetRelaxSol(var->data.original.transvar, set, relaxation, solval, updateobj) );
13907 break;
13908
13911 if( updateobj )
13912 SCIPrelaxationSolObjAdd(relaxation, var->obj * (solval - var->relaxsol));
13913 var->relaxsol = solval;
13914 break;
13915
13917 if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
13918 {
13919 SCIPerrorMessage("cannot set relaxation solution value for variable <%s> fixed to %.15g to different value %.15g\n",
13920 SCIPvarGetName(var), var->glbdom.lb, solval);
13921 return SCIP_INVALIDDATA;
13922 }
13923 break;
13924
13925 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13926 assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
13927 SCIP_CALL( SCIPvarSetRelaxSol(var->data.aggregate.var, set, relaxation,
13928 (solval - var->data.aggregate.constant)/var->data.aggregate.scalar, updateobj) );
13929 break;
13931 SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
13932 return SCIP_INVALIDDATA;
13933
13935 SCIP_CALL( SCIPvarSetRelaxSol(var->negatedvar, set, relaxation, var->data.negate.constant - solval, updateobj) );
13936 break;
13937
13938 default:
13939 SCIPerrorMessage("unknown variable status\n");
13940 return SCIP_INVALIDDATA;
13941 }
13942
13943 return SCIP_OKAY;
13944}
13945
13946/** returns the solution value of the problem variable in the relaxation solution
13947 *
13948 * @todo Inline this function - similar to SCIPvarGetLPSol_rec.
13949 */
13951 SCIP_VAR* var, /**< problem variable */
13952 SCIP_SET* set /**< global SCIP settings */
13953 )
13954{
13955 SCIP_Real solvalsum;
13956 SCIP_Real solval;
13957 int i;
13958
13959 assert(var != NULL);
13960 assert(set != NULL);
13961 assert(var->scip == set->scip);
13962
13963 /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
13964 switch( SCIPvarGetStatus(var) )
13965 {
13968
13971 return var->relaxsol;
13972
13974 assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
13975 assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
13976 assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
13977 return SCIPvarGetLbGlobal(var);
13978
13979 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13980 solval = SCIPvarGetRelaxSol(var->data.aggregate.var, set);
13981 if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
13982 {
13983 if( var->data.aggregate.scalar * solval > 0.0 )
13984 return SCIPsetInfinity(set);
13985 if( var->data.aggregate.scalar * solval < 0.0 )
13986 return -SCIPsetInfinity(set);
13987 }
13988 return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
13989
13991 solvalsum = var->data.multaggr.constant;
13992 for( i = 0; i < var->data.multaggr.nvars; ++i )
13993 {
13994 solval = SCIPvarGetRelaxSol(var->data.multaggr.vars[i], set);
13995 if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
13996 {
13997 if( var->data.multaggr.scalars[i] * solval > 0.0 )
13998 return SCIPsetInfinity(set);
13999 if( var->data.multaggr.scalars[i] * solval < 0.0 )
14000 return -SCIPsetInfinity(set);
14001 }
14002 solvalsum += var->data.multaggr.scalars[i] * solval;
14003 }
14004 return solvalsum;
14005
14007 solval = SCIPvarGetRelaxSol(var->negatedvar, set);
14008 if( SCIPsetIsInfinity(set, solval) )
14009 return -SCIPsetInfinity(set);
14010 if( SCIPsetIsInfinity(set, -solval) )
14011 return SCIPsetInfinity(set);
14012 return var->data.negate.constant - solval;
14013
14014 default:
14015 SCIPerrorMessage("unknown variable status\n");
14016 SCIPABORT();
14017 return SCIP_INVALID; /*lint !e527*/
14018 }
14019}
14020
14021/** returns the solution value of the transformed problem variable in the relaxation solution */
14023 SCIP_VAR* var /**< problem variable */
14024 )
14025{
14026 assert(var != NULL);
14028
14029 return var->relaxsol;
14030}
14031
14032/** stores the solution value as NLP solution in the problem variable */
14034 SCIP_VAR* var, /**< problem variable */
14035 SCIP_SET* set, /**< global SCIP settings */
14036 SCIP_Real solval /**< solution value in the current NLP solution */
14037 )
14038{
14039 assert(var != NULL);
14040 assert(set != NULL);
14041 assert(var->scip == set->scip);
14042
14043 /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
14044 switch( SCIPvarGetStatus(var) )
14045 {
14048 break;
14049
14052 var->nlpsol = solval;
14053 break;
14054
14056 if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
14057 {
14058 SCIPerrorMessage("cannot set NLP solution value for variable <%s> fixed to %.15g to different value %.15g\n",
14059 SCIPvarGetName(var), var->glbdom.lb, solval);
14060 SCIPABORT();
14061 return SCIP_INVALIDCALL; /*lint !e527*/
14062 }
14063 break;
14064
14065 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
14066 assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
14068 break;
14069
14071 SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
14072 SCIPABORT();
14073 return SCIP_INVALIDCALL; /*lint !e527*/
14074
14076 SCIP_CALL( SCIPvarSetNLPSol(var->negatedvar, set, var->data.negate.constant - solval) );
14077 break;
14078
14079 default:
14080 SCIPerrorMessage("unknown variable status\n");
14081 SCIPABORT();
14082 return SCIP_ERROR; /*lint !e527*/
14083 }
14084
14085 return SCIP_OKAY;
14086}
14087
14088/** returns a weighted average solution value of the variable in all feasible primal solutions found so far */
14090 SCIP_VAR* var /**< problem variable */
14091 )
14092{
14093 SCIP_Real avgsol;
14094 int i;
14095
14096 assert(var != NULL);
14097
14098 switch( SCIPvarGetStatus(var) )
14099 {
14101 if( var->data.original.transvar == NULL )
14102 return 0.0;
14104
14107 avgsol = var->primsolavg;
14108 avgsol = MAX(avgsol, var->glbdom.lb);
14109 avgsol = MIN(avgsol, var->glbdom.ub);
14110 return avgsol;
14111
14113 assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
14114 return var->locdom.lb;
14115
14117 assert(!var->donotaggr);
14118 assert(var->data.aggregate.var != NULL);
14120 + var->data.aggregate.constant;
14121
14123 assert(!var->donotmultaggr);
14124 assert(var->data.multaggr.vars != NULL);
14125 assert(var->data.multaggr.scalars != NULL);
14126 /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
14127 * assert(var->data.multaggr.nvars >= 2);
14128 */
14129 avgsol = var->data.multaggr.constant;
14130 for( i = 0; i < var->data.multaggr.nvars; ++i )
14131 avgsol += var->data.multaggr.scalars[i] * SCIPvarGetAvgSol(var->data.multaggr.vars[i]);
14132 return avgsol;
14133
14134 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
14135 assert(var->negatedvar != NULL);
14137 assert(var->negatedvar->negatedvar == var);
14138 return var->data.negate.constant - SCIPvarGetAvgSol(var->negatedvar);
14139
14140 default:
14141 SCIPerrorMessage("unknown variable status\n");
14142 SCIPABORT();
14143 return 0.0; /*lint !e527*/
14144 }
14145}
14146
14147/** returns solution value and index of variable lower bound that is closest to the variable's value in the given primal solution
14148 * or current LP solution if no primal solution is given; returns an index of -1 if no variable lower bound is available
14149 */
14151 SCIP_VAR* var, /**< active problem variable */
14152 SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
14153 SCIP_SET* set, /**< global SCIP settings */
14154 SCIP_STAT* stat, /**< problem statistics */
14155 SCIP_Real* closestvlb, /**< pointer to store the value of the closest variable lower bound */
14156 int* closestvlbidx /**< pointer to store the index of the closest variable lower bound */
14157 )
14158{
14159 int nvlbs;
14160
14161 assert(var != NULL);
14162 assert(stat != NULL);
14163 assert(set != NULL);
14164 assert(var->scip == set->scip);
14165 assert(closestvlb != NULL);
14166 assert(closestvlbidx != NULL);
14167
14168 *closestvlbidx = -1;
14169 *closestvlb = SCIP_REAL_MIN;
14170
14171 nvlbs = SCIPvarGetNVlbs(var);
14172 if( nvlbs > 0 )
14173 {
14174 SCIP_VAR** vlbvars;
14175 SCIP_Real* vlbcoefs;
14176 SCIP_Real* vlbconsts;
14177 int i;
14178
14179 vlbvars = SCIPvarGetVlbVars(var);
14180 vlbcoefs = SCIPvarGetVlbCoefs(var);
14181 vlbconsts = SCIPvarGetVlbConstants(var);
14182
14183 /* check for cached values */
14184 if( var->closestvblpcount == stat->lpcount && var->closestvlbidx != -1 && sol == NULL)
14185 {
14186 i = var->closestvlbidx;
14187 assert(0 <= i && i < nvlbs);
14188 assert(SCIPvarIsActive(vlbvars[i]));
14189 *closestvlbidx = i;
14190 *closestvlb = vlbcoefs[i] * SCIPvarGetLPSol(vlbvars[i]) + vlbconsts[i];
14191 }
14192 else
14193 {
14194 /* search best VUB */
14195 for( i = 0; i < nvlbs; i++ )
14196 {
14197 if( SCIPvarIsActive(vlbvars[i]) )
14198 {
14199 SCIP_Real vlbsol;
14200
14201 vlbsol = vlbcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vlbvars[i]) : SCIPsolGetVal(sol, set, stat, vlbvars[i])) + vlbconsts[i];
14202 if( vlbsol > *closestvlb )
14203 {
14204 *closestvlb = vlbsol;
14205 *closestvlbidx = i;
14206 }
14207 }
14208 }
14209
14210 if( sol == NULL )
14211 {
14212 /* update cached value */
14213 if( var->closestvblpcount != stat->lpcount )
14214 var->closestvubidx = -1;
14215 var->closestvlbidx = *closestvlbidx;
14216 var->closestvblpcount = stat->lpcount;
14217 }
14218 }
14219 }
14220}
14221
14222/** returns solution value and index of variable upper bound that is closest to the variable's value in the given primal solution;
14223 * or current LP solution if no primal solution is given; returns an index of -1 if no variable upper bound is available
14224 */
14226 SCIP_VAR* var, /**< active problem variable */
14227 SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
14228 SCIP_SET* set, /**< global SCIP settings */
14229 SCIP_STAT* stat, /**< problem statistics */
14230 SCIP_Real* closestvub, /**< pointer to store the value of the closest variable upper bound */
14231 int* closestvubidx /**< pointer to store the index of the closest variable upper bound */
14232 )
14233{
14234 int nvubs;
14235
14236 assert(var != NULL);
14237 assert(set != NULL);
14238 assert(var->scip == set->scip);
14239 assert(closestvub != NULL);
14240 assert(closestvubidx != NULL);
14241
14242 *closestvubidx = -1;
14243 *closestvub = SCIP_REAL_MAX;
14244
14245 nvubs = SCIPvarGetNVubs(var);
14246 if( nvubs > 0 )
14247 {
14248 SCIP_VAR** vubvars;
14249 SCIP_Real* vubcoefs;
14250 SCIP_Real* vubconsts;
14251 int i;
14252
14253 vubvars = SCIPvarGetVubVars(var);
14254 vubcoefs = SCIPvarGetVubCoefs(var);
14255 vubconsts = SCIPvarGetVubConstants(var);
14256
14257 /* check for cached values */
14258 if( var->closestvblpcount == stat->lpcount && var->closestvubidx != -1 && sol == NULL)
14259 {
14260 i = var->closestvubidx;
14261 assert(0 <= i && i < nvubs);
14262 assert(SCIPvarIsActive(vubvars[i]));
14263 *closestvubidx = i;
14264 *closestvub = vubcoefs[i] * SCIPvarGetLPSol(vubvars[i]) + vubconsts[i];
14265 }
14266 else
14267 {
14268 /* search best VUB */
14269 for( i = 0; i < nvubs; i++ )
14270 {
14271 if( SCIPvarIsActive(vubvars[i]) )
14272 {
14273 SCIP_Real vubsol;
14274
14275 vubsol = vubcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vubvars[i]) : SCIPsolGetVal(sol, set, stat, vubvars[i])) + vubconsts[i];
14276 if( vubsol < *closestvub )
14277 {
14278 *closestvub = vubsol;
14279 *closestvubidx = i;
14280 }
14281 }
14282 }
14283
14284 if( sol == NULL )
14285 {
14286 /* update cached value */
14287 if( var->closestvblpcount != stat->lpcount )
14288 var->closestvlbidx = -1;
14289 var->closestvubidx = *closestvubidx;
14290 var->closestvblpcount = stat->lpcount;
14291 }
14292 }
14293 }
14294}
14295
14296/** resolves variable to columns and adds them with the coefficient to the row */
14298 SCIP_VAR* var, /**< problem variable */
14299 BMS_BLKMEM* blkmem, /**< block memory */
14300 SCIP_SET* set, /**< global SCIP settings */
14301 SCIP_STAT* stat, /**< problem statistics */
14302 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
14303 SCIP_PROB* prob, /**< problem data */
14304 SCIP_LP* lp, /**< current LP data */
14305 SCIP_ROW* row, /**< LP row */
14306 SCIP_Real val /**< value of coefficient */
14307 )
14308{
14309 int i;
14310
14311 assert(var != NULL);
14312 assert(set != NULL);
14313 assert(var->scip == set->scip);
14314 assert(row != NULL);
14315 assert(!SCIPsetIsInfinity(set, REALABS(val)));
14316
14317 SCIPsetDebugMsg(set, "adding coefficient %g<%s> to row <%s>\n", val, var->name, row->name);
14318
14319 if ( SCIPsetIsZero(set, val) )
14320 return SCIP_OKAY;
14321
14322 switch( SCIPvarGetStatus(var) )
14323 {
14325 if( var->data.original.transvar == NULL )
14326 {
14327 SCIPerrorMessage("cannot add untransformed original variable <%s> to LP row <%s>\n", var->name, row->name);
14328 return SCIP_INVALIDDATA;
14329 }
14330 SCIP_CALL( SCIPvarAddToRow(var->data.original.transvar, blkmem, set, stat, eventqueue, prob, lp, row, val) );
14331 return SCIP_OKAY;
14332
14334 /* add globally fixed variables as constant */
14335 if( SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub) )
14336 {
14337 SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->glbdom.lb) );
14338 return SCIP_OKAY;
14339 }
14340 /* convert loose variable into column */
14341 SCIP_CALL( SCIPvarColumn(var, blkmem, set, stat, prob, lp) );
14343 /*lint -fallthrough*/
14344
14346 assert(var->data.col != NULL);
14347 assert(var->data.col->var == var);
14348 SCIP_CALL( SCIProwIncCoef(row, blkmem, set, eventqueue, lp, var->data.col, val) );
14349 return SCIP_OKAY;
14350
14352 assert(var->glbdom.lb == var->glbdom.ub); /*lint !e777*/
14353 assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
14354 assert(var->locdom.lb == var->glbdom.lb); /*lint !e777*/
14355 assert(!SCIPsetIsInfinity(set, REALABS(var->locdom.lb)));
14356 SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->locdom.lb) );
14357 return SCIP_OKAY;
14358
14360 assert(!var->donotaggr);
14361 assert(var->data.aggregate.var != NULL);
14362 SCIP_CALL( SCIPvarAddToRow(var->data.aggregate.var, blkmem, set, stat, eventqueue, prob, lp,
14363 row, var->data.aggregate.scalar * val) );
14364 SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.aggregate.constant * val) );
14365 return SCIP_OKAY;
14366
14368 assert(!var->donotmultaggr);
14369 assert(var->data.multaggr.vars != NULL);
14370 assert(var->data.multaggr.scalars != NULL);
14371 /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
14372 * assert(var->data.multaggr.nvars >= 2);
14373 */
14374 for( i = 0; i < var->data.multaggr.nvars; ++i )
14375 {
14376 SCIP_CALL( SCIPvarAddToRow(var->data.multaggr.vars[i], blkmem, set, stat, eventqueue, prob, lp,
14377 row, var->data.multaggr.scalars[i] * val) );
14378 }
14379 SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.multaggr.constant * val) );
14380 return SCIP_OKAY;
14381
14382 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
14383 assert(var->negatedvar != NULL);
14385 assert(var->negatedvar->negatedvar == var);
14386 SCIP_CALL( SCIPvarAddToRow(var->negatedvar, blkmem, set, stat, eventqueue, prob, lp, row, -val) );
14387 SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.negate.constant * val) );
14388 return SCIP_OKAY;
14389
14390 default:
14391 SCIPerrorMessage("unknown variable status\n");
14392 return SCIP_INVALIDDATA;
14393 }
14394}
14395
14396/* optionally, define this compiler flag to write complete variable histories to a file */
14397#ifdef SCIP_HISTORYTOFILE
14398SCIP_Longint counter = 0l;
14399const char* historypath="."; /* allows for user-defined path; use '.' for calling directory of SCIP */
14400#include "scip/scip.h"
14401#endif
14402
14403/** updates the pseudo costs of the given variable and the global pseudo costs after a change of
14404 * "solvaldelta" in the variable's solution value and resulting change of "objdelta" in the in the LP's objective value
14405 */
14407 SCIP_VAR* var, /**< problem variable */
14408 SCIP_SET* set, /**< global SCIP settings */
14409 SCIP_STAT* stat, /**< problem statistics */
14410 SCIP_Real solvaldelta, /**< difference of variable's new LP value - old LP value */
14411 SCIP_Real objdelta, /**< difference of new LP's objective value - old LP's objective value */
14412 SCIP_Real weight /**< weight in (0,1] of this update in pseudo cost sum */
14413 )
14414{
14415 SCIP_Real oldrootpseudocosts;
14416 assert(var != NULL);
14417 assert(set != NULL);
14418 assert(var->scip == set->scip);
14419 assert(stat != NULL);
14420
14421 /* check if history statistics should be collected for a variable */
14422 if( !stat->collectvarhistory )
14423 return SCIP_OKAY;
14424
14425 switch( SCIPvarGetStatus(var) )
14426 {
14428 if( var->data.original.transvar == NULL )
14429 {
14430 SCIPerrorMessage("cannot update pseudo costs of original untransformed variable\n");
14431 return SCIP_INVALIDDATA;
14432 }
14433 SCIP_CALL( SCIPvarUpdatePseudocost(var->data.original.transvar, set, stat, solvaldelta, objdelta, weight) );
14434 return SCIP_OKAY;
14435
14438 /* store old pseudo-costs for root LP best-estimate update */
14439 oldrootpseudocosts = SCIPvarGetMinPseudocostScore(var, stat, set, SCIPvarGetRootSol(var));
14440
14441 /* update history */
14442 SCIPhistoryUpdatePseudocost(var->history, set, solvaldelta, objdelta, weight);
14443 SCIPhistoryUpdatePseudocost(var->historycrun, set, solvaldelta, objdelta, weight);
14444 SCIPhistoryUpdatePseudocost(stat->glbhistory, set, solvaldelta, objdelta, weight);
14445 SCIPhistoryUpdatePseudocost(stat->glbhistorycrun, set, solvaldelta, objdelta, weight);
14446
14447 /* update root LP best-estimate */
14448 SCIP_CALL( SCIPstatUpdateVarRootLPBestEstimate(stat, set, var, oldrootpseudocosts) );
14449
14450 /* append history to file */
14451#ifdef SCIP_HISTORYTOFILE
14452 {
14453 FILE* f;
14454 char filename[256];
14455 SCIP_NODE* currentnode;
14456 SCIP_NODE* parentnode;
14457 currentnode = SCIPgetFocusNode(set->scip);
14458 parentnode = SCIPnodeGetParent(currentnode);
14459
14460 sprintf(filename, "%s/%s.pse", historypath, SCIPgetProbName(set->scip));
14461 f = fopen(filename, "a");
14462 if( NULL != f )
14463 {
14464 fprintf(f, "%lld %s \t %lld \t %lld \t %lld \t %d \t %15.9f \t %.3f\n",
14465 ++counter,
14466 SCIPvarGetName(var),
14467 SCIPnodeGetNumber(currentnode),
14468 parentnode != NULL ? SCIPnodeGetNumber(parentnode) : -1,
14470 SCIPgetDepth(set->scip),
14471 objdelta,
14472 solvaldelta);
14473 fclose(f);
14474 }
14475 }
14476#endif
14477 return SCIP_OKAY;
14478
14480 SCIPerrorMessage("cannot update pseudo cost values of a fixed variable\n");
14481 return SCIP_INVALIDDATA;
14482
14484 assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
14486 solvaldelta/var->data.aggregate.scalar, objdelta, weight) );
14487 return SCIP_OKAY;
14488
14490 SCIPerrorMessage("cannot update pseudo cost values of a multi-aggregated variable\n");
14491 return SCIP_INVALIDDATA;
14492
14494 SCIP_CALL( SCIPvarUpdatePseudocost(var->negatedvar, set, stat, -solvaldelta, objdelta, weight) );
14495 return SCIP_OKAY;
14496
14497 default:
14498 SCIPerrorMessage("unknown variable status\n");
14499 return SCIP_INVALIDDATA;
14500 }
14501}
14502
14503/** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value */
14505 SCIP_VAR* var, /**< problem variable */
14506 SCIP_STAT* stat, /**< problem statistics */
14507 SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
14508 )
14509{
14510 SCIP_BRANCHDIR dir;
14511
14512 assert(var != NULL);
14513 assert(stat != NULL);
14514
14515 switch( SCIPvarGetStatus(var) )
14516 {
14518 if( var->data.original.transvar == NULL )
14519 return SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
14520 else
14521 return SCIPvarGetPseudocost(var->data.original.transvar, stat, solvaldelta);
14522
14525 dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
14526
14527 return SCIPhistoryGetPseudocostCount(var->history, dir) > 0.0
14528 ? SCIPhistoryGetPseudocost(var->history, solvaldelta)
14529 : SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
14530
14532 return 0.0;
14533
14535 return SCIPvarGetPseudocost(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
14536
14538 return 0.0;
14539
14541 return SCIPvarGetPseudocost(var->negatedvar, stat, -solvaldelta);
14542
14543 default:
14544 SCIPerrorMessage("unknown variable status\n");
14545 SCIPABORT();
14546 return 0.0; /*lint !e527*/
14547 }
14548}
14549
14550/** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value,
14551 * only using the pseudo cost information of the current run
14552 */
14554 SCIP_VAR* var, /**< problem variable */
14555 SCIP_STAT* stat, /**< problem statistics */
14556 SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
14557 )
14558{
14559 SCIP_BRANCHDIR dir;
14560
14561 assert(var != NULL);
14562 assert(stat != NULL);
14563
14564 switch( SCIPvarGetStatus(var) )
14565 {
14567 if( var->data.original.transvar == NULL )
14568 return SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
14569 else
14570 return SCIPvarGetPseudocostCurrentRun(var->data.original.transvar, stat, solvaldelta);
14571
14574 dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
14575
14576 return SCIPhistoryGetPseudocostCount(var->historycrun, dir) > 0.0
14577 ? SCIPhistoryGetPseudocost(var->historycrun, solvaldelta)
14578 : SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
14579
14581 return 0.0;
14582
14584 return SCIPvarGetPseudocostCurrentRun(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
14585
14587 return 0.0;
14588
14590 return SCIPvarGetPseudocostCurrentRun(var->negatedvar, stat, -solvaldelta);
14591
14592 default:
14593 SCIPerrorMessage("unknown variable status\n");
14594 SCIPABORT();
14595 return 0.0; /*lint !e527*/
14596 }
14597}
14598
14599/** gets the variable's (possible fractional) number of pseudo cost updates for the given direction */
14601 SCIP_VAR* var, /**< problem variable */
14602 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14603 )
14604{
14605 assert(var != NULL);
14606 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14607
14608 switch( SCIPvarGetStatus(var) )
14609 {
14611 if( var->data.original.transvar == NULL )
14612 return 0.0;
14613 else
14615
14618 return SCIPhistoryGetPseudocostCount(var->history, dir);
14619
14621 return 0.0;
14622
14624 if( var->data.aggregate.scalar > 0.0 )
14625 return SCIPvarGetPseudocostCount(var->data.aggregate.var, dir);
14626 else
14628
14630 return 0.0;
14631
14634
14635 default:
14636 SCIPerrorMessage("unknown variable status\n");
14637 SCIPABORT();
14638 return 0.0; /*lint !e527*/
14639 }
14640}
14641
14642/** gets the variable's (possible fractional) number of pseudo cost updates for the given direction,
14643 * only using the pseudo cost information of the current run
14644 */
14646 SCIP_VAR* var, /**< problem variable */
14647 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14648 )
14649{
14650 assert(var != NULL);
14651 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14652
14653 switch( SCIPvarGetStatus(var) )
14654 {
14656 if( var->data.original.transvar == NULL )
14657 return 0.0;
14658 else
14660
14664
14666 return 0.0;
14667
14669 if( var->data.aggregate.scalar > 0.0 )
14671 else
14673
14675 return 0.0;
14676
14679
14680 default:
14681 SCIPerrorMessage("unknown variable status\n");
14682 SCIPABORT();
14683 return 0.0; /*lint !e527*/
14684 }
14685}
14686
14687/** compares both possible directions for rounding the given solution value and returns the minimum pseudo-costs of the variable */
14689 SCIP_VAR* var, /**< problem variable */
14690 SCIP_STAT* stat, /**< problem statistics */
14691 SCIP_SET* set, /**< global SCIP settings */
14692 SCIP_Real solval /**< solution value, e.g., LP solution value */
14693 )
14694{
14695 SCIP_Real upscore;
14696 SCIP_Real downscore;
14697 SCIP_Real solvaldeltaup;
14698 SCIP_Real solvaldeltadown;
14699
14700 /* LP root estimate only works for variables with fractional LP root solution */
14701 if( SCIPsetIsFeasIntegral(set, solval) )
14702 return 0.0;
14703
14704 /* no min pseudo-cost score is calculated as long as the variable was not initialized in a direction */
14706 return 0.0;
14707
14708 /* compute delta's to ceil and floor of root LP solution value */
14709 solvaldeltaup = SCIPsetCeil(set, solval) - solval;
14710 solvaldeltadown = SCIPsetFloor(set, solval) - solval;
14711
14712 upscore = SCIPvarGetPseudocost(var, stat, solvaldeltaup);
14713 downscore = SCIPvarGetPseudocost(var, stat, solvaldeltadown);
14714
14715 return MIN(upscore, downscore);
14716}
14717
14718/** gets the an estimate of the variable's pseudo cost variance in direction \p dir */
14720 SCIP_VAR* var, /**< problem variable */
14721 SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
14722 SCIP_Bool onlycurrentrun /**< return pseudo cost variance only for current branch and bound run */
14723 )
14724{
14725 assert(var != NULL);
14726 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14727
14728 switch( SCIPvarGetStatus(var) )
14729 {
14731 if( var->data.original.transvar == NULL )
14732 return 0.0;
14733 else
14734 return SCIPvarGetPseudocostVariance(var->data.original.transvar, dir, onlycurrentrun);
14735
14738 if( onlycurrentrun )
14740 else
14741 return SCIPhistoryGetPseudocostVariance(var->history, dir);
14742
14744 return 0.0;
14745
14747 if( var->data.aggregate.scalar > 0.0 )
14748 return SCIPvarGetPseudocostVariance(var->data.aggregate.var, dir, onlycurrentrun);
14749 else
14750 return SCIPvarGetPseudocostVariance(var->data.aggregate.var, SCIPbranchdirOpposite(dir), onlycurrentrun);
14751
14753 return 0.0;
14754
14756 return SCIPvarGetPseudocostVariance(var->negatedvar, SCIPbranchdirOpposite(dir), onlycurrentrun);
14757
14758 default:
14759 SCIPerrorMessage("unknown variable status\n");
14760 SCIPABORT();
14761 return 0.0; /*lint !e527*/
14762 }
14763}
14764
14765/** calculates a confidence bound for this variable under the assumption of normally distributed pseudo costs
14766 *
14767 * The confidence bound \f$ \theta \geq 0\f$ denotes the interval borders \f$ [X - \theta, \ X + \theta]\f$, which contains
14768 * the true pseudo costs of the variable, i.e., the expected value of the normal distribution, with a probability
14769 * of 2 * clevel - 1.
14770 *
14771 * @return value of confidence bound for this variable
14772 */
14774 SCIP_VAR* var, /**< variable in question */
14775 SCIP_SET* set, /**< global SCIP settings */
14776 SCIP_BRANCHDIR dir, /**< the branching direction for the confidence bound */
14777 SCIP_Bool onlycurrentrun, /**< should only the current run be taken into account */
14778 SCIP_CONFIDENCELEVEL clevel /**< confidence level for the interval */
14779 )
14780{
14781 SCIP_Real confidencebound;
14782
14783 confidencebound = SCIPvarGetPseudocostVariance(var, dir, onlycurrentrun);
14784 if( SCIPsetIsFeasPositive(set, confidencebound) )
14785 {
14786 SCIP_Real count;
14787
14788 if( onlycurrentrun )
14789 count = SCIPvarGetPseudocostCountCurrentRun(var, dir);
14790 else
14791 count = SCIPvarGetPseudocostCount(var, dir);
14792 /* assertion is valid because variance is positive */
14793 assert(count >= 1.9);
14794
14795 confidencebound /= count; /*lint !e414 division by zero can obviously not occur */
14796 confidencebound = sqrt(confidencebound);
14797
14798 /* the actual, underlying distribution of the mean is a student-t-distribution with degrees of freedom equal to
14799 * the number of pseudo cost evaluations of this variable in the respective direction. */
14800 confidencebound *= SCIPstudentTGetCriticalValue(clevel, (int)SCIPsetFloor(set, count) - 1);
14801 }
14802 else
14803 confidencebound = 0.0;
14804
14805 return confidencebound;
14806}
14807
14808/** check if the current pseudo cost relative error in a direction violates the given threshold. The Relative
14809 * Error is calculated at a specific confidence level
14810 */
14812 SCIP_VAR* var, /**< variable in question */
14813 SCIP_SET* set, /**< global SCIP settings */
14814 SCIP_STAT* stat, /**< problem statistics */
14815 SCIP_Real threshold, /**< threshold for relative errors to be considered reliable (enough) */
14816 SCIP_CONFIDENCELEVEL clevel /**< a given confidence level */
14817 )
14818{
14819 SCIP_Real downsize;
14820 SCIP_Real upsize;
14821 SCIP_Real size;
14822 SCIP_Real relerrorup;
14823 SCIP_Real relerrordown;
14824 SCIP_Real relerror;
14825
14826 /* check, if the pseudo cost score of the variable is reliable */
14829 size = MIN(downsize, upsize);
14830
14831 /* Pseudo costs relative error can only be reliable if both directions have been tried at least twice */
14832 if( size <= 1.9 )
14833 return FALSE;
14834
14835 /* use the relative error between the current mean pseudo cost value of the candidate and its upper
14836 * confidence interval bound at confidence level of 95% for individual variable reliability.
14837 * this is only possible if we have at least 2 measurements and therefore a valid variance estimate.
14838 */
14839 if( downsize >= 1.9 )
14840 {
14841 SCIP_Real normval;
14842
14844 normval = SCIPvarGetPseudocostCurrentRun(var, stat, -1.0);
14845 normval = MAX(1.0, normval);
14846
14847 relerrordown /= normval;
14848 }
14849 else
14850 relerrordown = 0.0;
14851
14852 if( upsize >= 1.9 )
14853 {
14854 SCIP_Real normval;
14855
14857 normval = SCIPvarGetPseudocostCurrentRun(var, stat, +1.0);
14858 normval = MAX(1.0, normval);
14859 relerrorup /= normval;
14860 }
14861 else
14862 relerrorup = 0.0;
14863
14864 /* consider the relative error threshold violated, if it is violated in at least one branching direction */
14865 relerror = MAX(relerrorup, relerrordown);
14866
14867 return (relerror <= threshold);
14868}
14869
14870/** check if variable pseudo-costs have a significant difference in location. The significance depends on
14871 * the choice of \p clevel and on the kind of tested hypothesis. The one-sided hypothesis, which
14872 * should be rejected, is that fracy * mu_y >= fracx * mu_x, where mu_y and mu_x denote the
14873 * unknown location means of the underlying pseudo-cost distributions of x and y.
14874 *
14875 * This method is applied best if variable x has a better pseudo-cost score than y. The method hypothesizes that y were actually
14876 * better than x (despite the current information), meaning that y can be expected to yield branching
14877 * decisions as least as good as x in the long run. If the method returns TRUE, the current history information is
14878 * sufficient to safely rely on the alternative hypothesis that x yields indeed a better branching score (on average)
14879 * than y.
14880 *
14881 * @note The order of x and y matters for the one-sided hypothesis
14882 *
14883 * @note set \p onesided to FALSE if you are not sure which variable is better. The hypothesis tested then reads
14884 * fracy * mu_y == fracx * mu_x vs the alternative hypothesis fracy * mu_y != fracx * mu_x.
14885 *
14886 * @return TRUE if the hypothesis can be safely rejected at the given confidence level
14887 */
14889 SCIP_SET* set, /**< global SCIP settings */
14890 SCIP_STAT* stat, /**< problem statistics */
14891 SCIP_VAR* varx, /**< variable x */
14892 SCIP_Real fracx, /**< the fractionality of variable x */
14893 SCIP_VAR* vary, /**< variable y */
14894 SCIP_Real fracy, /**< the fractionality of variable y */
14895 SCIP_BRANCHDIR dir, /**< branching direction */
14896 SCIP_CONFIDENCELEVEL clevel, /**< confidence level for rejecting hypothesis */
14897 SCIP_Bool onesided /**< should a one-sided hypothesis y >= x be tested? */
14898 )
14899{
14900 SCIP_Real meanx;
14901 SCIP_Real meany;
14902 SCIP_Real variancex;
14903 SCIP_Real variancey;
14904 SCIP_Real countx;
14905 SCIP_Real county;
14906 SCIP_Real tresult;
14907 SCIP_Real realdirection;
14908
14909 if( varx == vary )
14910 return FALSE;
14911
14912 countx = SCIPvarGetPseudocostCount(varx, dir);
14913 county = SCIPvarGetPseudocostCount(vary, dir);
14914
14915 /* if not at least 2 measurements were taken, return FALSE */
14916 if( countx <= 1.9 || county <= 1.9 )
14917 return FALSE;
14918
14919 realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
14920
14921 meanx = fracx * SCIPvarGetPseudocost(varx, stat, realdirection);
14922 meany = fracy * SCIPvarGetPseudocost(vary, stat, realdirection);
14923
14924 variancex = SQR(fracx) * SCIPvarGetPseudocostVariance(varx, dir, FALSE);
14925 variancey = SQR(fracy) * SCIPvarGetPseudocostVariance(vary, dir, FALSE);
14926
14927 /* if there is no variance, the means are taken from a constant distribution */
14928 if( SCIPsetIsFeasEQ(set, variancex + variancey, 0.0) )
14929 return (onesided ? SCIPsetIsFeasGT(set, meanx, meany) : !SCIPsetIsFeasEQ(set, meanx, meany));
14930
14931 tresult = SCIPcomputeTwoSampleTTestValue(meanx, meany, variancex, variancey, countx, county);
14932
14933 /* for the two-sided hypothesis, just take the absolute of t */
14934 if( !onesided )
14935 tresult = REALABS(tresult);
14936
14937 return (tresult >= SCIPstudentTGetCriticalValue(clevel, (int)(countx + county - 2)));
14938}
14939
14940/** tests at a given confidence level whether the variable pseudo-costs only have a small probability to
14941 * exceed a \p threshold. This is useful to determine if past observations provide enough evidence
14942 * to skip an expensive strong-branching step if there is already a candidate that has been proven to yield an improvement
14943 * of at least \p threshold.
14944 *
14945 * @note use \p clevel to adjust the level of confidence. For SCIP_CONFIDENCELEVEL_MIN, the method returns TRUE if
14946 * the estimated probability to exceed \p threshold is less than 25 %.
14947 *
14948 * @see SCIP_Confidencelevel for a list of available levels. The used probability limits refer to the one-sided levels
14949 * of confidence.
14950 *
14951 * @return TRUE if the variable pseudo-cost probabilistic model is likely to be smaller than \p threshold
14952 * at the given confidence level \p clevel.
14953 */
14955 SCIP_SET* set, /**< global SCIP settings */
14956 SCIP_STAT* stat, /**< problem statistics */
14957 SCIP_VAR* var, /**< variable x */
14958 SCIP_Real frac, /**< the fractionality of variable x */
14959 SCIP_Real threshold, /**< the threshold to test against */
14960 SCIP_BRANCHDIR dir, /**< branching direction */
14961 SCIP_CONFIDENCELEVEL clevel /**< confidence level for rejecting hypothesis */
14962 )
14963{
14964 SCIP_Real mean;
14965 SCIP_Real variance;
14966 SCIP_Real count;
14967 SCIP_Real realdirection;
14968 SCIP_Real probability;
14969 SCIP_Real problimit;
14970
14971 count = SCIPvarGetPseudocostCount(var, dir);
14972
14973 /* if not at least 2 measurements were taken, return FALSE */
14974 if( count <= 1.9 )
14975 return FALSE;
14976
14977 realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
14978
14979 mean = frac * SCIPvarGetPseudocost(var, stat, realdirection);
14980 variance = SQR(frac) * SCIPvarGetPseudocostVariance(var, dir, FALSE);
14981
14982 /* if mean is at least threshold, it has at least a 50% probability to exceed threshold, we therefore return FALSE */
14983 if( SCIPsetIsFeasGE(set, mean, threshold) )
14984 return FALSE;
14985
14986 /* if there is no variance, the means are taken from a constant distribution */
14987 if( SCIPsetIsFeasEQ(set, variance, 0.0) )
14988 return SCIPsetIsFeasLT(set, mean, threshold);
14989
14990 /* obtain probability of a normally distributed random variable at given mean and variance to yield at most threshold */
14991 probability = SCIPnormalCDF(mean, variance, threshold);
14992
14993 /* determine a probability limit corresponding to the given confidence level */
14994 switch( clevel )
14995 {
14997 problimit = 0.75;
14998 break;
15000 problimit = 0.875;
15001 break;
15003 problimit = 0.9;
15004 break;
15006 problimit = 0.95;
15007 break;
15009 problimit = 0.975;
15010 break;
15011 default:
15012 problimit = -1;
15013 SCIPerrorMessage("Confidence level set to unknown value <%d>", (int)clevel);
15014 SCIPABORT();
15015 break;
15016 }
15017
15018 return (probability >= problimit);
15019}
15020
15021/** find the corresponding history entry if already existing, otherwise create new entry */
15022static
15024 SCIP_VAR* var, /**< problem variable */
15025 SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15026 BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15027 SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15028 SCIP_HISTORY** history /**< pointer to store the value based history, or NULL */
15029 )
15030{
15031 assert(var != NULL);
15032 assert(blkmem != NULL);
15033 assert(set != NULL);
15034 assert(history != NULL);
15035
15036 (*history) = NULL;
15037
15038 if( var->valuehistory == NULL )
15039 {
15041 }
15042
15043 SCIP_CALL( SCIPvaluehistoryFind(var->valuehistory, blkmem, set, value, history) );
15044
15045 return SCIP_OKAY;
15046}
15047
15048/** check if value based history should be used */
15049static
15051 SCIP_VAR* var, /**< problem variable */
15052 SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15053 SCIP_SET* set /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15054 )
15055{
15056 /* check if the domain value is unknown (not specific) */
15057 if( value == SCIP_UNKNOWN ) /*lint !e777*/
15058 return FALSE;
15059
15060 assert(set != NULL);
15061
15062 /* check if value based history should be collected */
15063 if( !set->history_valuebased )
15064 return FALSE;
15065
15066 /* value based history is not collected for binary variable since the standard history already contains all information */
15068 return FALSE;
15069
15070 /* value based history is not collected for continuous variables */
15072 return FALSE;
15073
15074 return TRUE;
15075}
15076
15077/** increases VSIDS of the variable by the given weight */
15079 SCIP_VAR* var, /**< problem variable */
15080 BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15081 SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15082 SCIP_STAT* stat, /**< problem statistics */
15083 SCIP_BRANCHDIR dir, /**< branching direction */
15084 SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15085 SCIP_Real weight /**< weight of this update in VSIDS */
15086 )
15087{
15088 assert(var != NULL);
15089 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15090
15091 /* check if history statistics should be collected for a variable */
15092 if( !stat->collectvarhistory )
15093 return SCIP_OKAY;
15094
15095 if( SCIPsetIsZero(set, weight) )
15096 return SCIP_OKAY;
15097
15098 switch( SCIPvarGetStatus(var) )
15099 {
15101 if( var->data.original.transvar == NULL )
15102 {
15103 SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
15104 return SCIP_INVALIDDATA;
15105 }
15106 SCIP_CALL( SCIPvarIncVSIDS(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
15107 return SCIP_OKAY;
15108
15111 {
15112 SCIPhistoryIncVSIDS(var->history, dir, weight);
15113 SCIPhistoryIncVSIDS(var->historycrun, dir, weight);
15114
15115 if( useValuehistory(var, value, set) )
15116 {
15117 SCIP_HISTORY* history;
15118
15119 SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15120 assert(history != NULL);
15121
15122 SCIPhistoryIncVSIDS(history, dir, weight);
15123 SCIPsetDebugMsg(set, "variable (<%s> %s %g) + <%g> = <%g>\n", SCIPvarGetName(var), dir == SCIP_BRANCHDIR_UPWARDS ? ">=" : "<=",
15124 value, weight, SCIPhistoryGetVSIDS(history, dir));
15125 }
15126
15127 return SCIP_OKAY;
15128 }
15130 SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
15131 return SCIP_INVALIDDATA;
15132
15134 value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15135
15136 if( var->data.aggregate.scalar > 0.0 )
15137 {
15138 SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
15139 }
15140 else
15141 {
15142 assert(var->data.aggregate.scalar < 0.0);
15143 SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15144 }
15145 return SCIP_OKAY;
15146
15148 SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
15149 return SCIP_INVALIDDATA;
15150
15152 value = 1.0 - value;
15153
15154 SCIP_CALL( SCIPvarIncVSIDS(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15155 return SCIP_OKAY;
15156
15157 default:
15158 SCIPerrorMessage("unknown variable status\n");
15159 return SCIP_INVALIDDATA;
15160 }
15161}
15162
15163/** scales the VSIDS of the variable by the given scalar */
15165 SCIP_VAR* var, /**< problem variable */
15166 SCIP_Real scalar /**< scalar to multiply the VSIDSs with */
15167 )
15168{
15169 assert(var != NULL);
15170
15171 switch( SCIPvarGetStatus(var) )
15172 {
15174 if( var->data.original.transvar == NULL )
15175 {
15176 SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
15177 return SCIP_INVALIDDATA;
15178 }
15180 return SCIP_OKAY;
15181
15184 {
15185 SCIPhistoryScaleVSIDS(var->history, scalar);
15186 SCIPhistoryScaleVSIDS(var->historycrun, scalar);
15188
15189 return SCIP_OKAY;
15190 }
15192 SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
15193 return SCIP_INVALIDDATA;
15194
15196 SCIP_CALL( SCIPvarScaleVSIDS(var->data.aggregate.var, scalar) );
15197 return SCIP_OKAY;
15198
15200 SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
15201 return SCIP_INVALIDDATA;
15202
15204 SCIP_CALL( SCIPvarScaleVSIDS(var->negatedvar, scalar) );
15205 return SCIP_OKAY;
15206
15207 default:
15208 SCIPerrorMessage("unknown variable status\n");
15209 return SCIP_INVALIDDATA;
15210 }
15211}
15212
15213/** increases the number of active conflicts by one and the overall length of the variable by the given length */
15215 SCIP_VAR* var, /**< problem variable */
15216 BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15217 SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15218 SCIP_STAT* stat, /**< problem statistics */
15219 SCIP_BRANCHDIR dir, /**< branching direction */
15220 SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15221 SCIP_Real length /**< length of the conflict */
15222 )
15223{
15224 assert(var != NULL);
15225 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15226
15227 /* check if history statistics should be collected for a variable */
15228 if( !stat->collectvarhistory )
15229 return SCIP_OKAY;
15230
15231 switch( SCIPvarGetStatus(var) )
15232 {
15234 if( var->data.original.transvar == NULL )
15235 {
15236 SCIPerrorMessage("cannot update conflict score of original untransformed variable\n");
15237 return SCIP_INVALIDDATA;
15238 }
15239 SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.original.transvar, blkmem, set, stat, dir, value, length) );
15240 return SCIP_OKAY;
15241
15244 {
15245 SCIPhistoryIncNActiveConflicts(var->history, dir, length);
15247
15248 if( useValuehistory(var, value, set) )
15249 {
15250 SCIP_HISTORY* history;
15251
15252 SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15253 assert(history != NULL);
15254
15255 SCIPhistoryIncNActiveConflicts(history, dir, length);
15256 }
15257
15258 return SCIP_OKAY;
15259 }
15261 SCIPerrorMessage("cannot update conflict score of a fixed variable\n");
15262 return SCIP_INVALIDDATA;
15263
15265 value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15266
15267 if( var->data.aggregate.scalar > 0.0 )
15268 {
15269 SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, dir, value, length) );
15270 }
15271 else
15272 {
15273 assert(var->data.aggregate.scalar < 0.0);
15274 SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
15275 }
15276 return SCIP_OKAY;
15277
15279 SCIPerrorMessage("cannot update conflict score of a multi-aggregated variable\n");
15280 return SCIP_INVALIDDATA;
15281
15283 value = 1.0 - value;
15284
15285 SCIP_CALL( SCIPvarIncNActiveConflicts(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
15286 return SCIP_OKAY;
15287
15288 default:
15289 SCIPerrorMessage("unknown variable status\n");
15290 return SCIP_INVALIDDATA;
15291 }
15292}
15293
15294/** gets the number of active conflicts containing this variable in given direction */
15296 SCIP_VAR* var, /**< problem variable */
15297 SCIP_STAT* stat, /**< problem statistics */
15298 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15299 )
15300{
15301 assert(var != NULL);
15302 assert(stat != NULL);
15303 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15304
15305 switch( SCIPvarGetStatus(var) )
15306 {
15308 if( var->data.original.transvar == NULL )
15309 return 0;
15310 else
15311 return SCIPvarGetNActiveConflicts(var->data.original.transvar, stat, dir);
15312
15315 return SCIPhistoryGetNActiveConflicts(var->history, dir);
15316
15318 return 0;
15319
15321 if( var->data.aggregate.scalar > 0.0 )
15322 return SCIPvarGetNActiveConflicts(var->data.aggregate.var, stat, dir);
15323 else
15325
15327 return 0;
15328
15331
15332 default:
15333 SCIPerrorMessage("unknown variable status\n");
15334 SCIPABORT();
15335 return 0; /*lint !e527*/
15336 }
15337}
15338
15339/** gets the number of active conflicts containing this variable in given direction
15340 * in the current run
15341 */
15343 SCIP_VAR* var, /**< problem variable */
15344 SCIP_STAT* stat, /**< problem statistics */
15345 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15346 )
15347{
15348 assert(var != NULL);
15349 assert(stat != NULL);
15350 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15351
15352 switch( SCIPvarGetStatus(var) )
15353 {
15355 if( var->data.original.transvar == NULL )
15356 return 0;
15357 else
15359
15363
15365 return 0;
15366
15368 if( var->data.aggregate.scalar > 0.0 )
15370 else
15372
15374 return 0;
15375
15378
15379 default:
15380 SCIPerrorMessage("unknown variable status\n");
15381 SCIPABORT();
15382 return 0; /*lint !e527*/
15383 }
15384}
15385
15386/** gets the average conflict length in given direction due to branching on the variable */
15388 SCIP_VAR* var, /**< problem variable */
15389 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15390 )
15391{
15392 assert(var != NULL);
15393 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15394
15395 switch( SCIPvarGetStatus(var) )
15396 {
15398 if( var->data.original.transvar == NULL )
15399 return 0.0;
15400 else
15402
15405 return SCIPhistoryGetAvgConflictlength(var->history, dir);
15407 return 0.0;
15408
15410 if( var->data.aggregate.scalar > 0.0 )
15412 else
15414
15416 return 0.0;
15417
15420
15421 default:
15422 SCIPerrorMessage("unknown variable status\n");
15423 SCIPABORT();
15424 return 0.0; /*lint !e527*/
15425 }
15426}
15427
15428/** gets the average conflict length in given direction due to branching on the variable
15429 * in the current run
15430 */
15432 SCIP_VAR* var, /**< problem variable */
15433 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15434 )
15435{
15436 assert(var != NULL);
15437 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15438
15439 switch( SCIPvarGetStatus(var) )
15440 {
15442 if( var->data.original.transvar == NULL )
15443 return 0.0;
15444 else
15446
15450
15452 return 0.0;
15453
15455 if( var->data.aggregate.scalar > 0.0 )
15457 else
15459
15461 return 0.0;
15462
15465
15466 default:
15467 SCIPerrorMessage("unknown variable status\n");
15468 SCIPABORT();
15469 return 0.0; /*lint !e527*/
15470 }
15471}
15472
15473/** increases the number of branchings counter of the variable */
15475 SCIP_VAR* var, /**< problem variable */
15476 BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15477 SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15478 SCIP_STAT* stat, /**< problem statistics */
15479 SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
15480 SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15481 int depth /**< depth at which the bound change took place */
15482 )
15483{
15484 assert(var != NULL);
15485 assert(stat != NULL);
15486 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15487
15488 /* check if history statistics should be collected for a variable */
15489 if( !stat->collectvarhistory )
15490 return SCIP_OKAY;
15491
15492 switch( SCIPvarGetStatus(var) )
15493 {
15495 if( var->data.original.transvar == NULL )
15496 {
15497 SCIPerrorMessage("cannot update branching counter of original untransformed variable\n");
15498 return SCIP_INVALIDDATA;
15499 }
15500 SCIP_CALL( SCIPvarIncNBranchings(var->data.original.transvar, blkmem, set, stat, dir, value, depth) );
15501 return SCIP_OKAY;
15502
15505 {
15506 SCIPhistoryIncNBranchings(var->history, dir, depth);
15507 SCIPhistoryIncNBranchings(var->historycrun, dir, depth);
15508 SCIPhistoryIncNBranchings(stat->glbhistory, dir, depth);
15509 SCIPhistoryIncNBranchings(stat->glbhistorycrun, dir, depth);
15510
15511 if( useValuehistory(var, value, set) )
15512 {
15513 SCIP_HISTORY* history;
15514
15515 SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15516 assert(history != NULL);
15517
15518 SCIPhistoryIncNBranchings(history, dir, depth);
15519 }
15520
15521 return SCIP_OKAY;
15522 }
15524 SCIPerrorMessage("cannot update branching counter of a fixed variable\n");
15525 return SCIP_INVALIDDATA;
15526
15528 value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15529
15530 if( var->data.aggregate.scalar > 0.0 )
15531 {
15532 SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, dir, value, depth) );
15533 }
15534 else
15535 {
15536 assert(var->data.aggregate.scalar < 0.0);
15537 SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
15538 }
15539 return SCIP_OKAY;
15540
15542 SCIPerrorMessage("cannot update branching counter of a multi-aggregated variable\n");
15543 return SCIP_INVALIDDATA;
15544
15546 value = 1.0 - value;
15547
15548 SCIP_CALL( SCIPvarIncNBranchings(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
15549 return SCIP_OKAY;
15550
15551 default:
15552 SCIPerrorMessage("unknown variable status\n");
15553 return SCIP_INVALIDDATA;
15554 }
15555}
15556
15557/** increases the inference sum of the variable by the given weight */
15559 SCIP_VAR* var, /**< problem variable */
15560 BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15561 SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15562 SCIP_STAT* stat, /**< problem statistics */
15563 SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
15564 SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15565 SCIP_Real weight /**< weight of this update in inference score */
15566 )
15567{
15568 assert(var != NULL);
15569 assert(stat != NULL);
15570 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15571
15572 /* check if history statistics should be collected for a variable */
15573 if( !stat->collectvarhistory )
15574 return SCIP_OKAY;
15575
15576 switch( SCIPvarGetStatus(var) )
15577 {
15579 if( var->data.original.transvar == NULL )
15580 {
15581 SCIPerrorMessage("cannot update inference counter of original untransformed variable\n");
15582 return SCIP_INVALIDDATA;
15583 }
15584 SCIP_CALL( SCIPvarIncInferenceSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
15585 return SCIP_OKAY;
15586
15589 {
15590 SCIPhistoryIncInferenceSum(var->history, dir, weight);
15591 SCIPhistoryIncInferenceSum(var->historycrun, dir, weight);
15592 SCIPhistoryIncInferenceSum(stat->glbhistory, dir, weight);
15593 SCIPhistoryIncInferenceSum(stat->glbhistorycrun, dir, weight);
15594
15595 if( useValuehistory(var, value, set) )
15596 {
15597 SCIP_HISTORY* history;
15598
15599 SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15600 assert(history != NULL);
15601
15602 SCIPhistoryIncInferenceSum(history, dir, weight);
15603 }
15604
15605 return SCIP_OKAY;
15606 }
15608 SCIPerrorMessage("cannot update inference counter of a fixed variable\n");
15609 return SCIP_INVALIDDATA;
15610
15612 value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15613
15614 if( var->data.aggregate.scalar > 0.0 )
15615 {
15616 SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
15617 }
15618 else
15619 {
15620 assert(var->data.aggregate.scalar < 0.0);
15621 SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15622 }
15623 return SCIP_OKAY;
15624
15626 SCIPerrorMessage("cannot update inference counter of a multi-aggregated variable\n");
15627 return SCIP_INVALIDDATA;
15628
15630 value = 1.0 - value;
15631
15632 SCIP_CALL( SCIPvarIncInferenceSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15633 return SCIP_OKAY;
15634
15635 default:
15636 SCIPerrorMessage("unknown variable status\n");
15637 return SCIP_INVALIDDATA;
15638 }
15639}
15640
15641/** increases the cutoff sum of the variable by the given weight */
15643 SCIP_VAR* var, /**< problem variable */
15644 BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15645 SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15646 SCIP_STAT* stat, /**< problem statistics */
15647 SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
15648 SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15649 SCIP_Real weight /**< weight of this update in cutoff score */
15650 )
15651{
15652 assert(var != NULL);
15653 assert(stat != NULL);
15654 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15655
15656 /* check if history statistics should be collected for a variable */
15657 if( !stat->collectvarhistory )
15658 return SCIP_OKAY;
15659
15660 switch( SCIPvarGetStatus(var) )
15661 {
15663 if( var->data.original.transvar == NULL )
15664 {
15665 SCIPerrorMessage("cannot update cutoff sum of original untransformed variable\n");
15666 return SCIP_INVALIDDATA;
15667 }
15668 SCIP_CALL( SCIPvarIncCutoffSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
15669 return SCIP_OKAY;
15670
15673 {
15674 SCIPhistoryIncCutoffSum(var->history, dir, weight);
15675 SCIPhistoryIncCutoffSum(var->historycrun, dir, weight);
15676 SCIPhistoryIncCutoffSum(stat->glbhistory, dir, weight);
15677 SCIPhistoryIncCutoffSum(stat->glbhistorycrun, dir, weight);
15678
15679 if( useValuehistory(var, value, set) )
15680 {
15681 SCIP_HISTORY* history;
15682
15683 SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15684 assert(history != NULL);
15685
15686 SCIPhistoryIncCutoffSum(history, dir, weight);
15687 }
15688
15689 return SCIP_OKAY;
15690 }
15692 SCIPerrorMessage("cannot update cutoff sum of a fixed variable\n");
15693 return SCIP_INVALIDDATA;
15694
15696 value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15697
15698 if( var->data.aggregate.scalar > 0.0 )
15699 {
15700 SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
15701 }
15702 else
15703 {
15704 assert(var->data.aggregate.scalar < 0.0);
15705 SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15706 }
15707 return SCIP_OKAY;
15708
15710 SCIPerrorMessage("cannot update cutoff sum of a multi-aggregated variable\n");
15711 return SCIP_INVALIDDATA;
15712
15714 value = 1.0 - value;
15715
15716 SCIP_CALL( SCIPvarIncCutoffSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15717 return SCIP_OKAY;
15718
15719 default:
15720 SCIPerrorMessage("unknown variable status\n");
15721 return SCIP_INVALIDDATA;
15722 }
15723}
15724
15725/** returns the number of times, a bound of the variable was changed in given direction due to branching */
15727 SCIP_VAR* var, /**< problem variable */
15728 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15729 )
15730{
15731 assert(var != NULL);
15732 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15733
15734 switch( SCIPvarGetStatus(var) )
15735 {
15737 if( var->data.original.transvar == NULL )
15738 return 0;
15739 else
15740 return SCIPvarGetNBranchings(var->data.original.transvar, dir);
15741
15744 return SCIPhistoryGetNBranchings(var->history, dir);
15745
15747 return 0;
15748
15750 if( var->data.aggregate.scalar > 0.0 )
15751 return SCIPvarGetNBranchings(var->data.aggregate.var, dir);
15752 else
15754
15756 return 0;
15757
15760
15761 default:
15762 SCIPerrorMessage("unknown variable status\n");
15763 SCIPABORT();
15764 return 0; /*lint !e527*/
15765 }
15766}
15767
15768/** returns the number of times, a bound of the variable was changed in given direction due to branching
15769 * in the current run
15770 */
15772 SCIP_VAR* var, /**< problem variable */
15773 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15774 )
15775{
15776 assert(var != NULL);
15777 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15778
15779 switch( SCIPvarGetStatus(var) )
15780 {
15782 if( var->data.original.transvar == NULL )
15783 return 0;
15784 else
15786
15789 return SCIPhistoryGetNBranchings(var->historycrun, dir);
15790
15792 return 0;
15793
15795 if( var->data.aggregate.scalar > 0.0 )
15797 else
15799
15801 return 0;
15802
15805
15806 default:
15807 SCIPerrorMessage("unknown variable status\n");
15808 SCIPABORT();
15809 return 0; /*lint !e527*/
15810 }
15811}
15812
15813/** returns the average depth of bound changes in given direction due to branching on the variable */
15815 SCIP_VAR* var, /**< problem variable */
15816 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15817 )
15818{
15819 assert(var != NULL);
15820 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15821
15822 switch( SCIPvarGetStatus(var) )
15823 {
15825 if( var->data.original.transvar == NULL )
15826 return 0.0;
15827 else
15829
15832 return SCIPhistoryGetAvgBranchdepth(var->history, dir);
15833
15835 return 0.0;
15836
15838 if( var->data.aggregate.scalar > 0.0 )
15839 return SCIPvarGetAvgBranchdepth(var->data.aggregate.var, dir);
15840 else
15842
15844 return 0.0;
15845
15848
15849 default:
15850 SCIPerrorMessage("unknown variable status\n");
15851 SCIPABORT();
15852 return 0.0; /*lint !e527*/
15853 }
15854}
15855
15856/** returns the average depth of bound changes in given direction due to branching on the variable
15857 * in the current run
15858 */
15860 SCIP_VAR* var, /**< problem variable */
15861 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15862 )
15863{
15864 assert(var != NULL);
15865 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15866
15867 switch( SCIPvarGetStatus(var) )
15868 {
15870 if( var->data.original.transvar == NULL )
15871 return 0.0;
15872 else
15874
15877 return SCIPhistoryGetAvgBranchdepth(var->historycrun, dir);
15878
15880 return 0.0;
15881
15883 if( var->data.aggregate.scalar > 0.0 )
15885 else
15888
15890 return 0.0;
15891
15895
15896 default:
15897 SCIPerrorMessage("unknown variable status\n");
15898 SCIPABORT();
15899 return 0.0; /*lint !e527*/
15900 }
15901}
15902
15903/** returns the variable's VSIDS score */
15905 SCIP_VAR* var, /**< problem variable */
15906 SCIP_STAT* stat, /**< problem statistics */
15907 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15908 )
15909{
15910 assert(var != NULL);
15911 assert(stat != NULL);
15912 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15913
15915 return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
15916
15917 switch( SCIPvarGetStatus(var) )
15918 {
15920 if( var->data.original.transvar == NULL )
15921 return 0.0;
15922 else
15923 return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
15924
15927 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE); /* column case already handled in if condition above */
15928 return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
15929
15931 return 0.0;
15932
15934 if( var->data.aggregate.scalar > 0.0 )
15935 return SCIPvarGetVSIDS(var->data.aggregate.var, stat, dir);
15936 else
15937 /* coverity[overrun-local] */
15938 return SCIPvarGetVSIDS(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
15939
15941 return 0.0;
15942
15944 /* coverity[overrun-local] */
15945 return SCIPvarGetVSIDS(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15946
15947 default:
15948 SCIPerrorMessage("unknown variable status\n");
15949 SCIPABORT();
15950 return 0.0; /*lint !e527*/
15951 }
15952}
15953
15954/** returns the variable's VSIDS score only using conflicts of the current run */
15956 SCIP_VAR* var, /**< problem variable */
15957 SCIP_STAT* stat, /**< problem statistics */
15958 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15959 )
15960{
15961 assert(var != NULL);
15962 assert(stat != NULL);
15963 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15964
15966 {
15967 SCIPerrorMessage("invalid branching direction %d when asking for VSIDS value\n", dir);
15968 return SCIP_INVALID;
15969 }
15970
15971 switch( SCIPvarGetStatus(var) )
15972 {
15974 if( var->data.original.transvar == NULL )
15975 return 0.0;
15976 else
15977 return SCIPvarGetVSIDSCurrentRun(var->data.original.transvar, stat, dir);
15978
15981 return SCIPhistoryGetVSIDS(var->historycrun, dir)/stat->vsidsweight;
15982
15984 return 0.0;
15985
15987 if( var->data.aggregate.scalar > 0.0 )
15988 return SCIPvarGetVSIDSCurrentRun(var->data.aggregate.var, stat, dir);
15989 else
15991
15993 return 0.0;
15994
15997
15998 default:
15999 SCIPerrorMessage("unknown variable status\n");
16000 SCIPABORT();
16001 return 0.0; /*lint !e527*/
16002 }
16003}
16004
16005/** returns the number of inferences branching on this variable in given direction triggered */
16007 SCIP_VAR* var, /**< problem variable */
16008 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16009 )
16010{
16011 assert(var != NULL);
16012 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16013
16014 switch( SCIPvarGetStatus(var) )
16015 {
16017 if( var->data.original.transvar == NULL )
16018 return 0.0;
16019 else
16020 return SCIPvarGetInferenceSum(var->data.original.transvar, dir);
16021
16024 return SCIPhistoryGetInferenceSum(var->history, dir);
16025
16027 return 0.0;
16028
16030 if( var->data.aggregate.scalar > 0.0 )
16031 return SCIPvarGetInferenceSum(var->data.aggregate.var, dir);
16032 else
16034
16036 return 0.0;
16037
16040
16041 default:
16042 SCIPerrorMessage("unknown variable status\n");
16043 SCIPABORT();
16044 return 0.0; /*lint !e527*/
16045 }
16046}
16047
16048/** returns the number of inferences branching on this variable in given direction triggered
16049 * in the current run
16050 */
16052 SCIP_VAR* var, /**< problem variable */
16053 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16054 )
16055{
16056 assert(var != NULL);
16057 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16058
16059 switch( SCIPvarGetStatus(var) )
16060 {
16062 if( var->data.original.transvar == NULL )
16063 return 0.0;
16064 else
16066
16069 return SCIPhistoryGetInferenceSum(var->historycrun, dir);
16070
16072 return 0.0;
16073
16075 if( var->data.aggregate.scalar > 0.0 )
16077 else
16079
16081 return 0.0;
16082
16085
16086 default:
16087 SCIPerrorMessage("unknown variable status\n");
16088 SCIPABORT();
16089 return 0.0; /*lint !e527*/
16090 }
16091}
16092
16093/** returns the average number of inferences found after branching on the variable in given direction */
16095 SCIP_VAR* var, /**< problem variable */
16096 SCIP_STAT* stat, /**< problem statistics */
16097 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16098 )
16099{
16100 assert(var != NULL);
16101 assert(stat != NULL);
16102 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16103
16104 switch( SCIPvarGetStatus(var) )
16105 {
16107 if( var->data.original.transvar == NULL )
16108 return SCIPhistoryGetAvgInferences(stat->glbhistory, dir);
16109 else
16110 return SCIPvarGetAvgInferences(var->data.original.transvar, stat, dir);
16111
16114 if( SCIPhistoryGetNBranchings(var->history, dir) > 0 )
16115 return SCIPhistoryGetAvgInferences(var->history, dir);
16116 else
16117 {
16118 int nimpls;
16119 int ncliques;
16120
16121 nimpls = SCIPvarGetNImpls(var, dir == SCIP_BRANCHDIR_UPWARDS);
16122 ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
16123 return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistory, dir); /*lint !e790*/
16124 }
16125
16127 return 0.0;
16128
16130 if( var->data.aggregate.scalar > 0.0 )
16131 return SCIPvarGetAvgInferences(var->data.aggregate.var, stat, dir);
16132 else
16134
16136 return 0.0;
16137
16140
16141 default:
16142 SCIPerrorMessage("unknown variable status\n");
16143 SCIPABORT();
16144 return 0.0; /*lint !e527*/
16145 }
16146}
16147
16148/** returns the average number of inferences found after branching on the variable in given direction
16149 * in the current run
16150 */
16152 SCIP_VAR* var, /**< problem variable */
16153 SCIP_STAT* stat, /**< problem statistics */
16154 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16155 )
16156{
16157 assert(var != NULL);
16158 assert(stat != NULL);
16159 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16160
16161 switch( SCIPvarGetStatus(var) )
16162 {
16164 if( var->data.original.transvar == NULL )
16166 else
16168
16171 if( SCIPhistoryGetNBranchings(var->historycrun, dir) > 0 )
16172 return SCIPhistoryGetAvgInferences(var->historycrun, dir);
16173 else
16174 {
16175 int nimpls;
16176 int ncliques;
16177
16178 nimpls = SCIPvarGetNImpls(var, dir == SCIP_BRANCHDIR_UPWARDS);
16179 ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
16180 return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir); /*lint !e790*/
16181 }
16182
16184 return 0.0;
16185
16187 if( var->data.aggregate.scalar > 0.0 )
16188 return SCIPvarGetAvgInferencesCurrentRun(var->data.aggregate.var, stat, dir);
16189 else
16191
16193 return 0.0;
16194
16197
16198 default:
16199 SCIPerrorMessage("unknown variable status\n");
16200 SCIPABORT();
16201 return 0.0; /*lint !e527*/
16202 }
16203}
16204
16205/** returns the number of cutoffs branching on this variable in given direction produced */
16207 SCIP_VAR* var, /**< problem variable */
16208 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16209 )
16210{
16211 assert(var != NULL);
16212 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16213
16214 switch( SCIPvarGetStatus(var) )
16215 {
16217 if( var->data.original.transvar == NULL )
16218 return 0;
16219 else
16220 return SCIPvarGetCutoffSum(var->data.original.transvar, dir);
16221
16224 return SCIPhistoryGetCutoffSum(var->history, dir);
16225
16227 return 0;
16228
16230 if( var->data.aggregate.scalar > 0.0 )
16231 return SCIPvarGetCutoffSum(var->data.aggregate.var, dir);
16232 else
16234
16236 return 0;
16237
16240
16241 default:
16242 SCIPerrorMessage("unknown variable status\n");
16243 SCIPABORT();
16244 return 0; /*lint !e527*/
16245 }
16246}
16247
16248/** returns the number of cutoffs branching on this variable in given direction produced in the current run */
16250 SCIP_VAR* var, /**< problem variable */
16251 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16252 )
16253{
16254 assert(var != NULL);
16255 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16256
16257 switch( SCIPvarGetStatus(var) )
16258 {
16260 if( var->data.original.transvar == NULL )
16261 return 0;
16262 else
16264
16267 return SCIPhistoryGetCutoffSum(var->historycrun, dir);
16268
16270 return 0;
16271
16273 if( var->data.aggregate.scalar > 0.0 )
16275 else
16277
16279 return 0;
16280
16283
16284 default:
16285 SCIPerrorMessage("unknown variable status\n");
16286 SCIPABORT();
16287 return 0; /*lint !e527*/
16288 }
16289}
16290
16291/** returns the average number of cutoffs found after branching on the variable in given direction */
16293 SCIP_VAR* var, /**< problem variable */
16294 SCIP_STAT* stat, /**< problem statistics */
16295 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16296 )
16297{
16298 assert(var != NULL);
16299 assert(stat != NULL);
16300 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16301
16302 switch( SCIPvarGetStatus(var) )
16303 {
16305 if( var->data.original.transvar == NULL )
16306 return SCIPhistoryGetAvgCutoffs(stat->glbhistory, dir);
16307 else
16308 return SCIPvarGetAvgCutoffs(var->data.original.transvar, stat, dir);
16309
16312 return SCIPhistoryGetNBranchings(var->history, dir) > 0
16315
16317 return 0.0;
16318
16320 if( var->data.aggregate.scalar > 0.0 )
16321 return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, dir);
16322 else
16324
16326 return 0.0;
16327
16329 return SCIPvarGetAvgCutoffs(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
16330
16331 default:
16332 SCIPerrorMessage("unknown variable status\n");
16333 SCIPABORT();
16334 return 0.0; /*lint !e527*/
16335 }
16336}
16337
16338/** returns the average number of cutoffs found after branching on the variable in given direction in the current run */
16340 SCIP_VAR* var, /**< problem variable */
16341 SCIP_STAT* stat, /**< problem statistics */
16342 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16343 )
16344{
16345 assert(var != NULL);
16346 assert(stat != NULL);
16347 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16348
16349 switch( SCIPvarGetStatus(var) )
16350 {
16352 if( var->data.original.transvar == NULL )
16353 return SCIPhistoryGetAvgCutoffs(stat->glbhistorycrun, dir);
16354 else
16355 return SCIPvarGetAvgCutoffsCurrentRun(var->data.original.transvar, stat, dir);
16356
16359 return SCIPhistoryGetNBranchings(var->historycrun, dir) > 0
16362
16364 return 0.0;
16365
16367 if( var->data.aggregate.scalar > 0.0 )
16368 return SCIPvarGetAvgCutoffsCurrentRun(var->data.aggregate.var, stat, dir);
16369 else
16371
16373 return 0.0;
16374
16377
16378 default:
16379 SCIPerrorMessage("unknown variable status\n");
16380 SCIPABORT();
16381 return 0.0; /*lint !e527*/
16382 }
16383}
16384
16385/** returns the variable's average GMI efficacy score value generated from simplex tableau rows of this variable */
16387 SCIP_VAR* var, /**< problem variable */
16388 SCIP_STAT* stat /**< problem statistics */
16389 )
16390{
16391 assert(var != NULL);
16392 assert(stat != NULL);
16393
16394 switch( SCIPvarGetStatus(var) )
16395 {
16397 if( var->data.original.transvar == NULL )
16398 return 0.0;
16399 else
16400 return SCIPvarGetAvgGMIScore(var->data.original.transvar, stat);
16401
16404 return SCIPhistoryGetAvgGMIeff(var->history);
16405
16407 return 0.0;
16408
16410 return SCIPvarGetAvgGMIScore(var->data.aggregate.var, stat);
16411
16413 return 0.0;
16414
16416 return SCIPvarGetAvgGMIScore(var->negatedvar, stat);
16417
16418 default:
16419 SCIPerrorMessage("unknown variable status\n");
16420 SCIPABORT();
16421 return 0.0; /*lint !e527*/
16422 }
16423}
16424
16425/** increase the variable's GMI efficacy scores generated from simplex tableau rows of this variable */
16427 SCIP_VAR* var, /**< problem variable */
16428 SCIP_STAT* stat, /**< problem statistics */
16429 SCIP_Real gmieff /**< efficacy of last GMI cut produced when variable was frac and basic */
16430 )
16431{
16432 assert(var != NULL);
16433 assert(stat != NULL);
16434 assert(gmieff >= 0);
16435
16436 switch( SCIPvarGetStatus(var) )
16437 {
16439 if( var->data.original.transvar != NULL )
16440 SCIP_CALL( SCIPvarIncGMIeffSum(var->data.original.transvar, stat, gmieff) );
16441 return SCIP_OKAY;
16442
16445 SCIPhistoryIncGMIeffSum(var->history, gmieff);
16446 return SCIP_OKAY;
16447
16449 return SCIP_INVALIDDATA;
16450
16452 SCIP_CALL( SCIPvarIncGMIeffSum(var->data.aggregate.var, stat, gmieff) );
16453 return SCIP_OKAY;
16454
16456 SCIP_CALL( SCIPvarIncGMIeffSum(var->negatedvar, stat, gmieff) );
16457 return SCIP_OKAY;
16458
16460 return SCIP_INVALIDDATA;
16461
16462 default:
16463 SCIPerrorMessage("unknown variable status\n");
16464 SCIPABORT();
16465 return SCIP_INVALIDDATA; /*lint !e527*/
16466 }
16467}
16468
16469/** returns the variable's last GMI efficacy score value generated from a simplex tableau row of this variable */
16471 SCIP_VAR* var, /**< problem variable */
16472 SCIP_STAT* stat /**< problem statistics */
16473 )
16474{
16475 assert(var != NULL);
16476 assert(stat != NULL);
16477
16478 switch( SCIPvarGetStatus(var) )
16479 {
16481 if( var->data.original.transvar != NULL )
16482 return SCIPvarGetLastGMIScore(var->data.original.transvar, stat);
16483 return 0.0;
16484
16487 return SCIPhistoryGetLastGMIeff(var->history);
16488
16490 return 0.0;
16491
16493 return SCIPvarGetLastGMIScore(var->data.aggregate.var, stat);
16494
16496 return 0.0;
16497
16499 return SCIPvarGetLastGMIScore(var->negatedvar, stat);
16500
16501 default:
16502 SCIPerrorMessage("unknown variable status\n");
16503 SCIPABORT();
16504 return 0.0; /*lint !e527*/
16505 }
16506}
16507
16508
16509/** sets the variable's last GMI efficacy score value generated from a simplex tableau row of this variable */
16511 SCIP_VAR* var, /**< problem variable */
16512 SCIP_STAT* stat, /**< problem statistics */
16513 SCIP_Real gmieff /**< efficacy of last GMI cut produced when variable was frac and basic */
16514 )
16515{
16516 assert(var != NULL);
16517 assert(stat != NULL);
16518 assert(gmieff >= 0);
16519
16520 switch( SCIPvarGetStatus(var) )
16521 {
16523 if( var->data.original.transvar != NULL )
16524 SCIP_CALL( SCIPvarSetLastGMIScore(var->data.original.transvar, stat, gmieff) );
16525 return SCIP_OKAY;
16526
16529 SCIPhistorySetLastGMIeff(var->history, gmieff);
16530 return SCIP_OKAY;
16531
16533 return SCIP_INVALIDDATA;
16534
16536 SCIP_CALL( SCIPvarSetLastGMIScore(var->data.aggregate.var, stat, gmieff) );
16537 return SCIP_OKAY;
16538
16540 SCIP_CALL( SCIPvarSetLastGMIScore(var->negatedvar, stat, gmieff) );
16541 return SCIP_OKAY;
16542
16544 return SCIP_INVALIDDATA;
16545
16546 default:
16547 SCIPerrorMessage("unknown variable status\n");
16548 SCIPABORT();
16549 return SCIP_INVALIDDATA; /*lint !e527*/
16550 }
16551}
16552
16553
16554
16555/*
16556 * information methods for bound changes
16557 */
16558
16559/** creates an artificial bound change information object with depth = INT_MAX and pos = -1 */
16561 SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
16562 BMS_BLKMEM* blkmem, /**< block memory */
16563 SCIP_VAR* var, /**< active variable that changed the bounds */
16564 SCIP_BOUNDTYPE boundtype, /**< type of bound for var: lower or upper bound */
16565 SCIP_Real oldbound, /**< old value for bound */
16566 SCIP_Real newbound /**< new value for bound */
16567 )
16568{
16569 assert(bdchginfo != NULL);
16570
16571 SCIP_ALLOC( BMSallocBlockMemory(blkmem, bdchginfo) );
16572 (*bdchginfo)->oldbound = oldbound;
16573 (*bdchginfo)->newbound = newbound;
16574 (*bdchginfo)->var = var;
16575 (*bdchginfo)->inferencedata.var = var;
16576 (*bdchginfo)->inferencedata.reason.prop = NULL;
16577 (*bdchginfo)->inferencedata.info = 0;
16578 (*bdchginfo)->bdchgidx.depth = INT_MAX;
16579 (*bdchginfo)->bdchgidx.pos = -1;
16580 (*bdchginfo)->pos = 0;
16581 (*bdchginfo)->boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
16582 (*bdchginfo)->boundtype = boundtype; /*lint !e641*/
16583 (*bdchginfo)->inferboundtype = boundtype; /*lint !e641*/
16584 (*bdchginfo)->redundant = FALSE;
16585
16586 return SCIP_OKAY;
16587}
16588
16589/** frees a bound change information object */
16591 SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
16592 BMS_BLKMEM* blkmem /**< block memory */
16593 )
16594{
16595 assert(bdchginfo != NULL);
16596
16597 BMSfreeBlockMemory(blkmem, bdchginfo);
16598}
16599
16600/** returns the bound change information for the last lower bound change on given active problem variable before or
16601 * after the bound change with the given index was applied;
16602 * returns NULL, if no change to the lower bound was applied up to this point of time
16603 */
16605 SCIP_VAR* var, /**< active problem variable */
16606 SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16607 SCIP_Bool after /**< should the bound change with given index be included? */
16608 )
16609{
16610 int i;
16611
16612 assert(var != NULL);
16613 assert(SCIPvarIsActive(var));
16614
16615 /* search the correct bound change information for the given bound change index */
16616 if( after )
16617 {
16618 for( i = var->nlbchginfos-1; i >= 0; --i )
16619 {
16620 assert(var->lbchginfos[i].var == var);
16622 assert(var->lbchginfos[i].pos == i);
16623
16624 /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16625 if( var->lbchginfos[i].redundant )
16626 return NULL;
16627 assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
16628
16629 /* if we reached the bound change index, return the current bound change info */
16630 if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->lbchginfos[i].bdchgidx) )
16631 return &var->lbchginfos[i];
16632 }
16633 }
16634 else
16635 {
16636 for( i = var->nlbchginfos-1; i >= 0; --i )
16637 {
16638 assert(var->lbchginfos[i].var == var);
16640 assert(var->lbchginfos[i].pos == i);
16641
16642 /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16643 if( var->lbchginfos[i].redundant )
16644 return NULL;
16645 assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
16646
16647 /* if we reached the bound change index, return the current bound change info */
16648 if( SCIPbdchgidxIsEarlier(&var->lbchginfos[i].bdchgidx, bdchgidx) )
16649 return &var->lbchginfos[i];
16650 }
16651 }
16652
16653 return NULL;
16654}
16655
16656/** returns the bound change information for the last upper bound change on given active problem variable before or
16657 * after the bound change with the given index was applied;
16658 * returns NULL, if no change to the upper bound was applied up to this point of time
16659 */
16661 SCIP_VAR* var, /**< active problem variable */
16662 SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16663 SCIP_Bool after /**< should the bound change with given index be included? */
16664 )
16665{
16666 int i;
16667
16668 assert(var != NULL);
16669 assert(SCIPvarIsActive(var));
16670
16671 /* search the correct bound change information for the given bound change index */
16672 if( after )
16673 {
16674 for( i = var->nubchginfos-1; i >= 0; --i )
16675 {
16676 assert(var->ubchginfos[i].var == var);
16678 assert(var->ubchginfos[i].pos == i);
16679
16680 /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16681 if( var->ubchginfos[i].redundant )
16682 return NULL;
16683 assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
16684
16685 /* if we reached the bound change index, return the current bound change info */
16686 if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->ubchginfos[i].bdchgidx) )
16687 return &var->ubchginfos[i];
16688 }
16689 }
16690 else
16691 {
16692 for( i = var->nubchginfos-1; i >= 0; --i )
16693 {
16694 assert(var->ubchginfos[i].var == var);
16696 assert(var->ubchginfos[i].pos == i);
16697
16698 /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16699 if( var->ubchginfos[i].redundant )
16700 return NULL;
16701 assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
16702
16703 /* if we reached the bound change index, return the current bound change info */
16704 if( SCIPbdchgidxIsEarlier(&var->ubchginfos[i].bdchgidx, bdchgidx) )
16705 return &var->ubchginfos[i];
16706 }
16707 }
16708
16709 return NULL;
16710}
16711
16712/** returns the bound change information for the last lower or upper bound change on given active problem variable
16713 * before or after the bound change with the given index was applied;
16714 * returns NULL, if no change to the lower/upper bound was applied up to this point of time
16715 */
16717 SCIP_VAR* var, /**< active problem variable */
16718 SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
16719 SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16720 SCIP_Bool after /**< should the bound change with given index be included? */
16721 )
16722{
16723 if( boundtype == SCIP_BOUNDTYPE_LOWER )
16724 return SCIPvarGetLbchgInfo(var, bdchgidx, after);
16725 else
16726 {
16727 assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16728 return SCIPvarGetUbchgInfo(var, bdchgidx, after);
16729 }
16730}
16731
16732/** returns lower bound of variable directly before or after the bound change given by the bound change index
16733 * was applied
16734 *
16735 * @deprecated Please use SCIPgetVarLbAtIndex()
16736 */
16738 SCIP_VAR* var, /**< problem variable */
16739 SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16740 SCIP_Bool after /**< should the bound change with given index be included? */
16741 )
16742{
16743 SCIP_VARSTATUS varstatus;
16744 assert(var != NULL);
16745
16746 varstatus = SCIPvarGetStatus(var);
16747
16748 /* get bounds of attached variables */
16749 switch( varstatus )
16750 {
16752 assert(var->data.original.transvar != NULL);
16753 return SCIPvarGetLbAtIndex(var->data.original.transvar, bdchgidx, after);
16754
16757 if( bdchgidx == NULL )
16758 return SCIPvarGetLbLocal(var);
16759 else
16760 {
16761 SCIP_BDCHGINFO* bdchginfo;
16762
16763 bdchginfo = SCIPvarGetLbchgInfo(var, bdchgidx, after);
16764 if( bdchginfo != NULL )
16765 return SCIPbdchginfoGetNewbound(bdchginfo);
16766 else
16767 return var->glbdom.lb;
16768 }
16770 return var->glbdom.lb;
16771
16772 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
16773 assert(var->data.aggregate.var != NULL);
16774 /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
16775 * corresponding infinity value instead of performing an arithmetical transformation (compare method
16776 * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
16777 * (or is called by) a public interface method; instead, we only assert that values are finite
16778 * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
16779 * positives and negatives if the parameter <numerics/infinity> is modified by the user
16780 */
16781 if( var->data.aggregate.scalar > 0.0 )
16782 {
16783 /* a > 0 -> get lower bound of y */
16784 assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16785 assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16786 return var->data.aggregate.scalar * SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after)
16787 + var->data.aggregate.constant;
16788 }
16789 else if( var->data.aggregate.scalar < 0.0 )
16790 {
16791 /* a < 0 -> get upper bound of y */
16792 assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16793 assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16794 return var->data.aggregate.scalar * SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after)
16795 + var->data.aggregate.constant;
16796 }
16797 else
16798 {
16799 SCIPerrorMessage("scalar is zero in aggregation\n");
16800 SCIPABORT();
16801 return SCIP_INVALID; /*lint !e527*/
16802 }
16803
16805 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
16806 if ( var->data.multaggr.nvars == 1 )
16807 {
16808 assert(var->data.multaggr.vars != NULL);
16809 assert(var->data.multaggr.scalars != NULL);
16810 assert(var->data.multaggr.vars[0] != NULL);
16811
16812 if( var->data.multaggr.scalars[0] > 0.0 )
16813 {
16814 /* a > 0 -> get lower bound of y */
16815 assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16816 assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16817 return var->data.multaggr.scalars[0] * SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16818 + var->data.multaggr.constant;
16819 }
16820 else if( var->data.multaggr.scalars[0] < 0.0 )
16821 {
16822 /* a < 0 -> get upper bound of y */
16823 assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16824 assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16825 return var->data.multaggr.scalars[0] * SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16826 + var->data.multaggr.constant;
16827 }
16828 else
16829 {
16830 SCIPerrorMessage("scalar is zero in multi-aggregation\n");
16831 SCIPABORT();
16832 return SCIP_INVALID; /*lint !e527*/
16833 }
16834 }
16835 SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
16836 SCIPABORT();
16837 return SCIP_INVALID; /*lint !e527*/
16838
16839 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
16840 assert(var->negatedvar != NULL);
16842 assert(var->negatedvar->negatedvar == var);
16843 return var->data.negate.constant - SCIPvarGetUbAtIndex(var->negatedvar, bdchgidx, after);
16844 default:
16845 SCIPerrorMessage("unknown variable status\n");
16846 SCIPABORT();
16847 return SCIP_INVALID; /*lint !e527*/
16848 }
16849}
16850
16851/** returns upper bound of variable directly before or after the bound change given by the bound change index
16852 * was applied
16853 *
16854 * @deprecated Please use SCIPgetVarUbAtIndex()
16855 */
16857 SCIP_VAR* var, /**< problem variable */
16858 SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16859 SCIP_Bool after /**< should the bound change with given index be included? */
16860 )
16861{
16862 SCIP_VARSTATUS varstatus;
16863 assert(var != NULL);
16864
16865 varstatus = SCIPvarGetStatus(var);
16866
16867 /* get bounds of attached variables */
16868 switch( varstatus )
16869 {
16871 assert(var->data.original.transvar != NULL);
16872 return SCIPvarGetUbAtIndex(var->data.original.transvar, bdchgidx, after);
16873
16876 if( bdchgidx == NULL )
16877 return SCIPvarGetUbLocal(var);
16878 else
16879 {
16880 SCIP_BDCHGINFO* bdchginfo;
16881
16882 bdchginfo = SCIPvarGetUbchgInfo(var, bdchgidx, after);
16883 if( bdchginfo != NULL )
16884 return SCIPbdchginfoGetNewbound(bdchginfo);
16885 else
16886 return var->glbdom.ub;
16887 }
16888
16890 return var->glbdom.ub;
16891
16892 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
16893 assert(var->data.aggregate.var != NULL);
16894 /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
16895 * corresponding infinity value instead of performing an arithmetical transformation (compare method
16896 * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
16897 * (or is called by) a public interface method; instead, we only assert that values are finite
16898 * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
16899 * positives and negatives if the parameter <numerics/infinity> is modified by the user
16900 */
16901 if( var->data.aggregate.scalar > 0.0 )
16902 {
16903 /* a > 0 -> get lower bound of y */
16904 assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16905 assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16906 return var->data.aggregate.scalar * SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after)
16907 + var->data.aggregate.constant;
16908 }
16909 else if( var->data.aggregate.scalar < 0.0 )
16910 {
16911 /* a < 0 -> get upper bound of y */
16912 assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16913 assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16914 return var->data.aggregate.scalar * SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after)
16915 + var->data.aggregate.constant;
16916 }
16917 else
16918 {
16919 SCIPerrorMessage("scalar is zero in aggregation\n");
16920 SCIPABORT();
16921 return SCIP_INVALID; /*lint !e527*/
16922 }
16923
16925 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
16926 if ( var->data.multaggr.nvars == 1 )
16927 {
16928 assert(var->data.multaggr.vars != NULL);
16929 assert(var->data.multaggr.scalars != NULL);
16930 assert(var->data.multaggr.vars[0] != NULL);
16931
16932 if( var->data.multaggr.scalars[0] > 0.0 )
16933 {
16934 /* a > 0 -> get lower bound of y */
16935 assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16936 assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16937 return var->data.multaggr.scalars[0] * SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16938 + var->data.multaggr.constant;
16939 }
16940 else if( var->data.multaggr.scalars[0] < 0.0 )
16941 {
16942 /* a < 0 -> get upper bound of y */
16943 assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16944 assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16945 return var->data.multaggr.scalars[0] * SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16946 + var->data.multaggr.constant;
16947 }
16948 else
16949 {
16950 SCIPerrorMessage("scalar is zero in multi-aggregation\n");
16951 SCIPABORT();
16952 return SCIP_INVALID; /*lint !e527*/
16953 }
16954 }
16955 SCIPerrorMessage("cannot get the bounds of a multiple aggregated variable.\n");
16956 SCIPABORT();
16957 return SCIP_INVALID; /*lint !e527*/
16958
16959 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
16960 assert(var->negatedvar != NULL);
16962 assert(var->negatedvar->negatedvar == var);
16963 return var->data.negate.constant - SCIPvarGetLbAtIndex(var->negatedvar, bdchgidx, after);
16964
16965 default:
16966 SCIPerrorMessage("unknown variable status\n");
16967 SCIPABORT();
16968 return SCIP_INVALID; /*lint !e527*/
16969 }
16970}
16971
16972/** returns lower or upper bound of variable directly before or after the bound change given by the bound change index
16973 * was applied
16974 *
16975 * @deprecated Please use SCIPgetVarBdAtIndex()
16976 */
16978 SCIP_VAR* var, /**< problem variable */
16979 SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
16980 SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16981 SCIP_Bool after /**< should the bound change with given index be included? */
16982 )
16983{
16984 if( boundtype == SCIP_BOUNDTYPE_LOWER )
16985 return SCIPvarGetLbAtIndex(var, bdchgidx, after);
16986 else
16987 {
16988 assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16989 return SCIPvarGetUbAtIndex(var, bdchgidx, after);
16990 }
16991}
16992
16993/** returns whether the binary variable was fixed at the time given by the bound change index
16994 *
16995 * @deprecated Please use SCIPgetVarWasFixedAtIndex()
16996 */
16998 SCIP_VAR* var, /**< problem variable */
16999 SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
17000 SCIP_Bool after /**< should the bound change with given index be included? */
17001 )
17002{
17003 assert(var != NULL);
17004 assert(SCIPvarIsBinary(var));
17005
17006 /* check the current bounds first in order to decide at which bound change information we have to look
17007 * (which is expensive because we have to follow the aggregation tree to the active variable)
17008 */
17009 return ((SCIPvarGetLbLocal(var) > 0.5 && SCIPvarGetLbAtIndex(var, bdchgidx, after) > 0.5)
17010 || (SCIPvarGetUbLocal(var) < 0.5 && SCIPvarGetUbAtIndex(var, bdchgidx, after) < 0.5));
17011}
17012
17013/** bound change index representing the initial time before any bound changes took place */
17015
17016/** bound change index representing the presolving stage */
17018
17019/** returns the last bound change index, at which the bounds of the given variable were tightened */
17021 SCIP_VAR* var /**< problem variable */
17022 )
17023{
17024 SCIP_BDCHGIDX* lbchgidx;
17025 SCIP_BDCHGIDX* ubchgidx;
17026
17027 assert(var != NULL);
17028
17029 var = SCIPvarGetProbvar(var);
17030
17031 /* check, if variable is original without transformed variable */
17032 if( var == NULL )
17033 return &initbdchgidx;
17034
17035 /* check, if variable was fixed in presolving */
17036 if( !SCIPvarIsActive(var) )
17037 return &presolvebdchgidx;
17038
17040
17041 /* get depths of last bound change information for the lower and upper bound */
17042 lbchgidx = (var->nlbchginfos > 0 && !var->lbchginfos[var->nlbchginfos-1].redundant
17043 ? &var->lbchginfos[var->nlbchginfos-1].bdchgidx : &initbdchgidx);
17044 ubchgidx = (var->nubchginfos > 0 && !var->ubchginfos[var->nubchginfos-1].redundant
17045 ? &var->ubchginfos[var->nubchginfos-1].bdchgidx : &initbdchgidx);
17046
17047 if( SCIPbdchgidxIsEarlierNonNull(lbchgidx, ubchgidx) )
17048 return ubchgidx;
17049 else
17050 return lbchgidx;
17051}
17052
17053/** returns the last depth level, at which the bounds of the given variable were tightened;
17054 * returns -2, if the variable's bounds are still the global bounds
17055 * returns -1, if the variable was fixed in presolving
17056 */
17058 SCIP_VAR* var /**< problem variable */
17059 )
17060{
17061 SCIP_BDCHGIDX* bdchgidx;
17062
17063 bdchgidx = SCIPvarGetLastBdchgIndex(var);
17064 assert(bdchgidx != NULL);
17065
17066 return bdchgidx->depth;
17067}
17068
17069/** returns at which depth in the tree a bound change was applied to the variable that conflicts with the
17070 * given bound; returns -1 if the bound does not conflict with the current local bounds of the variable
17071 */
17073 SCIP_VAR* var, /**< problem variable */
17074 SCIP_SET* set, /**< global SCIP settings */
17075 SCIP_BOUNDTYPE boundtype, /**< bound type of the conflicting bound */
17076 SCIP_Real bound /**< conflicting bound */
17077 )
17078{
17079 int i;
17080
17081 assert(var != NULL);
17082 assert(set != NULL);
17083 assert(var->scip == set->scip);
17084
17085 if( boundtype == SCIP_BOUNDTYPE_LOWER )
17086 {
17087 /* check if the bound is in conflict with the current local bounds */
17088 if( SCIPsetIsLE(set, bound, var->locdom.ub) )
17089 return -1;
17090
17091 /* check if the bound is in conflict with the global bound */
17092 if( SCIPsetIsGT(set, bound, var->glbdom.ub) )
17093 return 0;
17094
17095 /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
17096 assert(var->nubchginfos > 0);
17097 assert(SCIPsetIsGT(set, bound, var->ubchginfos[var->nubchginfos-1].newbound));
17098
17099 /* search for the first conflicting bound change */
17100 for( i = var->nubchginfos-1; i > 0 && SCIPsetIsGT(set, bound, var->ubchginfos[i-1].newbound); --i )
17101 {
17102 assert(var->ubchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
17104 }
17105 assert(SCIPsetIsGT(set, bound, var->ubchginfos[i].newbound)); /* bound change i is conflicting */
17106 assert(i == 0 || SCIPsetIsLE(set, bound, var->ubchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
17107
17108 /* return the depth at which the first conflicting bound change took place */
17109 return var->ubchginfos[i].bdchgidx.depth;
17110 }
17111 else
17112 {
17113 assert(boundtype == SCIP_BOUNDTYPE_UPPER);
17114
17115 /* check if the bound is in conflict with the current local bounds */
17116 if( SCIPsetIsGE(set, bound, var->locdom.lb) )
17117 return -1;
17118
17119 /* check if the bound is in conflict with the global bound */
17120 if( SCIPsetIsLT(set, bound, var->glbdom.lb) )
17121 return 0;
17122
17123 /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
17124 assert(var->nlbchginfos > 0);
17125 assert(SCIPsetIsLT(set, bound, var->lbchginfos[var->nlbchginfos-1].newbound));
17126
17127 /* search for the first conflicting bound change */
17128 for( i = var->nlbchginfos-1; i > 0 && SCIPsetIsLT(set, bound, var->lbchginfos[i-1].newbound); --i )
17129 {
17130 assert(var->lbchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
17132 }
17133 assert(SCIPsetIsLT(set, bound, var->lbchginfos[i].newbound)); /* bound change i is conflicting */
17134 assert(i == 0 || SCIPsetIsGE(set, bound, var->lbchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
17135
17136 /* return the depth at which the first conflicting bound change took place */
17137 return var->lbchginfos[i].bdchgidx.depth;
17138 }
17139}
17140
17141/** returns whether the first binary variable was fixed earlier than the second one;
17142 * returns FALSE, if the first variable is not fixed, and returns TRUE, if the first variable is fixed, but the
17143 * second one is not fixed
17144 */
17146 SCIP_VAR* var1, /**< first binary variable */
17147 SCIP_VAR* var2 /**< second binary variable */
17148 )
17149{
17150 SCIP_BDCHGIDX* bdchgidx1;
17151 SCIP_BDCHGIDX* bdchgidx2;
17152
17153 assert(var1 != NULL);
17154 assert(var2 != NULL);
17155 assert(SCIPvarIsBinary(var1));
17156 assert(SCIPvarIsBinary(var2));
17157
17158 var1 = SCIPvarGetProbvar(var1);
17159 var2 = SCIPvarGetProbvar(var2);
17160 assert(var1 != NULL);
17161 assert(var2 != NULL);
17162
17163 /* check, if variables are globally fixed */
17164 if( !SCIPvarIsActive(var2) || var2->glbdom.lb > 0.5 || var2->glbdom.ub < 0.5 )
17165 return FALSE;
17166 if( !SCIPvarIsActive(var1) || var1->glbdom.lb > 0.5 || var1->glbdom.ub < 0.5 )
17167 return TRUE;
17168
17171 assert(SCIPvarIsBinary(var1));
17172 assert(SCIPvarIsBinary(var2));
17173 assert(var1->nlbchginfos + var1->nubchginfos <= 1);
17174 assert(var2->nlbchginfos + var2->nubchginfos <= 1);
17175 assert(var1->nlbchginfos == 0 || !var1->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
17176 assert(var1->nubchginfos == 0 || !var1->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
17177 assert(var2->nlbchginfos == 0 || !var2->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
17178 assert(var2->nubchginfos == 0 || !var2->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
17179
17180 if( var1->nlbchginfos == 1 )
17181 bdchgidx1 = &var1->lbchginfos[0].bdchgidx;
17182 else if( var1->nubchginfos == 1 )
17183 bdchgidx1 = &var1->ubchginfos[0].bdchgidx;
17184 else
17185 bdchgidx1 = NULL;
17186
17187 if( var2->nlbchginfos == 1 )
17188 bdchgidx2 = &var2->lbchginfos[0].bdchgidx;
17189 else if( var2->nubchginfos == 1 )
17190 bdchgidx2 = &var2->ubchginfos[0].bdchgidx;
17191 else
17192 bdchgidx2 = NULL;
17193
17194 return SCIPbdchgidxIsEarlier(bdchgidx1, bdchgidx2);
17195}
17196
17197
17198
17199/*
17200 * Hash functions
17201 */
17202
17203/** gets the key (i.e. the name) of the given variable */
17204SCIP_DECL_HASHGETKEY(SCIPhashGetKeyVar)
17205{ /*lint --e{715}*/
17206 SCIP_VAR* var = (SCIP_VAR*)elem;
17207
17208 assert(var != NULL);
17209 return var->name;
17210}
17211
17212
17213
17214
17215/*
17216 * simple functions implemented as defines
17217 */
17218
17219/* In debug mode, the following methods are implemented as function calls to ensure
17220 * type validity.
17221 * In optimized mode, the methods are implemented as defines to improve performance.
17222 * However, we want to have them in the library anyways, so we have to undef the defines.
17223 */
17224
17225#undef SCIPboundchgGetNewbound
17226#undef SCIPboundchgGetVar
17227#undef SCIPboundchgGetBoundchgtype
17228#undef SCIPboundchgGetBoundtype
17229#undef SCIPboundchgIsRedundant
17230#undef SCIPdomchgGetNBoundchgs
17231#undef SCIPdomchgGetBoundchg
17232#undef SCIPholelistGetLeft
17233#undef SCIPholelistGetRight
17234#undef SCIPholelistGetNext
17235#undef SCIPvarGetName
17236#undef SCIPvarGetNUses
17237#undef SCIPvarGetData
17238#undef SCIPvarSetData
17239#undef SCIPvarSetDelorigData
17240#undef SCIPvarSetTransData
17241#undef SCIPvarSetDeltransData
17242#undef SCIPvarGetStatus
17243#undef SCIPvarIsOriginal
17244#undef SCIPvarIsTransformed
17245#undef SCIPvarIsNegated
17246#undef SCIPvarGetType
17247#undef SCIPvarIsBinary
17248#undef SCIPvarIsIntegral
17249#undef SCIPvarIsInitial
17250#undef SCIPvarIsRemovable
17251#undef SCIPvarIsDeleted
17252#undef SCIPvarIsDeletable
17253#undef SCIPvarMarkDeletable
17254#undef SCIPvarMarkNotDeletable
17255#undef SCIPvarIsActive
17256#undef SCIPvarGetIndex
17257#undef SCIPvarGetProbindex
17258#undef SCIPvarGetTransVar
17259#undef SCIPvarGetCol
17260#undef SCIPvarIsInLP
17261#undef SCIPvarGetAggrVar
17262#undef SCIPvarGetAggrScalar
17263#undef SCIPvarGetAggrConstant
17264#undef SCIPvarGetMultaggrNVars
17265#undef SCIPvarGetMultaggrVars
17266#undef SCIPvarGetMultaggrScalars
17267#undef SCIPvarGetMultaggrConstant
17268#undef SCIPvarGetNegatedVar
17269#undef SCIPvarGetNegationVar
17270#undef SCIPvarGetNegationConstant
17271#undef SCIPvarGetObj
17272#undef SCIPvarGetLbOriginal
17273#undef SCIPvarGetUbOriginal
17274#undef SCIPvarGetHolelistOriginal
17275#undef SCIPvarGetLbGlobal
17276#undef SCIPvarGetUbGlobal
17277#undef SCIPvarGetHolelistGlobal
17278#undef SCIPvarGetBestBoundGlobal
17279#undef SCIPvarGetWorstBoundGlobal
17280#undef SCIPvarGetLbLocal
17281#undef SCIPvarGetUbLocal
17282#undef SCIPvarGetHolelistLocal
17283#undef SCIPvarGetBestBoundLocal
17284#undef SCIPvarGetWorstBoundLocal
17285#undef SCIPvarGetBestBoundType
17286#undef SCIPvarGetWorstBoundType
17287#undef SCIPvarGetLbLazy
17288#undef SCIPvarGetUbLazy
17289#undef SCIPvarGetBranchFactor
17290#undef SCIPvarGetBranchPriority
17291#undef SCIPvarGetBranchDirection
17292#undef SCIPvarGetNVlbs
17293#undef SCIPvarGetVlbVars
17294#undef SCIPvarGetVlbCoefs
17295#undef SCIPvarGetVlbConstants
17296#undef SCIPvarGetNVubs
17297#undef SCIPvarGetVubVars
17298#undef SCIPvarGetVubCoefs
17299#undef SCIPvarGetVubConstants
17300#undef SCIPvarGetNImpls
17301#undef SCIPvarGetImplVars
17302#undef SCIPvarGetImplTypes
17303#undef SCIPvarGetImplBounds
17304#undef SCIPvarGetImplIds
17305#undef SCIPvarGetNCliques
17306#undef SCIPvarGetCliques
17307#undef SCIPvarGetLPSol
17308#undef SCIPvarGetNLPSol
17309#undef SCIPvarGetBdchgInfoLb
17310#undef SCIPvarGetNBdchgInfosLb
17311#undef SCIPvarGetBdchgInfoUb
17312#undef SCIPvarGetNBdchgInfosUb
17313#undef SCIPvarGetValuehistory
17314#undef SCIPvarGetPseudoSol
17315#undef SCIPvarCatchEvent
17316#undef SCIPvarDropEvent
17317#undef SCIPvarGetVSIDS
17318#undef SCIPvarGetCliqueComponentIdx
17319#undef SCIPvarIsRelaxationOnly
17320#undef SCIPvarMarkRelaxationOnly
17321#undef SCIPbdchgidxGetPos
17322#undef SCIPbdchgidxIsEarlierNonNull
17323#undef SCIPbdchgidxIsEarlier
17324#undef SCIPbdchginfoGetOldbound
17325#undef SCIPbdchginfoGetNewbound
17326#undef SCIPbdchginfoGetVar
17327#undef SCIPbdchginfoGetChgtype
17328#undef SCIPbdchginfoGetBoundtype
17329#undef SCIPbdchginfoGetDepth
17330#undef SCIPbdchginfoGetPos
17331#undef SCIPbdchginfoGetIdx
17332#undef SCIPbdchginfoGetInferVar
17333#undef SCIPbdchginfoGetInferCons
17334#undef SCIPbdchginfoGetInferProp
17335#undef SCIPbdchginfoGetInferInfo
17336#undef SCIPbdchginfoGetInferBoundtype
17337#undef SCIPbdchginfoIsRedundant
17338#undef SCIPbdchginfoHasInferenceReason
17339#undef SCIPbdchginfoIsTighter
17340
17341
17342/** returns the new value of the bound in the bound change data */
17344 SCIP_BOUNDCHG* boundchg /**< bound change data */
17345 )
17346{
17347 assert(boundchg != NULL);
17348
17349 return boundchg->newbound;
17350}
17351
17352/** returns the variable of the bound change in the bound change data */
17354 SCIP_BOUNDCHG* boundchg /**< bound change data */
17355 )
17356{
17357 assert(boundchg != NULL);
17358
17359 return boundchg->var;
17360}
17361
17362/** returns the bound change type of the bound change in the bound change data */
17364 SCIP_BOUNDCHG* boundchg /**< bound change data */
17365 )
17366{
17367 assert(boundchg != NULL);
17368
17369 return (SCIP_BOUNDCHGTYPE)(boundchg->boundchgtype);
17370}
17371
17372/** returns the bound type of the bound change in the bound change data */
17374 SCIP_BOUNDCHG* boundchg /**< bound change data */
17375 )
17376{
17377 assert(boundchg != NULL);
17378
17379 return (SCIP_BOUNDTYPE)(boundchg->boundtype);
17380}
17381
17382/** returns whether the bound change is redundant due to a more global bound that is at least as strong */
17384 SCIP_BOUNDCHG* boundchg /**< bound change data */
17385 )
17386{
17387 assert(boundchg != NULL);
17388
17389 return boundchg->redundant;
17390}
17391
17392/** returns the number of bound changes in the domain change data */
17394 SCIP_DOMCHG* domchg /**< domain change data */
17395 )
17396{
17397 return domchg != NULL ? domchg->domchgbound.nboundchgs : 0;
17398}
17399
17400/** returns a particular bound change in the domain change data */
17402 SCIP_DOMCHG* domchg, /**< domain change data */
17403 int pos /**< position of the bound change in the domain change data */
17404 )
17405{
17406 assert(domchg != NULL);
17407 assert(0 <= pos && pos < (int)domchg->domchgbound.nboundchgs);
17408
17409 return &domchg->domchgbound.boundchgs[pos];
17410}
17411
17412/** returns left bound of open interval in hole */
17414 SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
17415 )
17416{
17417 assert(holelist != NULL);
17418
17419 return holelist->hole.left;
17420}
17421
17422/** returns right bound of open interval in hole */
17424 SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
17425 )
17426{
17427 assert(holelist != NULL);
17428
17429 return holelist->hole.right;
17430}
17431
17432/** returns next hole in list */
17434 SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
17435 )
17436{
17437 assert(holelist != NULL);
17438
17439 return holelist->next;
17440}
17441
17442/** returns the name of the variable
17443 *
17444 * @note to change the name of a variable, use SCIPchgVarName() from scip.h
17445 */
17446const char* SCIPvarGetName(
17447 SCIP_VAR* var /**< problem variable */
17448 )
17449{
17450 assert(var != NULL);
17451
17452 return var->name;
17453}
17454
17455/** gets number of times, the variable is currently captured */
17457 SCIP_VAR* var /**< problem variable */
17458 )
17459{
17460 assert(var != NULL);
17461
17462 return var->nuses;
17463}
17464
17465/** returns the user data of the variable */
17467 SCIP_VAR* var /**< problem variable */
17468 )
17469{
17470 assert(var != NULL);
17471
17472 return var->vardata;
17473}
17474
17475/** sets the user data for the variable */
17477 SCIP_VAR* var, /**< problem variable */
17478 SCIP_VARDATA* vardata /**< user variable data */
17479 )
17480{
17481 assert(var != NULL);
17482
17483 var->vardata = vardata;
17484}
17485
17486/** sets method to free user data for the original variable */
17488 SCIP_VAR* var, /**< problem variable */
17489 SCIP_DECL_VARDELORIG ((*vardelorig)) /**< frees user data of original variable */
17490 )
17491{
17492 assert(var != NULL);
17494
17495 var->vardelorig = vardelorig;
17496}
17497
17498/** sets method to transform user data of the variable */
17500 SCIP_VAR* var, /**< problem variable */
17501 SCIP_DECL_VARTRANS ((*vartrans)) /**< creates transformed user data by transforming original user data */
17502 )
17503{
17504 assert(var != NULL);
17506
17507 var->vartrans = vartrans;
17508}
17509
17510/** sets method to free transformed user data for the variable */
17512 SCIP_VAR* var, /**< problem variable */
17513 SCIP_DECL_VARDELTRANS ((*vardeltrans)) /**< frees user data of transformed variable */
17514 )
17515{
17516 assert(var != NULL);
17517
17518 var->vardeltrans = vardeltrans;
17519}
17520
17521/** sets method to copy this variable into sub-SCIPs */
17523 SCIP_VAR* var, /**< problem variable */
17524 SCIP_DECL_VARCOPY ((*varcopy)) /**< copy method of the variable */
17525 )
17526{
17527 assert(var != NULL);
17528
17529 var->varcopy = varcopy;
17530}
17531
17532/** sets the initial flag of a variable; only possible for original or loose variables */
17534 SCIP_VAR* var, /**< problem variable */
17535 SCIP_Bool initial /**< initial flag */
17536 )
17537{
17538 assert(var != NULL);
17539
17541 return SCIP_INVALIDCALL;
17542
17543 var->initial = initial;
17544
17545 return SCIP_OKAY;
17546}
17547
17548/** sets the removable flag of a variable; only possible for original or loose variables */
17550 SCIP_VAR* var, /**< problem variable */
17551 SCIP_Bool removable /**< removable flag */
17552 )
17553{
17554 assert(var != NULL);
17555
17557 return SCIP_INVALIDCALL;
17558
17559 var->removable = removable;
17560
17561 return SCIP_OKAY;
17562}
17563
17564/** gets status of variable */
17566 SCIP_VAR* var /**< problem variable */
17567 )
17568{
17569 assert(var != NULL);
17570
17571 return (SCIP_VARSTATUS)(var->varstatus);
17572}
17573
17574/** returns whether the variable belongs to the original problem */
17576 SCIP_VAR* var /**< problem variable */
17577 )
17578{
17579 assert(var != NULL);
17580 assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED || var->negatedvar != NULL);
17581
17585}
17586
17587/** returns whether the variable belongs to the transformed problem */
17589 SCIP_VAR* var /**< problem variable */
17590 )
17591{
17592 assert(var != NULL);
17593 assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED || var->negatedvar != NULL);
17594
17598}
17599
17600/** returns whether the variable was created by negation of a different variable */
17602 SCIP_VAR* var /**< problem variable */
17603 )
17604{
17605 assert(var != NULL);
17606
17608}
17609
17610/** gets type of variable */
17612 SCIP_VAR* var /**< problem variable */
17613 )
17614{
17615 assert(var != NULL);
17616
17617 return (SCIP_VARTYPE)(var->vartype);
17618}
17619
17620/** returns TRUE if the variable is of binary type; this is the case if:
17621 * (1) variable type is binary
17622 * (2) variable type is integer or implicit integer and
17623 * (i) the global lower bound is greater than or equal to zero
17624 * (ii) the global upper bound is less than or equal to one
17625 */
17627 SCIP_VAR* var /**< problem variable */
17628 )
17629{
17630 assert(var != NULL);
17631
17632 return (SCIPvarGetType(var) == SCIP_VARTYPE_BINARY ||
17633 (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && var->glbdom.lb >= 0.0 && var->glbdom.ub <= 1.0));
17634}
17635
17636/** returns whether variable is of integral type (binary, integer, or implicit integer) */
17638 SCIP_VAR* var /**< problem variable */
17639 )
17640{
17641 assert(var != NULL);
17642
17643 return (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
17644}
17645
17646/** returns whether variable's column should be present in the initial root LP */
17648 SCIP_VAR* var /**< problem variable */
17649 )
17650{
17651 assert(var != NULL);
17652
17653 return var->initial;
17654}
17655
17656/** returns whether variable's column is removable from the LP (due to aging or cleanup) */
17658 SCIP_VAR* var /**< problem variable */
17659 )
17660{
17661 assert(var != NULL);
17662
17663 return var->removable;
17664}
17665
17666/** returns whether the variable was deleted from the problem */
17668 SCIP_VAR* var /**< problem variable */
17669 )
17670{
17671 assert(var != NULL);
17672
17673 return var->deleted;
17674}
17675
17676/** marks the variable to be deletable, i.e., it may be deleted completely from the problem;
17677 * method can only be called before the variable is added to the problem by SCIPaddVar() or SCIPaddPricedVar()
17678 */
17680 SCIP_VAR* var /**< problem variable */
17681 )
17682{
17683 assert(var != NULL);
17684 assert(var->probindex == -1);
17685
17686 var->deletable = TRUE;
17687}
17688
17689/** marks the variable to be not deletable from the problem */
17691 SCIP_VAR* var
17692 )
17693{
17694 assert(var != NULL);
17695
17696 var->deletable = FALSE;
17697}
17698
17699/** marks variable to be deleted from global structures (cliques etc.) when cleaning up
17700 *
17701 * @note: this is not equivalent to marking the variable itself for deletion, this is done by using SCIPvarMarkDeletable()
17702 */
17704 SCIP_VAR* var /**< problem variable */
17705 )
17706{
17707 assert(var != NULL);
17708
17709 var->delglobalstructs = TRUE;
17710}
17711
17712/** returns whether the variable was flagged for deletion from global structures (cliques etc.) */
17714 SCIP_VAR* var /**< problem variable */
17715 )
17716{
17717 assert(var != NULL);
17718
17719 return var->delglobalstructs;
17720}
17721
17722/** returns whether a variable has been introduced to define a relaxation
17723 *
17724 * These variables are only valid for the current SCIP solve round,
17725 * they are not contained in any (checked) constraints, but may be used
17726 * in cutting planes, for example.
17727 * Relaxation-only variables are not copied by SCIPcopyVars and cuts
17728 * that contain these variables are not added as linear constraints when
17729 * restarting or transferring information from a copied SCIP to a SCIP.
17730 * Also conflicts with relaxation-only variables are not generated at
17731 * the moment.
17732 */
17734 SCIP_VAR* var /**< problem variable */
17735 )
17736{
17737 assert(var != NULL);
17738
17739 return var->relaxationonly;
17740}
17741
17742/** marks that this variable has only been introduced to define a relaxation
17743 *
17744 * The variable must not have a coefficient in the objective and must be deletable.
17745 * If it is not marked deletable, it will be marked as deletable, which is only possible
17746 * before the variable is added to a problem.
17747 *
17748 * @see SCIPvarIsRelaxationOnly
17749 * @see SCIPvarMarkDeletable
17750 */
17752 SCIP_VAR* var /**< problem variable */
17753 )
17754{
17755 assert(var != NULL);
17756 assert(SCIPvarGetObj(var) == 0.0);
17757
17758 if( !SCIPvarIsDeletable(var) )
17760
17761 var->relaxationonly = TRUE;
17762}
17763
17764/** returns whether variable is allowed to be deleted completely from the problem */
17766 SCIP_VAR* var
17767 )
17768{
17769 assert(var != NULL);
17770
17771 return var->deletable;
17772}
17773
17774/** returns whether variable is an active (neither fixed nor aggregated) variable */
17776 SCIP_VAR* var /**< problem variable */
17777 )
17778{
17779 assert(var != NULL);
17780
17781 return (var->probindex >= 0);
17782}
17783
17784/** gets unique index of variable */
17786 SCIP_VAR* var /**< problem variable */
17787 )
17788{
17789 assert(var != NULL);
17790
17791 return var->index;
17792}
17793
17794/** gets position of variable in problem, or -1 if variable is not active */
17796 SCIP_VAR* var /**< problem variable */
17797 )
17798{
17799 assert(var != NULL);
17800
17801 return var->probindex;
17802}
17803
17804/** gets transformed variable of ORIGINAL variable */
17806 SCIP_VAR* var /**< problem variable */
17807 )
17808{
17809 assert(var != NULL);
17811
17812 return var->data.original.transvar;
17813}
17814
17815/** gets column of COLUMN variable */
17817 SCIP_VAR* var /**< problem variable */
17818 )
17819{
17820 assert(var != NULL);
17822
17823 return var->data.col;
17824}
17825
17826/** returns whether the variable is a COLUMN variable that is member of the current LP */
17828 SCIP_VAR* var /**< problem variable */
17829 )
17830{
17831 assert(var != NULL);
17832
17834}
17835
17836/** gets aggregation variable y of an aggregated variable x = a*y + c */
17838 SCIP_VAR* var /**< problem variable */
17839 )
17840{
17841 assert(var != NULL);
17843 assert(!var->donotaggr);
17844
17845 return var->data.aggregate.var;
17846}
17847
17848/** gets aggregation scalar a of an aggregated variable x = a*y + c */
17850 SCIP_VAR* var /**< problem variable */
17851 )
17852{
17853 assert(var != NULL);
17855 assert(!var->donotaggr);
17856
17857 return var->data.aggregate.scalar;
17858}
17859
17860/** gets aggregation constant c of an aggregated variable x = a*y + c */
17862 SCIP_VAR* var /**< problem variable */
17863 )
17864{
17865 assert(var != NULL);
17867 assert(!var->donotaggr);
17868
17869 return var->data.aggregate.constant;
17870}
17871
17872/** gets number n of aggregation variables of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17874 SCIP_VAR* var /**< problem variable */
17875 )
17876{
17877 assert(var != NULL);
17879 assert(!var->donotmultaggr);
17880
17881 return var->data.multaggr.nvars;
17882}
17883
17884/** gets vector of aggregation variables y of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17886 SCIP_VAR* var /**< problem variable */
17887 )
17888{
17889 assert(var != NULL);
17891 assert(!var->donotmultaggr);
17892
17893 return var->data.multaggr.vars;
17894}
17895
17896/** gets vector of aggregation scalars a of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17898 SCIP_VAR* var /**< problem variable */
17899 )
17900{
17901 assert(var != NULL);
17903 assert(!var->donotmultaggr);
17904
17905 return var->data.multaggr.scalars;
17906}
17907
17908/** gets aggregation constant c of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17910 SCIP_VAR* var /**< problem variable */
17911 )
17912{
17913 assert(var != NULL);
17915 assert(!var->donotmultaggr);
17916
17917 return var->data.multaggr.constant;
17918}
17919
17920/** gets the negation of the given variable; may return NULL, if no negation is existing yet */
17922 SCIP_VAR* var /**< negated problem variable */
17923 )
17924{
17925 assert(var != NULL);
17926
17927 return var->negatedvar;
17928}
17929
17930/** gets the negation variable x of a negated variable x' = offset - x */
17932 SCIP_VAR* var /**< negated problem variable */
17933 )
17934{
17935 assert(var != NULL);
17937
17938 return var->negatedvar;
17939}
17940
17941/** gets the negation offset of a negated variable x' = offset - x */
17943 SCIP_VAR* var /**< negated problem variable */
17944 )
17945{
17946 assert(var != NULL);
17948
17949 return var->data.negate.constant;
17950}
17951
17952/** gets objective function value of variable */
17954 SCIP_VAR* var /**< problem variable */
17955 )
17956{
17957 assert(var != NULL);
17958
17959 return var->obj;
17960}
17961
17962/** gets the unchanged objective function value of a variable (ignoring temproray changes performed in probing mode) */
17964 SCIP_VAR* var /**< problem variable */
17965 )
17966{
17967 assert(var != NULL);
17968
17969 return var->unchangedobj;
17970}
17971
17972/** gets corresponding objective value of active, fixed, or multi-aggregated problem variable of given variable
17973 * e.g. obj(x) = 1 this method returns for ~x the value -1
17974 */
17976 SCIP_VAR* var, /**< problem variable */
17977 SCIP_Real* aggrobj /**< pointer to store the aggregated objective value */
17978 )
17979{
17980 SCIP_VAR* probvar = var;
17981 SCIP_Real mult = 1.0;
17982
17983 assert(probvar != NULL);
17984 assert(aggrobj != NULL);
17985
17986 while( probvar != NULL )
17987 {
17988 switch( SCIPvarGetStatus(probvar) )
17989 {
17993 (*aggrobj) = mult * SCIPvarGetObj(probvar);
17994 return SCIP_OKAY;
17995
17997 assert(SCIPvarGetObj(probvar) == 0.0);
17998 (*aggrobj) = 0.0;
17999 return SCIP_OKAY;
18000
18002 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
18003 if ( probvar->data.multaggr.nvars == 1 )
18004 {
18005 assert( probvar->data.multaggr.vars != NULL );
18006 assert( probvar->data.multaggr.scalars != NULL );
18007 assert( probvar->data.multaggr.vars[0] != NULL );
18008 mult *= probvar->data.multaggr.scalars[0];
18009 probvar = probvar->data.multaggr.vars[0];
18010 break;
18011 }
18012 else
18013 {
18014 SCIP_Real tmpobj;
18015 int v;
18016
18017 (*aggrobj) = 0.0;
18018
18019 for( v = probvar->data.multaggr.nvars - 1; v >= 0; --v )
18020 {
18021 SCIP_CALL( SCIPvarGetAggregatedObj(probvar->data.multaggr.vars[v], &tmpobj) );
18022 (*aggrobj) += probvar->data.multaggr.scalars[v] * tmpobj;
18023 }
18024 return SCIP_OKAY;
18025 }
18026
18027 case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
18028 assert(probvar->data.aggregate.var != NULL);
18029 mult *= probvar->data.aggregate.scalar;
18030 probvar = probvar->data.aggregate.var;
18031 break;
18032
18033 case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
18034 assert(probvar->negatedvar != NULL);
18036 assert(probvar->negatedvar->negatedvar == probvar);
18037 mult *= -1.0;
18038 probvar = probvar->negatedvar;
18039 break;
18040
18041 default:
18042 SCIPABORT();
18043 return SCIP_INVALIDDATA; /*lint !e527*/
18044 }
18045 }
18046
18047 return SCIP_INVALIDDATA;
18048}
18049
18050/** gets original lower bound of original problem variable (i.e. the bound set in problem creation) */
18052 SCIP_VAR* var /**< original problem variable */
18053 )
18054{
18055 assert(var != NULL);
18056 assert(SCIPvarIsOriginal(var));
18057
18059 return var->data.original.origdom.lb;
18060 else
18061 {
18063 assert(var->negatedvar != NULL);
18065
18066 return var->data.negate.constant - var->negatedvar->data.original.origdom.ub;
18067 }
18068}
18069
18070/** gets original upper bound of original problem variable (i.e. the bound set in problem creation) */
18072 SCIP_VAR* var /**< original problem variable */
18073 )
18074{
18075 assert(var != NULL);
18076 assert(SCIPvarIsOriginal(var));
18077
18079 return var->data.original.origdom.ub;
18080 else
18081 {
18083 assert(var->negatedvar != NULL);
18085
18086 return var->data.negate.constant - var->negatedvar->data.original.origdom.lb;
18087 }
18088}
18089
18090/** gets the original hole list of an original variable */
18092 SCIP_VAR* var /**< problem variable */
18093 )
18094{
18095 assert(var != NULL);
18096 assert(SCIPvarIsOriginal(var));
18097
18099 return var->data.original.origdom.holelist;
18100
18101 return NULL;
18102}
18103
18104/** gets global lower bound of variable */
18106 SCIP_VAR* var /**< problem variable */
18107 )
18108{
18109 assert(var != NULL);
18110
18111 return var->glbdom.lb;
18112}
18113
18114/** gets global upper bound of variable */
18116 SCIP_VAR* var /**< problem variable */
18117 )
18118{
18119 assert(var != NULL);
18120
18121 return var->glbdom.ub;
18122}
18123
18124/** gets the global hole list of an active variable */
18126 SCIP_VAR* var /**< problem variable */
18127 )
18128{
18129 assert(var != NULL);
18130
18131 return var->glbdom.holelist;
18132}
18133
18134/** gets best global bound of variable with respect to the objective function */
18136 SCIP_VAR* var /**< problem variable */
18137 )
18138{
18139 assert(var != NULL);
18140
18141 if( var->obj >= 0.0 )
18142 return var->glbdom.lb;
18143 else
18144 return var->glbdom.ub;
18145}
18146
18147/** gets worst global bound of variable with respect to the objective function */
18149 SCIP_VAR* var /**< problem variable */
18150 )
18151{
18152 assert(var != NULL);
18153
18154 if( var->obj >= 0.0 )
18155 return var->glbdom.ub;
18156 else
18157 return var->glbdom.lb;
18158}
18159
18160/** gets current lower bound of variable */
18162 SCIP_VAR* var /**< problem variable */
18163 )
18164{
18165 assert(var != NULL);
18166
18167 return var->locdom.lb;
18168}
18169
18170/** gets current upper bound of variable */
18172 SCIP_VAR* var /**< problem variable */
18173 )
18174{
18175 assert(var != NULL);
18176
18177 return var->locdom.ub;
18178}
18179
18180/** gets the current hole list of an active variable */
18182 SCIP_VAR* var /**< problem variable */
18183 )
18184{
18185 assert(var != NULL);
18186
18187 return var->locdom.holelist;
18188}
18189
18190/** gets best local bound of variable with respect to the objective function */
18192 SCIP_VAR* var /**< problem variable */
18193 )
18194{
18195 assert(var != NULL);
18196
18197 if( var->obj >= 0.0 )
18198 return var->locdom.lb;
18199 else
18200 return var->locdom.ub;
18201}
18202
18203/** gets worst local bound of variable with respect to the objective function */
18205 SCIP_VAR* var /**< problem variable */
18206 )
18207{
18208 assert(var != NULL);
18209
18210 if( var->obj >= 0.0 )
18211 return var->locdom.ub;
18212 else
18213 return var->locdom.lb;
18214}
18215
18216/** gets type (lower or upper) of best bound of variable with respect to the objective function */
18218 SCIP_VAR* var /**< problem variable */
18219 )
18220{
18221 assert(var != NULL);
18222
18223 if( var->obj >= 0.0 )
18224 return SCIP_BOUNDTYPE_LOWER;
18225 else
18226 return SCIP_BOUNDTYPE_UPPER;
18227}
18228
18229/** gets type (lower or upper) of worst bound of variable with respect to the objective function */
18231 SCIP_VAR* var /**< problem variable */
18232 )
18233{
18234 assert(var != NULL);
18235
18236 if( var->obj >= 0.0 )
18237 return SCIP_BOUNDTYPE_UPPER;
18238 else
18239 return SCIP_BOUNDTYPE_LOWER;
18240}
18241
18242/** gets lazy lower bound of variable, returns -infinity if the variable has no lazy lower bound */
18244 SCIP_VAR* var /**< problem variable */
18245 )
18246{
18247 assert(var != NULL);
18248
18249 return var->lazylb;
18250}
18251
18252/** gets lazy upper bound of variable, returns infinity if the variable has no lazy upper bound */
18254 SCIP_VAR* var /**< problem variable */
18255 )
18256{
18257 assert(var != NULL);
18258
18259 return var->lazyub;
18260}
18261
18262/** gets the branch factor of the variable; this value can be used in the branching methods to scale the score
18263 * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
18264 */
18266 SCIP_VAR* var /**< problem variable */
18267 )
18268{
18269 assert(var != NULL);
18270
18271 return var->branchfactor;
18272}
18273
18274/** gets the branch priority of the variable; variables with higher priority should always be preferred to variables
18275 * with lower priority
18276 */
18278 SCIP_VAR* var /**< problem variable */
18279 )
18280{
18281 assert(var != NULL);
18282
18283 return var->branchpriority;
18284}
18285
18286/** gets the preferred branch direction of the variable (downwards, upwards, or auto) */
18288 SCIP_VAR* var /**< problem variable */
18289 )
18290{
18291 assert(var != NULL);
18292
18293 return (SCIP_BRANCHDIR)var->branchdirection;
18294}
18295
18296/** gets number of variable lower bounds x >= b_i*z_i + d_i of given variable x */
18298 SCIP_VAR* var /**< problem variable */
18299 )
18300{
18301 assert(var != NULL);
18302
18303 return SCIPvboundsGetNVbds(var->vlbs);
18304}
18305
18306/** gets array with bounding variables z_i in variable lower bounds x >= b_i*z_i + d_i of given variable x;
18307 * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
18308 */
18310 SCIP_VAR* var /**< problem variable */
18311 )
18312{
18313 assert(var != NULL);
18314
18315 return SCIPvboundsGetVars(var->vlbs);
18316}
18317
18318/** gets array with bounding coefficients b_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
18320 SCIP_VAR* var /**< problem variable */
18321 )
18322{
18323 assert(var != NULL);
18324
18325 return SCIPvboundsGetCoefs(var->vlbs);
18326}
18327
18328/** gets array with bounding constants d_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
18330 SCIP_VAR* var /**< problem variable */
18331 )
18332{
18333 assert(var != NULL);
18334
18335 return SCIPvboundsGetConstants(var->vlbs);
18336}
18337
18338/** gets number of variable upper bounds x <= b_i*z_i + d_i of given variable x */
18340 SCIP_VAR* var /**< problem variable */
18341 )
18342{
18343 assert(var != NULL);
18344
18345 return SCIPvboundsGetNVbds(var->vubs);
18346}
18347
18348/** gets array with bounding variables z_i in variable upper bounds x <= b_i*z_i + d_i of given variable x;
18349 * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
18350 */
18352 SCIP_VAR* var /**< problem variable */
18353 )
18354{
18355 assert(var != NULL);
18356
18357 return SCIPvboundsGetVars(var->vubs);
18358}
18359
18360/** gets array with bounding coefficients b_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
18362 SCIP_VAR* var /**< problem variable */
18363 )
18364{
18365 assert(var != NULL);
18366
18367 return SCIPvboundsGetCoefs(var->vubs);
18368}
18369
18370/** gets array with bounding constants d_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
18372 SCIP_VAR* var /**< problem variable */
18373 )
18374{
18375 assert(var != NULL);
18376
18377 return SCIPvboundsGetConstants(var->vubs);
18378}
18379
18380/** gets number of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
18381 * there are no implications for nonbinary variable x
18382 */
18384 SCIP_VAR* var, /**< active problem variable */
18385 SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
18386 )
18387{
18388 assert(var != NULL);
18389 assert(SCIPvarIsActive(var));
18390
18391 return SCIPimplicsGetNImpls(var->implics, varfixing);
18392}
18393
18394/** gets array with implication variables y of implications y <= b or y >= b for x == 0 or x == 1 of given active
18395 * problem variable x, there are no implications for nonbinary variable x;
18396 * the implications are sorted such that implications with binary implied variables precede the ones with non-binary
18397 * implied variables, and as a second criteria, the implied variables are sorted by increasing variable index
18398 * (see SCIPvarGetIndex())
18399 */
18401 SCIP_VAR* var, /**< active problem variable */
18402 SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
18403 )
18404{
18405 assert(var != NULL);
18406 assert(SCIPvarIsActive(var));
18407
18408 return SCIPimplicsGetVars(var->implics, varfixing);
18409}
18410
18411/** gets array with implication types of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
18412 * variable x (SCIP_BOUNDTYPE_UPPER if y <= b, SCIP_BOUNDTYPE_LOWER if y >= b),
18413 * there are no implications for nonbinary variable x
18414 */
18416 SCIP_VAR* var, /**< active problem variable */
18417 SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
18418 )
18419{
18420 assert(var != NULL);
18421 assert(SCIPvarIsActive(var));
18422
18423 return SCIPimplicsGetTypes(var->implics, varfixing);
18424}
18425
18426/** gets array with implication bounds b of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
18427 * variable x, there are no implications for nonbinary variable x
18428 */
18430 SCIP_VAR* var, /**< active problem variable */
18431 SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
18432 )
18433{
18434 assert(var != NULL);
18435 assert(SCIPvarIsActive(var));
18436
18437 return SCIPimplicsGetBounds(var->implics, varfixing);
18438}
18439
18440/** Gets array with unique ids of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
18441 * there are no implications for nonbinary variable x.
18442 * If an implication is a shortcut, i.e., it was added as part of the transitive closure of another implication,
18443 * its id is negative, otherwise it is nonnegative.
18444 */
18446 SCIP_VAR* var, /**< active problem variable */
18447 SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
18448 )
18449{
18450 assert(var != NULL);
18451 assert(SCIPvarIsActive(var));
18452
18453 return SCIPimplicsGetIds(var->implics, varfixing);
18454}
18455
18456/** gets number of cliques, the active variable is contained in */
18458 SCIP_VAR* var, /**< active problem variable */
18459 SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
18460 )
18461{
18462 assert(var != NULL);
18463
18464 return SCIPcliquelistGetNCliques(var->cliquelist, varfixing);
18465}
18466
18467/** gets array of cliques, the active variable is contained in */
18469 SCIP_VAR* var, /**< active problem variable */
18470 SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
18471 )
18472{
18473 assert(var != NULL);
18474
18475 return SCIPcliquelistGetCliques(var->cliquelist, varfixing);
18476}
18477
18478/** gets primal LP solution value of variable */
18480 SCIP_VAR* var /**< problem variable */
18481 )
18482{
18483 assert(var != NULL);
18484
18486 return SCIPcolGetPrimsol(var->data.col);
18487 else
18488 return SCIPvarGetLPSol_rec(var);
18489}
18490
18491/** gets primal NLP solution value of variable */
18493 SCIP_VAR* var /**< problem variable */
18494 )
18495{
18496 assert(var != NULL);
18497
18499 return var->nlpsol;
18500 else
18501 return SCIPvarGetNLPSol_rec(var);
18502}
18503
18504/** return lower bound change info at requested position */
18506 SCIP_VAR* var, /**< problem variable */
18507 int pos /**< requested position */
18508 )
18509{
18510 assert(pos >= 0);
18511 assert(pos < var->nlbchginfos);
18512
18513 return &var->lbchginfos[pos];
18514}
18515
18516/** gets the number of lower bound change info array */
18518 SCIP_VAR* var /**< problem variable */
18519 )
18520{
18521 return var->nlbchginfos;
18522}
18523
18524/** return upper bound change info at requested position */
18526 SCIP_VAR* var, /**< problem variable */
18527 int pos /**< requested position */
18528 )
18529{
18530 assert(pos >= 0);
18531 assert(pos < var->nubchginfos);
18532
18533 return &var->ubchginfos[pos];
18534}
18535
18536/** gets the number upper bound change info array */
18538 SCIP_VAR* var /**< problem variable */
18539 )
18540{
18541 assert(var != NULL);
18542
18543 return var->nubchginfos;
18544}
18545
18546/** returns the value based history for the variable */
18548 SCIP_VAR* var /**< problem variable */
18549 )
18550{
18551 assert(var != NULL);
18552
18553 return var->valuehistory;
18554}
18555
18556/** gets pseudo solution value of variable */
18558 SCIP_VAR* var /**< problem variable */
18559 )
18560{
18561 assert(var != NULL);
18562
18564 return SCIPvarGetBestBoundLocal(var);
18565 else
18566 return SCIPvarGetPseudoSol_rec(var);
18567}
18568
18569/** returns the variable's VSIDS score */
18571 SCIP_VAR* var, /**< problem variable */
18572 SCIP_STAT* stat, /**< problem statistics */
18573 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
18574 )
18575{
18576 assert(var != NULL);
18577
18579 return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
18580 else
18581 return SCIPvarGetVSIDS_rec(var, stat, dir);
18582}
18583
18584/** includes event handler with given data in variable's event filter */
18586 SCIP_VAR* var, /**< problem variable */
18587 BMS_BLKMEM* blkmem, /**< block memory */
18588 SCIP_SET* set, /**< global SCIP settings */
18589 SCIP_EVENTTYPE eventtype, /**< event type to catch */
18590 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
18591 SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
18592 int* filterpos /**< pointer to store position of event filter entry, or NULL */
18593 )
18594{
18595 assert(var != NULL);
18596 assert(set != NULL);
18597 assert(var->scip == set->scip);
18598 assert(var->eventfilter != NULL);
18599 assert((eventtype & ~SCIP_EVENTTYPE_VARCHANGED) == 0);
18600 assert((eventtype & SCIP_EVENTTYPE_VARCHANGED) != 0);
18601 assert(SCIPvarIsTransformed(var));
18602
18603 SCIPsetDebugMsg(set, "catch event of type 0x%" SCIP_EVENTTYPE_FORMAT " of variable <%s> with handler %p and data %p\n",
18604 eventtype, var->name, (void*)eventhdlr, (void*)eventdata);
18605
18606 SCIP_CALL( SCIPeventfilterAdd(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
18607
18608 return SCIP_OKAY;
18609}
18610
18611/** deletes event handler with given data from variable's event filter */
18613 SCIP_VAR* var, /**< problem variable */
18614 BMS_BLKMEM* blkmem, /**< block memory */
18615 SCIP_SET* set, /**< global SCIP settings */
18616 SCIP_EVENTTYPE eventtype, /**< event type mask of dropped event */
18617 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
18618 SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
18619 int filterpos /**< position of event filter entry returned by SCIPvarCatchEvent(), or -1 */
18620 )
18621{
18622 assert(var != NULL);
18623 assert(set != NULL);
18624 assert(var->scip == set->scip);
18625 assert(var->eventfilter != NULL);
18626 assert(SCIPvarIsTransformed(var));
18627
18628 SCIPsetDebugMsg(set, "drop event of variable <%s> with handler %p and data %p\n", var->name, (void*)eventhdlr,
18629 (void*)eventdata);
18630
18631 SCIP_CALL( SCIPeventfilterDel(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
18632
18633 return SCIP_OKAY;
18634}
18635
18636/** returns the position of the bound change index */
18638 SCIP_BDCHGIDX* bdchgidx /**< bound change index */
18639 )
18640{
18641 assert(bdchgidx != NULL);
18642
18643 return bdchgidx->pos;
18644}
18645
18646/** returns whether first bound change index belongs to an earlier applied bound change than second one */
18648 SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index */
18649 SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index */
18650 )
18651{
18652 assert(bdchgidx1 != NULL);
18653 assert(bdchgidx1->depth >= -2);
18654 assert(bdchgidx1->pos >= 0);
18655 assert(bdchgidx2 != NULL);
18656 assert(bdchgidx2->depth >= -2);
18657 assert(bdchgidx2->pos >= 0);
18658
18659 return (bdchgidx1->depth < bdchgidx2->depth)
18660 || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
18661}
18662
18663/** returns whether first bound change index belongs to an earlier applied bound change than second one;
18664 * if a bound change index is NULL, the bound change index represents the current time, i.e. the time after the
18665 * last bound change was applied to the current node
18666 */
18668 SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index, or NULL */
18669 SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index, or NULL */
18670 )
18671{
18672 assert(bdchgidx1 == NULL || bdchgidx1->depth >= -2);
18673 assert(bdchgidx1 == NULL || bdchgidx1->pos >= 0);
18674 assert(bdchgidx2 == NULL || bdchgidx2->depth >= -2);
18675 assert(bdchgidx2 == NULL || bdchgidx2->pos >= 0);
18676
18677 if( bdchgidx1 == NULL )
18678 return FALSE;
18679 else if( bdchgidx2 == NULL )
18680 return TRUE;
18681 else
18682 return (bdchgidx1->depth < bdchgidx2->depth)
18683 || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
18684}
18685
18686/** returns old bound that was overwritten for given bound change information */
18688 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18689 )
18690{
18691 assert(bdchginfo != NULL);
18692
18693 return bdchginfo->oldbound;
18694}
18695
18696/** returns new bound installed for given bound change information */
18698 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18699 )
18700{
18701 assert(bdchginfo != NULL);
18702
18703 return bdchginfo->newbound;
18704}
18705
18706/** returns variable that belongs to the given bound change information */
18708 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18709 )
18710{
18711 assert(bdchginfo != NULL);
18712
18713 return bdchginfo->var;
18714}
18715
18716/** returns whether the bound change information belongs to a branching decision or a deduction */
18718 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18719 )
18720{
18721 assert(bdchginfo != NULL);
18722
18723 return (SCIP_BOUNDCHGTYPE)(bdchginfo->boundchgtype);
18724}
18725
18726/** returns whether the bound change information belongs to a lower or upper bound change */
18728 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18729 )
18730{
18731 assert(bdchginfo != NULL);
18732
18733 return (SCIP_BOUNDTYPE)(bdchginfo->boundtype);
18734}
18735
18736/** returns depth level of given bound change information */
18738 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18739 )
18740{
18741 assert(bdchginfo != NULL);
18742
18743 return bdchginfo->bdchgidx.depth;
18744}
18745
18746/** returns bound change position in its depth level of given bound change information */
18748 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18749 )
18750{
18751 assert(bdchginfo != NULL);
18752
18753 return bdchginfo->bdchgidx.pos;
18754}
18755
18756/** returns bound change index of given bound change information */
18758 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18759 )
18760{
18761 assert(bdchginfo != NULL);
18762
18763 return &bdchginfo->bdchgidx;
18764}
18765
18766/** returns inference variable of given bound change information */
18768 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18769 )
18770{
18771 assert(bdchginfo != NULL);
18774
18775 return bdchginfo->inferencedata.var;
18776}
18777
18778/** returns inference constraint of given bound change information */
18780 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18781 )
18782{
18783 assert(bdchginfo != NULL);
18785 assert(bdchginfo->inferencedata.reason.cons != NULL);
18786
18787 return bdchginfo->inferencedata.reason.cons;
18788}
18789
18790/** returns inference propagator of given bound change information, or NULL if no propagator was responsible */
18792 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18793 )
18794{
18795 assert(bdchginfo != NULL);
18797
18798 return bdchginfo->inferencedata.reason.prop;
18799}
18800
18801/** returns inference user information of given bound change information */
18803 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18804 )
18805{
18806 assert(bdchginfo != NULL);
18809
18810 return bdchginfo->inferencedata.info;
18811}
18812
18813/** returns inference bound of inference variable of given bound change information */
18815 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18816 )
18817{
18818 assert(bdchginfo != NULL);
18821
18822 return (SCIP_BOUNDTYPE)(bdchginfo->inferboundtype);
18823}
18824
18825/** returns the relaxed bound change type */
18827 SCIP_BDCHGINFO* bdchginfo /**< bound change to add to the conflict set */
18828 )
18829{
18830 return ((SCIP_BOUNDTYPE)(bdchginfo->boundtype) == SCIP_BOUNDTYPE_LOWER ? bdchginfo->var->conflictrelaxedlb : bdchginfo->var->conflictrelaxedub);
18831}
18832
18833
18834/** returns whether the bound change information belongs to a redundant bound change */
18836 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18837 )
18838{
18839 assert(bdchginfo != NULL);
18840 assert(bdchginfo->redundant == (bdchginfo->oldbound == bdchginfo->newbound)); /*lint !e777*/
18841
18842 return bdchginfo->redundant;
18843}
18844
18845/** returns whether the bound change has an inference reason (constraint or propagator), that can be resolved */
18847 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18848 )
18849{
18850 assert(bdchginfo != NULL);
18851
18854 && bdchginfo->inferencedata.reason.prop != NULL);
18855}
18856
18857/** for two bound change informations belonging to the same variable and bound, returns whether the first bound change
18858 * has a tighter new bound as the second bound change
18859 */
18861 SCIP_BDCHGINFO* bdchginfo1, /**< first bound change information */
18862 SCIP_BDCHGINFO* bdchginfo2 /**< second bound change information */
18863 )
18864{
18865 assert(bdchginfo1 != NULL);
18866 assert(bdchginfo2 != NULL);
18867 assert(bdchginfo1->var == bdchginfo2->var);
18868 assert(bdchginfo1->boundtype == bdchginfo2->boundtype);
18869
18870 return (SCIPbdchginfoGetBoundtype(bdchginfo1) == SCIP_BOUNDTYPE_LOWER
18871 ? bdchginfo1->newbound > bdchginfo2->newbound
18872 : bdchginfo1->newbound < bdchginfo2->newbound);
18873}
static long bound
static GRAPHNODE ** active
SCIP_VAR * a
Definition: circlepacking.c:66
SCIP_VAR ** b
Definition: circlepacking.c:65
void SCIPconsCapture(SCIP_CONS *cons)
Definition: cons.c:6254
SCIP_RETCODE SCIPconsRelease(SCIP_CONS **cons, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: cons.c:6266
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:177
#define NULL
Definition: def.h:266
#define SCIP_MAXSTRLEN
Definition: def.h:287
#define SCIP_Longint
Definition: def.h:157
#define EPSISINT(x, eps)
Definition: def.h:209
#define SCIP_REAL_MAX
Definition: def.h:173
#define SCIP_INVALID
Definition: def.h:192
#define SCIP_Bool
Definition: def.h:91
#define EPSLE(x, y, eps)
Definition: def.h:199
#define MIN(x, y)
Definition: def.h:242
#define SCIP_ALLOC(x)
Definition: def.h:384
#define SCIP_Real
Definition: def.h:172
#define SCIP_UNKNOWN
Definition: def.h:193
#define ABS(x)
Definition: def.h:234
#define SQR(x)
Definition: def.h:213
#define EPSEQ(x, y, eps)
Definition: def.h:197
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:238
#define SCIP_CALL_ABORT(x)
Definition: def.h:352
#define SCIPABORT()
Definition: def.h:345
#define SCIP_REAL_MIN
Definition: def.h:174
#define REALABS(x)
Definition: def.h:196
#define EPSZ(x, eps)
Definition: def.h:202
#define SCIP_CALL(x)
Definition: def.h:373
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 SCIPeventProcess(SCIP_EVENT *event, SCIP_SET *set, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter)
Definition: event.c:1574
SCIP_RETCODE SCIPeventCreateImplAdded(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition: event.c:814
SCIP_RETCODE SCIPeventChgType(SCIP_EVENT *event, SCIP_EVENTTYPE eventtype)
Definition: event.c:1040
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:3159
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3426
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9124
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9376
SCIP_Bool SCIPrealToRational(SCIP_Real val, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Longint *nominator, SCIP_Longint *denominator)
Definition: misc.c:9397
SCIP_Real SCIPcolGetObj(SCIP_COL *col)
Definition: lp.c:16981
SCIP_Real SCIPcolGetLb(SCIP_COL *col)
Definition: lp.c:16991
SCIP_Real SCIPcolGetPrimsol(SCIP_COL *col)
Definition: lp.c:17024
SCIP_Real SCIPcolGetUb(SCIP_COL *col)
Definition: lp.c:17001
SCIP_Bool SCIPcolIsInLP(SCIP_COL *col)
Definition: lp.c:17143
SCIP_BASESTAT SCIPcolGetBasisStatus(SCIP_COL *col)
Definition: lp.c:17059
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8214
SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
Definition: tree.c:7511
SCIP_NODE * SCIPnodeGetParent(SCIP_NODE *node)
Definition: tree.c:7806
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:672
SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition: var.c:17647
SCIP_Real SCIPvarGetLPSol_rec(SCIP_VAR *var)
Definition: var.c:13096
int SCIPvarCompareActiveAndNegated(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11931
void SCIPvarSetDelorigData(SCIP_VAR *var, SCIP_DECL_VARDELORIG((*vardelorig)))
Definition: var.c:17487
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12801
SCIP_HOLELIST * SCIPvarGetHolelistLocal(SCIP_VAR *var)
Definition: var.c:18181
int SCIPvarGetNVlbs(SCIP_VAR *var)
Definition: var.c:18297
SCIP_RETCODE SCIPvarGetProbvarBound(SCIP_VAR **var, SCIP_Real *bound, SCIP_BOUNDTYPE *boundtype)
Definition: var.c:12496
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition: var.c:17667
SCIP_Real SCIPvarGetNegationConstant(SCIP_VAR *var)
Definition: var.c:17942
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition: var.c:17816
SCIP_Bool SCIPbdchginfoIsRedundant(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18835
SCIP_Bool SCIPvarWasFixedAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16997
SCIP_Real SCIPvarGetAvgBranchdepthCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15859
SCIP_Bool SCIPvarMayRoundUp(SCIP_VAR *var)
Definition: var.c:3451
SCIP_Real SCIPvarGetMultaggrConstant(SCIP_VAR *var)
Definition: var.c:17909
SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
Definition: var.c:18217
void SCIPvarsGetProbvar(SCIP_VAR **vars, int nvars)
Definition: var.c:12225
SCIP_Real SCIPvarGetSol(SCIP_VAR *var, SCIP_Bool getlpval)
Definition: var.c:13284
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:17921
SCIP_Real * SCIPvarGetVlbCoefs(SCIP_VAR *var)
Definition: var.c:18319
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:17775
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:17626
SCIP_BOUNDTYPE SCIPboundchgGetBoundtype(SCIP_BOUNDCHG *boundchg)
Definition: var.c:17373
SCIP_Real SCIPholelistGetRight(SCIP_HOLELIST *holelist)
Definition: var.c:17423
void SCIPvarSetTransData(SCIP_VAR *var, SCIP_DECL_VARTRANS((*vartrans)))
Definition: var.c:17499
SCIP_Real SCIPvarGetAvgBranchdepth(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15814
SCIP_Real SCIPvarGetBestBoundGlobal(SCIP_VAR *var)
Definition: var.c:18135
SCIP_Bool SCIPbdchgidxIsEarlier(SCIP_BDCHGIDX *bdchgidx1, SCIP_BDCHGIDX *bdchgidx2)
Definition: var.c:18667
SCIP_Bool SCIPvarWasFixedEarlier(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:17145
SCIP_BDCHGIDX * SCIPbdchginfoGetIdx(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18757
SCIP_VAR * SCIPboundchgGetVar(SCIP_BOUNDCHG *boundchg)
Definition: var.c:17353
SCIP_Bool SCIPvarHasImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition: var.c:11138
SCIP_BOUNDCHG * SCIPdomchgGetBoundchg(SCIP_DOMCHG *domchg, int pos)
Definition: var.c:17401
int SCIPvarGetNImpls(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18383
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:17565
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:3353
SCIP_BOUNDCHGTYPE SCIPboundchgGetBoundchgtype(SCIP_BOUNDCHG *boundchg)
Definition: var.c:17363
SCIP_Real SCIPvarGetInferenceSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:16006
SCIP_Real SCIPvarGetAggrConstant(SCIP_VAR *var)
Definition: var.c:17861
SCIP_RETCODE SCIPvarGetAggregatedObj(SCIP_VAR *var, SCIP_Real *aggrobj)
Definition: var.c:17975
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:18171
int SCIPvarGetNLocksDown(SCIP_VAR *var)
Definition: var.c:3416
SCIP_Real SCIPvarGetBestRootSol(SCIP_VAR *var)
Definition: var.c:13742
void SCIPvarSetDeltransData(SCIP_VAR *var, SCIP_DECL_VARDELTRANS((*vardeltrans)))
Definition: var.c:17511
SCIP_HOLELIST * SCIPholelistGetNext(SCIP_HOLELIST *holelist)
Definition: var.c:17433
SCIP_Real SCIPvarGetLbOriginal(SCIP_VAR *var)
Definition: var.c:18051
SCIP_BDCHGINFO * SCIPvarGetLbchgInfo(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16604
SCIP_DECL_HASHGETKEY(SCIPvarGetHashkey)
Definition: var.c:12012
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:17588
void SCIPvarMarkDeletable(SCIP_VAR *var)
Definition: var.c:17679
void SCIPvarGetImplicVarBounds(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_Real *lb, SCIP_Real *ub)
Definition: var.c:11173
SCIP_PROP * SCIPbdchginfoGetInferProp(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18791
SCIP_Real SCIPboundchgGetNewbound(SCIP_BOUNDCHG *boundchg)
Definition: var.c:17343
SCIP_Bool SCIPvarMayRoundDown(SCIP_VAR *var)
Definition: var.c:3440
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17953
SCIP_Real SCIPvarGetAggrScalar(SCIP_VAR *var)
Definition: var.c:17849
SCIP_DECL_SORTPTRCOMP(SCIPvarCompActiveAndNegated)
Definition: var.c:11961
SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
Definition: var.c:12245
void SCIPvarMarkRelaxationOnly(SCIP_VAR *var)
Definition: var.c:17751
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:17611
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:18115
SCIP_RETCODE SCIPvarSetInitial(SCIP_VAR *var, SCIP_Bool initial)
Definition: var.c:17533
SCIP_VAR ** SCIPvarGetImplVars(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18400
void SCIPvarSetBestRootSol(SCIP_VAR *var, SCIP_Real rootsol, SCIP_Real rootredcost, SCIP_Real rootlpobjval)
Definition: var.c:13874
int SCIPbdchginfoGetDepth(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18737
int SCIPbdchginfoGetInferInfo(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18802
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:17785
SCIP_CONS * SCIPbdchginfoGetInferCons(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18779
SCIP_Real SCIPvarGetNLPSol_rec(SCIP_VAR *var)
Definition: var.c:13169
SCIP_BDCHGIDX * SCIPvarGetLastBdchgIndex(SCIP_VAR *var)
Definition: var.c:17020
int SCIPbdchginfoGetPos(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18747
SCIP_Real SCIPvarGetWorstBoundLocal(SCIP_VAR *var)
Definition: var.c:18204
int SCIPvarGetNUses(SCIP_VAR *var)
Definition: var.c:17456
int SCIPdomchgGetNBoundchgs(SCIP_DOMCHG *domchg)
Definition: var.c:17393
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:17795
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17446
SCIP_Real SCIPvarGetUbOriginal(SCIP_VAR *var)
Definition: var.c:18071
SCIP_Real SCIPvarGetWorstBoundGlobal(SCIP_VAR *var)
Definition: var.c:18148
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18707
SCIP_Bool SCIPvarHasBinaryImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_Bool implvarfixing)
Definition: var.c:11158
void SCIPvarMarkDeleteGlobalStructures(SCIP_VAR *var)
Definition: var.c:17703
SCIP_Real * SCIPvarGetVlbConstants(SCIP_VAR *var)
Definition: var.c:18329
SCIP_Real SCIPvarGetRootSol(SCIP_VAR *var)
Definition: var.c:13377
int * SCIPvarGetImplIds(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18445
SCIP_Real SCIPvarGetBestBoundLocal(SCIP_VAR *var)
Definition: var.c:18191
int SCIPvarGetNVubs(SCIP_VAR *var)
Definition: var.c:18339
SCIP_Real SCIPvarGetBranchFactor(SCIP_VAR *var)
Definition: var.c:18265
SCIP_Real SCIPvarGetAvgSol(SCIP_VAR *var)
Definition: var.c:14089
SCIP_Bool SCIPvarIsDeletable(SCIP_VAR *var)
Definition: var.c:17765
SCIP_Real SCIPbdchginfoGetOldbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18687
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:17637
SCIP_Bool SCIPvarIsTransformedOrigvar(SCIP_VAR *var)
Definition: var.c:12888
SCIP_Real SCIPvarGetUbLazy(SCIP_VAR *var)
Definition: var.c:18253
SCIP_Real SCIPvarGetPseudoSol(SCIP_VAR *var)
Definition: var.c:18557
SCIP_BRANCHDIR SCIPvarGetBranchDirection(SCIP_VAR *var)
Definition: var.c:18287
SCIP_BOUNDTYPE SCIPbdchginfoGetInferBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18814
void SCIPvarSetData(SCIP_VAR *var, SCIP_VARDATA *vardata)
Definition: var.c:17476
SCIP_Real * SCIPvarGetImplBounds(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18429
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition: var.c:18479
SCIP_BDCHGINFO * SCIPvarGetBdchgInfo(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16716
SCIP_VARDATA * SCIPvarGetData(SCIP_VAR *var)
Definition: var.c:17466
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition: var.c:17885
SCIP_Bool SCIPbdchginfoIsTighter(SCIP_BDCHGINFO *bdchginfo1, SCIP_BDCHGINFO *bdchginfo2)
Definition: var.c:18860
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:17873
SCIP_RETCODE SCIPvarSetRemovable(SCIP_VAR *var, SCIP_Bool removable)
Definition: var.c:17549
SCIP_HOLELIST * SCIPvarGetHolelistOriginal(SCIP_VAR *var)
Definition: var.c:18091
SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
Definition: var.c:17657
int SCIPvarGetNCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18457
SCIP_BOUNDCHGTYPE SCIPbdchginfoGetChgtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18717
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:18161
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:17601
SCIP_DECL_HASHKEYEQ(SCIPvarIsHashkeyEq)
Definition: var.c:12018
SCIP_VAR * SCIPbdchginfoGetInferVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18767
SCIP_Bool SCIPbdchginfoHasInferenceReason(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18846
SCIP_Bool SCIPboundchgIsRedundant(SCIP_BOUNDCHG *boundchg)
Definition: var.c:17383
SCIP_Longint SCIPvarGetNBranchings(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15726
SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
Definition: var.c:17733
SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition: var.c:17931
SCIP_RETCODE SCIPvarGetProbvarHole(SCIP_VAR **var, SCIP_Real *left, SCIP_Real *right)
Definition: var.c:12589
SCIP_VAR ** SCIPvarGetVlbVars(SCIP_VAR *var)
Definition: var.c:18309
SCIP_BDCHGINFO * SCIPvarGetUbchgInfo(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16660
SCIP_Real SCIPholelistGetLeft(SCIP_HOLELIST *holelist)
Definition: var.c:17413
int SCIPvarGetBranchPriority(SCIP_VAR *var)
Definition: var.c:18277
SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
Definition: var.c:17575
SCIP_CLIQUE ** SCIPvarGetCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18468
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:18105
void SCIPvarMarkNotDeletable(SCIP_VAR *var)
Definition: var.c:17690
SCIP_Real SCIPvarGetBestRootRedcost(SCIP_VAR *var)
Definition: var.c:13809
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoLb(SCIP_VAR *var, int pos)
Definition: var.c:18505
SCIP_DECL_HASHKEYVAL(SCIPvarGetHashkeyVal)
Definition: var.c:12026
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11969
SCIP_Real SCIPvarGetCutoffSumCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:16249
SCIP_Real SCIPvarGetBestRootLPObjval(SCIP_VAR *var)
Definition: var.c:13843
SCIP_Real SCIPvarGetLbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16737
SCIP_RETCODE SCIPvarGetProbvarBinary(SCIP_VAR **var, SCIP_Bool *negated)
Definition: var.c:12337
SCIP_Longint SCIPvarGetNBranchingsCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15771
SCIP_Real * SCIPvarGetVubConstants(SCIP_VAR *var)
Definition: var.c:18371
int SCIPvarGetNLocksUp(SCIP_VAR *var)
Definition: var.c:3429
SCIP_VAR * SCIPvarGetTransVar(SCIP_VAR *var)
Definition: var.c:17805
SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
Definition: var.c:18492
SCIP_VAR ** SCIPvarGetVubVars(SCIP_VAR *var)
Definition: var.c:18351
int SCIPvarGetNBdchgInfosUb(SCIP_VAR *var)
Definition: var.c:18537
SCIP_BOUNDTYPE SCIPbdchginfoGetBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18727
SCIP_VALUEHISTORY * SCIPvarGetValuehistory(SCIP_VAR *var)
Definition: var.c:18547
SCIP_BOUNDTYPE SCIPvarGetWorstBoundType(SCIP_VAR *var)
Definition: var.c:18230
SCIP_Real SCIPvarGetInferenceSumCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:16051
SCIP_Bool SCIPvarsHaveCommonClique(SCIP_VAR *var1, SCIP_Bool value1, SCIP_VAR *var2, SCIP_Bool value2, SCIP_Bool regardimplics)
Definition: var.c:11502
SCIP_Bool SCIPbdchgidxIsEarlierNonNull(SCIP_BDCHGIDX *bdchgidx1, SCIP_BDCHGIDX *bdchgidx2)
Definition: var.c:18647
SCIP_Real * SCIPvarGetVubCoefs(SCIP_VAR *var)
Definition: var.c:18361
SCIP_HOLELIST * SCIPvarGetHolelistGlobal(SCIP_VAR *var)
Definition: var.c:18125
SCIP_Real SCIPvarGetBdAtIndex(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16977
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18697
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:16856
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoUb(SCIP_VAR *var, int pos)
Definition: var.c:18525
int SCIPvarGetNBdchgInfosLb(SCIP_VAR *var)
Definition: var.c:18517
SCIP_BOUNDTYPE * SCIPvarGetImplTypes(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18415
int SCIPvarGetLastBdchgDepth(SCIP_VAR *var)
Definition: var.c:17057
void SCIPvarSetCopyData(SCIP_VAR *var, SCIP_DECL_VARCOPY((*varcopy)))
Definition: var.c:17522
SCIP_RETCODE SCIPvarsGetProbvarBinary(SCIP_VAR ***vars, SCIP_Bool **negatedarr, int nvars)
Definition: var.c:12305
SCIP_Real SCIPvarGetUnchangedObj(SCIP_VAR *var)
Definition: var.c:17963
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition: var.c:17897
SCIP_Real SCIPvarGetCutoffSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:16206
SCIP_Real SCIPvarGetLbLazy(SCIP_VAR *var)
Definition: var.c:18243
SCIP_Bool SCIPvarIsInLP(SCIP_VAR *var)
Definition: var.c:17827
SCIP_VAR * SCIPvarGetAggrVar(SCIP_VAR *var)
Definition: var.c:17837
SCIP_Real SCIPnormalCDF(SCIP_Real mean, SCIP_Real variance, SCIP_Real value)
Definition: misc.c:199
SCIP_Real SCIPcomputeTwoSampleTTestValue(SCIP_Real meanx, SCIP_Real meany, SCIP_Real variancex, SCIP_Real variancey, SCIP_Real countx, SCIP_Real county)
Definition: misc.c:126
SCIP_Real SCIPstudentTGetCriticalValue(SCIP_CONFIDENCELEVEL clevel, int df)
Definition: misc.c:109
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:10880
SCIP_Bool SCIPstrToRealValue(const char *str, SCIP_Real *value, char **endptr)
Definition: misc.c:11008
void SCIPstrCopySection(const char *str, char startchar, char endchar, char *token, int size, char **endptr)
Definition: misc.c:11038
SCIP_RETCODE SCIPvaluehistoryCreate(SCIP_VALUEHISTORY **valuehistory, BMS_BLKMEM *blkmem)
Definition: history.c:243
SCIP_RETCODE SCIPvaluehistoryFind(SCIP_VALUEHISTORY *valuehistory, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real value, SCIP_HISTORY **history)
Definition: history.c:284
void SCIPvaluehistoryFree(SCIP_VALUEHISTORY **valuehistory, BMS_BLKMEM *blkmem)
Definition: history.c:262
void SCIPvaluehistoryScaleVSIDS(SCIP_VALUEHISTORY *valuehistory, SCIP_Real scalar)
Definition: history.c:329
void SCIPhistoryReset(SCIP_HISTORY *history)
Definition: history.c:78
SCIP_Real SCIPhistoryGetPseudocost(SCIP_HISTORY *history, SCIP_Real solvaldelta)
Definition: history.c:446
SCIP_Real SCIPhistoryGetAvgInferences(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:665
SCIP_Longint SCIPhistoryGetNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:565
SCIP_Longint SCIPhistoryGetNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:639
SCIP_Real SCIPhistoryGetAvgConflictlength(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:578
SCIP_Real SCIPhistoryGetAvgCutoffs(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:691
SCIP_RETCODE SCIPhistoryCreate(SCIP_HISTORY **history, BMS_BLKMEM *blkmem)
Definition: history.c:51
void SCIPhistorySetLastGMIeff(SCIP_HISTORY *history, SCIP_Real gmieff)
Definition: history.c:782
void SCIPhistoryIncInferenceSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition: history.c:607
SCIP_Real SCIPhistoryGetCutoffSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:678
SCIP_Real SCIPhistoryGetPseudocostCount(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:484
SCIP_Real SCIPhistoryGetPseudocostVariance(SCIP_HISTORY *history, SCIP_BRANCHDIR direction)
Definition: history.c:460
void SCIPhistoryIncNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real length)
Definition: history.c:549
void SCIPhistoryScaleVSIDS(SCIP_HISTORY *history, SCIP_Real scalar)
Definition: history.c:524
void SCIPhistoryIncCutoffSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition: history.c:623
void SCIPhistoryIncNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, int depth)
Definition: history.c:591
void SCIPhistoryUpdatePseudocost(SCIP_HISTORY *history, SCIP_SET *set, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition: history.c:174
SCIP_Real SCIPhistoryGetVSIDS(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:536
SCIP_Real SCIPhistoryGetAvgBranchdepth(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:704
SCIP_Real SCIPhistoryGetLastGMIeff(SCIP_HISTORY *history)
Definition: history.c:772
SCIP_Real SCIPhistoryGetAvgGMIeff(SCIP_HISTORY *history)
Definition: history.c:749
SCIP_Real SCIPhistoryGetInferenceSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:652
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:113
void SCIPhistoryIncGMIeffSum(SCIP_HISTORY *history, SCIP_Real gmieff)
Definition: history.c:759
SCIP_BRANCHDIR SCIPbranchdirOpposite(SCIP_BRANCHDIR dir)
Definition: history.c:437
void SCIPhistoryIncVSIDS(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition: history.c:510
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:17865
SCIP_RETCODE SCIPcolChgUb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newub)
Definition: lp.c:3800
SCIP_RETCODE SCIPcolFree(SCIP_COL **col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: lp.c:3375
SCIP_RETCODE SCIPcolChgLb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newlb)
Definition: lp.c:3755
void SCIPlpDecNLoosevars(SCIP_LP *lp)
Definition: lp.c:14332
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:5638
SCIP_RETCODE SCIPcolChgObj(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newobj)
Definition: lp.c:3696
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:5526
SCIP_Bool SCIPlpDiving(SCIP_LP *lp)
Definition: lp.c:17875
SCIP_Real SCIPcolGetRedcost(SCIP_COL *col, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:3950
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:3277
SCIP_RETCODE SCIPlpUpdateVarLoose(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:14311
static const SCIP_Real scalars[]
Definition: lp.c:5741
SCIP_RETCODE SCIPlpUpdateVarColumn(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:14187
internal methods for LP management
#define BMSreallocBlockMemorySize(mem, ptr, oldsize, newsize)
Definition: memory.h:456
#define BMSduplicateBlockMemoryArray(mem, ptr, source, num)
Definition: memory.h:462
#define BMSfreeBlockMemory(mem, ptr)
Definition: memory.h:465
#define BMSallocBlockMemory(mem, ptr)
Definition: memory.h:451
#define BMSfreeBlockMemoryArrayNull(mem, ptr, num)
Definition: memory.h:468
#define BMSfreeBlockMemorySize(mem, ptr, size)
Definition: memory.h:469
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:134
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition: memory.h:467
#define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
Definition: memory.h:458
#define BMSallocBlockMemorySize(mem, ptr, size)
Definition: memory.h:453
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:437
void SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr,...)
Definition: message.c:618
void SCIPmessagePrintWarning(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
Definition: message.c:427
real eps
SCIP_RETCODE 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:471
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:1592
int SCIPprobGetNContVars(SCIP_PROB *prob)
Definition: prob.c:2437
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:970
SCIP_RETCODE SCIPprobVarChangedStatus(SCIP_PROB *prob, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_BRANCHCAND *branchcand, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var)
Definition: prob.c:1224
const char * SCIPprobGetName(SCIP_PROB *prob)
Definition: prob.c:2392
void SCIPprobAddObjoffset(SCIP_PROB *prob, SCIP_Real addval)
Definition: prob.c:1481
int SCIPprobGetNVars(SCIP_PROB *prob)
Definition: prob.c:2401
SCIP_VAR ** SCIPprobGetVars(SCIP_PROB *prob)
Definition: prob.c:2446
SCIP_Bool SCIPprobIsTransformed(SCIP_PROB *prob)
Definition: prob.c:2336
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:6918
SCIP_Real SCIPsetFloor(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6386
SCIP_Bool SCIPsetIsFeasPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6718
SCIP_Bool SCIPsetIsGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6293
SCIP_Real SCIPsetFeasCeil(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6775
SCIP_Bool SCIPsetIsFeasNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6729
SCIP_Real SCIPsetFeastol(SCIP_SET *set)
Definition: set.c:6106
SCIP_Real SCIPsetCeil(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6397
SCIP_Bool SCIPsetIsFeasGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6663
SCIP_Bool SCIPsetIsFeasLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6641
SCIP_Bool SCIPsetIsFeasEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6597
SCIP_Bool SCIPsetIsPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6322
SCIP_Bool SCIPsetIsLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6257
SCIP_Real SCIPsetFeasFloor(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6764
SCIP_Bool SCIPsetIsDualfeasNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6940
SCIP_Real SCIPsetEpsilon(SCIP_SET *set)
Definition: set.c:6086
SCIP_Bool SCIPsetIsEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6221
SCIP_Bool SCIPsetIsFeasZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6707
SCIP_STAGE SCIPsetGetStage(SCIP_SET *set)
Definition: set.c:2952
SCIP_Bool SCIPsetIsFeasLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6619
SCIP_Real SCIPsetInfinity(SCIP_SET *set)
Definition: set.c:6064
SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6239
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6199
SCIP_Bool SCIPsetIsDualfeasPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6929
SCIP_Bool SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6275
SCIP_Bool SCIPsetIsIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6344
SCIP_Bool SCIPsetIsZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6311
SCIP_Bool SCIPsetIsFeasGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6685
SCIP_Real SCIPsetGetHugeValue(SCIP_SET *set)
Definition: set.c:6076
SCIP_Real SCIPsetRound(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6408
int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
Definition: set.c:5764
SCIP_Bool SCIPsetIsFeasIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6740
SCIP_Bool SCIPsetIsNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6333
internal methods for global SCIP settings
#define SCIPsetFreeBufferArray(set, ptr)
Definition: set.h:1755
#define SCIPsetFreeCleanBufferArray(set, ptr)
Definition: set.h:1762
#define SCIPsetAllocBufferArray(set, ptr, num)
Definition: set.h:1748
#define SCIPsetAllocCleanBufferArray(set, ptr, num)
Definition: set.h:1759
#define SCIPsetDuplicateBufferArray(set, ptr, source, num)
Definition: set.h:1750
#define SCIPsetDebugMsg
Definition: set.h:1784
#define SCIPsetReallocBufferArray(set, ptr, num)
Definition: set.h:1752
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
union SCIP_BoundChg::@21 data
SCIP_Real newbound
Definition: struct_var.h:93
unsigned int applied
Definition: struct_var.h:103
unsigned int boundtype
Definition: struct_var.h:101
SCIP_INFERENCEDATA inferencedata
Definition: struct_var.h:97
unsigned int redundant
Definition: struct_var.h:104
SCIP_VAR * var
Definition: struct_var.h:99
SCIP_BRANCHINGDATA branchingdata
Definition: struct_var.h:96
unsigned int inferboundtype
Definition: struct_var.h:102
unsigned int boundchgtype
Definition: struct_var.h:100
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
Definition: struct_event.h:198
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:87
SCIP_Real objscale
Definition: struct_prob.h:51
char * name
Definition: struct_lp.h:226
SCIP_VAR * lastbranchvar
Definition: struct_stat.h:183
SCIP_Longint lpcount
Definition: struct_stat.h:190
SCIP_HISTORY * glbhistory
Definition: struct_stat.h:181
int nrootboundchgs
Definition: struct_stat.h:222
int nrootintfixingsrun
Definition: struct_stat.h:225
int nrootintfixings
Definition: struct_stat.h:224
SCIP_Real vsidsweight
Definition: struct_stat.h:132
SCIP_BRANCHDIR lastbranchdir
Definition: struct_stat.h:187
int nrootboundchgsrun
Definition: struct_stat.h:223
SCIP_Bool collectvarhistory
Definition: struct_stat.h:281
SCIP_HISTORY * glbhistorycrun
Definition: struct_stat.h:182
SCIP_Real lastbranchvalue
Definition: struct_stat.h:143
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
union SCIP_Var::@22 data
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_Real conflictrelaxedub
Definition: struct_var.h:222
SCIP_BDCHGINFO * ubchginfos
Definition: struct_var.h:249
SCIP_Real bestrootredcost
Definition: struct_var.h:214
char * name
Definition: struct_var.h:235
SCIP_Real conflictrelaxedlb
Definition: struct_var.h:221
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
int lbchginfossize
Definition: struct_var.h:266
SCIP_HISTORY * history
Definition: struct_var.h:250
int index
Definition: struct_var.h:254
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 nuses
Definition: struct_var.h:262
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:81
SCIP_PROB * transprob
Definition: struct_scip.h:99
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
Definition: heur_padm.c:135
SCIP_NODE * SCIPtreeGetRootNode(SCIP_TREE *tree)
Definition: tree.c:8553
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:2107
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
#define SCIP_EVENTTYPE_LHOLEADDED
Definition: type_event.h:83
uint64_t SCIP_EVENTTYPE
Definition: type_event.h:151
@ SCIP_BRANCHDIR_DOWNWARDS
Definition: type_history.h:43
@ SCIP_BRANCHDIR_AUTO
Definition: type_history.h:46
@ SCIP_BRANCHDIR_UPWARDS
Definition: type_history.h:44
enum SCIP_BranchDir SCIP_BRANCHDIR
Definition: type_history.h:48
@ 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
@ 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
Definition: type_retcode.h:53
@ SCIP_READERROR
Definition: type_retcode.h:45
@ SCIP_INVALIDDATA
Definition: type_retcode.h:52
@ SCIP_OKAY
Definition: type_retcode.h:42
@ SCIP_INVALIDCALL
Definition: type_retcode.h:51
@ SCIP_ERROR
Definition: type_retcode.h:43
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
@ 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:6056
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:6336
SCIP_Real SCIPvarGetObjLP(SCIP_VAR *var)
Definition: var.c:12913
SCIP_Real SCIPvarGetPseudocost(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition: var.c:14504
SCIP_RETCODE SCIPvarsGetActiveVars(SCIP_SET *set, SCIP_VAR **vars, int *nvars, int varssize, int *requiredsize)
Definition: var.c:12033
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:5051
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:15474
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:6683
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:7476
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:7811
SCIP_Real SCIPvarGetPseudocostCount(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14600
SCIP_RETCODE SCIPvarResetBounds(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat)
Definition: var.c:9237
void SCIPbdchginfoFree(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem)
Definition: var.c:16590
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:6261
static SCIP_RETCODE varProcessChgBranchPriority(SCIP_VAR *var, int branchpriority)
Definition: var.c:11658
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:14719
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:13495
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 SCIPvarSetLastGMIScore(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real gmieff)
Definition: var.c:16510
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:9518
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:15558
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:15078
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:7644
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:9000
SCIP_Real SCIPvarGetAvgCutoffs(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:16292
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:9388
static SCIP_VAR * varGetActiveVar(SCIP_VAR *var)
Definition: var.c:5796
SCIP_RETCODE SCIPvarUpdatePseudocost(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition: var.c:14406
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:8700
SCIP_RETCODE SCIPvarAddCliqueToList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:11420
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:6226
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:8881
SCIP_Real SCIPvarGetAvgInferencesCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:16151
static SCIP_RETCODE varEventImplAdded(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:9270
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:14225
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:15214
void SCIPvarAdjustLb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *lb)
Definition: var.c:6514
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:18612
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:7182
SCIP_RETCODE SCIPvarSetNLPSol(SCIP_VAR *var, SCIP_SET *set, SCIP_Real solval)
Definition: var.c:14033
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:14773
static SCIP_BDCHGIDX presolvebdchgidx
Definition: var.c:17017
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:7553
SCIP_Bool SCIPvarIsPscostRelerrorReliable(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real threshold, SCIP_CONFIDENCELEVEL clevel)
Definition: var.c:14811
SCIP_RETCODE SCIPvarChgLbOriginal(SCIP_VAR *var, SCIP_SET *set, SCIP_Real newbound)
Definition: var.c:6564
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:14297
SCIP_Real SCIPvarGetLbLP(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:12959
void SCIPvarAdjustBd(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real *bd)
Definition: var.c:6548
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:7591
SCIP_RETCODE SCIPvarChgObjDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newobj)
Definition: var.c:6451
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:14022
SCIP_RETCODE SCIPvarPrint(SCIP_VAR *var, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: var.c:3006
SCIP_Real SCIPvarGetAvgGMIScore(SCIP_VAR *var, SCIP_STAT *stat)
Definition: var.c:16386
SCIP_Real SCIPvarGetVSIDS(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:18570
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:15642
SCIP_Real SCIPvarGetMultaggrLbLocal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8441
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:4547
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:14888
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:6721
SCIP_RETCODE SCIPvarChgBranchDirection(SCIP_VAR *var, SCIP_BRANCHDIR branchdirection)
Definition: var.c:11845
SCIP_Real SCIPvarGetPseudocostCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition: var.c:14553
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:13296
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:5845
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:6175
SCIP_RETCODE SCIPvarFlattenAggregationGraph(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:4421
SCIP_Longint SCIPvarGetNActiveConflicts(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15295
void SCIPvarUpdateBestRootSol(SCIP_VAR *var, SCIP_SET *set, SCIP_Real rootsol, SCIP_Real rootredcost, SCIP_Real rootlpobjval)
Definition: var.c:13307
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:15904
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:8230
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:11209
SCIP_RETCODE SCIPvarScaleVSIDS(SCIP_VAR *var, SCIP_Real scalar)
Definition: var.c:15164
static SCIP_RETCODE findValuehistoryEntry(SCIP_VAR *var, SCIP_Real value, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HISTORY **history)
Definition: var.c:15023
SCIP_Real SCIPvarGetAvgConflictlength(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15387
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:7008
SCIP_Real SCIPvarGetPseudocostCountCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14645
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:7330
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:3926
#define MAX_CLIQUELENGTH
Definition: var.c:13491
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:13029
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:6623
SCIP_RETCODE SCIPvarChgUbDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newbound)
Definition: var.c:8346
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:16094
int SCIPvarGetConflictingBdchgDepth(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real bound)
Definition: var.c:17072
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:8639
void SCIPvarGetClosestVlb(SCIP_VAR *var, SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *closestvlb, int *closestvlbidx)
Definition: var.c:14150
SCIP_RETCODE SCIPvarChgUbLazy(SCIP_VAR *var, SCIP_SET *set, SCIP_Real lazyub)
Definition: var.c:7499
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:9290
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:14954
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:5289
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:6092
#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:4516
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:6759
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:18585
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:9128
SCIP_Bool SCIPvarIsMarkedDeleteGlobalStructures(SCIP_VAR *var)
Definition: var.c:17713
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:11459
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:4738
SCIP_Real SCIPvarGetRelaxSol(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:13950
SCIP_RETCODE SCIPvarDelCliqueFromList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:11442
int SCIPbdchgidxGetPos(SCIP_BDCHGIDX *bdchgidx)
Definition: var.c:18637
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:7525
static SCIP_Bool useValuehistory(SCIP_VAR *var, SCIP_Real value, SCIP_SET *set)
Definition: var.c:15050
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:10939
SCIP_RETCODE SCIPvarsAddClique(SCIP_VAR **vars, SCIP_Bool *values, int nvars, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_CLIQUE *clique)
Definition: var.c:11382
SCIP_RETCODE SCIPvarMarkDoNotAggr(SCIP_VAR *var)
Definition: var.c:6103
static SCIP_RETCODE varProcessChgBranchFactor(SCIP_VAR *var, SCIP_SET *set, SCIP_Real branchfactor)
Definition: var.c:11523
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:7977
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:17014
SCIP_RETCODE SCIPvarChgBranchPriority(SCIP_VAR *var, int branchpriority)
Definition: var.c:11714
static SCIP_RETCODE domchgCreate(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem)
Definition: var.c:1039
SCIP_RETCODE SCIPvarMarkDoNotMultaggr(SCIP_VAR *var)
Definition: var.c:6139
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:5914
SCIP_Real SCIPvarGetMultaggrUbLocal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8507
SCIP_RETCODE SCIPbdchginfoCreate(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_Real oldbound, SCIP_Real newbound)
Definition: var.c:16560
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:9799
SCIP_Real SCIPvarGetMinPseudocostScore(SCIP_VAR *var, SCIP_STAT *stat, SCIP_SET *set, SCIP_Real solval)
Definition: var.c:14688
SCIP_RETCODE SCIPvarGetProbvarSum(SCIP_VAR **var, SCIP_SET *set, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12674
SCIP_RETCODE SCIPvarIncGMIeffSum(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real gmieff)
Definition: var.c:16426
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:6832
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:9419
SCIP_Real SCIPvarGetLastGMIScore(SCIP_VAR *var, SCIP_STAT *stat)
Definition: var.c:16470
void SCIPvarAdjustUb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *ub)
Definition: var.c:6531
SCIP_Real SCIPbdchginfoGetRelaxedBound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18826
static SCIP_Real getImplVarRedcost(SCIP_VAR *var, SCIP_SET *set, SCIP_Bool varfixing, SCIP_STAT *stat, SCIP_LP *lp)
Definition: var.c:13442
SCIP_RETCODE SCIPvarChgLbDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newbound)
Definition: var.c:8256
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:5443
static SCIP_Real SCIPvarGetPseudoSol_rec(SCIP_VAR *var)
Definition: var.c:13217
#define MAXABSVBCOEF
Definition: var.c:79
SCIP_Real SCIPvarGetAvgConflictlengthCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15431
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:8104
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:10007
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:15955
static void varIncRootboundchgs(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat)
Definition: var.c:6791
void SCIPvarSetNamePointer(SCIP_VAR *var, const char *name)
Definition: var.c:6038
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:4532
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:8752
void SCIPvarSetProbindex(SCIP_VAR *var, int probindex)
Definition: var.c:6023
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:10482
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:8573
SCIP_RETCODE SCIPvarSetRelaxSol(SCIP_VAR *var, SCIP_SET *set, SCIP_RELAXATION *relaxation, SCIP_Real solval, SCIP_Bool updateobj)
Definition: var.c:13889
SCIP_RETCODE SCIPvarChgBranchFactor(SCIP_VAR *var, SCIP_SET *set, SCIP_Real branchfactor)
Definition: var.c:11587
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:15342
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:11297
static SCIP_RETCODE boundchgCaptureData(SCIP_BOUNDCHG *boundchg)
Definition: var.c:970
static SCIP_RETCODE varProcessChgBranchDirection(SCIP_VAR *var, SCIP_BRANCHDIR branchdirection)
Definition: var.c:11778
SCIP_Real SCIPvarGetAvgCutoffsCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:16339
SCIP_Bool SCIPvarDoNotMultaggr(SCIP_VAR *var)
Definition: var.c:5878
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:6004
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:9726
internal methods for problem variables